XRPL Snap Adapter
XRPL Snap connects XRPL accounts through MetaMask's Snaps APIs. The wallet appears as MetaMask in the connect UI.
| Integration | Value |
|---|---|
| Package | @xrpl-wallet-kit/adapter-xrpl-snap |
| Adapter ID | xrplsnap |
| Wallet type | MetaMask Snap |
| Client registration | Included in default XRPL wallet lists; xrpl-snap is a client alias |
Installation
npm install @xrpl-wallet-kit/core @xrpl-wallet-kit/adapter-xrpl-snap xrpl@^4For the Client tab below, install @xrpl-wallet-kit/client instead. MetaMask must expose Snaps APIs such as wallet_getSnaps and wallet_requestSnaps.
Connect
import { createWalletKit } from "@xrpl-wallet-kit/client";
const kit = createWalletKit({ network: "mainnet", wallets: ["xrplsnap"] });
const { manager } = kit;
const { account } = await kit.connect("xrplsnap");import { WalletManager } from "@xrpl-wallet-kit/core";
import { createXrplSnapAdapter } from "@xrpl-wallet-kit/adapter-xrpl-snap";
const manager = new WalletManager({
network: "mainnet",
adapters: [createXrplSnapAdapter()],
});
const { account } = await manager.connect("xrplsnap");Start connection from a user action. MetaMask requests permission to install the Snap if needed, then returns the selected account. The adapter prefers a detected MetaMask provider over another extension occupying window.ethereum.
Networks
XRPL mainnet, testnet and devnet map to Snap chain IDs 0, 1 and 2. Network selection/verification depends on the installed Snap's network methods. Xahau is not supported by this adapter.
Capabilities
This table describes Kit's Snap integration, not all possible methods of custom Snaps.
| Operation | Support |
|---|---|
| Connect | Yes |
| Disconnect | Local Kit cleanup; no provider-level disconnect |
| Session restore | Cached account with an available Snaps provider; not fresh account verification |
signTransaction() | Not exposed |
signAndSubmit() | Yes |
signMessage() | Yes; signedTx proof |
signIn() | Not exposed |
switchNetwork() | Not exposed as a manager operation |
| Payment / NFT transactions | Generic txJson; installed Snap dependent |
| QR / deep link | No |
Options
These options apply to createXrplSnapAdapter(). Pass a configured adapter through the client's adapters option when needed.
| Option | Type | Default | Description |
|---|---|---|---|
ethereum | Eip1193Provider | Detected MetaMask provider | Supply a specific Snaps-capable provider |
snapId | string | "npm:xrpl-snap" | Snap to install and invoke |
icon | string | Embedded MetaMask icon | Custom icon URL or data URI |
signMessageDestination | string | Connected account | Destination of the sign-only message-proof Payment |
signMessageMethods | string[] | xrpl_signMessage, xrpl_sign, xrpl_signTransaction, npm:xrpl-snap | Signing methods tried in order |
providerDiscoveryTimeoutMs | number | 1000 | Time to wait for provider discovery |
snapRequestRetryDelaysMs | number[] | [120, 350, 800] | Retry delays for Snap keyring hydration errors only |
Transactions
These XRPL examples use manager and account from either Connect tab. Run each request separately from a user action. Replace recipient addresses and 64-character NFT/offer IDs before signing. Amounts are in drops: "1000000" is 1 XRP. Include DestinationTag when the recipient requires it.
maxFeeDrops is an application-selected ceiling, not the expected fee. Adjust the example limit for your application.
A returned hash or submitted status is not validated ledger confirmation. Check the transaction result before treating a payment or NFT transfer as complete. See WalletManager Events.
Payment
const result = await manager.signAndSubmit({
txJson: {
TransactionType: "Payment",
Account: account.address,
Destination: "<recipient_address>",
Amount: "1000000",
},
maxFeeDrops: "50000",
});
console.log(result.hash);Submission uses the Snap's xrpl_signAndSubmit method. The adapter does not expose generic manager.signTransaction(); message-proof signing does not make transaction sign-only generally available.
NFT Transactions
Each tab signs and submits one transaction. Wallet display and supported transaction types depend on the wallet/provider; generic signing is not a promise of support for every amendment.
await manager.signAndSubmit({
txJson: {
TransactionType: "NFTokenMint",
Account: account.address,
NFTokenTaxon: 0,
Flags: 8, // tfTransferable
},
maxFeeDrops: "50000",
});await manager.signAndSubmit({
txJson: {
TransactionType: "NFTokenCreateOffer",
Account: account.address,
NFTokenID: "<nft_id>",
Amount: "1000000",
Flags: 1, // tfSellNFToken
},
maxFeeDrops: "50000",
});await manager.signAndSubmit({
txJson: {
TransactionType: "NFTokenAcceptOffer",
Account: account.address, // Buyer's account
NFTokenSellOffer: "<sell_offer_id>",
},
maxFeeDrops: "50000",
});await manager.signAndSubmit({
txJson: {
TransactionType: "NFTokenCancelOffer",
Account: account.address, // Offer creator's account
NFTokenOffers: ["<offer_id>"],
},
maxFeeDrops: "50000",
});await manager.signAndSubmit({
txJson: {
TransactionType: "NFTokenBurn",
Account: account.address,
NFTokenID: "<nft_id>",
},
maxFeeDrops: "50000",
});Burning permanently destroys the NFT. For buy offers, brokered acceptance and additional fields, see NFT Marketplace. Xahau uses different transaction examples; see the Xahau guide.
The installed Snap must understand the requested transaction type and fields. Do not infer universal amendment or Batch support.
Authentication
const proof = await manager.signMessage({ message: "Verify wallet ownership" });
console.log(proof.signatureKind); // "signedTx"
console.log(proof.txBlob);Kit builds a 1-drop Payment containing the message in a Memo and asks the Snap to sign without submitting. This is a signed transaction proof, not a compact signature. Use Message Authentication for server verification. Native signIn() is not exposed; never broadcast the authentication transaction.
Sessions and Disconnect
manager.autoReconnect() restores cached account metadata only when a Snaps-capable MetaMask provider is available. This path does not freshly verify the cached account against a passive Snap account query; it must not establish a backend login session.
manager.disconnect() clears Kit state, not MetaMask/Snap site permissions.
Integration Notes
- Provider discovery considers
window.ethereum.providersand EIP-6963 announcements before falling back towindow.ethereum. - When another extension overrides MetaMask, pass the intended
ethereumprovider explicitly. - Generic submission and message-proof methods depend on the installed Snap. Keep
signMessageMethodsaligned with the Snap you select.
Troubleshooting
| Symptom | Action |
|---|---|
| MetaMask is not detected | Enable a Snaps-capable MetaMask provider for the site |
wallet_requestSnaps is unavailable | The active provider/environment does not support Snaps; select the correct provider |
| Installation is rejected | Retry only after the user chooses to grant Snap permissions |
| Signing method is missing | Check the installed Snap's supported methods and your signMessageMethods |
| Snap network cannot be verified | Check its network API support and the network selected in the wallet |