Xaman Adapter
Xaman connects a mobile wallet using browser authorization, QR codes and deep links. No browser extension is required.
| Integration | Value |
|---|---|
| Package | @xrpl-wallet-kit/adapter-xaman |
| Adapter ID | xaman |
| Wallet type | Mobile app |
| Client registration | Included when xamanClientId is provided |
Installation
npm install @xrpl-wallet-kit/core @xrpl-wallet-kit/adapter-xaman xrpl@^4For 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
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");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.
| Operation | Support |
|---|---|
| Connect | Yes |
| Disconnect | Yes; clears the Xaman authorization/session |
| Session restore | Yes, 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 transactions | Yes, through txJson |
| QR / deep link | Yes |
Options
These options apply to createXamanAdapter(), not directly to createWalletKit().
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | Required unless auth or sdk is supplied | Xaman OAuth client/API key; the client helper calls this xamanClientId |
auth | XamanPkceAuth | Not set | Custom authorization handler |
sdk | XamanSdkLike | Not set | Existing Xaman SDK instance |
icon | string | Embedded Xaman icon | Custom icon URL or data URI |
deeplink | (uri: string) => string | Wallet default | Build a deep link for a payload |
onQr | (event) => void | Not set | Receive { adapterId, uri, deeplink?, qrPng? } |
recoveryStorage | WalletStorage | Browser storage | Storage for pending mobile-return recovery |
supportedChains | WalletChainFilter | XRPL integration | Restrict allowed chains for protocol-aware integrations |
maxLastLedgerSequenceExtension | number | 50 | Maximum 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
const result = await manager.signAndSubmit({
txJson: {
TransactionType: "Payment",
Account: account.address,
Destination: "<recipient_address>",
Amount: "1000000",
},
maxFeeDrops: "50000",
});
console.log(result.hash);const result = await manager.signTransaction({
txJson: {
TransactionType: "Payment",
Account: account.address,
Destination: "<recipient_address>",
Amount: "1000000",
},
maxFeeDrops: "50000",
});
console.log(result.txBlob); // Signed, not broadcastXaman 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.
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.
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:
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
| Symptom | Action |
|---|---|
| Authorization or QR does not appear | Check apiKey/xamanClientId, the allowed domain and popup permissions |
| Connection times out | Start a new connection and approve it in Xaman |
| Mobile return cannot recover | Start a fresh connection if the recovery marker expired |
| Wrong chain/network | Select the requested network in Xaman and reconnect |