Skip to content

Xaman Adapter ​

Xaman connects a mobile wallet using browser authorization, QR codes and deep links. No browser extension is required.

IntegrationValue
Package@xrpl-wallet-kit/adapter-xaman
Adapter IDxaman
Wallet typeMobile app
Client registrationIncluded when xamanClientId is provided

Installation ​

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

For the Client tab below, install @xrpl-wallet-kit/client instead. Create an API key at apps.xaman.dev and allow your dApp's domain.

Connect ​

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

const kit = createWalletKit({
  network: "mainnet",
  wallets: ["xaman"],
  xamanClientId: "YOUR_XAMAN_CLIENT_ID",
});
const { manager } = kit;
const { account } = await kit.connect("xaman");
ts
import { WalletManager } from "@xrpl-wallet-kit/core";
import { createXamanAdapter } from "@xrpl-wallet-kit/adapter-xaman";

const manager = new WalletManager({
  network: "mainnet",
  adapters: [createXamanAdapter({ apiKey: "YOUR_XAMAN_CLIENT_ID" })],
});
const { account } = await manager.connect("xaman");

Start connection from a user action. On desktop, approve the browser authorization and scan the QR when shown; on mobile, open Xaman using the deep link. For custom QR UI, listen to manager qr events or provide onQr.

Networks ​

Supports XRPL and Xahau. With the full client, set network: "xahau-mainnet" or "xahau-testnet" and a positive preflight.maxFeeDrops; the client configures the protocol automatically. Core/selective integrations must register the Xahau protocol and adapter chain filter explicitly. See Xahau Configuration.

Capabilities ​

This table describes manager-level operations on XRPL. Xahau connection and signing requirements are documented in the network guide above.

OperationSupport
ConnectYes
DisconnectYes; clears the Xaman authorization/session
Session restoreYes, with matching saved SDK account on XRPL
signTransaction()Yes, through the declared sign-only fallback
signAndSubmit()Yes
signMessage()Yes; signedTx proof
signIn()Not exposed
switchNetwork()Not exposed; reconnect for the selected network
Payment / NFT transactionsYes, through txJson
QR / deep linkYes

Options ​

These options apply to createXamanAdapter(), not directly to createWalletKit().

OptionTypeDefaultDescription
apiKeystringRequired unless auth or sdk is suppliedXaman OAuth client/API key; the client helper calls this xamanClientId
authXamanPkceAuthNot setCustom authorization handler
sdkXamanSdkLikeNot setExisting Xaman SDK instance
iconstringEmbedded Xaman iconCustom icon URL or data URI
deeplink(uri: string) => stringWallet defaultBuild a deep link for a payload
onQr(event) => voidNot setReceive { adapterId, uri, deeplink?, qrPng? }
recoveryStorageWalletStorageBrowser storageStorage for pending mobile-return recovery
supportedChainsWalletChainFilterXRPL integrationRestrict allowed chains for protocol-aware integrations
maxLastLedgerSequenceExtensionnumber50Maximum permitted expiry extension; set 0 for exact preservation

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);
ts
const result = await manager.signTransaction({
  txJson: {
    TransactionType: "Payment",
    Account: account.address,
    Destination: "<recipient_address>",
    Amount: "1000000",
  },
  maxFeeDrops: "50000",
});
console.log(result.txBlob); // Signed, not broadcast

Xaman implements sign-only through signAndSubmit({ submit: false }) internally. DApps still call the standard manager.signTransaction() and receive txBlob without submission.

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.

For sign-only NFT requests, pass the same txJson to manager.signTransaction().

Authentication ​

signMessage() returns a signed SignIn transaction with the message in a Memo, not a compact signature:

ts
const proof = await manager.signMessage({ message: "Verify wallet ownership" });
console.log(proof.signatureKind); // "signedTx"
console.log(proof.txBlob);

Verify the transaction proof on your backend using the Message Authentication guide. The adapter does not expose the separate wallet-native signIn() operation.

Sessions and Disconnect ​

Call manager.autoReconnect() on startup to restore a matching XRPL SDK account or complete a pending mobile return. Mobile recovery markers expire after three minutes. Stored network context is not proof that the mobile wallet changed networks; reconnect explicitly on Xahau after reload.

Use manager.disconnect() to clear the active session and authorization.

Integration Notes ​

  • Allow browser authorization popups/redirects and register the dApp domain in the Xaman developer portal.
  • Xaman may extend a transaction's expiry within maxLastLedgerSequenceExtension; other requested transaction fields must remain consistent.
  • Message proofs and sign-only transactions must not be submitted as authentication requests.

Troubleshooting ​

SymptomAction
Authorization or QR does not appearCheck apiKey/xamanClientId, the allowed domain and popup permissions
Connection times outStart a new connection and approve it in Xaman
Mobile return cannot recoverStart a fresh connection if the recovery marker expired
Wrong chain/networkSelect the requested network in Xaman and reconnect

Released under the MIT License.