> ## Documentation Index
> Fetch the complete documentation index at: https://docs.relay.link/llms.txt
> Use this file to discover all available pages before exploring further.

# Adapters

> An introduction to adapters and how to use them

### What is an adapter anyway?

An adapter is a function that takes parameters and returns an object that adheres to this [interface](https://github.com/reservoirprotocol/relay-sdk/blob/main/packages/sdk/src/types/AdaptedWallet.ts). Let's review the interface in depth:

| Property                         | Description                                                                                                                                                                                                    | Required |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| **vmType**                       | A string representing a supported vmType (`evm`  `svm`  `bvm`  `suivm` `tvm` `lvm`)                                                                                                                            | ✅        |
| **getChainId**                   | An async function that returns a chain id                                                                                                                                                                      | ✅        |
| **handleSignMessageStep**        | An async function that given a signature step item and a step generates a signature                                                                                                                            | ✅        |
| **handleSendTransactionStep**    | An async function that given a chain id, a transaction step item and a step returns a transaction hash                                                                                                         | ✅        |
| **handleConfirmTransactionStep** | An async function that given a transaction hash, a chain id, an onReplaced function and an onCancelled function returns a promise with either an evm receipt or an svm receipt                                 | ✅        |
| **address**                      | An async function that returns the currently connected to address, an address that can sign messages and submit transactions                                                                                   | ✅        |
| **switchChain**                  | An async function that given a chain id switches to that chain, either by prompting the user or automatically switching chains                                                                                 | ✅        |
| **transport**                    | An optional [transport](https://viem.sh/docs/clients/intro.html) to use when making rpc calls.                                                                                                                 | ❌        |
| **getBalance**                   | An optional method to override the default balance fetching logic for selected tokens in the ui kit.                                                                                                           | ❌        |
| **supportsAtomicBatch**          | An optional async function that takes a chain ID and returns whether the wallet supports [EIP-5792's atomic batch capability](https://www.eip5792.xyz/introduction). EVM wallets only.                         | ❌        |
| **handleBatchTransactionStep**   | An optional async function that takes a chain ID and an array of transaction step items, returning a call bundle identifier for batch processing. Only available for EVM wallets that support atomic batching. | ❌        |
| **isEOA**                        | An optional boolean that indicates if the wallet is an EOA (Externally Owned Account). This is used to determine if the wallet is an EOA or a contract account.                                                | ❌        |

### What adapters are available out of the box?

The following adapters are officially maintained and developed by the Relay team:

[SVM Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-svm-wallet-adapter): This adapter gives the sdk the ability to submit transactions on SVM (Solana Virtual Machine) networks. It does not support signing messages and under the hood it uses the [solana web3 sdk](https://solana-foundation.github.io/solana-web3.js/).

[Bitcoin Adapter](https://github.com/relayprotocol/relay-kit/blob/main/packages/relay-bitcoin-wallet-adapter): This adapter gives the sdk the ability to submit transaction to the Bitcoin blockchain. Under the hood it uses [bitcoinjs-lib](https://www.npmjs.com/package/bitcoinjs-lib) to sign and submit transactions. Note that bitcoin transactions have a long finalization period and unlike quicker vms are not polled in real time for confirmation.

[Viem Adapter](https://github.com/relayprotocol/relay-kit/blob/main/packages/sdk/src/utils/viemWallet.ts): This adapter is the default one used when no adapter is provided. You can also import it yourself to convert any viem wallet client into an adapted wallet ready to be used in the sdk.

[Ethers Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-ethers-wallet-adapter): If your application uses ethers then you'll need this adapter to use the SDK. You'll still need to install viem as that's required for polling transactions but you can pass in your ethers signer to submit transactions and sign messages.

[Sui Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-sui-wallet-adapter): This adapter gives the sdk the ability to submit transactions to the Sui blockchain. Under the hood it uses the [@mysten/sui](https://www.npmjs.com/package/@mysten/sui) sdk.

[Tron Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-tron-wallet-adapter): This adapter gives the sdk the ability to submit transactions to the Tron blockchain. Under the hood it uses the [tronweb](https://www.npmjs.com/package/tronweb) sdk.

[Lighter Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-lighter-wallet-adapter): This adapter gives the SDK the ability to deposit to [Lighter](https://lighter.exchange/) from any Relay-supported chain. It owns the full Lighter session lifecycle — resolving the user's Lighter account index, generating an in-memory API key, and registering it via `changeApiKey` on first transfer. Integrators who already run their own Lighter session (backend-provisioned key, wallet-level integration) can pass a pre-built `signerClient` to bypass the bootstrap entirely.

### How can I use an adapter?

You can either make your own adapter, as long as it adheres to the interface above or you can use one of the officials adapters developed and maintained by the Relay team. All of our sdk methods handle a viem wallet or adapted wallet. The viem wallet adapter is used by default when a [viem wallet](https://viem.sh/docs/clients/wallet.html) is passed in for convenience. Refer below for implementation details:

<CodeGroup>
  ```typescript Solana theme={null}
  import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk";
  import { adaptSolanaWallet } from '@relayprotocol/relay-solana-wallet-adapter'
  import { Connection, Keypair, clusterApiUrl, SystemProgram, Transaction } from '@solana/web3.js';
  ...

  //In this example we are loading a keypair as the wallet, but if you have a connector like dynamic you can just fetch the connection from that library
  const wallet = Keypair.generate();
  const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
  const walletAddress = wallet.publicKey.toString()

  const adaptedWallet = adaptSolanaWallet(
    walletAddress,
    792703809, // Chain ID that Relay uses to identify Solana 
    connection, // The Solana web3.js Connection instance for interacting with the network
    connection.sendTransaction // Function to sign and send a transaction, returning a promise with a base58 encoded transaction signature
  )

  const options = ... // define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
          // custom handling
    },
    ...
  })
  ```

  ```typescript Viem theme={null}
  import { getClient, Execute, getQuote, adaptViemWallet } from "@relayprotocol/relay-sdk";
  import { createWalletClient } from 'wagmi'
  import { mainnet } from 'viem/chains'

  ...
   
  const walletClient = createWalletClient({
    chain: mainnet,
    transport: custom(window.ethereum!)
  })

  const options = ... // define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptViemWallet(walletClient),
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
          // custom handling
    },
    ...
  })
  ```

  ```typescript Bitcoin theme={null}
  import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk";
  import { adaptBitcoinWallet } from '@relayprotocol/relay-bitcoin-wallet-adapter'
  import { createWalletClient } from 'wagmi'
  import { mainnet } from 'viem/chains'

  ...
   
  const walletClient = createWalletClient({
    chain: mainnet,
    transport: custom(window.ethereum!)
  })

  const options = ... //define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  const adaptedWallet = adaptBitcoinWallet(
    primaryWallet.address,
    async (_address, _psbt, dynamicParams) => {
      try {
        // Request the wallet to sign the PSBT (this is using dynamic but you could use whatever framework you want)
        const response = await primaryWallet.signPsbt(dynamicParams)
        if (!response) {
          throw 'Missing psbt response'
        }
        return response.signedPsbt
      } catch (e) {
        throw e
      }
    }
  )

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
          //custom handling
    },
    ...
  })
  ```

  ```typescript Ethers theme={null}
  import { getClient } from '@relayprotocol/relay-sdk'
  import { adaptEthersSigner } from '@relayprotocol/relay-ethers-wallet-adapter'
  import { useSigner } from 'wagmi'

  ...

  const { data: signer } = useSigner()
  const adaptedWallet = adaptEthersSigner(signer)

  const options = ... //define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
          //custom handling
    },
    ...
  })
  ```

  ```typescript Sui expandable theme={null}
  import { getFullnodeUrl, SuiClient } from '@mysten/sui/client'
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'
  import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk"
  import { adaptSuiWallet } from '@relayprotocol/relay-sui-wallet-adapter'

  // Create a connection to Sui mainnet
  const rpcUrl = getFullnodeUrl('mainnet')
  const suiClient = new SuiClient({ url: rpcUrl })

  const keypair = new Ed25519Keypair()
  const walletAddress = keypair.toSuiAddress()

  const adaptedWallet = adaptSuiWallet(
    walletAddress,
    103665049, //chain id that Relay uses to identify Sui 
    suiClient,
    async (tx) => {
     const result = await suiClient.signAndExecuteTransaction({
        transaction: tx,
        signer: keypair,
        requestType: 'WaitForLocalExecution',
        options: {
          showEffects: true,
        }
      });

      return result
    }
  )

  const options = ... //define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
      //custom handling
    },
      ...
  })

  ```

  ```typescript Tron theme={null}
  import { TronWallet } from 'tronweb'
  import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk"
  import { adaptTronWallet } from '@relayprotocol/relay-tron-wallet-adapter'

  // Create a TronWeb instance, we recommend using a provider like dynamiclabs if using this on the frontend
  // Note: you should never share your private key with anyone or use on the frontend
  const tronWeb = new TronWeb({fullHost: 'xxx', privateKey: 'privateKey'});
  const walletAddress = tronWeb.defaultAddress.base58
  if (!tronWeb) {
    throw 'Unable to setup Tron wallet'
  }

  const adaptedWallet = adaptTronWallet(
    walletAddress,
    tronWeb
  )
  const options = ... //define this based on getQuote options

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({steps, fees, breakdown, currentStep, currentStepItem, txHashes, details}) => {
      //custom handling
    },
      ...
  })

  ```

  ```typescript Lighter theme={null}
  import { getClient, getQuote } from '@relayprotocol/relay-sdk'
  import { adaptLighterWallet } from '@relayprotocol/relay-lighter-wallet-adapter'
  import { createWalletClient, custom } from 'viem'
  import { mainnet } from 'viem/chains'

  // Lighter deposits are authorized by an L1 (EVM) signature, so the adapter
  // only needs the user's connected EVM address and a signMessage callback.
  const walletClient = createWalletClient({
    chain: mainnet,
    transport: custom(window.ethereum!)
  })

  const [address] = await walletClient.requestAddresses()

  const adaptedWallet = adaptLighterWallet({
    l1Address: address,
    signL1Message: (message) =>
      walletClient.signMessage({ account: address, message })
  })

  const options = ... // define this based on getQuote options (destinationChainId: 3586256, recipient: <Lighter account index>)

  const quote = await getClient().actions.getQuote(options)

  getClient().actions.execute({
    quote,
    wallet: adaptedWallet,
    onProgress: ({ steps, fees, breakdown, currentStep, currentStepItem, txHashes, details }) => {
      // custom handling
    }
  })
  ```
</CodeGroup>

### Viem adapter options

`adaptViemWallet` accepts an optional second argument for adapter-level configuration:

| Property                     | Description                                                                                                                                                                                                                                                            |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **disableCapabilitiesCheck** | Skip `wallet.getCapabilities` calls used for EIP-5792 atomic-batch detection and smart-wallet detection. Set this for wallets with a broken `getCapabilities` implementation that hangs or never resolves. When true, execution falls back to sequential transactions. |

```typescript theme={null}
import { adaptViemWallet } from "@relayprotocol/relay-sdk";

const adaptedWallet = adaptViemWallet(walletClient, {
  disableCapabilitiesCheck: true,
});
```

<Tip>The same flag is available directly on `getQuote`, `execute`, and `claimAppFees` when you pass a raw viem `WalletClient` — the SDK forwards it to `adaptViemWallet` internally.</Tip>
