Skip to content

XRPL Snap Adapter ​

XRPL Snap connects XRPL accounts through MetaMask's Snaps APIs. The wallet appears as MetaMask in the connect UI.

IntegrationValue
Package@xrpl-wallet-kit/adapter-xrpl-snap
Adapter IDxrplsnap
Wallet typeMetaMask Snap
Client registrationIncluded in default XRPL wallet lists; xrpl-snap is a client alias

Installation ​

sh
npm install @xrpl-wallet-kit/core @xrpl-wallet-kit/adapter-xrpl-snap xrpl@^4

For the Client tab below, install @xrpl-wallet-kit/client instead. MetaMask must expose Snaps APIs such as wallet_getSnaps and wallet_requestSnaps.

Connect ​

ts
import { createWalletKit } from "@xrpl-wallet-kit/client";

const kit = createWalletKit({ network: "mainnet", wallets: ["xrplsnap"] });
const { manager } = kit;
const { account } = await kit.connect("xrplsnap");
ts
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.

OperationSupport
ConnectYes
DisconnectLocal Kit cleanup; no provider-level disconnect
Session restoreCached 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 transactionsGeneric txJson; installed Snap dependent
QR / deep linkNo

Options ​

These options apply to createXrplSnapAdapter(). Pass a configured adapter through the client's adapters option when needed.

OptionTypeDefaultDescription
ethereumEip1193ProviderDetected MetaMask providerSupply a specific Snaps-capable provider
snapIdstring"npm:xrpl-snap"Snap to install and invoke
iconstringEmbedded MetaMask iconCustom icon URL or data URI
signMessageDestinationstringConnected accountDestination of the sign-only message-proof Payment
signMessageMethodsstring[]xrpl_signMessage, xrpl_sign, xrpl_signTransaction, npm:xrpl-snapSigning methods tried in order
providerDiscoveryTimeoutMsnumber1000Time to wait for provider discovery
snapRequestRetryDelaysMsnumber[][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 ​

ts
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.

ts
await manager.signAndSubmit({
  txJson: {
    TransactionType: "NFTokenMint",
    Account: account.address,
    NFTokenTaxon: 0,
    Flags: 8, // tfTransferable
  },
  maxFeeDrops: "50000",
});
ts
await manager.signAndSubmit({
  txJson: {
    TransactionType: "NFTokenCreateOffer",
    Account: account.address,
    NFTokenID: "<nft_id>",
    Amount: "1000000",
    Flags: 1, // tfSellNFToken
  },
  maxFeeDrops: "50000",
});
ts
await manager.signAndSubmit({
  txJson: {
    TransactionType: "NFTokenAcceptOffer",
    Account: account.address, // Buyer's account
    NFTokenSellOffer: "<sell_offer_id>",
  },
  maxFeeDrops: "50000",
});
ts
await manager.signAndSubmit({
  txJson: {
    TransactionType: "NFTokenCancelOffer",
    Account: account.address, // Offer creator's account
    NFTokenOffers: ["<offer_id>"],
  },
  maxFeeDrops: "50000",
});
ts
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 ​

ts
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.providers and EIP-6963 announcements before falling back to window.ethereum.
  • When another extension overrides MetaMask, pass the intended ethereum provider explicitly.
  • Generic submission and message-proof methods depend on the installed Snap. Keep signMessageMethods aligned with the Snap you select.

Troubleshooting ​

SymptomAction
MetaMask is not detectedEnable a Snaps-capable MetaMask provider for the site
wallet_requestSnaps is unavailableThe active provider/environment does not support Snaps; select the correct provider
Installation is rejectedRetry only after the user chooses to grant Snap permissions
Signing method is missingCheck the installed Snap's supported methods and your signMessageMethods
Snap network cannot be verifiedCheck its network API support and the network selected in the wallet

Released under the MIT License.