Skip to content

Joey Wallet Adapter ​

Joey Wallet connects directly to the browser extension through its official SDK. This adapter uses joey-wallet; the separate joey entry connects through WalletConnect.

IntegrationValue
Package@xrpl-wallet-kit/adapter-joey-wallet
Adapter IDjoey-wallet
Wallet typeBrowser extension
Client registrationOpt-in; excluded from default lists and wallets: "all"

Installation ​

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

For the Client tab below, install @xrpl-wallet-kit/client instead. Enable the Joey Wallet extension for the dApp.

Connect ​

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

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

const manager = new WalletManager({
  network: "mainnet",
  adapters: [createJoeyWalletAdapter({
    onDisconnected: () => manager.emitDisconnected("joey-wallet"),
  })],
});
const { account } = await manager.connect("joey-wallet");

Call connect from a user action. The client wires disconnection events automatically; core integrations should provide onDisconnected so revoked access or account/network changes invalidate the manager session.

Networks ​

Supports the standard XRPL Mainnet, Testnet and Devnet presets (mainnet, testnet, devnet). Select the same network in Joey and the dApp. Custom RPC/network definitions and Xahau are not supported by this adapter.

Capabilities ​

This table describes the native extension adapter, not the Joey WalletConnect entry.

OperationSupport
ConnectYes
DisconnectYes
Session restoreYes, for an existing grant on the same network
signTransaction()Yes
signAndSubmit()Yes
signMessage()Not exposed
signIn()Yes; CAIP-122 or Ledger transaction challenge
switchNetwork()Not exposed; select in Joey and reconnect
Payment / NFT transactionsThrough generic txJson signing
QR / deep linkNo; use the WalletConnect entry for that flow

Options ​

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

OptionTypeDefaultDescription
providerJoeyInjectedProviderDetected Joey providerSupply a specific provider
maxFeeDropsstring"1000000"Adapter fee ceiling; a request can lower it
onDisconnected() => voidNot setInvalidate the manager session after access, account or network changes

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

The adapter verifies the returned blob, signer, transaction hash, requested fields and fee ceiling.

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(). Generic signing does not enable Batch, bulk signing or multisigning in this adapter.

Authentication ​

Obtain nonceFromServer from your backend, then use the separate native signIn() API, not signMessage():

ts
const proof = await manager.signIn({
  nonce: nonceFromServer,
  statement: "Sign in to My dApp",
});
// Send proof to your backend before establishing a login session.

Joey returns a CAIP-122 message signature for software accounts or a transaction challenge for Ledger accounts. Verify the actual proof with verifyWalletSignIn() and atomically consume the nonce on the server. See Wallet-Native Sign In. Arbitrary signMessage() remains unsupported; do not substitute one API for the other.

Sessions and Disconnect ​

manager.autoReconnect() reads already granted accounts and the current network without an approval popup. It restores only a matching account/network. Account changes, network changes and revoked access require reconnecting.

manager.disconnect() clears the Kit session and calls Joey's disconnect API.

Integration Notes ​

Wallet Standard Discovery ​

If you also enable Wallet Standard discovery, exclude the native Joey entry from discovery to avoid duplicate listings:

ts
import { startWalletStandardDiscovery } from "@xrpl-wallet-kit/core";

startWalletStandardDiscovery(manager, {
  resolveId: wallet => wallet.name === "Joey" ? null
    : `standard-${wallet.name.toLowerCase().replace(/[^a-z0-9-]/g, "-")}`,
});

This display-name filter controls listing only; it is not wallet authentication. Use joey-wallet for the extension and joey for WalletConnect.

Troubleshooting ​

SymptomAction
Joey is not in the wallet listAdd "joey-wallet" explicitly to wallets
Network mismatchSelect the matching standard XRPL network in Joey and reconnect
Two Joey entries appearDistinguish native/WalletConnect entries or filter Wallet Standard discovery
Message signing is unavailableUse native signIn() for login; arbitrary signMessage() is not exposed

Released under the MIT License.