` - The signed transaction payload. Wallet modules may narrow this return type, such as a hex string for EVM and Bitcoin transactions.
**Example:**
```typescript title="Sign Without Broadcasting"
const account = await wdk.getAccount('ethereum', 0)
const signedTransaction = await account.signTransaction({
to: '0x71C7656EC7ab88b098defB751B7401B5f6d8976F',
value: 1000000000000000n
})
console.log('Signed transaction:', signedTransaction)
```
## IWalletAccountWithProtocols
Extended wallet account interface that supports protocol registration and access. Extends `IWalletAccount` from `@tetherto/wdk-wallet`.
### Methods
| Method | Description | Returns | Throws |
|--------|-------------|---------|--------|
| `registerProtocol(label, protocol, config)` | Registers a protocol for this specific account | `IWalletAccountWithProtocols` | - |
| `getSwapProtocol(label)` | Returns the swap protocol with the given label | `ISwapProtocol` | If protocol not found |
| `getBridgeProtocol(label)` | Returns the bridge protocol with the given label | `IBridgeProtocol` | If protocol not found |
| `getLendingProtocol(label)` | Returns the lending protocol with the given label | `ILendingProtocol` | If protocol not found |
##### `registerProtocol(label, protocol, config)`
Registers a new protocol for this specific account.
**Type Parameters:**
- `P`: `typeof SwapProtocol | typeof BridgeProtocol | typeof LendingProtocol` - A class that extends one of the `@tetherto/wdk-wallet/protocol`'s classes
**Parameters:**
- `label` (string): Unique label for the protocol (must be unique per account and protocol type)
- `protocol` (P): The protocol class
- `config` (`ConstructorParameters[1]`): The protocol configuration
**Returns:** `IWalletAccountWithProtocols` - The account instance (supports method chaining)
**Example:**
```javascript title="Register Protocol for Account"
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
const account = await wdk.getAccount('ethereum', 0)
// Register protocol for this specific account
account.registerProtocol('usdt0', Usdt0ProtocolEvm, {
apiKey: 'YOUR_API_KEY'
})
// Method chaining
const account2 = await wdk.getAccount('ethereum', 1)
.registerProtocol('usdt0', Usdt0ProtocolEvm, usdt0ProtocolConfig)
```
##### `getSwapProtocol(label)`
Returns the swap protocol with the given label.
**Parameters:**
- `label` (string): The protocol label
**Returns:** `ISwapProtocol` - The swap protocol instance
**Throws:** Error if no swap protocol with the given label has been registered
**Example:**
```javascript title="Get Swap Protocol"
import veloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
// Register swap protocol
account.registerProtocol('velora', veloraProtocolEvm, veloraProtocolConfig)
// Get swap protocol
const velora = account.getSwapProtocol('velora')
// Use the protocol
const swapResult = await velora.swap({
tokenIn: '0x...',
tokenOut: '0x...',
tokenInAmount: 1000000n
})
// This will throw an error
// try {
// const uniswap = account.getSwapProtocol('uniswap')
// } catch (error) {
// console.error('No swap protocol with label "uniswap" found')
// }
```
##### `getBridgeProtocol(label)`
Returns the bridge protocol with the given label.
**Parameters:**
- `label` (string): The protocol label
**Returns:** `IBridgeProtocol` - The bridge protocol instance
**Throws:** Error if no bridge protocol with the given label has been registered
**Example:**
```javascript title="Get Bridge Protocol"
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
// Register bridge protocol
account.registerProtocol('usdt0', Usdt0ProtocolEvm)
// Get bridge protocol
const usdt0 = account.getBridgeProtocol('usdt0')
// Use the protocol
await account.approve({
token: '0x...',
spender: '0x...', // OFT or bridge spender address
amount: 1000000n
})
const bridgeResult = await usdt0.bridge({
targetChain: 'arbitrum',
recipient: '0x...',
token: '0x...',
amount: 1000000n,
oftContractAddress: '0x...' // Same address used as approval spender
})
```
##### `getLendingProtocol(label)`
Returns the lending protocol with the given label.
**Parameters:**
- `label` (string): The protocol label
**Returns:** `ILendingProtocol` - The lending protocol instance
**Throws:** Error if no lending protocol with the given label has been registered
**Example:**
```javascript title="Get Lending Protocol"
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'
// Register lending protocol
account.registerProtocol('aave', AaveProtocolEvm, aaveProtocolConfig)
// Get lending protocol
const aave = account.getLendingProtocol('aave')
// Use the protocol
const supplyResult = await aave.supply({
token: '0x...',
amount: 1000000n
})
```
## Complete Example
```javascript title="Complete WDK Flow"
import WDK from '@tetherto/wdk'
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerTon from '@tetherto/wdk-wallet-ton'
import veloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
// Initialize WDK Manager
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth.drpc.org'
})
.registerWallet('ton', WalletManagerTon, {
tonApiKey: 'YOUR_TON_API_KEY',
tonApiEndpoint: 'https://tonapi.io'
})
.registerProtocol('ethereum', 'velora', veloraProtocolEvm, {
apiKey: 'YOUR_velora_API_KEY'
})
.registerProtocol('ethereum', 'usdt0', Usdt0ProtocolEvm)
// Get accounts
const accountEth = await wdk.getAccount('ethereum', 3)
const accountTon = await wdk.getAccountByPath('ton', "1'/2/3")
// Use wallet account methods
const { hash, fee } = await accountEth.sendTransaction({
to: '0x...',
value: 1000000000000000000n // 1 ETH
})
// Use protocols
const velora = accountEth.getSwapProtocol('velora')
const swapResult = await velora.swap(swapOptions)
const usdt0 = accountEth.getBridgeProtocol('usdt0')
// bridgeOptions.oftContractAddress is the source-chain bridge spender.
await accountEth.approve({
token: bridgeOptions.token,
spender: bridgeOptions.oftContractAddress,
amount: bridgeOptions.amount
})
const bridgeResult = await usdt0.bridge(bridgeOptions)
// Clean up
wdk.dispose()
```
## Types
### FeeRates
```typescript title="Type: FeeRates"
interface FeeRates {
[blockchain: string]: {
normal: number;
fast: number;
};
}
```
### Middleware Function
```typescript title="Type: MiddlewareFunction"
type MiddlewareFunction = (
account: A
) => Promise;
```
### Protocol Types
```typescript title="Types: Protocol Interfaces"
// Swap Protocol
interface ISwapProtocol {
swap(options: SwapOptions): Promise;
}
// Bridge Protocol
interface IBridgeProtocol {
bridge(options: BridgeOptions): Promise;
}
// Lending Protocol
interface ILendingProtocol {
supply(options: LendingOptions): Promise;
withdraw(options: LendingOptions): Promise;
borrow(options: LendingOptions): Promise;
repay(options: LendingOptions): Promise;
}
// Swidge Protocol (unified swap + bridge + route)
interface ISwidgeProtocol extends ISwapProtocol, IBridgeProtocol {
quoteSwidge(options: SwidgeOptions): Promise;
swidge(options: SwidgeOptions, config?: SwidgeProtocolConfig): Promise;
getSwidgeStatus(id: string, options?: SwidgeStatusOptions): Promise;
getSupportedChains(): Promise;
getSupportedTokens(options?: SwidgeSupportedTokensOptions): Promise;
}
```
### Swidge Protocol
`SwidgeProtocol` is an abstract base class exported from `@tetherto/wdk-wallet/protocols` for provider packages that implement a single, route-aware surface for same-chain swaps and cross-chain bridges. It implements `ISwidgeProtocol`, which extends both `ISwapProtocol` and `IBridgeProtocol`, so the base class derives `swap()`, `quoteSwap()`, `bridge()`, and `quoteBridge()` by delegating to `swidge()` and `quoteSwidge()`. Provider subclasses implement the abstract methods below.
| Method | Description | Returns |
|--------|-------------|---------|
| `quoteSwidge(options)` | Returns a non-binding quote for a swap/bridge operation | `Promise` |
| `swidge(options, config?)` | Executes a swap/bridge operation | `Promise` |
| `getSwidgeStatus(id, options?)` | Returns the current status of an in-flight operation | `Promise` |
| `getSupportedChains()` | Returns the chains the provider supports | `Promise` |
| `getSupportedTokens(options?)` | Returns the tokens the provider supports, optionally route-scoped | `Promise` |
The `SwidgeOptions` input combines common fields (`fromToken`, `toToken`, optional `toChain`, `recipient`, `refundAddress`, `slippage`) with either an exact-in (`fromTokenAmount`) or exact-out (`toTokenAmount`) amount. The optional `SwidgeProtocolConfig` accepts `maxNetworkFeeBps` and `maxProtocolFeeBps` to cap acceptable fees.
See the [Swidge Protocol Interface](/sdk/swidge-modules) page for the full discovery, quote, execution, status, fee, and result shapes.
```typescript title="Type: ISwidgeProtocol Options and Results"
type SwidgeProtocolConfig = {
maxNetworkFeeBps?: number | bigint;
maxProtocolFeeBps?: number | bigint;
};
type SwidgeOptions = {
fromToken: string;
toToken: string;
toChain?: string | number; // defaults to the source chain (same-chain swap)
recipient?: string;
refundAddress?: string;
slippage?: number; // decimal, e.g. 0.01 for 1%
} & (
| { fromTokenAmount: number | bigint } // exact-in
| { toTokenAmount: number | bigint } // exact-out
);
type SwidgeStatus =
| 'pending' | 'action-required' | 'completed' | 'failed'
| 'refund-pending' | 'refunded' | 'cancelled' | 'expired' | 'partial';
```
***
## Next Steps
Get started with WDK's configuration
Get started with WDK's Usage
Explore blockchain-specific wallet modules
Cross-chain USD₮0 bridges
***
### Need Help?
***
## WDK Core Configuration
URL: https://docs.wdk.tether.io/sdk/core-module/configuration
Description: Configuration options and settings for @tetherto/wdk
# Configuration
## WDK Manager Configuration
```javascript title="Create WDK Instance"
import WDK from '@tetherto/wdk'
const wdk = new WDK(seedPhrase)
```
The WDK Manager itself only requires a seed phrase for initialization. Configuration is done through the registration of wallets and protocols.
## Wallet Registration Configuration
```javascript title="Register WDK Wallet"
import WDK from '@tetherto/wdk'
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerTon from '@tetherto/wdk-wallet-ton'
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth.drpc.org'
})
.registerWallet('ton', WalletManagerTon, {
tonApiKey: 'YOUR_TON_API_KEY',
tonApiEndpoint: 'https://tonapi.io'
})
```
## Protocol Registration Configuration
```javascript title="Register WDK Protocol"
import veloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
const wdk = new WDK(seedPhrase)
.registerProtocol('ethereum', 'velora', veloraProtocolEvm, {
apiKey: 'YOUR_velora_API_KEY'
})
```
## Configuration Options
### Wallet Configuration
Each wallet manager requires its own configuration object when registered. The configuration depends on the specific wallet module being used.
#### EVM Wallet Configuration
```javascript title="Ethereum WDK Wallet Configuration"
const ethereumWalletConfig = {
provider: 'https://eth.drpc.org', // RPC endpoint
// Additional EVM-specific configuration options
}
wdk.registerWallet('ethereum', WalletManagerEvm, ethereumWalletConfig)
```
#### TON Wallet Configuration
```javascript title="TON WDK Wallet Configuration"
const tonWalletConfig = {
tonClient: {
secretKey: 'YOUR_TON_API_KEY',
url: 'https://toncenter.com/api/v2/jsonRPC'
}
}
wdk.registerWallet('ton', WalletManagerTon, tonWalletConfig)
```
### Protocol Configuration
Protocols also require their own configuration objects when registered.
#### Swap Protocol Configuration
```javascript title="Swap WDK Protocol Configuration"
const veloraProtocolConfig = {
apiKey: 'YOUR_velora_API_KEY',
baseUrl: 'https://apiv5.velora.io'
}
wdk.registerProtocol('ethereum', 'velora', veloraProtocolEvm, veloraProtocolConfig)
```
### Middleware Configuration
Middleware functions can be registered to enhance account functionality.
```javascript title="Middleware WDK Protocol Configuration"
// Simple logging middleware
wdk.registerMiddleware('ethereum', async (account) => {
console.log('New account created:', await account.getAddress())
})
```
## Environment Variables
For production applications, consider using environment variables for sensitive configuration:
```javascript title="WDK environment variables Configuration"
const wdk = new WDK(process.env.SEED_PHRASE)
.registerWallet('ethereum', WalletManagerEvm, {
provider: process.env.ETHEREUM_RPC_URL
})
.registerProtocol('ethereum', 'velora', veloraProtocolEvm, {
apiKey: process.env.velora_API_KEY
})
```
## Configuration Validation
The WDK Manager will validate configurations when wallets and protocols are registered:
- **Wallet Registration**: Ensures the wallet class extends the required base class
- **Protocol Registration**: Validates that protocol labels are unique per blockchain and protocol type
- **Middleware Registration**: Validates that middleware functions have the correct signature
## Error Handling
Configuration errors will be thrown during registration:
```javascript title="Configuration errors"
try {
wdk.registerWallet('ethereum', InvalidWalletClass, config)
} catch (error) {
console.error('Wallet registration failed:', error.message)
}
try {
wdk.registerProtocol('ethereum', 'velora', veloraProtocolEvm, invalidConfig)
} catch (error) {
console.error('Protocol registration failed:', error.message)
}
```
***
## Next Steps
Get started with WDK's usage
Get started with WDK's API
Explore blockchain-specific wallet modules
Cross-chain USD₮0 bridges
***
### Need Help?
***
## Manage Accounts
URL: https://docs.wdk.tether.io/sdk/core-module/guides/account-management
Description: Learn how to work with accounts and addresses.
This guide explains how to access accounts from your registered wallets. An "Account" object in WDK is your interface for inspecting balances and sending transactions on a specific blockchain.
## Retrieve Accounts
You can retrieve an account using a simple index or a custom derivation path.
### By Index (Recommended)
The simplest way to get an account is by its index (starting at `0`). This uses the default derivation path for the specified blockchain.
```typescript title="Get Account by Index"
// Get the first account (index 0) for Ethereum and TON
const ethAccount = await wdk.getAccount('ethereum', 0)
const tonAccount = await wdk.getAccount('ton', 0)
```
### By Derivation Path (Advanced)
If you need a specific hierarchy, you can request an account by its unique derivation path.
```typescript title="Get Account by Path"
// Custom path for Ethereum
const customEthAccount = await wdk.getAccountByPath('ethereum', "0'/0/1")
```
The WDK instance caches accounts. If you call `getAccount` twice using the same index, the function will return the same `Account` object instance.
**Network Mismatch Warning**
Ensure your WDK instance configuration matches your account environment.
* If using **Testnet** keys, ensure you registered the wallet with a **Testnet RPC** (e.g., `https://sepolia.drpc.org` for ETH, `https://testnet.toncenter.com/api/v2/jsonRPC` for TON).
* If using **Mainnet** keys, ensure you registered the wallet with a **Mainnet RPC** (e.g., `https://eth.drpc.org` for ETH, `https://toncenter.com/api/v2/jsonRPC` for TON).
Using a Mainnet key on a Testnet RPC (or vice versa) will result in "Network not allowed" or zero balance errors.
## View Addresses
Once you have an account object, you can retrieve its public blockchain address using the `getAddress` function.
```typescript title="Get Addresses"
const ethAddress = await ethAccount.getAddress()
console.log('Ethereum address:', ethAddress)
```
## Check Balances
You can check the native token balance of any account (e.g., ETH on Ethereum, TON on TON) by using the `getBalance()` function.
```typescript title="Get Balance"
try {
const balance = await ethAccount.getBalance()
console.log('Balance:', balance)
} catch (error) {
console.error('Failed to fetch balance:', error)
}
```
### Multi-Chain Balance Check
Because WDK offers a unified interface, you can easily iterate through multiple chains to fetch balances.
The following example:
1. Iterates over an array of user defined chains.
2. Retrieves the first account using the respective chain's `getAccount(index)` function.
3. Retrieves the first account's balance using the `getBalance()` function.
4. Logs the balance to the console.
```typescript title="Check All Balances"
const chains = ['ethereum', 'ton', 'bitcoin']
for (const chain of chains) {
try {
const account = await wdk.getAccount(chain, 0)
const balance = await account.getBalance()
console.log(`${chain} balance:`, balance)
} catch (error) {
console.log(`${chain}: Wallet not registered or unavailable`)
}
}
```
## Next Steps
Now that you can access your accounts, learn how to [send transactions](/sdk/core-module/guides/transactions).
***
## Error Handling
URL: https://docs.wdk.tether.io/sdk/core-module/guides/error-handling
Description: Learn about common errors and best practices.
# Error Handling & Best Practices
This guide covers recommended patterns for error handling and security when using the WDK.
## Handling Common Errors
When interacting with multiple chains and protocols, various runtime issues may occur.
### Missing Registration
The most common error is attempting to access a wallet or protocol that hasn't been registered.
```typescript title="Check Registration Pattern"
try {
// This will throw if 'tron' was never registered via .registerWallet()
const tronAccount = await wdk.getAccount('tron', 0)
} catch (error) {
console.error('Tron wallet not available:', error.message)
}
```
Always use `try/catch` blocks when initializing sessions or accessing dynamic features.
## Memory Management
For security, clear sensitive data from memory when a session is complete. The WDK provides [`dispose()`](/sdk/core-module/api-reference) for this purpose.
### Disposing the Instance
You can clear every registered wallet using [`dispose()`](/sdk/core-module/api-reference):
```typescript title="Dispose WDK"
function endSession(wdk) {
// 1. Clean up sensitive data
wdk.dispose()
// 2. Modify app state to reflect logged-out status
// ...
console.log('Session ended, wallet data cleared.')
}
```
### Disposing Specific Wallets
You can dispose only the wallets you no longer need using [`dispose()`](/sdk/core-module/api-reference):
```typescript title="Dispose Specific Wallets"
// Keep the TON wallet registered, but dispose the Ethereum wallet
wdk.dispose(['ethereum'])
```
**After Disposal:** Once a wallet is disposed, any later call that depends on that wallet registration will fail until you register it again. If you call `wdk.dispose()` without arguments, you must instantiate a new WDK instance or register fresh wallets before resuming operations.
## Security Best Practices
### Environment Variables
Never hardcode API keys or seed phrases in your source code. Use environment variables (e.g., `process.env.TON_API_KEY`).
### Secure Storage
If you persist a session, never store the raw seed phrase in local storage. Use secure operating system storage (like Keychain on macOS or Keystore on Android).
***
## Getting Started
URL: https://docs.wdk.tether.io/sdk/core-module/guides/getting-started
Description: Install and instantiate the WDK Core module.
This guide explains how to install the [`@tetherto/wdk`](https://www.npmjs.com/package/@tetherto/wdk) package and create a new instance to start managing your wallets.
## 1. Installation
### Prerequisites
Before you begin, ensure you have the following installed:
* **[Node.js](https://nodejs.org/)**: version 18 or higher.
* **[npm](https://www.npmjs.com/)**: usually comes with Node.js.
### Install Package
To install the WDK Core package, run the following command in your terminal:
```bash
npm install @tetherto/wdk
```
This package allows you to manage different blockchain wallets and protocols through a single interface.
## 2. Instantiation
To use WDK, you must create an instance of the `WDK` class. This instance acts as the central manager for all your wallets and protocols.
### Import the Module
First, import the `WDK` class from the package:
```typescript title="Import WDK Core"
import WDK from '@tetherto/wdk'
```
### Initialize WDK
You can initialize `WDK` in two ways: with a [new seed phrase](#generate-a-new-wallet) or an [existing one](#restore-an-existing-wallet).
#### Generate a New Wallet
If you are creating a fresh wallet for a user, use the static `getRandomSeedPhrase()` method to generate a secure mnemonic.
```typescript title="Create new WDK Instance"
// 1. Generate a secure random seed phrase
// Generate 24-word seed phrase for higher security
const seedPhrase = WDK.getRandomSeedPhrase(24)
// Or use 12-word seed phrase (default)
// const seedPhrase = WDK.getRandomSeedPhrase()
// 2. Initialize the WDK instance with the new seed
const wdk = new WDK(seedPhrase)
```
**Secure the Seed Phrase:** You must securely store this seed phrase immediately. If it is lost, the user will permanently lose access to their funds.
#### Restore an Existing Wallet
If a user already has a seed phrase (e.g., from a previous session or another wallet), you can pass it directly to the constructor.
```typescript title="Restore WDK Instance"
// Replace this string with the user's actual seed phrase
const existingSeed = 'witch collapse practice feed shame open despair creek road again ice ...'
const wdk = new WDK(existingSeed)
```
## Next Steps
With your WDK instance ready, you can now [register wallet modules](/sdk/core-module/guides/wallet-registration) to interact with specific blockchains like [Ethereum](/sdk/wallet-modules/wallet-evm/), [TON](/sdk/wallet-modules/wallet-ton/), or [Bitcoin](/sdk/wallet-modules/wallet-btc/).
***
## Configure Middleware
URL: https://docs.wdk.tether.io/sdk/core-module/guides/middleware
Description: Learn how to intercept and enhance wallet operations with middleware.
Middleware allows you to intercept wallet operations. You can use this to add [logging](#logging), implement retry logic, or handle [failovers for RPC providers](#failover-protection-with-provider-failover).
## Register Middleware
When registering middleware, you should reference a specific chain. The middleware function runs every time an account is instantiated or an operation is performed, depending on the implementation.
### Logging
This simple middleware logs a message whenever a new account is accessed.
```typescript title="Logging Middleware"
wdk.registerMiddleware('ethereum', async (account) => {
const address = await account.getAddress()
console.log('Accessed Ethereum account:', address)
// You can also attach custom properties or wrap methods here
})
```
## Failover Protection with Provider Failover
The [`@tetherto/wdk-provider-failover`](https://www.npmjs.com/package/@tetherto/wdk-provider-failover) package provides a resilient wrapper for wallet instances. Unlike standard middleware, you wrap your wallet class instantiation directly.
### Install `@tetherto/wdk-provider-failover`
You can install the `@tetherto/wdk-provider-failover` using npm with the following command:
```bash
npm install @tetherto/wdk-provider-failover
```
### Use `createFallbackWallet`
You can import the `createFallbackWallet` function to ensure that if your primary RPC fails, the wallet automatically retries with the fallback providers.
With this configuration, if `sendTransaction` fails due to a network error, the WDK will automatically retry using the fallback providers without throwing an error to your application.
```typescript title="Failover Wrapper Usage"
import { createFallbackWallet } from '@tetherto/wdk-provider-failover'
import { WalletAccountReadOnlyEvm } from '@tetherto/wdk-wallet-evm'
const wallet = createFallbackWallet(
WalletAccountReadOnlyEvm,
['0x...'], // constructor args
{
primary: { provider: 'https://mainnet.infura.io/v3/YOUR_KEY' },
fallbacks: [
{ provider: 'https://eth.llamarpc.com' },
{ provider: 'https://ethereum.publicnode.com' }
]
}
)
// Use the wallet instance directly
const balance = await wallet.getBalance()
```
## Next Steps
Learn about [error handling and best practices](/sdk/core-module/guides/error-handling) to ensure your application is robust and secure.
***
## Integrate Protocols
URL: https://docs.wdk.tether.io/sdk/core-module/guides/protocol-integration
Description: Learn how to use Swidge, Swap, Bridge, and Lending protocols.
The WDK Core module supports registering external protocols. This allows you to extend the basic wallet functionality with advanced features like [swidge routes](/sdk/swidge-modules), [token swapping](#swapping-tokens), [cross-chain bridging](#bridging-assets), and lending.
## Register Protocols
You can register protocols globally (for all new accounts).
### Global Registration (Recommended)
Global registration ensures that every account you retrieve already has the protocol ready to use. You can do this by chaining a call to `.registerProtocol()` on the WDK instance.
### 1. Install Protocol Modules
Install the [`@tetherto/wdk-protocol-swap-velora-evm`](https://www.npmjs.com/package/@tetherto/wdk-protocol-swap-velora-evm) and [`@tetherto/wdk-protocol-bridge-usdt0-evm`](https://www.npmjs.com/package/@tetherto/wdk-protocol-bridge-usdt0-evm) packages:
```bash
npm install @tetherto/wdk-protocol-swap-velora-evm && npm install @tetherto/wdk-protocol-bridge-usdt0-evm
```
### 2. Register in Code
Now, import the protocol modules and register them with your WDK instance. This makes the protocol methods available to any account derived from that instance.
First, import the necessary modules:
```typescript title="Import Protocols"
import veloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
```
Then, register the protocols for the specific chains they support:
```typescript title="Register Protocols"
// Register protocols for specific chains
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvm, ethConfig)
// Register Velora Swap for Ethereum
.registerProtocol('ethereum', 'velora', veloraProtocolEvm, {
apiKey: 'YOUR_API_KEY'
})
// Register USDT0 Bridge for Ethereum
.registerProtocol('ethereum', 'usdt0', usdt0ProtocolEvm, {
ethereumRpcUrl: 'https://eth.drpc.org' // Configuration depends on the module
})
```
## Use Protocols
Once [registered](#register-protocols), you can access the protocol instance using the specific getter methods, such as `getSwapProtocol`, `getBridgeProtocol`, `getLendingProtocol`, or `getFiatProtocol`.
### Swidge Routes
Use a swidge provider module for new swap, bridge, or combined route integrations. The shared swidge interface discovers supported chains and tokens with `getSupportedChains()` and `getSupportedTokens()`, quotes with `quoteSwidge()`, executes with `swidge()`, and tracks asynchronous settlement with `getSwidgeStatus()`. The provider can decide whether the route is fulfilled as a same-chain swap, same-token bridge, combined route, intent, solver route, or aggregator route. The example below assumes `swidge` is an instance of a concrete provider module that implements the shared interface.
```typescript title="Swidge route flow"
const chains = await swidge.getSupportedChains()
const tokens = await swidge.getSupportedTokens({
fromChain: 'ethereum',
toChain: 'arbitrum'
})
const options = {
fromToken: '0xSourceToken...',
toToken: '0xDestinationToken...',
toChain: 'arbitrum',
recipient: '0xRecipient...',
fromTokenAmount: 1000000n,
slippage: 0.01
}
const quote = await swidge.quoteSwidge(options)
const result = await swidge.swidge(options, {
maxNetworkFeeBps: 50,
maxProtocolFeeBps: 25
})
const status = await swidge.getSwidgeStatus(result.id, {
toChain: 'arbitrum'
})
```
Use discovery results to build token and chain selectors, but continue to show the quote details before execution. `swidge()` is the write step in the shared swidge flow.
Existing swap and bridge modules keep their current accessors for released modules. Prefer the [swidge protocol interface](/sdk/swidge-modules) for new protocol integrations because the standalone swap and bridge interfaces are expected to be deprecated after swidge provider coverage is available.
### Swapping Tokens
Use `getSwapProtocol` to access registered swap services on any wallet account.
```typescript title="Swap Tokens"
const ethAccount = await wdk.getAccount('ethereum', 0)
const velora = ethAccount.getSwapProtocol('velora')
const result = await velora.swap({
tokenIn: '0x...', // Address of token to sell
tokenOut: '0x...', // Address of token to buy
tokenInAmount: 1000000n // Amount to swap
})
```
### Bridging Assets
1. Use `getBridgeProtocol` to access cross-chain bridges.
2. Approve the source-chain bridge spender for the token and amount.
3. Call `bridge` from the bridge protocol to send tokens from one protocol to another.
```typescript title="Bridge Assets"
const ethAccount = await wdk.getAccount('ethereum', 0)
const usdt0 = ethAccount.getBridgeProtocol('usdt0')
await ethAccount.approve({
token: '0x...', // ERC20 Token Address
spender: '0x...', // OFT or bridge spender address
amount: 1000000n
})
const result = await usdt0.bridge({
targetChain: 'ton',
recipient: 'UQBla...', // TON address
token: '0x...', // ERC20 Token Address
amount: 1000000n,
oftContractAddress: '0x...' // Same address used as approval spender
})
```
**Protocol Availability:** If you try to access a protocol that hasn't been registered (e.g., `getSwapProtocol('uniswap')`), the SDK will throw an error. always ensure registration matches the ID you request.
## Next Steps
Learn how to [configure middleware](/sdk/core-module/guides/middleware) to add logging or failover protection to your wallet interactions.
***
## Send Transactions
URL: https://docs.wdk.tether.io/sdk/core-module/guides/transactions
Description: Learn how to send native tokens on different blockchains.
You can [send native tokens](#send-native-tokens), [sign a transaction without broadcasting it](#sign-without-broadcasting), [handle transaction responses](#handling-responses), and [orchestrate multi-chain payments](#multi-chain-transactions) from WDK wallet accounts.
**Get Testnet Funds:** To test these transactions without spending real money, ensure you are on a testnet and have obtained funds. See [Testnet Funds & Faucets](/resources/concepts#testnet-funds--faucets) for a list of available faucets.
**BigInt Usage:** Always use `BigInt` (the `n` suffix) for monetary values to avoid precision loss with large numbers.
## Send Native Tokens
The `sendTransaction` method allows you to transfer value. It accepts a unified configuration object, though specific parameters (like `value` formatting) may vary slightly depending on the blockchain.
### Ethereum Example
On EVM chains, values are typically expressed in Wei (1 ETH = 10^18 Wei).
The following example will:
1. Retrieve the first Ethereum account (see [Manage Accounts](/sdk/core-module/guides/account-management))
2. Send 0.001 ETH (1000000000000000 wei) to an account using `sendTransaction`.
```typescript title="Send ETH"
const ethAccount = await wdk.getAccount('ethereum', 0)
const result = await ethAccount.sendTransaction({
to: '0x71C7656EC7ab88b098defB751B7401B5f6d8976F',
value: 1000000000000000n // 0.001 ETH (in Wei)
})
console.log('Transaction sent! Hash:', result.hash)
```
### TON Example
On TON, values are expressed in Nanotons (1 TON = 10^9 Nanotons).
The following example will:
1. Retrieve the first TON account
2. Send 1 TON (1000000000 nton) to an account using `sendTransaction`.
```typescript title="Send TON"
// Send TON transaction
const tonAccount = await wdk.getAccount('ton', 0)
const tonResult = await tonAccount.sendTransaction({
to: 'UQCz5ON7jjK32HnqPushubsHxgsXgeSZDZPvh8P__oqol90r',
value: 1000000000n // 1 TON (in nanotons)
})
console.log('TON transaction:', tonResult.hash)
```
## Sign Without Broadcasting
Use [`account.signTransaction()`](/sdk/core-module/api-reference#signtransactiontx) when your app needs a signed transaction payload but does not want WDK to broadcast it immediately. Wallet modules accept their own transaction shape and may return a module-specific signed payload.
```typescript title="Sign An EVM Transaction"
const ethAccount = await wdk.getAccount('ethereum', 0)
const signedTransaction = await ethAccount.signTransaction({
to: '0x71C7656EC7ab88b098defB751B7401B5f6d8976F',
value: 1000000000000000n
})
console.log('Signed transaction:', signedTransaction)
```
`signTransaction()` only signs. Use `sendTransaction()` when you want WDK to sign, broadcast, and return the transaction hash.
## Handling Responses
The `sendTransaction` method returns a [transaction result object](/sdk/core-module/api-reference). The most important field is typically `hash`, which represents the transaction ID on the blockchain. You can use this hash to track the status of your payment on a block explorer.
## Multi-Chain Transactions
You can orchestrate payments across different chains in a single function by acting on multiple account objects sequentially.
The following example will:
1. Retrieve an ETH and ton account using the `getAccount()` method.
2. Send ETH and `await` the transaction.
3. Send TON and `await` the transaction.
```typescript title="Multi-Chain Payment"
async function sendCrossChainPayments(wdk) {
const ethAccount = await wdk.getAccount('ethereum', 0)
const tonAccount = await wdk.getAccount('ton', 0)
// 1. Send ETH
await ethAccount.sendTransaction({
to: '0x...',
value: 1000000000000000000n
})
// 2. Send TON
await tonAccount.sendTransaction({
to: 'EQ...',
value: 1000000000n
})
}
```
## Next Steps
For more complex interactions like swapping tokens or bridging assets, learn how to [integrate protocols](/sdk/core-module/guides/protocol-integration).
***
## Register Wallets
URL: https://docs.wdk.tether.io/sdk/core-module/guides/wallet-registration
Description: Learn how to register wallet modules for different blockchains.
This guide explains how to register wallet modules with your WDK instance. The WDK Core module itself doesn't contain blockchain-specific logic; instead, you register separate modules for each chain you want to support (e.g., Ethereum, TON, Bitcoin).
## How it works
The WDK uses a builder pattern, allowing you to chain `.registerWallet()` calls. Each call connects a blockchain-specific manager to your central WDK instance.
### Parameters
The `registerWallet` method (see [API Reference](/sdk/core-module/api-reference)) requires three arguments:
1. **Symbol**: A unique string identifier for the chain (e.g., `'ethereum'`, `'ton'`). You will use this ID later to retrieve accounts.
2. **Manager Class**: The wallet manager class imported from the specific module (e.g., `WalletManagerEvm`).
3. **Configuration**: An object containing the chain-specific settings (e.g., RPC providers, API keys).
## Installation
Install the [wallet managers](/sdk/wallet-modules/) for the blockchains you want to support:
```bash
npm install @tetherto/wdk-wallet-evm @tetherto/wdk-wallet-tron @tetherto/wdk-wallet-btc
```
## Example: Registering Multiple Wallets
### Import the Wallet Manager Packages
First, import the necessary wallet manager packages:
```typescript title="Import Modules"
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerTron from '@tetherto/wdk-wallet-tron'
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
```
### Register the Wallets
Then, [instantiate WDK](/sdk/core-module/guides/getting-started#initialize-wdk) and chain the registration calls:
```typescript title="Register Wallets"
const wdk = new WDK(seedPhrase)
// 1. Register Ethereum
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth.drpc.org'
})
// 2. Register TRON
.registerWallet('tron', WalletManagerTron, {
provider: 'https://api.trongrid.io'
})
// 3. Register Bitcoin
.registerWallet('bitcoin', WalletManagerBtc, {
provider: 'https://blockstream.info/api'
})
```
**RPC Providers:** The examples use public RPC endpoints for demonstration. We do not endorse any specific provider.
* **Testnets:** You can find public RPCs for Ethereum and other EVM chains on [Chainlist](https://chainlist.org).
* **Mainnet:** For production environments, we recommend using reliable, paid RPC providers to ensure stability.
**TRON Networks:** Choose the correct provider for your environment.
* **Mainnet:** `https://api.trongrid.io`
* **Shasta (Testnet):** `https://api.shasta.trongrid.io`
## Next Steps
Once your wallets are registered, you can [manage accounts and specific addresses](/sdk/core-module/guides/account-management).
***
## Usage
URL: https://docs.wdk.tether.io/sdk/core-module/usage
Description: Guide to using the WDK Core module.
The WDK Core module is the central orchestrator for your wallet interactions.
Install and instantiate the WDK.
Connect specific blockchains (Ethereum, TON, etc.).
Retrieve accounts and check balances.
Transfer native tokens.
Use Swidge, Swap, Bridge, and Lending protocols.
Add logging and failover protection.
Best practices for security and stability.
***
## Fiat Modules Overview
URL: https://docs.wdk.tether.io/sdk/fiat-modules
Description: Explore WDK fiat modules for on-ramp and off-ramp integrations.
The Wallet Development Kit (WDK) provides fiat modules that enable on-ramp and off-ramp functionality, allowing users to seamlessly convert between fiat currencies and cryptocurrencies within your application.
## Fiat Protocol Modules
On-ramp and off-ramp functionality for fiat currency integration:
| Module | Provider | Status | Documentation |
|--------|----------|--------|---------------|
| [`@tetherto/wdk-protocol-fiat-moonpay`](https://github.com/tetherto/wdk-protocol-fiat-moonpay) | MoonPay | ✅ Ready | [Documentation](/sdk/fiat-modules/fiat-moonpay/) |
## Features
Fiat modules provide:
- **On-Ramp**: Allow users to purchase cryptocurrency using fiat currencies (credit card, bank transfer, etc.)
- **Off-Ramp**: Enable users to sell cryptocurrency and receive fiat currencies
- **Multiple Payment Methods**: Support for various payment options depending on the provider
- **KYC Integration**: Built-in Know Your Customer verification flows
- **Multi-Currency Support**: Support for multiple fiat and cryptocurrencies
## Next Steps
To get started with WDK fiat modules, follow these steps:
1. Get up and running quickly with our [Quickstart Guide](/start-building/nodejs-bare-quickstart)
2. Choose the fiat module that best fits your needs from the table above
3. Check specific documentation for the module you wish to use
You can also:
- Learn about key concepts in our [Concepts](/resources/concepts) page
- Explore [wallet modules](/sdk/wallet-modules/) to manage user wallets
- Check our [examples](/examples-and-starters/react-native-starter) for production-ready implementations
***
## Fiat MoonPay Overview
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay
Description: Overview of the @tetherto/wdk-protocol-fiat-moonpay module
# @tetherto/wdk-protocol-fiat-moonpay Overview
A WDK module for integrating MoonPay's fiat on-ramp and off-ramp services. This module generates signed or unsigned widget URLs that allow users to buy and sell cryptocurrency using fiat currencies directly within your application. Provide a `signUrl` callback if you want the protocol to return signed URLs from a trusted backend, or omit it to use the unsigned widget URLs directly.
Get started by reading the [Usage](/sdk/fiat-modules/fiat-moonpay/usage) guide.
This module requires a MoonPay developer account. [Create your account here](https://dashboard.moonpay.com/signup).
If you want MoonPay to sign the widget URLs before they are returned, provide a `signUrl` callback that talks to a trusted backend signer. If you omit `signUrl`, the protocol returns unsigned widget URLs directly.
## Features
- **Fiat On-Ramp**: Generate signed or unsigned widget URLs for users to buy cryptocurrency with fiat
- **Fiat Off-Ramp**: Generate signed or unsigned widget URLs for users to sell cryptocurrency with fiat
- **Price Quotes**: Get real-time quotes for buy and sell operations
- **Transaction Tracking**: Retrieve transaction status and details
- **Currency Support**: Query supported cryptocurrencies, fiat currencies, and countries
- **Customizable Widget**: Configure colors, themes, language, and behavior
## Supported Payment Methods
- Credit and debit cards (Visa, Mastercard, etc.)
- Bank transfers (ACH, SEPA, etc.)
- Apple Pay and Google Pay
- Local payment methods (varies by region)
For the full list of supported payment methods by country, see [MoonPay's Supported Payment Methods](https://support.moonpay.com/en/articles/380823-moonpay-s-supported-payment-methods).
## Supported Cryptocurrencies
This module supports purchasing and selling cryptocurrencies on networks compatible with WDK wallet modules, including:
- Ethereum and EVM-compatible chains (ETH, USD₮, etc.)
- Bitcoin (BTC)
- TRON (TRX, USD₮)
- TON
- Solana (SOL, USD₮)
## Next Steps
Set up your MoonPay API key, optional signing callback, and environment
Learn how to integrate MoonPay in your application
Complete API documentation for the module
---
### MoonPay Resources
- [MoonPay Dashboard](https://dashboard.moonpay.com/signup) - Create your developer account
- [MoonPay Support Center](https://support.moonpay.com/) - Official MoonPay documentation and support
- [Supported Payment Methods](https://support.moonpay.com/en/articles/380823-moonpay-s-supported-payment-methods) - Full list by country
---
### Need Help?
***
## Fiat MoonPay API Reference
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/api-reference
Description: API Reference for the @tetherto/wdk-protocol-fiat-moonpay module
# API Reference
Complete API documentation for the `@tetherto/wdk-protocol-fiat-moonpay` module.
## Constructor
### `new MoonPayProtocol(account, config)`
Creates a new MoonPayProtocol instance.
**Parameters:**
| Name | Type | Description |
|------|------|-------------|
| `account` | `IWalletAccount` \| `IWalletAccountReadOnly` \| `undefined` | Wallet account for transactions |
| `config` | `MoonPayProtocolConfig` | Configuration object |
**Config Options:**
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `apiKey` | string | Yes | - | Your MoonPay publishable API key |
| `signUrl` | function | No | - | Callback used to sign buy and sell widget URLs through a trusted backend |
| `cacheTime` | number | No | `600000` | Cache duration for currencies (ms) |
| `environment` | `'production' \| 'sandbox'` | No | `production` | MoonPay widget URL endpoint set |
**Example:**
```typescript
import MoonPayProtocol from '@tetherto/wdk-protocol-fiat-moonpay';
const moonpay = new MoonPayProtocol(walletAccount, {
apiKey: 'pk_live_xxxxx',
signUrl: async (urlForSignature) => urlForSignature,
environment: 'production',
});
```
---
## Methods
### `buy(options)`
Generates a MoonPay widget URL for purchasing cryptocurrency. If `signUrl` is configured, the URL is signed through that callback before being returned.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `options.cryptoAsset` | string | Yes | Cryptocurrency code (e.g., 'eth', 'btc') |
| `options.fiatCurrency` | string | Yes | Fiat currency code (e.g., 'usd', 'eur') |
| `options.cryptoAmount` | number \| bigint | No* | Amount in smallest crypto units |
| `options.fiatAmount` | number \| bigint | No* | Amount in smallest fiat units (cents) |
| `options.recipient` | string | No | Wallet address (uses account address if not provided) |
| `options.config` | MoonPayBuyParams | No | Widget configuration options |
*Either `cryptoAmount` or `fiatAmount` must be provided, but not both.
**Returns:** `Promise\<{ buyUrl: string }\>`
---
### `sell(options)`
Generates a MoonPay widget URL for selling cryptocurrency. If `signUrl` is configured, the URL is signed through that callback before being returned.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `options.cryptoAsset` | string | Yes | Cryptocurrency code |
| `options.fiatCurrency` | string | Yes | Fiat currency code |
| `options.cryptoAmount` | number \| bigint | No* | Amount in smallest crypto units |
| `options.fiatAmount` | number \| bigint | No* | Amount in smallest fiat units |
| `options.refundAddress` | string | No | Refund wallet address |
| `options.config` | MoonPaySellParams | No | Widget configuration options |
**Returns:** `Promise\<{ sellUrl: string }\>`
---
### `quoteBuy(options)`
Gets a price quote for a cryptocurrency purchase.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `options.cryptoAsset` | string | Yes | Cryptocurrency code |
| `options.fiatCurrency` | string | Yes | Fiat currency code |
| `options.cryptoAmount` | number \| bigint | No* | Amount in smallest crypto units |
| `options.fiatAmount` | number \| bigint | No* | Amount in smallest fiat units |
| `options.config` | MoonPayQuoteBuyParams | No | Quote parameters |
**Returns:** `Promise\`
```typescript
{
cryptoAmount: bigint, // Crypto amount you'll receive
fiatAmount: bigint, // Fiat amount to pay
fee: bigint, // Total fee amount
rate: string, // Exchange rate
metadata: MoonPayBuyQuoteMetadata
}
```
---
### `quoteSell(options)`
Gets a price quote for selling cryptocurrency.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `options.cryptoAsset` | string | Yes | Cryptocurrency code |
| `options.fiatCurrency` | string | Yes | Fiat currency code |
| `options.cryptoAmount` | number \| bigint | Yes | Amount in smallest crypto units |
| `options.config` | MoonPayQuoteSellParams | No | Quote parameters |
**Returns:** `Promise\`
```typescript
{
cryptoAmount: bigint, // Crypto amount to sell
fiatAmount: bigint, // Fiat amount you'll receive
fee: bigint, // Total fee amount
rate: string, // Exchange rate
metadata: MoonPaySellQuoteMetadata
}
```
---
### `getSupportedCryptoAssets()`
Fetches the list of supported cryptocurrencies. Results are cached.
**Returns:** `Promise\`
```typescript
{
code: string, // Currency code (e.g., 'eth')
decimals: number, // Decimal places
networkCode: string, // Network identifier
name: string, // Display name
metadata: MoonPayCryptoCurrencyDetails
}
```
---
### `getSupportedFiatCurrencies()`
Fetches the list of supported fiat currencies. Results are cached.
**Returns:** `Promise\`
```typescript
{
code: string, // Currency code (e.g., 'usd')
decimals: number, // Decimal places
name: string, // Display name
metadata: MoonPayFiatCurrencyDetails
}
```
---
### `getSupportedCountries()`
Fetches the list of supported countries.
**Returns:** `Promise\`
```typescript
{
code: string, // ISO country code
name: string, // Country name
isBuyAllowed: boolean, // Buy operations allowed
isSellAllowed: boolean,// Sell operations allowed
metadata: MoonPayCountryDetail
}
```
---
### `getTransactionDetail(txId, direction?)`
Retrieves details of a specific transaction.
**Parameters:**
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `txId` | string | Yes | - | MoonPay transaction ID |
| `direction` | `'buy' \| 'sell'` | No | `'buy'` | Transaction type |
**Returns:** `Promise\`
```typescript
{
status: 'completed' | 'failed' | 'in_progress',
cryptoAsset: string,
fiatCurrency: string,
metadata: MoonPayBuyTransaction | MoonPaySellTransaction
}
```
---
## Types
### `MoonPayProtocolConfig`
```typescript
interface MoonPayProtocolConfig {
apiKey: string;
signUrl?: (urlForSignature: string) => Promise;
cacheTime?: number;
environment?: 'production' | 'sandbox';
}
```
### `MoonPayBuyParams`
Widget configuration options for `buy()` operations:
```typescript
interface MoonPayBuyParams {
// UI options (shared with MoonPaySellParams)
colorCode?: string;
theme?: 'dark' | 'light';
themeId?: string;
language?: string;
showAllCurrencies?: boolean;
showOnlyCurrencies?: string;
showWalletAddressForm?: boolean;
redirectURL?: string;
unsupportedRegionRedirectUrl?: string;
skipUnsupportedRegionScreen?: boolean;
// Buy-specific options
defaultCurrencyCode?: string;
walletAddress?: string;
walletAddressTag?: string;
walletAddresses?: string;
walletAddressTags?: string;
contractAddress?: string;
networkCode?: string;
lockAmount?: boolean;
email?: string;
externalTransactionId?: string;
externalCustomerId?: string;
paymentMethod?: string;
}
```
### `MoonPaySellParams`
Widget configuration options for `sell()` operations:
```typescript
interface MoonPaySellParams {
// UI options (shared with MoonPayBuyParams)
colorCode?: string;
theme?: 'dark' | 'light';
themeId?: string;
language?: string;
showAllCurrencies?: boolean;
showOnlyCurrencies?: string;
showWalletAddressForm?: boolean;
redirectURL?: string;
unsupportedRegionRedirectUrl?: string;
skipUnsupportedRegionScreen?: boolean;
// Sell-specific options
defaultBaseCurrencyCode?: string;
refundWalletAddresses?: string;
lockAmount?: boolean;
email?: string;
externalTransactionId?: string;
externalCustomerId?: string;
paymentMethod?: string;
}
```
### `MoonPayQuoteBuyParams`
```typescript
interface MoonPayQuoteBuyParams {
extraFeePercentage?: number; // 0-10%
paymentMethod?: string;
areFeesIncluded?: boolean;
walletAddress?: string;
}
```
### `MoonPayQuoteSellParams`
```typescript
interface MoonPayQuoteSellParams {
extraFeePercentage?: number; // 0-10%
payoutMethod?: string;
}
```
---
## Next Steps
- [Configuration](/sdk/fiat-modules/fiat-moonpay/configuration) - Setup and configuration options
- [Usage Guide](/sdk/fiat-modules/fiat-moonpay/usage) - Common usage patterns
***
## Fiat MoonPay Configuration
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/configuration
Description: Configuration options for the @tetherto/wdk-protocol-fiat-moonpay module
# Configuration
This page covers all configuration options for the MoonPay fiat module, including optional URL signing and environment selection.
## Prerequisites
Before using this module, you need:
1. A MoonPay developer account - [Create an account on MoonPay Dashboard](https://dashboard.moonpay.com/signup)
2. A publishable API key from your dashboard
3. If you want signed widget URLs, a trusted backend signing endpoint for the `signUrl` callback
## Installation
```bash
npm install @tetherto/wdk-protocol-fiat-moonpay
```
## Basic Configuration
```typescript
import MoonPayProtocol from '@tetherto/wdk-protocol-fiat-moonpay';
const moonpay = new MoonPayProtocol(walletAccount, {
apiKey: 'pk_live_xxxxx', // Your MoonPay publishable API key
signUrl: async (urlForSignature) => {
const response = await fetch('/api/moonpay/sign-url', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ urlForSignature }),
});
if (!response.ok) {
throw new Error(`Failed to sign MoonPay URL: ${response.status} ${response.statusText}`);
}
const { signedUrl } = await response.json();
return signedUrl;
},
environment: 'sandbox',
});
```
## Configuration Options
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| `apiKey` | string | Yes | - | Your MoonPay publishable API key |
| `signUrl` | function | No | - | Callback used to sign buy and sell widget URLs through a trusted backend |
| `cacheTime` | number | No | `600000` (10 min) | Duration in milliseconds to cache supported currencies |
| `environment` | `'production' \| 'sandbox'` | No | `production` | MoonPay widget URL endpoint set |
## Constructor Overloads
The `MoonPayProtocol` class supports three constructor patterns:
```typescript
// Without account (for public read operations like fetching supported currencies)
const moonpay = new MoonPayProtocol(undefined, config);
// With read-only account
const moonpay = new MoonPayProtocol(readOnlyAccount, config);
// With full wallet account (for buy/sell operations)
const moonpay = new MoonPayProtocol(walletAccount, config);
```
## Environment Configuration
### Sandbox (Testing)
Use sandbox endpoints for development and testing:
```typescript
const moonpay = new MoonPayProtocol(walletAccount, {
apiKey: 'pk_test_xxxxx',
signUrl: async (urlForSignature) => {
const response = await fetch('/api/moonpay/sign-url', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ urlForSignature }),
});
return (await response.json()).signedUrl;
},
environment: 'sandbox',
});
```
In sandbox mode:
- No real transactions are processed
- Use test card numbers provided by MoonPay
- KYC verification is simulated
If you do not need signed URLs, omit `signUrl` and the protocol returns unsigned widget URLs directly.
### Production
For production deployments, use live API keys and the production endpoint set:
```typescript
const moonpay = new MoonPayProtocol(walletAccount, {
apiKey: 'pk_live_xxxxx',
signUrl: async (urlForSignature) => {
const response = await fetch('/api/moonpay/sign-url', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ urlForSignature }),
});
return (await response.json()).signedUrl;
},
environment: 'production',
});
```
## Widget Customization
When calling `buy()` or `sell()`, you can customize the MoonPay widget appearance:
```typescript
const result = await moonpay.buy({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
fiatAmount: 10000n, // $100.00 in cents
config: {
colorCode: '#3B82F6', // Your brand color (hex)
theme: 'dark', // 'dark' or 'light'
language: 'en', // ISO 639-1 language code
redirectURL: 'https://yourapp.com/callback',
},
});
```
### Available Buy Widget Options
| Option | Type | Description |
|--------|------|-------------|
| `colorCode` | string | Hexadecimal color for widget accent |
| `theme` | `'dark' \| 'light'` | Widget appearance theme |
| `themeId` | string | ID of a custom theme |
| `language` | string | ISO 639-1 language code |
| `showAllCurrencies` | boolean | Show all supported cryptocurrencies |
| `showOnlyCurrencies` | string | Comma-separated currency codes to display |
| `showWalletAddressForm` | boolean | Show wallet address input form |
| `redirectURL` | string | URL to redirect after completion |
| `unsupportedRegionRedirectUrl` | string | URL for unsupported regions |
| `skipUnsupportedRegionScreen` | boolean | Skip unsupported region screen |
| `defaultCurrencyCode` | string | Pre-selected cryptocurrency code |
| `walletAddress` | string | Pre-filled wallet address |
| `walletAddressTag` | string | Wallet address memo/tag (for EOS, XRP, etc.) |
| `walletAddresses` | string | JSON string of wallet addresses for multiple currencies |
| `walletAddressTags` | string | JSON string of address tags for multiple currencies |
| `contractAddress` | string | Token contract address (DeFi Buy only) |
| `networkCode` | string | Network for the token contract (DeFi Buy only) |
| `lockAmount` | boolean | Prevent user from changing amount |
| `email` | string | Pre-fill customer email |
| `externalTransactionId` | string | Your transaction identifier |
| `externalCustomerId` | string | Your customer identifier |
| `paymentMethod` | string | Pre-select payment method |
### Available Sell Widget Options
For `sell()`, the widget config uses `MoonPaySellParams` with different options:
| Option | Type | Description |
|--------|------|-------------|
| `colorCode` | string | Hexadecimal color for widget accent |
| `theme` | `'dark'` \| `'light'` | Widget appearance theme |
| `themeId` | string | ID of a custom theme |
| `language` | string | ISO 639-1 language code |
| `showAllCurrencies` | boolean | Show all supported cryptocurrencies |
| `showOnlyCurrencies` | string | Comma-separated currency codes to display |
| `showWalletAddressForm` | boolean | Show wallet address input form |
| `redirectURL` | string | URL to redirect after completion |
| `unsupportedRegionRedirectUrl` | string | URL for unsupported regions |
| `skipUnsupportedRegionScreen` | boolean | Skip unsupported region screen |
| `defaultBaseCurrencyCode` | string | Pre-selected cryptocurrency to sell |
| `refundWalletAddresses` | string | JSON string of wallet addresses for refunds |
| `lockAmount` | boolean | Prevent user from changing amount |
| `email` | string | Pre-fill customer email |
| `externalTransactionId` | string | Your transaction identifier |
| `externalCustomerId` | string | Your customer identifier |
| `paymentMethod` | string | Pre-select payout method |
## Next Steps
- [Usage Guide](/sdk/fiat-modules/fiat-moonpay/usage) - Learn how to integrate MoonPay
- [API Reference](/sdk/fiat-modules/fiat-moonpay/api-reference) - Complete API documentation
***
## Buy and Sell
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/guides/buy-and-sell
Description: On-ramp, off-ramp, quotes, supported assets, widget options, and custom recipients.
This guide explains [buying crypto (on-ramp)](#buy-crypto-on-ramp), [selling crypto (off-ramp)](#sell-crypto-off-ramp), [quotes](#get-price-quotes), [supported currencies](#supported-currencies-and-countries), [widget customization](#widget-customization), and [custom recipients](#custom-recipient-addresses). It assumes a [`MoonPayProtocol`](/sdk/fiat-modules/fiat-moonpay/api-reference) instance named `moonpay`.
Amounts use smallest units: fiat in minor units (cents), crypto in on-chain base units (for example wei for ETH).
## Buy crypto (on-ramp)
You can build a signed purchase URL with [`buy()`](/sdk/fiat-modules/fiat-moonpay/api-reference) when you know the fiat spend:
```typescript title="Buy with fiat amount"
const result = await moonpay.buy({
cryptoAsset: 'usdt',
fiatCurrency: 'usd',
fiatAmount: 10000n
})
window.open(result.buyUrl, '_blank')
```
You can request a fixed crypto amount instead by passing `cryptoAmount` to [`buy()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Buy with crypto amount"
const result = await moonpay.buy({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
cryptoAmount: 100000000000000000n
})
window.open(result.buyUrl, '_blank')
```
## Sell crypto (off-ramp)
You can generate a sell widget URL with [`sell()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Sell ETH for USD"
const result = await moonpay.sell({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
cryptoAmount: 500000000000000000n
})
window.open(result.sellUrl, '_blank')
```
## Get price quotes
You can preview economics before opening the widget using [`quoteBuy()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Buy quote"
const buyQuote = await moonpay.quoteBuy({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
fiatAmount: 10000n
})
console.log('Crypto amount:', buyQuote.cryptoAmount)
console.log('Fee:', buyQuote.fee)
console.log('Exchange rate:', buyQuote.rate)
```
You can estimate proceeds for a sell with [`quoteSell()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Sell quote"
const sellQuote = await moonpay.quoteSell({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
cryptoAmount: 500000000000000000n
})
console.log('Fiat amount:', sellQuote.fiatAmount)
```
## Supported currencies and countries
You can list tradable assets with [`getSupportedCryptoAssets()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Supported crypto"
const cryptoAssets = await moonpay.getSupportedCryptoAssets()
console.log(cryptoAssets)
```
You can list fiat currencies with [`getSupportedFiatCurrencies()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Supported fiat"
const fiatCurrencies = await moonpay.getSupportedFiatCurrencies()
console.log(fiatCurrencies)
```
You can check regional availability with [`getSupportedCountries()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Supported countries"
const countries = await moonpay.getSupportedCountries()
console.log(countries)
```
## Widget customization
You can pass UI options under `config` to [`buy()`](/sdk/fiat-modules/fiat-moonpay/api-reference) (see [`MoonPayBuyParams`](/sdk/fiat-modules/fiat-moonpay/api-reference)):
```typescript title="Themed buy widget"
const result = await moonpay.buy({
cryptoAsset: 'usdt',
fiatCurrency: 'eur',
fiatAmount: 5000n,
config: {
colorCode: '#1f2937',
theme: 'dark',
language: 'de',
redirectURL: 'https://yourapp.com/payment-complete',
lockAmount: true,
email: 'user@example.com',
externalCustomerId: 'user_123'
}
})
window.open(result.buyUrl, '_blank')
```
## Custom recipient addresses
By default [`buy()`](/sdk/fiat-modules/fiat-moonpay/api-reference) credits the connected wallet. You can override the destination with `recipient`:
```typescript title="Custom buy recipient"
const result = await moonpay.buy({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
fiatAmount: 10000n,
recipient: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
})
window.open(result.buyUrl, '_blank')
```
You can set a refund destination on sells with `refundAddress` on [`sell()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Custom sell refund address"
const result = await moonpay.sell({
cryptoAsset: 'eth',
fiatCurrency: 'usd',
cryptoAmount: 500000000000000000n,
refundAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
})
window.open(result.sellUrl, '_blank')
```
## Next Steps
- [Manage transactions](manage-transactions)
- [Get started](get-started)
- [API reference](/sdk/fiat-modules/fiat-moonpay/api-reference)
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/guides/get-started
Description: Install the package and initialize MoonPayProtocol with your wallet and keys.
This guide covers [installation](#installation) and [initializing the protocol](#initialize-moonpayprotocol). You need [Node.js](https://nodejs.org/), [npm](https://www.npmjs.com/), and MoonPay API keys from your MoonPay dashboard.
## Installation
Run the following to install [@tetherto/wdk-protocol-fiat-moonpay](https://www.npmjs.com/package/@tetherto/wdk-protocol-fiat-moonpay):
```bash title="Install with npm"
npm install @tetherto/wdk-protocol-fiat-moonpay
```
## Initialize MoonPayProtocol
You can create a fiat ramp client with [`new MoonPayProtocol(account, config)`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Construct MoonPayProtocol"
import MoonPayProtocol from '@tetherto/wdk-protocol-fiat-moonpay'
const moonpay = new MoonPayProtocol(walletAccount, {
apiKey: process.env.MOONPAY_PUBLISHABLE_KEY,
secretKey: process.env.MOONPAY_SECRET_KEY
})
```
Never ship a secret key to browsers. Run server-side signing where your architecture allows, and rotate keys if they leak.
See [Configuration](/sdk/fiat-modules/fiat-moonpay/configuration) for `cacheTime` and related options.
## Next Steps
- [Buy and sell](buy-and-sell)
- [Manage transactions](manage-transactions)
***
## Manage Transactions
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/guides/manage-transactions
Description: Poll MoonPay for transaction status and inspect returned details.
This guide shows how to [check transaction status](#check-transaction-status) and [read transaction details](#read-transaction-details) with [`getTransactionDetail()`](/sdk/fiat-modules/fiat-moonpay/api-reference). Pass the identifier MoonPay returns after checkout (for example from your redirect URL or webhook payload).
## Check transaction status
You can read the high-level state of a buy with [`getTransactionDetail()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Buy transaction status"
const buyTx = await moonpay.getTransactionDetail(moonpayTransactionId, 'buy')
console.log('Status:', buyTx.status)
```
`status` is one of `completed`, `failed`, or `in_progress` as described in the API reference.
## Read transaction details
You can load the same record to inspect assets and currencies using [`getTransactionDetail()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Buy transaction fields"
const buyTx = await moonpay.getTransactionDetail(moonpayTransactionId, 'buy')
console.log('Crypto asset:', buyTx.cryptoAsset)
console.log('Fiat currency:', buyTx.fiatCurrency)
console.log('Metadata:', buyTx.metadata)
```
You can query a sell the same way by passing `sell` as the direction to [`getTransactionDetail()`](/sdk/fiat-modules/fiat-moonpay/api-reference):
```typescript title="Sell transaction details"
const sellTx = await moonpay.getTransactionDetail(moonpayTransactionId, 'sell')
console.log('Status:', sellTx.status)
console.log('Crypto asset:', sellTx.cryptoAsset)
console.log('Fiat currency:', sellTx.fiatCurrency)
```
The second argument defaults to `buy` when omitted; set it explicitly for sell flows.
## Next Steps
- [Buy and sell](buy-and-sell)
- [Get started](get-started)
- [Configuration](/sdk/fiat-modules/fiat-moonpay/configuration)
***
## Fiat MoonPay Usage
URL: https://docs.wdk.tether.io/sdk/fiat-modules/fiat-moonpay/usage
Description: How to use the @tetherto/wdk-protocol-fiat-moonpay module
# Usage
The [@tetherto/wdk-protocol-fiat-moonpay](https://www.npmjs.com/package/@tetherto/wdk-protocol-fiat-moonpay) module builds signed MoonPay widget URLs and quotes for on-ramp and off-ramp flows. Use the guides below for setup, trading, and transaction follow-up.
Install the package and initialize MoonPayProtocol.
On-ramp, off-ramp, quotes, supported assets, widget options, recipients.
Check status and load transaction details from MoonPay.
Get started with WDK in a Node.js environment
API keys, caching, and MoonPay configuration options
Constructor, methods, and types for MoonPayProtocol
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/get-started
Description: Learn about the SDK and modules architecture
The SDK is a comprehensive, modular plug-in framework designed to simplify multi-chain wallet development.
It is built on some core principles: **self-custodial and stateless** (private keys never leave your app and no data is stored by WDK), **unified interface** (consistent API across all blockchains), and **cross-platform compatibility** (works seamlessly from Node.js to React Native to embedded systems).
#### Capabilities
* **Multi-Chain Support**: Bitcoin, Ethereum, TON, TRON, Solana, Spark, and more
* **Account Abstraction**: Gasless transactions on supported chains
* **DeFi Integration**: Plug-in support for swidge routes, swaps, bridges, and lending protocols
* **Extensible Design**: Add custom modules for new blockchains or protocols
***
### Modular Architecture
WDK's architecture is built around the concept of composable modules. Each module is a specialized component that handles specific functionality, allowing you to build exactly what you need without unnecessary complexity.
Each module has a single responsibility. Wallet modules handle blockchain operations, protocol modules manage DeFi interactions, and the core module orchestrates everything.
New functionality is added through modules rather than modifying core code. Also, modules are configured through simple objects, making them easy to customize for different environments and use cases.
***
#### Module Types
WDK modules are organized into six main categories, each serving a specific purpose in the blockchain application stack:
Main orchestrator and shared utilities
Blockchain-specific wallet operations
Swap-only, bridge-only, or combined asset routes
Token swapping across DEXs
Cross-chain asset transfers
DeFi lending and borrowing
***
### How to use the SDK
The WDK SDK uses a registration-based system where modules are added to a central orchestrator. This creates a unified interface while maintaining module independence.
#### Registration Flow
**1. Core Module Initialization**
```typescript title="Initialize WDK"
import WDK from '@tetherto/wdk'
// Generate 24-word seed phrase for higher security
const seedPhrase = WDK.getRandomSeedPhrase(24)
// Or use 12-word seed phrase (default)
// const seedPhrase = WDK.getRandomSeedPhrase()
const wdk = new WDK(seedPhrase)
```
**2. Wallet Module Registration**
```typescript title="Register Wallets"
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
const wdkWithWallets = wdk
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://eth.drpc.org'
})
.registerWallet('bitcoin', WalletManagerBtc, {
provider: 'https://blockstream.info/api'
})
```
**3. Protocol Module Registration**
```typescript title="Register Protocols"
import SwapveloraEvm from '@tetherto/wdk-protocol-swap-velora-evm'
const wdkWithProtocols = wdkWithWallets
.registerProtocol('swap-velora-evm', SwapveloraEvm)
```
#### Unified Operations
Once registered, all modules work through the same interface:
```typescript title="Unified Operations"
// Get accounts from different blockchains using the same method
const ethAccount = await wdkWithProtocols.getAccount('ethereum', 0)
const btcAccount = await wdkWithProtocols.getAccount('bitcoin', 0)
// Check balances using unified interface
const ethBalance = await ethAccount.getBalance()
const btcBalance = await btcAccount.getBalance()
// Send transactions with consistent API
const ethTx = await ethAccount.sendTransaction({
to: '0x...',
value: '1000000000000000000'
})
const btcTx = await btcAccount.sendTransaction({
to: '1A1z...',
value: 100000000
})
// Use DeFi protocols through the same interface
const swapResult = await wdkWithProtocols.executeProtocol('swap-velora-evm', {
fromToken: 'ETH',
toToken: 'USDT',
amount: '1000000000000000000'
})
```
***
### Creating Custom Modules
WDK's modular architecture makes it straightforward to add support for new blockchains or protocols. Each module type has a specific interface that must be implemented.
#### Wallet Module Interface
```typescript title="Custom Wallet Module Setup"
interface WalletModule {
// Account management
getAccount(index: number): Promise
getAddress(index: number): Promise
getBalance(index: number): Promise
// Transaction operations
sendTransaction(params: TransactionParams): Promise
estimateTransaction(params: TransactionParams): Promise
// Key management
signMessage(message: string, index: number): Promise
verifySignature(message: string, signature: string, address: string): Promise
// Blockchain-specific operations
getTransactionHistory(index: number, limit?: number): Promise
getTokenBalance(index: number, tokenAddress: string): Promise
}
```
#### Protocol Module Interface
```typescript title="Custom Protocol Module Setup"
interface ProtocolModule {
// Protocol execution
execute(params: ProtocolParams): Promise
estimate(params: ProtocolParams): Promise
// Supported operations
getSupportedTokens(): Promise
getSupportedChains(): Promise
getOperationTypes(): Promise
// Protocol-specific methods
getLiquidityPools?(): Promise
getLendingRates?(): Promise
getBridgeRoutes?(): Promise
}
```
#### Module Implementation Example
```typescript title="Custom Wallet Module Implementation"
class CustomWalletModule implements WalletModule {
private provider: string
private chainId: number
constructor(config: { provider: string; chainId: number }) {
this.provider = config.provider
this.chainId = config.chainId
}
async getAccount(index: number): Promise {
// Implement account derivation logic
const privateKey = await this.derivePrivateKey(index)
return new CustomAccount(privateKey, this.provider)
}
async getAddress(index: number): Promise {
const account = await this.getAccount(index)
return account.getAddress()
}
async getBalance(index: number): Promise {
const address = await this.getAddress(index)
// Implement balance fetching logic
const balance = await this.fetchBalance(address)
return new BigNumber(balance)
}
async sendTransaction(params: TransactionParams): Promise {
// Implement transaction sending logic
const account = await this.getAccount(params.accountIndex)
const tx = await account.sendTransaction(params)
return tx
}
// Additional methods...
}
```
#### Module Registration
```typescript title="Custom Wallet Module Registration"
// Register your custom module
const wdkWithCustom = wdk.registerWallet('custom-chain', CustomWalletModule, {
provider: 'https://custom-rpc-endpoint.com',
chainId: 12345
})
// Use it like any other module
const customAccount = await wdkWithCustom.getAccount('custom-chain', 0)
const balance = await customAccount.getBalance()
```
***
### Quickstart Paths
Ready to start building? Choose your development environment:
Get started with WDK in a Node.js environment
Build mobile wallets with React Native Expo
***
## Need Help?
***
## Lending Modules Overview
URL: https://docs.wdk.tether.io/sdk/lending-modules
Description: Explore WDK lending modules for integrating lending protocols with WDK.
The Wallet Development Kit (WDK) provides a set of modules that support connection with lending protocols on different blockchain networks. All modules share a common interface, ensuring consistent behavior across different blockchain implementations.
## Lending & Borrowing Protocol Modules
DeFi lending functionality for different lending & borrowing protocols
| Module | Route | Status | Documentation |
|--------|-------|--------|---------------|
| [`@tetherto/wdk-protocol-lending-aave-evm`](https://github.com/tetherto/wdk-protocol-lending-aave-evm) | EVM | ✅ Ready | [Documentation](/sdk/lending-modules/lending-aave-evm/) |
| [`@morpho-org/wdk-protocol-lending-morpho-evm`](https://www.npmjs.com/package/@morpho-org/wdk-protocol-lending-morpho-evm) | EVM | Community | [Documentation](/sdk/lending-modules/lending-morpho-evm/) |
## Next Steps
Compare the available EVM lending modules and open the implementation that matches your protocol target:
Use the Tether-maintained Aave V3 lending module for EVM accounts.
Use the community Morpho module for Vault V2 and Morpho Blue EVM flows.
Install the Morpho module, create the client, and review prerequisites.
***
## Need Help?
***
## Lending Aave EVM Overview
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm
Description: Overview of the @tetherto/wdk-protocol-lending-aave-evm module
A lightweight package that lets EVM wallet accounts interact with Aave V3: supply, withdraw, borrow, repay, and read account data. It works with both standard EVM wallets and ERC‑4337 smart accounts.
## Features
- **Supply/Withdraw**: Add and remove supported assets from Aave pools
- **Borrow/Repay**: Borrow assets and repay debt
- **Account Data**: Read collateral, debt, health factor, and more
- **Quote System**: Estimate fees before sending transactions
- **AA Support**: Works with standard EVM and ERC‑4337 smart accounts
- **TypeScript Support**: Full TypeScript definitions
## Supported Networks
Works on Aave V3 supported EVM networks (e.g., Ethereum, Arbitrum, Base, Optimism, Polygon, Avalanche, BNB, Celo, Gnosis, Linea, Scroll, Soneium, Sonic, ZkSync, Metis). A working RPC provider and correct token addresses are required.
## Wallet Compatibility
- **Standard EVM Wallets**: `@tetherto/wdk-wallet-evm`
- **ERC‑4337 Smart Accounts**: `@tetherto/wdk-wallet-evm-erc-4337`
- **Read‑Only Accounts**: For quoting and reading account data without sending transactions
## Key Components
- **Aave V3 Integration**: Supply, withdraw, borrow, repay primitives
- **Quote Helpers**: `quoteSupply`, `quoteWithdraw`, `quoteBorrow`, `quoteRepay`
- **Collateral Controls**: Toggle collateral usage; set user eMode
## Next Steps
How to supply, withdraw, borrow and repay with Aave
Service setup, account config, ERC‑4337 options
Full API for Aave Protocol Evm methods and types
***
## Lending Aave EVM API Reference
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/api-reference
Description: API Reference for @tetherto/wdk-protocol-lending-aave-evm
# API Reference
## Class: AaveProtocolEvm
Main class for Aave V3 lending on EVM.
### Constructor
```javascript
new AaveProtocolEvm(account)
```
Parameters:
- `account`: `WalletAccountEvm | WalletAccountReadOnlyEvm | WalletAccountEvmErc4337 | WalletAccountReadOnlyEvmErc4337`
Example:
```javascript
const aave = new AaveProtocolEvm(account)
```
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `supply(options, config?)` | Add tokens to the pool | `Promise<{hash: string, fee: bigint, approveHash?: string, resetAllowanceHash?: string}>` |
| `quoteSupply(options, config?)` | Estimate cost to add tokens | `Promise<{fee: bigint}>` |
| `withdraw(options, config?)` | Remove tokens from the pool | `Promise<{hash: string, fee: bigint}>` |
| `quoteWithdraw(options, config?)` | Estimate cost to withdraw | `Promise<{fee: bigint}>` |
| `borrow(options, config?)` | Borrow tokens | `Promise<{hash: string, fee: bigint}>` |
| `quoteBorrow(options, config?)` | Estimate borrowing cost | `Promise<{fee: bigint}>` |
| `repay(options, config?)` | Repay borrowed tokens | `Promise<{hash: string, fee: bigint}>` |
| `quoteRepay(options, config?)` | Estimate repayment cost | `Promise<{fee: bigint}>` |
| `setUseReserveAsCollateral(token, use, config?)` | Toggle token as collateral | `Promise<{hash: string, fee: bigint}>` |
| `setUserEMode(categoryId, config?)` | Set user eMode | `Promise<{hash: string, fee: bigint}>` |
| `getAccountData(account?)` | Read account stats | `Promise<{ totalCollateralBase: bigint, totalDebtBase: bigint, availableBorrowsBase: bigint, currentLiquidationThreshold: bigint, ltv: bigint, healthFactor: bigint }>` |
---
When `AaveProtocolEvm` is initialized with an ERC‑4337 smart account, the optional `config` argument on mutating and quote methods accepts the same gas-payment override families documented in [`@tetherto/wdk-wallet-evm-erc-4337`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference): paymaster token, sponsorship policy, and native coins.
### `supply(options, config?)`
Add tokens to the pool.
Options:
- `token` (`string`): token address
- `amount` (`number | bigint`): amount in base units
- `onBehalfOf` (`string`, optional)
Returns:
- May include `approveHash` and `resetAllowanceHash` for standard accounts (e.g., USD₮ allowance reset on Ethereum mainnet)
Example:
```javascript
const res = await aave.supply({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `quoteSupply(options, config?)`
Estimate fee to add tokens.
```javascript
const q = await aave.quoteSupply({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `withdraw(options, config?)`
Remove tokens from the pool.
Options:
- `token` (`string`)
- `amount` (`number | bigint`)
- `to` (`string`, optional)
```javascript
const tx = await aave.withdraw({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `quoteWithdraw(options, config?)`
Estimate fee to withdraw tokens.
```javascript
const q = await aave.quoteWithdraw({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `borrow(options, config?)`
Borrow tokens.
Options:
- `token` (`string`)
- `amount` (`number | bigint`)
- `onBehalfOf` (`string`, optional)
```javascript
const tx = await aave.borrow({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `quoteBorrow(options, config?)`
Estimate fee to borrow tokens.
```javascript
const q = await aave.quoteBorrow({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `repay(options, config?)`
Repay borrowed tokens.
Options:
- `token` (`string`)
- `amount` (`number | bigint`)
- `onBehalfOf` (`string`, optional)
```javascript
const tx = await aave.repay({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
Returns:
- For standard accounts, may include `approveHash` / `resetAllowanceHash` when applicable.
---
### `quoteRepay(options, config?)`
Estimate fee to repay borrowed tokens.
```javascript
const q = await aave.quoteRepay({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
---
### `setUseReserveAsCollateral(token, use, config?)`
Toggle token as collateral for the user.
```javascript
const tx = await aave.setUseReserveAsCollateral('TOKEN_ADDRESS', true)
```
---
### `setUserEMode(categoryId, config?)`
Set user eMode category.
```javascript
const tx = await aave.setUserEMode(1)
```
---
### `getAccountData(account?)`
Read account stats like total collateral, debt, and health.
```javascript
const data = await aave.getAccountData()
```
Returns the following structure:
```javascript
{
totalCollateralBase: bigint,
totalDebtBase: bigint,
availableBorrowsBase: bigint,
currentLiquidationThreshold: bigint,
ltv: bigint,
healthFactor: bigint
}
```
---
## ERC‑4337 Config Override (optional)
When the protocol uses `WalletAccountEvmErc4337` or `WalletAccountReadOnlyEvmErc4337`, the optional `config` argument on `supply`, `quoteSupply`, `withdraw`, `quoteWithdraw`, `borrow`, `quoteBorrow`, `repay`, `quoteRepay`, `setUseReserveAsCollateral`, and `setUserEMode` accepts the wallet module's per-call gas-payment overrides.
- **Paymaster token mode**: `paymasterUrl`, `paymasterAddress`, `paymasterToken`, `transferMaxFee`
- **Sponsorship policy mode**: `isSponsored`, `paymasterUrl`, `sponsorshipPolicyId`
- **Native coin mode**: `useNativeCoins`, `transferMaxFee`
Example:
```javascript
const res = await aave.supply(
{ token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', amount: 1000000n },
{
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
}
)
```
## Rules & Notes
- `token` must be a valid (non‑zero) address
- `amount` > 0 and in token base units (use BigInt)
- `onBehalfOf`/`to` (if set) must be valid, non‑zero addresses
- A provider is required to read/send transactions
- For USD₮ on mainnet, allowance may be reset to 0 then set again before actions
Get started with WDK in a Node.js environment
Get started with WDK's Lending Aave EVM Protocol configuration
Get started with WDK's Lending Aave EVM Protocol usage
***
### Need Help?
***
## Lending Aave EVM Configuration
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/configuration
Description: Configuration options and settings for @tetherto/wdk-protocol-lending-aave-evm
# Configuration
## Service Setup
```javascript
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
// Create wallet account first
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Create lending service
const aave = new AaveProtocolEvm(account)
```
## Account Configuration
The service uses the wallet account configuration to connect to the target network and sign transactions.
```javascript
import { WalletAccountEvm, WalletAccountReadOnlyEvm } from '@tetherto/wdk-wallet-evm'
// Full access account
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Read-only account (quotes, reads)
const readOnly = new WalletAccountReadOnlyEvm('0xYourAddress', {
provider: 'https://ethereum-rpc.publicnode.com'
})
const aave = new AaveProtocolEvm(account)
```
## ERC‑4337 (Account Abstraction)
When using ERC‑4337 smart accounts, every mutating method and quote helper accepts an optional `config` override. In `v1.0.0-beta.4`, that override matches the three gas-payment families exposed by [`@tetherto/wdk-wallet-evm-erc-4337`](/sdk/wallet-modules/wallet-evm-erc-4337/configuration): paymaster token, sponsorship policy, or native coins.
Use the fields that match the gas-payment mode you want for that call. For the full field-level definitions, see the [`@tetherto/wdk-wallet-evm-erc-4337` configuration docs](/sdk/wallet-modules/wallet-evm-erc-4337/configuration) and [`Config Override`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) reference.
```javascript
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 1,
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: 'YOUR_BUNDLER_URL',
paymasterUrl: 'YOUR_PAYMASTER_URL'
})
const aaveAA = new AaveProtocolEvm(aa)
const result = await aaveAA.supply({ token: '0xdAC17F...ec7', amount: 1000000n }, {
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
})
```
### Supported Override Families
- **Paymaster token mode**: `paymasterUrl`, `paymasterAddress`, `paymasterToken`, `transferMaxFee`
- **Sponsorship policy mode**: `isSponsored`, `paymasterUrl`, `sponsorshipPolicyId`
- **Native coin mode**: `useNativeCoins`, `transferMaxFee`
## Network Support
Aave V3 spans multiple EVM chains (Ethereum, Arbitrum, Base, Optimism, Polygon, Avalanche, BNB, Celo, Gnosis, Linea, Scroll, Soneium, Sonic, ZkSync, Metis). Ensure the correct RPC and token addresses for the target chain.
```javascript
// Ethereum Mainnet
const eth = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Arbitrum
const arb = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://arb1.arbitrum.io/rpc'
})
```
## Operation Options
Each operation accepts a simple options object:
```javascript
// Supply
await aave.supply({ token: 'TOKEN_ADDRESS', amount: 1000000n })
// Withdraw
await aave.withdraw({ token: 'TOKEN_ADDRESS', amount: 1000000n })
// Borrow
await aave.borrow({ token: 'TOKEN_ADDRESS', amount: 1000000n })
// Repay
await aave.repay({ token: 'TOKEN_ADDRESS', amount: 1000000n })
```
### Common Parameters
- `token` (`string`): ERC‑20 token address
- `amount` (`number | bigint`): token amount in base units
- `onBehalfOf` (`string`, optional): another address to act for (supply/borrow/repay)
- `to` (`string`, optional): destination address (withdraw)
> Note: `amount` must be > 0. Addresses must be valid/non‑zero. A provider is required for any write.
Get started with WDK in a Node.js environment
Get started with WDK's Lending Aave EVM Protocol API
Get started with WDK's Lending Aave EVM Protocol usage
***
### Need Help?
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/guides/get-started
Description: Install the package, create AaveProtocolEvm, and review prerequisites.
This guide covers [installation](#installation), [creating the lending client](#create-the-lending-client), and [prerequisites](#prerequisites). Use [Node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/) on your machine.
## Installation
Run the following to install [@tetherto/wdk-protocol-lending-aave-evm](https://www.npmjs.com/package/@tetherto/wdk-protocol-lending-aave-evm):
```bash title="Install with npm"
npm install @tetherto/wdk-protocol-lending-aave-evm
```
## Create the lending client
You can attach Aave V3 actions to an EVM account from [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference) with [`new AaveProtocolEvm(account)`](/sdk/lending-modules/lending-aave-evm/api-reference) on [`AaveProtocolEvm`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Create AaveProtocolEvm"
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
const aave = new AaveProtocolEvm(account)
```
## Prerequisites
**Token balance:** To supply or repay, hold the ERC-20 in the wallet. **Gas:** Keep native balance (ETH on Ethereum, and so on) for transaction fees unless you use sponsored ERC-4337 flows. **Networks:** This module targets mainnet deployments; confirm your RPC matches [supported networks](/sdk/lending-modules/lending-aave-evm/configuration).
Use contract addresses for Aave-supported reserves. On Ethereum mainnet, USD₮ uses `0xdAC17F958D2ee523a2206206994597C13D831ec7` (use `USDT` in code identifiers and literals).
## Next Steps
- [Lending operations](lending-operations)
- [Handle errors](handle-errors)
***
## Handle Errors
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/guides/handle-errors
Description: Catch lending failures and release wallet secrets safely.
This guide explains how to [handle operation errors](#operation-errors) and follow [best practices](#best-practices) for disposing wallet state.
## Operation errors
You can catch failures from [`supply()`](/sdk/lending-modules/lending-aave-evm/api-reference), [`withdraw()`](/sdk/lending-modules/lending-aave-evm/api-reference), [`borrow()`](/sdk/lending-modules/lending-aave-evm/api-reference), and [`repay()`](/sdk/lending-modules/lending-aave-evm/api-reference) with `try/catch`:
```javascript title="Handle a failed supply"
try {
await aave.supply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 0n
})
} catch (e) {
console.error('Lending failed:', e.message)
if (e.message.includes('zero')) {
console.log('Amount must be greater than zero')
}
}
```
You can isolate quote failures from [`quoteSupply()`](/sdk/lending-modules/lending-aave-evm/api-reference) (or the other `quote*` methods) when you only need an estimate:
```javascript title="Handle quote errors"
try {
const q = await aave.quoteBorrow({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
console.log('Borrow fee (wei):', q.fee)
} catch (e) {
console.error('Quote failed:', e.message)
}
```
See [Rules & Notes](/sdk/lending-modules/lending-aave-evm/api-reference) for address and amount validation expectations.
## Best Practices
You can wipe private keys after lending work by calling [`dispose()`](/sdk/wallet-modules/wallet-evm/api-reference) on [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference), or [`dispose()`](/sdk/wallet-modules/wallet-evm/api-reference) on [`WalletManagerEvm`](/sdk/wallet-modules/wallet-evm/api-reference):
```javascript title="Dispose after lending session"
try {
await aave.supply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
} finally {
account.dispose()
}
```
For ERC-4337 accounts, use [`dispose()`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) on the smart-account type. Clear references to [`AaveProtocolEvm`](/sdk/lending-modules/lending-aave-evm/api-reference) when the session ends.
## Next Steps
- [Lending operations](lending-operations)
- [Get started](get-started)
- [API reference](/sdk/lending-modules/lending-aave-evm/api-reference)
***
## Lending Operations
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/guides/lending-operations
Description: Supply, withdraw, borrow, repay, quote fees, use ERC-4337, and read account data.
This guide walks through [supply](#supply), [withdraw](#withdraw), [borrow](#borrow), [repay](#repay), [quotes](#quotes-before-sending), [ERC-4337 usage](#erc-4337-smart-accounts), and [reading account data](#reading-account-data). It assumes an [`AaveProtocolEvm`](/sdk/lending-modules/lending-aave-evm/api-reference) instance named `aave` and the USD₮ contract on Ethereum mainnet `0xdAC17F958D2ee523a2206206994597C13D831ec7`.
## Supply
You can deposit reserves into the pool using [`supply()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Supply USDT"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const tx = await aave.supply({ token: USDT, amount: 1000000n })
console.log('Supply tx hash:', tx.hash)
```
## Withdraw
You can remove supplied liquidity using [`withdraw()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Withdraw USDT"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const tx = await aave.withdraw({ token: USDT, amount: 1000000n })
console.log('Withdraw tx hash:', tx.hash)
```
## Borrow
You can draw debt against your collateral using [`borrow()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Borrow USDT"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const tx = await aave.borrow({ token: USDT, amount: 1000000n })
console.log('Borrow tx hash:', tx.hash)
```
## Repay
You can pay down debt using [`repay()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Repay USDT"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const tx = await aave.repay({ token: USDT, amount: 1000000n })
console.log('Repay tx hash:', tx.hash)
```
## Quotes before sending
You can estimate the supply fee with [`quoteSupply()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Quote supply fee"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const supplyQuote = await aave.quoteSupply({ token: USDT, amount: 1000000n })
console.log('Supply fee (wei):', supplyQuote.fee)
```
You can estimate the withdraw fee with [`quoteWithdraw()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Quote withdraw fee"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const withdrawQuote = await aave.quoteWithdraw({ token: USDT, amount: 1000000n })
console.log('Withdraw fee (wei):', withdrawQuote.fee)
```
You can estimate the borrow fee with [`quoteBorrow()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Quote borrow fee"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const borrowQuote = await aave.quoteBorrow({ token: USDT, amount: 1000000n })
console.log('Borrow fee (wei):', borrowQuote.fee)
```
You can estimate the repay fee with [`quoteRepay()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Quote repay fee"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const repayQuote = await aave.quoteRepay({ token: USDT, amount: 1000000n })
console.log('Repay fee (wei):', repayQuote.fee)
```
Health factor and collateralization limits still apply. A quote does not guarantee the transaction will succeed if on-chain state changes.
## ERC-4337 smart accounts
You can run the same methods through [`WalletAccountEvmErc4337`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) and pass a second `config` argument to override per-call gas payment settings. In `v1.0.0-beta.4`, the lending methods accept the same override families as the wallet module: paymaster token, sponsorship policy, and native coins. See the [ERC-4337 config override](/sdk/lending-modules/lending-aave-evm/api-reference) section for the full field list.
```javascript title="Supply with paymaster"
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'
const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 42161,
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: process.env.BUNDLER_URL,
paymasterUrl: process.env.PAYMASTER_URL
})
const aaveAA = new AaveProtocolEvm(aa)
const result = await aaveAA.supply(
{ token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', amount: 1000000n },
{
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
}
)
console.log('Supply hash:', result.hash)
```
You can use the same second argument to:
- override paymaster-token mode with `paymasterUrl`, `paymasterAddress`, `paymasterToken`, or `transferMaxFee`
- switch one call to sponsorship mode with `isSponsored`, `paymasterUrl`, and `sponsorshipPolicyId`
- switch one call to native-coin gas mode with `useNativeCoins` and `transferMaxFee`
Use token addresses that exist on the same chain as the smart account RPC.
## Reading account data
You can inspect collateral, debt, and health using [`getAccountData()`](/sdk/lending-modules/lending-aave-evm/api-reference):
```javascript title="Read Aave account data"
const data = await aave.getAccountData()
console.log({
totalCollateralBase: data.totalCollateralBase,
totalDebtBase: data.totalDebtBase,
availableBorrowsBase: data.availableBorrowsBase,
currentLiquidationThreshold: data.currentLiquidationThreshold,
ltv: data.ltv,
healthFactor: data.healthFactor
})
```
## Next Steps
- [Handle errors](handle-errors)
- [Get started](get-started)
- [API reference](/sdk/lending-modules/lending-aave-evm/api-reference)
***
## Lending Aave EVM Guides
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-aave-evm/usage
Description: How to install and use @tetherto/wdk-protocol-lending-aave-evm on EVM
# Usage
The [@tetherto/wdk-protocol-lending-aave-evm](https://www.npmjs.com/package/@tetherto/wdk-protocol-lending-aave-evm) module exposes Aave V3 supply, borrow, and repayment flows for EVM accounts. Follow the guides below for setup, day-to-day operations, and error handling.
Install the package, create AaveProtocolEvm, and review prerequisites.
Supply, withdraw, borrow, repay, quotes, ERC-4337, and account data.
Handle failures and dispose wallet secrets when finished.
Get started with WDK in a Node.js environment
Networks and deployment settings for the Aave lending protocol
Methods and parameters for AaveProtocolEvm
***
## Lending Morpho EVM Overview
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm
Description: Overview of the @morpho-org/wdk-protocol-lending-morpho-evm community module
Community modules are developed and maintained independently by third-party contributors.
Tether and the WDK Team do not endorse or assume responsibility for their code, security, or maintenance. Use your own judgment and proceed at your own risk.
The [@morpho-org/wdk-protocol-lending-morpho-evm](https://www.npmjs.com/package/@morpho-org/wdk-protocol-lending-morpho-evm) community module lets WDK-compatible EVM wallet accounts interact with Morpho Vault V2 earn targets and Morpho Blue markets through [`@morpho-org/morpho-sdk`](https://www.npmjs.com/package/@morpho-org/morpho-sdk).
## Features
- **Vault earn flows**: Deposit into and withdraw from configured Morpho Vault V2 targets
- **Market collateral**: Supply and withdraw collateral in a configured Morpho Blue market
- **Borrow/Repay**: Borrow from and repay a configured Morpho Blue market
- **Requirements API**: Surface Morpho SDK approval, signature, and authorization requirements
- **Quotes**: Estimate transaction costs before sending
- **Account Reads**: Read vault, market, and combined account position data
- **Account Support**: Works with standard EVM accounts and ERC-4337 smart accounts
## Supported Targets
The module supports curated Ethereum mainnet presets and explicit Morpho target configuration.
### Earn Presets
| Preset | Vault |
|--------|-------|
| `sky-money-usdt-savings` | sky.money USDT Savings V2 |
| `steakhouse-prime-instant` | Steakhouse Prime Instant V2 |
### Borrow Presets
| Preset | Collateral |
|--------|------------|
| `susds` | sUSDS |
| `wsteth` | wstETH |
| `wbtc` | WBTC |
| `xaut` | XAUt |
## Wallet Compatibility
- **Standard EVM Wallets**: `@tetherto/wdk-wallet-evm`
- **ERC-4337 Smart Accounts**: `@tetherto/wdk-wallet-evm-erc-4337`
- **Read-Only Accounts**: For quoting and reading configured vault or market positions without sending transactions
## Key Components
- **MorphoProtocolEvm**: Main class for Morpho lending operations
- **Morpho Protocol Options**: Configure vaults, markets, presets, chain guards, slippage, signatures, and deployless reads
- **Requirement Helpers**: `getSupplyRequirements`, `getSupplyCollateralRequirements`, `getBorrowRequirements`, and `getRepayRequirements`
- **Position Reads**: `getVaultPosition`, `getMarketPosition`, and `getAccountData`
## Next Steps
Install the package, create MorphoProtocolEvm, and review prerequisites.
How to use Morpho vault, market, quote, requirement, and position flows.
Install the package and configure presets, explicit targets, and options.
Methods, options, presets, and return shapes for MorphoProtocolEvm.
***
## Lending Morpho EVM API Reference
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/api-reference
Description: API Reference for @morpho-org/wdk-protocol-lending-morpho-evm
# API Reference
## Class: MorphoProtocolEvm
Main class for Morpho Vault V2 and Morpho Blue lending on EVM.
### Constructor
```javascript
new MorphoProtocolEvm(account, options)
```
Parameters:
- `account`: `WalletAccountEvm | WalletAccountReadOnlyEvm | WalletAccountEvmErc4337 | WalletAccountReadOnlyEvmErc4337`
- `options`: `MorphoProtocolOptions`
Example:
```javascript
const morpho = new MorphoProtocolEvm(account, {
presets: {
earn: 'sky-money-usdt-savings',
borrow: 'wsteth'
}
})
```
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `supply(options, config?)` | Deposit assets into the configured vault | `Promise` |
| `getSupplyRequirements(options, requirementOptions?)` | Return approval or signature requirements for vault deposit | `Promise` |
| `quoteSupply(options, config?)` | Quote vault deposit | `Promise>` |
| `withdraw(options, config?)` | Withdraw assets from the configured vault | `Promise` |
| `quoteWithdraw(options, config?)` | Quote vault withdrawal | `Promise>` |
| `supplyCollateral(options, config?)` | Supply collateral to the configured market | `Promise` |
| `getSupplyCollateralRequirements(options, requirementOptions?)` | Return approval or signature requirements for collateral supply | `Promise` |
| `quoteSupplyCollateral(options, config?)` | Quote collateral supply | `Promise>` |
| `borrow(options, config?)` | Borrow from the configured market | `Promise` |
| `getBorrowRequirements(options)` | Return Morpho authorization requirements for borrow | `Promise` |
| `quoteBorrow(options, config?)` | Quote borrow | `Promise>` |
| `repay(options, config?)` | Repay the configured market | `Promise` |
| `getRepayRequirements(options, requirementOptions?)` | Return approval or signature requirements for repay | `Promise` |
| `quoteRepay(options, config?)` | Quote repay | `Promise>` |
| `withdrawCollateral(options, config?)` | Withdraw collateral from the configured market | `Promise` |
| `quoteWithdrawCollateral(options, config?)` | Quote collateral withdrawal | `Promise>` |
| `getVaultPosition(account?)` | Read configured vault position | `Promise` |
| `getMarketPosition(account?)` | Read configured market position | `Promise` |
| `getAccountData(account?)` | Read combined configured vault and market position | `Promise` |
| `getVaultAddress()` | Return the configured vault address | `Address` |
| `getBorrowMarketId()` | Return the configured borrow market id | `string` |
---
## Requirements and Results
- `ApprovalOrSignatureRequirement`: returned by supply, collateral supply, and repay requirement helpers. Each item is either a Morpho SDK approval transaction with `to`, `value`, and `data`, or a signature requirement with `sign(client, userAddress)`.
- `RequirementAuthorization`: returned by `getBorrowRequirements()`. These are Morpho authorization transactions with `to`, `value`, and `data`.
- `RequirementSignature`: returned by a signature requirement's `sign(client, userAddress)` helper. Pass it to `supply()`, `supplyCollateral()`, or `repay()` as `requirementSignature`.
- Write methods return the WDK wallet transaction result, including `hash` and `fee`. Quote methods return the same protocol result without `hash`.
---
### `supply(options, config?)`
Deposit assets into the configured Morpho vault.
Options:
- `token` (`string`): configured vault asset
- `amount` (`number | bigint`, optional when `nativeAmount` is set): ERC-20 amount in base units
- `nativeAmount` (`number | bigint`, optional): native amount to wrap and supply
- `onBehalfOf` (`string`, optional): must equal the connected wallet address when set
- `requirementSignature` (`RequirementSignature`, optional): signature returned by a Morpho SDK requirement
- `slippageTolerance` (`bigint`, optional): per-call Morpho SDK slippage tolerance
```javascript
const tx = await morpho.supply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
### `getSupplyRequirements(options, requirementOptions?)`
Return Morpho SDK approval or signature requirements for a vault deposit. Use it before `supply()` when the account has not approved the required spender or when signature support is enabled.
```javascript
const requirements = await morpho.getSupplyRequirements({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
### `quoteSupply(options, config?)`
Quote the fee for a vault deposit transaction.
```javascript
const quote = await morpho.quoteSupply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
---
### `withdraw(options, config?)`
Withdraw assets from the configured Morpho vault.
Options:
- `token` (`string`): configured vault asset
- `amount` (`number | bigint`): amount in base units
- `to` (`string`, optional): must equal the connected wallet address when set
```javascript
const tx = await morpho.withdraw({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
### `quoteWithdraw(options, config?)`
Quote the fee for a vault withdrawal transaction.
```javascript
const quote = await morpho.quoteWithdraw({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
---
### `supplyCollateral(options, config?)`
Supply collateral to the configured Morpho Blue market.
Options:
- `token` (`string`): configured market collateral token
- `amount` (`number | bigint`, optional when `nativeAmount` is set): ERC-20 amount in base units
- `nativeAmount` (`number | bigint`, optional): native amount to wrap and supply
- `onBehalfOf` (`string`, optional): must equal the connected wallet address when set
- `requirementSignature` (`RequirementSignature`, optional): signature returned by a Morpho SDK requirement
```javascript
const tx = await morpho.supplyCollateral({
token: 'COLLATERAL_TOKEN_ADDRESS',
amount: 1000000000000000000n
})
```
### `getSupplyCollateralRequirements(options, requirementOptions?)`
Return Morpho SDK approval or signature requirements for collateral supply.
```javascript
const requirements = await morpho.getSupplyCollateralRequirements({
token: 'COLLATERAL_TOKEN_ADDRESS',
amount: 1000000000000000000n
})
```
### `quoteSupplyCollateral(options, config?)`
Quote the fee for supplying collateral.
```javascript
const quote = await morpho.quoteSupplyCollateral({
token: 'COLLATERAL_TOKEN_ADDRESS',
amount: 1000000000000000000n
})
```
---
### `borrow(options, config?)`
Borrow assets from the configured Morpho Blue market.
Options:
- `token` (`string`): configured market loan token
- `amount` (`number | bigint`): amount in base units
- `onBehalfOf` (`string`, optional): must equal the connected wallet address when set
- `reallocations` (`readonly VaultReallocation[]`, optional): Morpho Vault V2 reallocations
- `slippageTolerance` (`bigint`, optional): per-call Morpho SDK slippage tolerance
```javascript
const tx = await morpho.borrow({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
### `getBorrowRequirements(options)`
Return Morpho authorization requirements for borrow flows.
```javascript
const requirements = await morpho.getBorrowRequirements({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
### `quoteBorrow(options, config?)`
Quote the fee for borrowing.
```javascript
const quote = await morpho.quoteBorrow({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
```
---
### `repay(options, config?)`
Repay assets to the configured Morpho Blue market.
Options:
- `token` (`string`): configured market loan token
- `amount` (`number | bigint | "max"`): amount in base units, or `"max"` to repay current borrow shares
- `onBehalfOf` (`string`, optional): must equal the connected wallet address when set
- `requirementSignature` (`RequirementSignature`, optional): signature returned by a Morpho SDK requirement
- `slippageTolerance` (`bigint`, optional): per-call Morpho SDK slippage tolerance
```javascript
const tx = await morpho.repay({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 'max'
})
```
When `amount` is `"max"`, Morpho repays borrow shares. Re-run `getRepayRequirements({ amount: "max" })` immediately before sending `repay()` so the approval or permit reflects current market state, or approve `getChainAddresses(chainId).bundler3.generalAdapter1` with a small buffer above current debt and pass a non-zero `slippageTolerance`. `slippageTolerance` caps the repay share price or transfer amount; it is not approval slippage.
### `getRepayRequirements(options, requirementOptions?)`
Return Morpho SDK approval or signature requirements for repayment.
```javascript
const requirements = await morpho.getRepayRequirements({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 'max'
})
```
### `quoteRepay(options, config?)`
Quote the fee for repayment.
```javascript
const quote = await morpho.quoteRepay({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 'max'
})
```
---
### `withdrawCollateral(options, config?)`
Withdraw collateral from the configured Morpho Blue market.
Options:
- `token` (`string`): configured market collateral token
- `amount` (`number | bigint`): amount in base units
- `to` (`string`, optional): must equal the connected wallet address when set
```javascript
const tx = await morpho.withdrawCollateral({
token: 'COLLATERAL_TOKEN_ADDRESS',
amount: 1000000000000000000n
})
```
### `quoteWithdrawCollateral(options, config?)`
Quote the fee for withdrawing collateral.
```javascript
const quote = await morpho.quoteWithdrawCollateral({
token: 'COLLATERAL_TOKEN_ADDRESS',
amount: 1000000000000000000n
})
```
---
## Position Reads
### `getVaultPosition(account?)`
Read this or another account's configured vault position.
Returns:
```javascript
{
shares: bigint,
assets: bigint,
vaultAddress: Address
}
```
### `getMarketPosition(account?)`
Read this or another account's configured market position.
Returns:
```javascript
{
supplyShares: bigint,
borrowShares: bigint,
borrowAssets: bigint,
collateral: bigint,
marketId: string
}
```
### `getAccountData(account?)`
Read combined configured vault and market position data.
Returns:
```javascript
{
vaultShares: bigint,
vaultAssets: bigint,
marketSupplyShares: bigint,
marketBorrowShares: bigint,
marketBorrowAssets: bigint,
collateral: bigint,
vaultAddress: Address,
marketId: string
}
```
## Rules & Notes
- The wallet account must include a provider.
- Write methods require a writable EVM account.
- `token`, `onBehalfOf`, `to`, and `account` addresses must be valid when provided.
- For vault supply and collateral supply, pass `amount`, `nativeAmount`, or both, and make sure the combined supplied amount is greater than zero.
- Withdraw, borrow, and collateral-withdraw amounts must be greater than zero. `repay()` also accepts `amount: "max"`.
- Vault operations require the token to match the configured vault asset.
- Market borrow and repay operations require the token to match the configured market loan token.
- Collateral operations require the token to match the configured market collateral token.
- `onBehalfOf` and vault or collateral withdrawal `to` must equal the connected wallet address when set.
- `slippageTolerance` applies to vault supply, borrow, and repay calls in the published adapter. Collateral supply uses the Morpho SDK collateral-supply action defaults.
- Use `get*Requirements` methods before final actions when the Morpho SDK reports approval, signature, or authorization requirements.
Presets, explicit targets, and Morpho SDK options
Get started with Morpho lending operations
***
### Need Help?
***
## Lending Morpho EVM Configuration
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/configuration
Description: Configuration options and settings for @morpho-org/wdk-protocol-lending-morpho-evm
# Configuration
## Installation
Install the Morpho lending module with the EVM wallet module used by the examples and the `viem` peer dependency:
```bash title="Install with npm"
npm install @morpho-org/wdk-protocol-lending-morpho-evm @tetherto/wdk-wallet-evm viem
```
```bash title="Install with pnpm"
pnpm add @morpho-org/wdk-protocol-lending-morpho-evm @tetherto/wdk-wallet-evm viem
```
The package declares Node.js `22.13` or later in its published engine metadata. If you use ERC-4337 smart accounts, also install `@tetherto/wdk-wallet-evm-erc-4337`.
## Service Setup
Create a WDK-compatible EVM wallet account, then pass it to `MorphoProtocolEvm` with either presets or explicit Morpho targets.
```javascript title="Create MorphoProtocolEvm with presets"
import MorphoProtocolEvm from '@morpho-org/wdk-protocol-lending-morpho-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
const morpho = new MorphoProtocolEvm(account, {
presets: {
earn: 'sky-money-usdt-savings',
borrow: 'wsteth'
}
})
```
## Constructor
```javascript
new MorphoProtocolEvm(account, options)
```
Parameters:
- `account`: `WalletAccountEvm`, `WalletAccountReadOnlyEvm`, `WalletAccountEvmErc4337`, or `WalletAccountReadOnlyEvmErc4337`
- `options`: Morpho target configuration
The wallet account must include a provider. Read-only accounts can read positions and quote transactions; mutating methods require a writable account.
## Presets
Built-in presets target Ethereum mainnet USDT earn and borrow flows.
```javascript title="Use built-in presets"
const morpho = new MorphoProtocolEvm(account, {
presets: {
earn: 'steakhouse-prime-instant',
borrow: 'wbtc'
}
})
```
Borrow presets:
| Preset | Chain ID | Market ID | Collateral | LLTV |
|--------|----------|-----------|------------|------|
| `susds` | `1` | `0x3274643db77a064abd3bc851de77556a4ad2e2f502f4f0c80845fa8f909ecf0b` | sUSDS | 96.5% |
| `wsteth` | `1` | `0xe7e9694b754c4d4f7e21faf7223f6fa71abaeb10296a4c43a54a7977149687d2` | wstETH | 86% |
| `wbtc` | `1` | `0xa921ef34e2fc7a27ccc50ae7e4b154e16c9799d3387076c421423ef52ac4df99` | WBTC | 86% |
| `xaut` | `1` | `0xb7843fe78e7e7fd3106a1b939645367967d1f986c2e45edb8932ad1896450877` | XAUt | 77% |
Earn presets:
| Preset | Chain ID | Vault Address | Vault |
|--------|----------|---------------|-------|
| `sky-money-usdt-savings` | `1` | `0x23f5E9c35820f4baB695Ac1F19c203cC3f8e1e11` | sky.money USDT Savings V2 |
| `steakhouse-prime-instant` | `1` | `0xbeef003C68896c7D2c3c60d363e8d71a49Ab2bf9` | Steakhouse Prime Instant V2 |
## Explicit Targets
Use explicit targets when you need a vault or market outside the built-in presets.
```javascript title="Use explicit Morpho targets"
const morpho = new MorphoProtocolEvm(account, {
chainId: 1,
earnVaultAddress: '0x23f5E9c35820f4baB695Ac1F19c203cC3f8e1e11',
borrowMarketId: '0xe7e9694b754c4d4f7e21faf7223f6fa71abaeb10296a4c43a54a7977149687d2'
})
```
When you use `earnVaultAddress`, `borrowMarketParams`, or `borrowMarketId` directly, pass `chainId`. The adapter uses it to guard transaction building if a browser wallet switches chains.
Use `borrowMarketParams` when you already know the full Morpho Blue market configuration:
```javascript title="Use explicit Morpho Blue market params"
const morpho = new MorphoProtocolEvm(account, {
chainId: 1,
borrowMarketParams: {
loanToken: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
collateralToken: 'COLLATERAL_TOKEN_ADDRESS',
oracle: 'ORACLE_ADDRESS',
irm: 'INTEREST_RATE_MODEL_ADDRESS',
lltv: 860000000000000000n
}
})
```
`InputMarketParams` contains `loanToken`, `collateralToken`, `oracle`, `irm`, and `lltv`. Confirm explicit market params against Morpho market data before using them in production.
## Options
| Option | Type | Description |
|--------|------|-------------|
| `chainId` | `number \| bigint` | Required with explicit Morpho targets |
| `earnVaultAddress` | `string` | Explicit Morpho Vault V2 address |
| `borrowMarketParams` | `InputMarketParams` | Explicit Morpho Blue market params |
| `borrowMarketId` | `string` | Market id used to fetch market params on-chain |
| `presets` | `{ earn?: string, borrow?: string }` | Built-in earn and borrow target names |
| `slippageTolerance` | `bigint` | Morpho SDK slippage tolerance in WAD precision |
| `supportSignature` | `boolean` | Enables Morpho SDK permit or Permit2 requirements |
| `supportDeployless` | `boolean` | Enables Morpho SDK deployless reads |
| `metadata` | `Metadata` | Optional Morpho SDK metadata passed to action encoders |
## Native Amounts
For vault deposits and collateral supply, pass either `amount`, `nativeAmount`, or both. `nativeAmount` follows Morpho SDK semantics and is only valid when the configured vault asset or collateral token is the wrapped native token for the chain.
```javascript title="Supply with native amount"
await morpho.supply({
token: 'WRAPPED_NATIVE_TOKEN_ADDRESS',
nativeAmount: 1000000000000000n
})
```
## ERC-4337 Config Overrides
When using `WalletAccountEvmErc4337`, mutating methods and quote helpers accept an optional second `config` argument for the wallet module's per-call gas payment settings.
```javascript title="Supply with an ERC-4337 config override"
await morpho.supply(
{
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
},
{
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
}
)
```
See the [`@tetherto/wdk-wallet-evm-erc-4337` configuration docs](/sdk/wallet-modules/wallet-evm-erc-4337/configuration) for paymaster token, sponsorship policy, and native coin override fields.
Get started with WDK in a Node.js environment
Methods and parameters for MorphoProtocolEvm
Get started with Morpho lending operations
***
### Need Help?
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/guides/get-started
Description: Install the package, create MorphoProtocolEvm, and review prerequisites.
This guide covers [installation](#installation), [creating the lending client](#create-the-lending-client), and [prerequisites](#prerequisites). Use [Node.js](https://nodejs.org/) `22.13` or later and [npm](https://www.npmjs.com/) on your machine.
## Installation
Run the following to install [@morpho-org/wdk-protocol-lending-morpho-evm](https://www.npmjs.com/package/@morpho-org/wdk-protocol-lending-morpho-evm), the EVM wallet module used by the examples, and the `viem` peer dependency:
```bash title="Install with npm"
npm install @morpho-org/wdk-protocol-lending-morpho-evm @tetherto/wdk-wallet-evm viem
```
```bash title="Install with pnpm"
pnpm add @morpho-org/wdk-protocol-lending-morpho-evm @tetherto/wdk-wallet-evm viem
```
If you use ERC-4337 smart accounts, also install `@tetherto/wdk-wallet-evm-erc-4337`.
## Create the lending client
You can attach Morpho actions to an EVM account from [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference) with [`new MorphoProtocolEvm(account, options)`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Create MorphoProtocolEvm"
import MorphoProtocolEvm from '@morpho-org/wdk-protocol-lending-morpho-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
const morpho = new MorphoProtocolEvm(account, {
presets: {
earn: 'sky-money-usdt-savings',
borrow: 'wsteth'
}
})
```
## Prerequisites
**Runtime:** Use Node.js `22.13` or later. **Token balance:** To supply, supply collateral, or repay, hold the required ERC-20 in the wallet. **Gas:** Keep native balance for transaction fees unless you use sponsored ERC-4337 flows. **Targets:** Confirm the configured vault or market matches the token and chain you plan to use.
The built-in presets target Ethereum mainnet. If you configure an explicit vault address, market id, or market params, set `chainId` in [`MorphoProtocolOptions`](/sdk/lending-modules/lending-morpho-evm/configuration).
## Requirements before actions
Morpho SDK actions can return approval, signature, or authorization requirements. Call the matching `get*Requirements` method before the final action when the account has not already satisfied those requirements.
```javascript title="Check supply requirements"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const requirements = await morpho.getSupplyRequirements({
token: USDT,
amount: 1000000n
})
console.log('Requirements:', requirements)
```
Send any returned transaction requirements with your EVM account flow before calling the final action. For signature requirements, call the requirement's `sign(client, userAddress)` helper, then pass the returned `requirementSignature` to `supply`, `supplyCollateral`, or `repay`.
## Next Steps
- [Lending operations](lending-operations)
- [Handle errors](handle-errors)
***
## Handle Errors
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/guides/handle-errors
Description: Catch Morpho lending failures and release wallet secrets safely.
This guide explains how to [handle operation errors](#operation-errors), [handle requirement errors](#requirement-errors), and follow [best practices](#best-practices) for disposing wallet state.
## Operation errors
You can catch failures from [`supply()`](/sdk/lending-modules/lending-morpho-evm/api-reference), [`withdraw()`](/sdk/lending-modules/lending-morpho-evm/api-reference), [`supplyCollateral()`](/sdk/lending-modules/lending-morpho-evm/api-reference), [`borrow()`](/sdk/lending-modules/lending-morpho-evm/api-reference), [`repay()`](/sdk/lending-modules/lending-morpho-evm/api-reference), and [`withdrawCollateral()`](/sdk/lending-modules/lending-morpho-evm/api-reference) with `try/catch`:
```javascript title="Handle a failed supply"
try {
await morpho.supply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 0n
})
} catch (e) {
console.error('Morpho lending failed:', e.message)
if (e.message.includes('amount')) {
console.log('Amount must be greater than zero')
}
}
```
Common failure causes include:
- wallet account does not have a provider configured
- write method is called with a read-only account
- token does not match the configured vault asset, market loan token, or market collateral token
- explicit target is used without the required `chainId`
- connected chain does not match the configured Morpho target
- amount is zero, invalid, or larger than the account balance
- `onBehalfOf` or `to` does not match the connected wallet address when required
Use this checklist to map the most common failures to fixes:
| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| Constructor fails before any operation | Wallet account has no provider | Create the EVM account with a provider or use a read-only account with an RPC provider |
| Write method fails on a read-only account | Read-only account can quote and read, but cannot send transactions | Use `WalletAccountEvm` or `WalletAccountEvmErc4337` for mutating methods |
| Explicit target fails during setup | `chainId` is missing, invalid, or does not match the wallet chain | Pass the expected `chainId` with `earnVaultAddress`, `borrowMarketId`, or `borrowMarketParams` |
| Token mismatch error | The supplied token is not the configured vault asset, market loan token, or collateral token | Use the token from the configured vault or market target |
| Zero amount error | `amount` and `nativeAmount` are both absent or zero | Pass a positive ERC-20 `amount`, a positive `nativeAmount`, or `amount: "max"` for repay |
| Requirement lookup returns approval or authorization | Allowance, permit, Permit2, or Morpho authorization is missing | Send returned transaction requirements or sign the returned signature requirement before the final action |
| Final action fails after requirements | Allowance, balance, signature, authorization, quote, or market state changed after the requirement lookup | Re-run the matching `get*Requirements()` method and rebuild the final action |
| Quote succeeds but write fails | On-chain state changed, the account lacks balance, or requirements were not satisfied | Re-check requirements, balances, token addresses, and chain before sending |
## Requirement errors
Requirement helpers can fail if the configured target, token, account, or provider cannot produce a valid Morpho SDK action.
```javascript title="Handle requirement errors"
try {
const requirements = await morpho.getBorrowRequirements({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
console.log('Borrow requirements:', requirements)
} catch (e) {
console.error('Requirement lookup failed:', e.message)
}
```
If a final action fails after requirements were returned, re-check the requirements. Allowances, signatures, authorizations, or on-chain market state can change between the requirement lookup and the final transaction.
## Quote errors
You can isolate quote failures from write failures when you only need an estimate:
```javascript title="Handle quote errors"
try {
const quote = await morpho.quoteBorrow({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
console.log('Borrow fee:', quote.fee)
} catch (e) {
console.error('Quote failed:', e.message)
}
```
See [Rules & Notes](/sdk/lending-modules/lending-morpho-evm/api-reference) for address, token, amount, and target validation expectations.
## Best Practices
Dispose wallet secrets after a lending session by calling [`dispose()`](/sdk/wallet-modules/wallet-evm/api-reference) on [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference), or the matching dispose method on your smart account type.
```javascript title="Dispose after a Morpho lending session"
try {
await morpho.supply({
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
})
} finally {
account.dispose()
}
```
For ERC-4337 accounts, use [`dispose()`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) on the smart-account type. Clear references to [`MorphoProtocolEvm`](/sdk/lending-modules/lending-morpho-evm/api-reference) when the session ends.
## Next Steps
- [Lending operations](lending-operations)
- [Get started](get-started)
- [API reference](/sdk/lending-modules/lending-morpho-evm/api-reference)
***
## Lending Operations
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/guides/lending-operations
Description: Supply, withdraw, manage collateral, borrow, repay, quote fees, handle requirements, and read positions.
This guide walks through [vault supply](#vault-supply), [vault withdraw](#vault-withdraw), [collateral](#collateral), [borrow](#borrow), [repay](#repay), [requirements](#requirements), [quotes](#quotes-before-sending), [ERC-4337 usage](#erc-4337-smart-accounts), and [position reads](#reading-positions). It assumes a [`MorphoProtocolEvm`](/sdk/lending-modules/lending-morpho-evm/api-reference) instance named `morpho`.
## Vault supply
Deposit into the configured Morpho Vault V2 target with [`supply()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Supply USDT to the configured vault"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const requirements = await morpho.getSupplyRequirements({
token: USDT,
amount: 1000000n
})
console.log('Supply requirements:', requirements)
const tx = await morpho.supply({
token: USDT,
amount: 1000000n
})
console.log('Supply tx hash:', tx.hash)
```
The `token` must match the configured vault asset.
## Vault withdraw
Withdraw from the configured vault with [`withdraw()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Withdraw USDT from the configured vault"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const tx = await morpho.withdraw({
token: USDT,
amount: 1000000n
})
console.log('Withdraw tx hash:', tx.hash)
```
If you pass `to`, it must equal the connected wallet address.
## Collateral
Supply collateral to the configured Morpho Blue market with [`supplyCollateral()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Supply collateral"
const COLLATERAL = 'COLLATERAL_TOKEN_ADDRESS'
const requirements = await morpho.getSupplyCollateralRequirements({
token: COLLATERAL,
amount: 1000000000000000000n
})
console.log('Collateral requirements:', requirements)
const tx = await morpho.supplyCollateral({
token: COLLATERAL,
amount: 1000000000000000000n
})
console.log('Collateral supply tx hash:', tx.hash)
```
Withdraw collateral with [`withdrawCollateral()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Withdraw collateral"
const COLLATERAL = 'COLLATERAL_TOKEN_ADDRESS'
const tx = await morpho.withdrawCollateral({
token: COLLATERAL,
amount: 1000000000000000000n
})
console.log('Collateral withdrawal tx hash:', tx.hash)
```
The collateral token must match the configured market collateral token. If you pass `to`, it must equal the connected wallet address.
## Borrow
Borrow from the configured market with [`borrow()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Borrow USDT"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const requirements = await morpho.getBorrowRequirements({
token: USDT,
amount: 1000000n
})
console.log('Borrow requirements:', requirements)
const tx = await morpho.borrow({
token: USDT,
amount: 1000000n
})
console.log('Borrow tx hash:', tx.hash)
```
The borrow token must match the configured market loan token.
## Repay
Repay by asset amount, or pass `amount: 'max'` to repay current borrow shares:
```javascript title="Repay max borrow shares"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const requirements = await morpho.getRepayRequirements({
token: USDT,
amount: 'max'
})
console.log('Repay requirements:', requirements)
const tx = await morpho.repay({
token: USDT,
amount: 'max'
})
console.log('Repay tx hash:', tx.hash)
```
For `amount: "max"`, Morpho repays borrow shares. The loan-token transfer amount returned by `getRepayRequirements()` is computed from live market state, so accrued interest can make a delayed approval or permit insufficient. Re-run `getRepayRequirements({ amount: "max" })` immediately before `repay()`, or approve `getChainAddresses(chainId).bundler3.generalAdapter1` with a small buffer above current debt and pass a non-zero `slippageTolerance`. `slippageTolerance` caps the repay share price or transfer amount; it is not approval slippage. Residual loan tokens pulled in shares mode are skimmed back to the user.
The repay token must match the configured market loan token.
## Requirements
Morpho SDK actions can require approvals, Permit or Permit2 signatures, or Morpho authorization before the final action.
| Requirement source | Final action |
|--------------------|--------------|
| `getSupplyRequirements()` | `supply()` |
| `getSupplyCollateralRequirements()` | `supplyCollateral()` |
| `getBorrowRequirements()` | `borrow()` |
| `getRepayRequirements()` | `repay()` |
For EOA accounts, send returned transaction requirements before the final operation. For signature requirements, call the returned requirement's `sign(client, userAddress)` method and pass the result as `requirementSignature`.
```javascript title="Resolve EOA requirements before the final action"
async function resolveRequirements({ account, walletClient, userAddress, requirements }) {
let requirementSignature
for (const requirement of requirements) {
if (typeof requirement.sign === 'function') {
requirementSignature = await requirement.sign(walletClient, userAddress)
continue
}
await account.sendTransaction({
to: requirement.to,
value: requirement.value,
data: requirement.data
})
}
return requirementSignature
}
const requirements = await morpho.getSupplyRequirements({
token: USDT,
amount: 1000000n
})
const requirementSignature = await resolveRequirements({
account,
walletClient,
userAddress,
requirements
})
const tx = await morpho.supply({
token: USDT,
amount: 1000000n,
requirementSignature
})
```
Create `walletClient` with `viem` using the same signer and address as the WDK EVM account. Borrow requirements are authorization transactions, so send them before `borrow()`:
```javascript title="Resolve borrow authorization requirements"
const requirements = await morpho.getBorrowRequirements({
token: USDT,
amount: 1000000n
})
for (const requirement of requirements) {
await account.sendTransaction({
to: requirement.to,
value: requirement.value,
data: requirement.data
})
}
await morpho.borrow({
token: USDT,
amount: 1000000n
})
```
For ERC-4337 accounts, you can batch returned transaction requirements with your account-level flow when supported by the wallet module. Signature requirements still need to be signed before the final action.
Morpho SDK enforces builder and executor invariants for bundled actions. In this WDK adapter, `onBehalfOf` and vault or collateral withdrawal `to` must equal the connected wallet address when set.
## Quotes before sending
Quote helpers build the target transaction and return the account-level fee estimate without sending it:
```javascript title="Quote Morpho operations"
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const COLLATERAL = 'COLLATERAL_TOKEN_ADDRESS'
const supplyQuote = await morpho.quoteSupply({ token: USDT, amount: 1000000n })
const withdrawQuote = await morpho.quoteWithdraw({ token: USDT, amount: 1000000n })
const collateralQuote = await morpho.quoteSupplyCollateral({
token: COLLATERAL,
amount: 1000000000000000000n
})
const borrowQuote = await morpho.quoteBorrow({ token: USDT, amount: 1000000n })
const repayQuote = await morpho.quoteRepay({ token: USDT, amount: 'max' })
console.log({
supplyQuote,
withdrawQuote,
collateralQuote,
borrowQuote,
repayQuote
})
```
Quotes do not guarantee that a later transaction will succeed if balances, allowances, authorization, market state, or vault state change.
## ERC-4337 smart accounts
You can use the same methods with [`WalletAccountEvmErc4337`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) and pass a second `config` argument for per-call gas payment overrides.
```javascript title="Supply with an ERC-4337 paymaster override"
const result = await morpho.supply(
{
token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amount: 1000000n
},
{
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
}
)
console.log('Supply hash:', result.hash)
```
Use token addresses that exist on the same chain as the smart account RPC.
## Reading positions
Read the configured vault position with [`getVaultPosition()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Read configured vault position"
const vaultPosition = await morpho.getVaultPosition()
console.log({
shares: vaultPosition.shares,
assets: vaultPosition.assets,
vaultAddress: vaultPosition.vaultAddress
})
```
Read the configured market position with [`getMarketPosition()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Read configured market position"
const marketPosition = await morpho.getMarketPosition()
console.log({
supplyShares: marketPosition.supplyShares,
borrowShares: marketPosition.borrowShares,
borrowAssets: marketPosition.borrowAssets,
collateral: marketPosition.collateral,
marketId: marketPosition.marketId
})
```
Read both configured positions with [`getAccountData()`](/sdk/lending-modules/lending-morpho-evm/api-reference):
```javascript title="Read combined Morpho account data"
const data = await morpho.getAccountData()
console.log({
vaultAssets: data.vaultAssets,
marketBorrowAssets: data.marketBorrowAssets,
collateral: data.collateral,
vaultAddress: data.vaultAddress,
marketId: data.marketId
})
```
## Next Steps
- [Handle errors](handle-errors)
- [Get started](get-started)
- [API reference](/sdk/lending-modules/lending-morpho-evm/api-reference)
***
## Lending Morpho EVM Guides
URL: https://docs.wdk.tether.io/sdk/lending-modules/lending-morpho-evm/usage
Description: How to install and use @morpho-org/wdk-protocol-lending-morpho-evm on EVM
# Usage
The [@morpho-org/wdk-protocol-lending-morpho-evm](https://www.npmjs.com/package/@morpho-org/wdk-protocol-lending-morpho-evm) community module exposes Morpho Vault V2 and Morpho Blue operations for WDK-compatible EVM accounts. Follow the guides below for setup, lending operations, and error handling.
Install the package, create MorphoProtocolEvm, and review prerequisites.
Supply, withdraw, manage collateral, borrow, repay, quotes, requirements, and position reads.
Handle target, token, requirement, and transaction failures.
Get started with WDK in a Node.js environment
Presets, explicit targets, and Morpho SDK options
Methods and parameters for MorphoProtocolEvm
***
## Swap Modules Overview
URL: https://docs.wdk.tether.io/sdk/swap-modules
Description: Explore WDK swap modules for token swap integrations across supported providers.
The Swap Development Kit (WDK) provides a set of modules that support swap on top of multiple blockchain networks. All modules share a common interface, ensuring consistent behavior across different blockchain implementations.
WDK is introducing the [swidge interface](/sdk/swidge-modules) as the preferred interface for new swap, bridge, and combined route providers. Existing swap modules remain supported, but new protocol integrations should prefer swidge because the standalone swap interface is expected to be deprecated in a future release once swidge provider coverage is available.
## Swap Protocol Modules
DeFi swap functionality for token exchanges across different DEXs:
| Module | Blockchain | Status | Documentation |
|--------|------------|--------|---------------|
| [`@tetherto/wdk-protocol-swap-velora-evm`](https://github.com/tetherto/wdk-protocol-swap-velora-evm) | EVM | ✅ Ready | [Documentation](/sdk/swap-modules/swap-velora-evm/) |
| `@tetherto/wdk-protocol-swap-stonfi-ton` | TON | In progress | Coming soon |
## Next steps
To get started with WDK modules, follow these steps:
1. Get up and running quickly with our [Quickstart Guide](/start-building/nodejs-bare-quickstart)
2. Choose the modules that best fit your needs from the tables above
3. Check specific documentation for modules you wish to use
You can also:
- Learn about key concepts like [Account Abstraction](/resources/concepts#account-abstraction) and other important definitions
- Use one of our ready-to-use examples to be production ready
***
## Swap velora EVM Overview
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm
Description: Overview of the @tetherto/wdk-protocol-swap-velora-evm module
A lightweight package that lets EVM wallet accounts swap tokens using the velora aggregator. It provides a clean SDK for token swaps on EVM chains and works with both standard wallets and ERC‑4337 smart accounts.
## Features
- **Token Swapping**: Execute token swaps through velora on supported EVM networks
- **Account Abstraction**: Compatible with standard EVM accounts and ERC‑4337 smart accounts
- **Fee Controls**: Optional `swapMaxFee` to cap gas costs
- **Allowance Safety**: Handles USD₮ mainnet pattern (reset allowance to 0 before approve)
- **Provider Flexibility**: Works with JSON‑RPC URLs and EIP‑1193 providers
- **TypeScript Support**: Full TypeScript definitions included
## Supported Networks
Works with EVM networks supported by velora (e.g., Ethereum, Polygon, Arbitrum, etc.). A working RPC provider is required.
## Wallet Compatibility
The swap service supports multiple EVM wallet types:
- **Standard EVM Wallets**: `@tetherto/wdk-wallet-evm` accounts
- **ERC‑4337 Smart Accounts**: `@tetherto/wdk-wallet-evm-erc-4337` accounts with bundler/paymaster
- **Read‑Only Accounts**: For quoting swaps without sending transactions
## Key Components
- **velora Integration**: Uses velora aggregator for routing and quotes
- **Quote System**: Pre‑transaction fee and amount estimation via `quoteSwap`
- **AA Integration**: Optional paymaster token and fee cap overrides when using ERC‑4337
- **Allowance Management**: Approve flow handled automatically when required
## Next Steps
Get started with WDK in a Node.js environment
Get started with WDK's velora Swap Protocol configuration
Get started with WDK's velora Swap Protocol API
Get started with WDK's velora Swap Protocol usage
***
## Need Help?
***
## API Reference
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/api-reference
Description: API Reference for @tetherto/wdk-protocol-swap-velora-evm
## Class: VeloraProtocolEvm
Main class for velora token swaps on EVM.
### Constructor
```javascript
new VeloraProtocolEvm(account, config?)
```
Parameters:
- `account`: `WalletAccountEvm | WalletAccountReadOnlyEvm | WalletAccountEvmErc4337 | WalletAccountReadOnlyEvmErc4337`
- `config` (optional):
- `swapMaxFee` (`bigint`): maximum total gas fee allowed (wei)
Example:
```javascript
const swap = new VeloraProtocolEvm(account, { swapMaxFee: 200000000000000n })
```
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `swap(options, config?)` | Perform a token swap | `Promise<{hash: string, fee: bigint, tokenInAmount: bigint, tokenOutAmount: bigint, approveHash?: string, resetAllowanceHash?: string}>` |
| `quoteSwap(options, config?)` | Get estimated fee and amounts | `Promise<{fee: bigint, tokenInAmount: bigint, tokenOutAmount: bigint}>` |
---
### `swap(options, config?)`
Execute a swap via velora.
Options:
- `tokenIn` (`string`): Address of the ERC‑20 token to sell
- `tokenOut` (`string`): Address of the ERC‑20 token to buy
- `tokenInAmount` (`bigint`, optional): Exact input amount (base units)
- `tokenOutAmount` (`bigint`, optional): Exact output amount (base units)
- `to` (`string`, optional): Recipient address (defaults to account address)
Config (ERC‑4337 only):
- `paymasterToken` (`string`, optional): Token symbol/address for fee sponsorship
- `swapMaxFee` (`bigint`, optional): Per‑swap fee cap (wei)
Returns:
- Standard account: `{ hash, fee, tokenInAmount, tokenOutAmount, approveHash?, resetAllowanceHash? }`
- ERC‑4337 account: `{ hash, fee, tokenInAmount, tokenOutAmount }` (approve may be bundled)
Notes:
- On Ethereum mainnet, selling USD₮ may first set allowance to 0, then approve.
- Requires a provider; requires a non read‑only account to send transactions.
Example:
```javascript
const tx = await swap.swap({
tokenIn: '0xdAC17F...ec7', // USD₮
tokenOut: '0xC02a...6Cc2', // WETH
tokenInAmount: 1000000n
})
```
---
### `quoteSwap(options, config?)`
Get estimated fee and token in/out amounts.
Options are the same as `swap`.
Returns: `{ fee, tokenInAmount, tokenOutAmount }`
Config (ERC‑4337 only):
- `paymasterToken` (`string`, optional): Token symbol/address for fee sponsorship
Works with read‑only accounts.
Example:
```javascript
const quote = await swap.quoteSwap({
tokenIn: '0xdAC17F...ec7', // USD₮
tokenOut: '0xC02a...6Cc2', // WETH
tokenOutAmount: 500000000000000000n // 0.5 WETH
})
```
---
## Errors
Common errors include:
- Insufficient liquidity / no route for pair
- Fee exceeds `swapMaxFee`
- Read‑only account cannot send swaps
- Provider/RPC errors (invalid endpoint, network mismatch)
---
## Types
- `swapMaxFee: bigint` — Upper bound for gas fees (wei)
- `tokenInAmount/tokenOutAmount: bigint` — ERC‑20 base units
- `paymasterToken: string` — token symbol or address (AA only)
Get started with WDK in a Node.js environment
Get started with WDK's Swap velora EVM Protocol configuration
Get started with WDK's Swap velora EVM Protocol usage
***
## Need Help?
***
## Configuration
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/configuration
Description: Configuration options and settings for @tetherto/wdk-protocol-swap-velora-evm
## Swap Service Configuration
The `VeloraProtocolEvm` accepts a configuration object that defines fee controls and behavior:
```javascript
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
// Create wallet account first
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Create swap service with configuration
const swapProtocol = new VeloraProtocolEvm(account, {
swapMaxFee: 200000000000000n // Optional: Max swap fee in wei
})
```
## Account Configuration
The swap service uses the wallet account configuration for network access and signing:
```javascript
import { WalletAccountEvm, WalletAccountReadOnlyEvm } from '@tetherto/wdk-wallet-evm'
// Full access account
const account = new WalletAccountEvm(
seedPhrase,
"0'/0/0",
{
provider: 'https://ethereum-rpc.publicnode.com'
}
)
// Read-only account (quotes only)
const readOnly = new WalletAccountReadOnlyEvm(
'0xYourAddress',
{
provider: 'https://ethereum-rpc.publicnode.com'
}
)
// Create swap service
const swapProtocol = new VeloraProtocolEvm(account, {
swapMaxFee: 200000000000000n
})
```
## Configuration Options
### Swap Max Fee
The `swapMaxFee` option sets an upper bound for total gas costs to prevent excessive fees.
**Type:** `bigint` (optional)
**Unit:** Wei
**Examples:**
```javascript
const config = {
// Cap total gas fee to 0.0002 ETH (in wei)
swapMaxFee: 200000000000000n,
}
// Usage example
try {
const result = await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USD₮ (6 decimals)
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH (18 decimals)
tokenInAmount: 1000000n
})
} catch (error) {
if (error.message.includes('max fee')) {
console.error('Swap stopped: Fee too high')
}
}
```
## ERC‑4337 (Account Abstraction) Configuration
When using ERC‑4337 smart accounts (`@tetherto/wdk-wallet-evm-erc-4337`), you can override fee behavior per swap and specify a paymaster token:
```javascript
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 1,
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: 'YOUR_BUNDLER_URL',
paymasterUrl: 'YOUR_PAYMASTER_URL'
})
const swapAA = new VeloraProtocolEvm(aa, { swapMaxFee: 200000000000000n })
const result = await swapAA.swap({
tokenIn: '0xTokenIn',
tokenOut: '0xTokenOut',
tokenInAmount: 1000000n
}, {
paymasterToken: 'USDT', // Token used to pay for gas
swapMaxFee: 200000000000000n // Per‑swap override
})
```
### Paymaster Token (ERC‑4337)
The `paymasterToken` option indicates which token the paymaster should use to sponsor gas.
**Type:** `string` (optional)
**Format:** Token symbol or address
**Example:**
```javascript
const result = await swapAA.swap({
tokenIn: '0xdAC17F...ec7',
tokenOut: '0xC02a...6Cc2', // WETH
tokenInAmount: 1000000n
}, {
paymasterToken: 'USDT'
})
```
## Network Support
velora supports multiple EVM networks (e.g., Ethereum, Polygon, Arbitrum). Ensure your account is configured with a valid provider for the target network.
```javascript
// Ethereum Mainnet
const eth = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Polygon
const polygon = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://polygon-bor-rpc.publicnode.com'
})
```
## Swap Options
When calling `swap`, provide the swap parameters:
```javascript
const swapOptions = {
tokenIn: '0xTokenIn', // ERC‑20 to sell
tokenOut: '0xTokenOut', // ERC‑20 to buy
tokenInAmount: 1000000n, // exact input (base units)
// OR
// tokenOutAmount: 1000000n, // exact output (base units)
to: '0xRecipient' // optional recipient (defaults to your address)
}
const result = await swapProtocol.swap(swapOptions)
```
### Parameters
- `tokenIn` (`string`): ERC‑20 address to sell
- `tokenOut` (`string`): ERC‑20 address to buy
- `tokenInAmount` (`bigint`, optional): exact input amount in token base units
- `tokenOutAmount` (`bigint`, optional): exact output amount in token base units
- `to` (`string`, optional): recipient address (defaults to account address)
> Note: Use either `tokenInAmount` OR `tokenOutAmount`, not both.
Get started with WDK in a Node.js environment
Get started with WDK's velora Swap Protocol API
Get started with WDK's velora Swap Protocol usage
***
## Need Help?
***
## Execute Swaps
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/guides/execute-swaps
Description: Run exact-input swaps, exact-output swaps, and swaps with ERC-4337 accounts.
This guide explains how to run a [basic exact-input swap](#basic-exact-input-swap), an [exact-output swap](#exact-output-swap), and a [swap from an ERC-4337 smart account](#swap-with-erc-4337). You should already have a [`VeloraProtocolEvm`](/sdk/swap-modules/swap-velora-evm/api-reference) instance.
Swaps spend tokens and gas on-chain. Use amounts you control and an RPC you trust.
## Basic exact-input swap
You can sell an exact amount of the input token using [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Exact input: USDT to WETH"
const result = await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
console.log('Swap transaction hash:', result.hash)
console.log('Total fee (wei):', result.fee)
console.log('Tokens sold (base units):', result.tokenInAmount)
console.log('Tokens bought (base units):', result.tokenOutAmount)
```
## Exact output swap
You can receive an exact amount of the output token by passing `tokenOutAmount` to [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Exact output amount"
const result = await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenOutAmount: 500000000000000000n
})
console.log('Swap hash:', result.hash)
console.log('Tokens sold (base units):', result.tokenInAmount)
console.log('Tokens bought (base units):', result.tokenOutAmount)
```
## Swap with ERC-4337
You can perform a user-operation-backed swap by constructing [`VeloraProtocolEvm`](/sdk/swap-modules/swap-velora-evm/api-reference) with [`WalletAccountEvmErc4337`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) and passing paymaster options to [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Swap with smart account and paymaster"
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 42161,
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: process.env.BUNDLER_URL,
paymasterUrl: process.env.PAYMASTER_URL
})
const swapAA = new VeloraProtocolEvm(aa, { swapMaxFee: 200000000000000n })
const result = await swapAA.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
}, {
paymasterToken: 'USDT',
swapMaxFee: 200000000000000n
})
console.log('Swap hash:', result.hash)
console.log('Total fee (wei):', result.fee)
```
Token addresses must match the chain your account uses (for example, mainnet USD₮ addresses differ from Arbitrum).
## Next Steps
- [Get swap quotes](/sdk/swap-modules/swap-velora-evm/guides/get-swap-quotes) before sending
- [Handle errors](/sdk/swap-modules/swap-velora-evm/guides/handle-errors)
- [Get started](/sdk/swap-modules/swap-velora-evm/guides/get-started) if you still need setup
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/guides/get-started
Description: Install the package, create VeloraProtocolEvm, and learn supported networks.
This guide covers [installation](#installation), [create the swap protocol](#create-the-swap-protocol), and [supported networks](#supported-networks). You need [Node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/) to follow along.
## Installation
Run the following to install [@tetherto/wdk-protocol-swap-velora-evm](https://www.npmjs.com/package/@tetherto/wdk-protocol-swap-velora-evm):
```bash title="Install with npm"
npm install @tetherto/wdk-protocol-swap-velora-evm
```
You also need an EVM wallet account from [`@tetherto/wdk-wallet-evm`](https://www.npmjs.com/package/@tetherto/wdk-wallet-evm) (or an ERC-4337 account from [`@tetherto/wdk-wallet-evm-erc-4337`](https://www.npmjs.com/package/@tetherto/wdk-wallet-evm-erc-4337)) on the same chain as your RPC provider.
## Create the swap protocol
You can construct a swap client with [`new VeloraProtocolEvm(account, config?)`](/sdk/swap-modules/swap-velora-evm/api-reference) on top of [`VeloraProtocolEvm`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Create VeloraProtocolEvm"
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
const swapProtocol = new VeloraProtocolEvm(account, {
swapMaxFee: 200000000000000n
})
```
Optional `swapMaxFee` caps the total gas fee in wei for swaps. See [configuration](/sdk/swap-modules/swap-velora-evm/configuration) for environment-specific settings.
## Supported networks
Velora routing works on EVM networks the aggregator supports, including **Ethereum**, **Polygon**, **Arbitrum**, and other chains where Velora exposes liquidity. Use an RPC endpoint for the network your [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference) is configured for so [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference) and [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference) target the correct chain.
## Next Steps
- [Execute swaps](/sdk/swap-modules/swap-velora-evm/guides/execute-swaps)
- [Get swap quotes](/sdk/swap-modules/swap-velora-evm/guides/get-swap-quotes)
- [Handle errors](/sdk/swap-modules/swap-velora-evm/guides/handle-errors)
***
## Get Swap Quotes
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/guides/get-swap-quotes
Description: Estimate fees and amounts with quoteSwap before executing a swap.
This guide shows how to [quote before swapping](#quote-before-swapping) and use quotes for [fee estimation](#fee-estimation). Quotes use [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference), which works with read-only accounts as well as signing accounts.
## Quote before swapping
You can preview fee and token amounts for the same parameters you would pass to [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference) using [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Quote exact input swap"
const quote = await swapProtocol.quoteSwap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
console.log('Estimated fee (wei):', quote.fee)
console.log('Tokens in (base units):', quote.tokenInAmount)
console.log('Tokens out (base units):', quote.tokenOutAmount)
```
You can quote an exact-output style trade the same way by passing `tokenOutAmount` instead of `tokenInAmount` to [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Quote exact output swap"
const quote = await swapProtocol.quoteSwap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenOutAmount: 500000000000000000n
})
console.log('Estimated fee (wei):', quote.fee)
console.log('Required token in (base units):', quote.tokenInAmount)
```
## Fee estimation
You can read `quote.fee` from [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference) as the estimated total swap fee in wei before calling [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference):
```javascript title="Quote fee before deciding"
const quote = await swapProtocol.quoteSwap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
const maxFee = 200000000000000n
console.log('Quoted fee (wei):', quote.fee, 'cap:', maxFee)
```
You can compare that estimate to `swapMaxFee` on [`VeloraProtocolEvm`](/sdk/swap-modules/swap-velora-evm/api-reference) and only then call [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference) when the quote is within your cap:
```javascript title="Swap when fee is under cap"
const maxFee = 200000000000000n
const quote = await swapProtocol.quoteSwap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
if (quote.fee <= maxFee) {
const result = await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
console.log('Swap hash:', result.hash)
}
```
On-chain conditions can change between quote and execution. The executed [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference) may still differ slightly from the last [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference) result.
## Next Steps
- [Execute swaps](/sdk/swap-modules/swap-velora-evm/guides/execute-swaps)
- [Handle errors](/sdk/swap-modules/swap-velora-evm/guides/handle-errors)
- [Get started](/sdk/swap-modules/swap-velora-evm/guides/get-started)
***
## Handle Errors
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/guides/handle-errors
Description: Catch swap failures, interpret common messages, and clean up sensitive state.
This guide covers [swap errors](#swap-errors), [quote errors](#quote-errors), and [best practices](#best-practices) for clearing wallet material after use.
## Swap errors
You can detect failed swaps by wrapping [`swap()`](/sdk/swap-modules/swap-velora-evm/api-reference) in `try/catch` and inspecting `error.message`:
```javascript title="Handle swap failures"
try {
const result = await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
console.log('Swap successful:', result.hash)
} catch (error) {
console.error('Swap failed:', error.message)
if (error.message.includes('liquidity')) {
console.log('No route or insufficient liquidity for this pair')
}
if (error.message.includes('max fee')) {
console.log('Swap fee exceeds swapMaxFee')
}
if (error.message.includes('read-only')) {
console.log('Read-only account cannot swap')
}
}
```
Match string fragments only as a convenience; production apps should prefer stable error codes from your runtime when available.
## Quote errors
You can handle failures from [`quoteSwap()`](/sdk/swap-modules/swap-velora-evm/api-reference) the same way, including provider or routing errors:
```javascript title="Handle quote failures"
try {
const quote = await swapProtocol.quoteSwap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
console.log('Quoted fee (wei):', quote.fee)
} catch (error) {
console.error('Quote failed:', error.message)
}
```
Common causes are listed under [Errors](/sdk/swap-modules/swap-velora-evm/api-reference) in the API reference (liquidity, fee cap, read-only send attempts, RPC issues).
## Best Practices
You can clear signing material when a session ends by calling [`dispose()`](/sdk/wallet-modules/wallet-evm/api-reference) on each [`WalletAccountEvm`](/sdk/wallet-modules/wallet-evm/api-reference), or [`dispose()`](/sdk/wallet-modules/wallet-evm/api-reference) on [`WalletManagerEvm`](/sdk/wallet-modules/wallet-evm/api-reference) if you use a manager:
```javascript title="Dispose wallet accounts"
try {
await swapProtocol.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
})
} finally {
account.dispose()
}
```
If you use an ERC-4337 account, call [`dispose()`](/sdk/wallet-modules/wallet-evm-erc-4337/api-reference) on that account type per its API reference. Drop references to your [`VeloraProtocolEvm`](/sdk/swap-modules/swap-velora-evm/api-reference) instance when you no longer need it.
## Next Steps
- [Get swap quotes](/sdk/swap-modules/swap-velora-evm/guides/get-swap-quotes)
- [Execute swaps](/sdk/swap-modules/swap-velora-evm/guides/execute-swaps)
- [API reference](/sdk/swap-modules/swap-velora-evm/api-reference)
***
## Swap velora EVM Guides
URL: https://docs.wdk.tether.io/sdk/swap-modules/swap-velora-evm/usage
Description: How to install and use @tetherto/wdk-protocol-swap-velora-evm for swapping tokens on EVM
# Usage
The [@tetherto/wdk-protocol-swap-velora-evm](https://www.npmjs.com/package/@tetherto/wdk-protocol-swap-velora-evm) module routes ERC-20 swaps on EVM chains through Velora. Use the guides below for setup, execution, quotes, and error handling.
Install the package, create VeloraProtocolEvm, and review supported networks.
Exact-input and exact-output swaps, including ERC-4337 smart accounts.
Quote before swapping and compare fees to your max fee cap.
Handle swap and quote failures and dispose wallet state safely.
Get started with WDK in a Node.js environment
RPC, fee limits, and environment settings for the Velora swap protocol
Methods, options, and error notes for VeloraProtocolEvm
***
## Swidge Protocol Interface
URL: https://docs.wdk.tether.io/sdk/swidge-modules
Description: Learn the preferred WDK swidge interface for swap-only, bridge-only, and combined asset routes.
The swidge interface is WDK's preferred route interface for protocol providers that can quote and execute asset movement. A swidge route moves from one token and chain to another token and chain. The provider may fulfill that route as a swap-only route, a bridge-only route, a combined swap and bridge route, an intent, a solver route, or an aggregator route.
Use swidge for new protocol integrations. Existing standalone swap and bridge interfaces remain supported for released modules, but WDK plans to deprecate those standalone interfaces in a future release after swidge provider coverage is available.
## When to use swidge
Use a swidge provider when a route matches any of these shapes:
- Swap one token into another token on the same chain.
- Bridge the same token from one chain to another chain.
- Swap and bridge in one route.
- Route between different tokens, different chains, or both.
Use the existing [swap modules](/sdk/swap-modules) and [bridge modules](/sdk/bridge-modules) docs when maintaining released modules that have not shipped a swidge implementation yet. For new provider modules, prefer the swidge interface.
## Interface methods
Concrete swidge provider modules extend `SwidgeProtocol` from `@tetherto/wdk-wallet/protocols`. The base interface exposes discovery, quote, execution, and status methods:
| Method | Description |
|--------|-------------|
| `quoteSwidge(options)` | Quotes the route before execution. |
| `swidge(options, config?)` | Executes a swidge operation. This is a write method and must be user-confirmed. |
| `getSwidgeStatus(id, options?)` | Looks up the status of an in-flight swidge execution. |
| `getSupportedChains()` | Lists the provider's supported chains for swidge operations. |
| `getSupportedTokens(options?)` | Lists supported tokens, optionally filtered by chain or route context. |
```typescript title="Swidge protocol shape"
interface ISwidgeProtocol {
quoteSwidge(options: SwidgeOptions): Promise
swidge(
options: SwidgeOptions,
config?: SwidgeProtocolConfig
): Promise
getSwidgeStatus(
id: string,
options?: SwidgeStatusOptions
): Promise
getSupportedChains(): Promise
getSupportedTokens(
options?: SwidgeSupportedTokensOptions
): Promise
}
```
## Discover supported chains and tokens
Use `getSupportedChains()` and `getSupportedTokens()` before building route pickers or validating a requested route. These methods are read-only discovery calls; they do not quote or execute a transaction.
```typescript title="Discover swidge support"
const chains = await swidge.getSupportedChains()
const ethereumTokens = await swidge.getSupportedTokens({
fromChain: 'ethereum'
})
const routeTokens = await swidge.getSupportedTokens({
fromChain: 'ethereum',
fromToken: '0xSourceToken...',
toChain: 'arbitrum'
})
```
`getSupportedChains()` returns provider-specific chain identifiers plus display metadata. `getSupportedTokens(options?)` returns provider-specific token identifiers, chain identifiers, symbols, decimals, and optional token addresses. Use the returned `token` and `chain` values when calling `quoteSwidge()` unless the provider module documents a stricter identifier format.
| Discovery type | Key fields |
|----------------|------------|
| `SwidgeSupportedChain` | `id`, `name`, `type`, `nativeToken` |
| `SwidgeSupportedToken` | `token`, `chain`, `symbol`, `decimals`, optional `address`, optional `name` |
| `SwidgeSupportedTokensOptions` | Optional `fromChain`, `fromToken`, and `toChain` filters |
## Quote a route
Call `quoteSwidge()` before execution so the user can review source amount, expected destination amount, minimum output, fees, and quote expiry.
```typescript title="Quote a swidge route"
const quote = await swidge.quoteSwidge({
fromToken: '0xSourceToken...',
toToken: '0xDestinationToken...',
toChain: 'arbitrum',
recipient: '0xRecipient...',
fromTokenAmount: 1000000n,
slippage: 0.01
})
console.log('Expected output:', quote.toTokenAmount)
console.log('Minimum output:', quote.toTokenAmountMin)
console.log('Fees:', quote.fees)
```
`SwidgeOptions` supports exact-in and exact-out routes:
| Option | Type | Description |
|--------|------|-------------|
| `fromToken` | `string` | Source token address or provider-specific asset identifier. |
| `toToken` | `string` | Destination token address or provider-specific asset identifier. |
| `toChain` | `string \| number` | Optional destination chain identifier. If omitted, it defaults to the source chain for same-chain swaps. |
| `recipient` | `string` | Optional recipient for the output tokens. |
| `refundAddress` | `string` | Optional address that receives refunds if the transaction cannot complete. |
| `slippage` | `number` | Optional decimal slippage tolerance, for example `0.01` for 1%. |
| `fromTokenAmount` | `number \| bigint` | Exact source amount to spend. Do not pass with `toTokenAmount`. |
| `toTokenAmount` | `number \| bigint` | Exact destination amount to receive. Do not pass with `fromTokenAmount`. |
## Execute a route
Call `quoteSwidge()` first, show the quote to the user, then call `swidge()` with the same route options after explicit confirmation. Apply fee caps with `SwidgeProtocolConfig` where supported by the provider.
```typescript title="Execute a swidge route"
const options = {
fromToken: '0xSourceToken...',
toToken: '0xDestinationToken...',
toChain: 'arbitrum',
recipient: '0xRecipient...',
fromTokenAmount: 1000000n,
slippage: 0.01
}
const quote = await swidge.quoteSwidge(options)
// Show quote details and ask for confirmation before continuing.
const result = await swidge.swidge(options, {
maxNetworkFeeBps: 50,
maxProtocolFeeBps: 25
})
console.log('Swidge ID:', result.id)
console.log('Primary transaction:', result.hash)
console.log('Transactions:', result.transactions)
```
`swidge()` can submit one or more transactions. Ask for explicit user confirmation before calling it, and display the quote amounts, fee breakdown, route, and recipient first.
`SwidgeProtocolConfig` supports fee limits expressed in basis points of the input amount:
| Config field | Type | Description |
|--------------|------|-------------|
| `maxNetworkFeeBps` | `number \| bigint` | Maximum acceptable network fee in basis points of the input amount. |
| `maxProtocolFeeBps` | `number \| bigint` | Maximum acceptable protocol fee in basis points of the input amount. |
## Track status
Use `getSwidgeStatus()` when the provider returns an execution ID and the final destination result may settle asynchronously.
```typescript title="Check swidge status"
const status = await swidge.getSwidgeStatus(result.id, {
fromChain: 'ethereum',
toChain: 'arbitrum'
})
if (status.status === 'completed') {
console.log('Swidge complete')
}
```
Supported statuses are:
| Status | Meaning |
|--------|---------|
| `pending` | The route has started and is waiting for progress. |
| `action-required` | The user or integrator must take another action. |
| `completed` | The route completed successfully. |
| `failed` | The route failed. |
| `refund-pending` | A refund has started but has not completed. |
| `refunded` | The route was refunded. |
| `cancelled` | The route was cancelled. |
| `expired` | The quote or route expired. |
| `partial` | The route partially completed. |
## Result fields
`SwidgeQuote` and `SwidgeResult` can include an itemized `fees` array. Prefer displaying the itemized fees when available. Public fee categories are `network`, `protocol`, `affiliate`, and `other`; providers can use the optional fee `description` for route-specific detail.
| Field | Type | Description |
|-------|------|-------------|
| `id` | `string` | Execution identifier returned by `swidge()`. |
| `hash` | `string` | Primary transaction hash, if available immediately. |
| `transactions` | `SwidgeTransaction[]` | Source, destination, approval, refund, or other transaction hashes. |
| `fromTokenAmount` | `bigint` | Actual source amount spent. |
| `toTokenAmount` | `bigint` | Actual or expected destination amount. |
| `toTokenAmountMin` | `bigint` | Minimum destination amount after slippage. |
| `fees` | `SwidgeFee[]` | Itemized fee breakdown. |
## Supported assets and chains
Provider modules should still document route shapes, network caveats, token identifier formats, and provider-specific limits on their module pages. Use `getSupportedChains()` and `getSupportedTokens(options?)` for runtime discovery, then consult the provider module docs for behavior that cannot be represented in the shared discovery response.
## Next steps
Register and use protocol modules with WDK accounts
Maintain existing standalone swap modules
Maintain existing standalone bridge modules
***
## Wallet Modules Overview
URL: https://docs.wdk.tether.io/sdk/wallet-modules
Description: Explore WDK wallet modules for building self-custodial wallets across supported chains.
The Wallet Development Kit (WDK) provides a set of modules that support multiple blockchain networks. All modules share a common interface, ensuring consistent behavior across different blockchain implementations.
## Supported Networks
This package works with multiple blockchain networks through wallet registration.
Bitcoin Mainnet
Ethereum, Sepolia Testnet, L2s, etc.
Tron Mainnet
TON Mainnet
Solana Mainnet
Spark Mainnet
## Classic Wallet Modules
Standard wallet implementations that use native blockchain tokens for transaction fees:
| Module | Blockchain | Status | Documentation |
|--------|------------|--------|---------------|
| [`@tetherto/wdk-wallet-evm`](https://github.com/tetherto/wdk-wallet-evm) | EVM | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-evm) |
| [`@tetherto/wdk-wallet-ton`](https://github.com/tetherto/wdk-wallet-ton) | TON | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-ton) |
| [`@tetherto/wdk-wallet-btc`](https://github.com/tetherto/wdk-wallet-btc) | Bitcoin | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-btc) |
| [`@tetherto/wdk-wallet-spark`](https://github.com/tetherto/wdk-wallet-spark) | Spark | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-spark) |
| [`@tetherto/wdk-wallet-tron`](https://github.com/tetherto/wdk-wallet-tron) | TRON | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-tron) |
| [`@tetherto/wdk-wallet-solana`](https://github.com/tetherto/wdk-wallet-solana) | Solana | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-solana) |
| `@tetherto/wdk-wallet-ark` | Ark | In progress | - |
## Account Abstraction Wallet Modules
Wallet implementations that support [Account Abstraction](/resources/concepts#account-abstraction) for gasless transactions using paymaster tokens like USD₮:
| Module | Blockchain | Status | Documentation |
|--------|------------|--------|---------------|
| [`@tetherto/wdk-wallet-evm-erc4337`](https://github.com/tetherto/wdk-wallet-evm-erc-4337) | EVM | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-evm-erc-4337) |
| [`@tetherto/wdk-wallet-ton-gasless`](https://github.com/tetherto/wdk-wallet-ton-gasless) | TON | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-ton-gasless) |
| [`@tetherto/wdk-wallet-tron-gasfree`](https://github.com/tetherto/wdk-wallet-tron-gasfree) | TRON | ✅ Ready | [Documentation](/sdk/wallet-modules/wallet-tron-gasfree) |
| `@tetherto/wdk-wallet-solana-jupiterz` | Solana | In progress | - |
## Community Wallet Modules
Wallet modules developed by the community. See the [Community Modules](/sdk/community-modules/) page for more details.
Community modules are developed and maintained independently. Use your own judgment and proceed at your own risk.
| Module | Blockchain | Description | Repository |
|--------|------------|-------------|------------|
| `@utexo/wdk-wallet-rgb` | Bitcoin (RGB) | RGB protocol wallet integration for Bitcoin-based smart contracts | [GitHub](https://github.com/UTEXO-Protocol/wdk-wallet-rgb) |
## Next Steps
To get started with WDK modules, follow these steps:
1. Get up and running quickly with our [Quickstart Guide](/start-building/nodejs-bare-quickstart)
2. Choose the modules that best fit your needs from the tables above
3. Check specific documentation for modules you wish to use
You can also:
- Learn about key concepts like [Account Abstraction](/resources/concepts#account-abstraction) and other important definitions
- Use one of our ready-to-use examples to be production ready
***
## Wallet BTC Overview
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc
Description: Overview of the @tetherto/wdk-wallet-btc module
A simple and secure package to manage BIP-84 (SegWit) and BIP-44 (Legacy) wallets for the Bitcoin blockchain. This package provides a clean API for creating, managing, and interacting with Bitcoin wallets using BIP-39 seed phrases and Bitcoin-specific derivation paths.
**Default Derivation Path Change in v1.0.0-beta.4+**
The default derivation path was updated in v1.0.0-beta.4 to use BIP-84 (Native SegWit) instead of BIP-44 (Legacy):
- **Previous path** (up to v1.0.0-beta.3): `m/44'/0'/0'/0/{index}` (Legacy addresses)
- **Current path** (v1.0.0-beta.4+): `m/84'/0'/0'/0/{index}` (Native SegWit addresses)
If you're upgrading from an earlier version, existing wallets created with the old path will generate different addresses. Make sure to migrate any existing wallets or use the old path explicitly if needed for compatibility.
Use [`getAccountByPath`](/sdk/wallet-modules/wallet-btc/api-reference#getaccountbypathpath) to supply an explicit derivation path when importing or recreating legacy wallets.
## Features
- **BIP-39 Seed Phrase Support**: Generate and validate BIP-39 mnemonic seed phrases
- **Bitcoin Derivation Paths**: Support for BIP-84 (Native SegWit, default) and BIP-44 (Legacy) derivation paths
- **Multi-Account Management**: Create and manage multiple accounts from a single seed phrase
- **Address Types Support**: Generate Native SegWit (P2WPKH) addresses by default, with Legacy (P2PKH) support via configuration
- **UTXO Management**: Track and manage unspent transaction outputs
- **Offline Transaction Signing**: Sign Bitcoin transactions with `signTransaction()` without broadcasting them
- **Transaction Management**: Create, sign, and broadcast Bitcoin transactions (single recipient per transaction)
- **Fee Estimation**: Dynamic fee calculation via mempool.space API
- **Provider Failover**: Configure ordered Electrum, WebSocket, Blockbook, or custom client fallbacks
- **TypeScript Support**: Full TypeScript definitions included
- **Memory Safety**: Secure private key management with memory-safe implementation
- **Network Flexibility**: Support for mainnet, testnet, and regtest
## Supported Networks
This package works with Bitcoin networks:
- **Bitcoin Mainnet** (`"bitcoin"`)
- **Bitcoin Testnet** (`"testnet"`)
- **Bitcoin Regtest** (`"regtest"`)
### Electrum Server Configuration
**Important**: While the package defaults to `electrum.blockstream.info:50001` for convenience, **we strongly recommend configuring your own Electrum server** for production use.
#### Recommended Approach:
**For Production:**
- Set up your own Fulcrum server for optimal performance and reliability
- Use recent Fulcrum versions that support pagination for high-transaction addresses
**For Development/Testing:**
- `fulcrum.frznode.com:50001` - Generally faster than default
- `electrum.blockstream.info:50001` - Default fallback
## Next Steps
Get started with WDK in a Node.js environment
Get started with WDK's Bitcoin Wallet configuration
Get started with WDK's Bitcoin Wallet API
Get started with WDK's Bitcoin Wallet usage
***
### Need Help?
***
## Wallet BTC API Reference
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/api-reference
Description: Complete API documentation for @tetherto/wdk-wallet-btc
## Table of Contents
| Class | Description | Methods |
|-------|-------------|---------|
| [WalletManagerBtc](#walletmanagerbtc) | Main class for managing Bitcoin wallets. Extends `WalletManager` from `@tetherto/wdk-wallet`. | [Constructor](#constructor), [Methods](#methods) |
| [WalletAccountBtc](#walletaccountbtc) | Individual Bitcoin wallet account implementation. Implements `IWalletAccount`. | [Constructor](#constructor-1), [Methods](#methods-1), [Properties](#properties) |
| [WalletAccountReadOnlyBtc](#walletaccountreadonlybtc) | Read-only Bitcoin wallet account. Extends `WalletAccountReadOnly` from `@tetherto/wdk-wallet`. | [Constructor](#constructor-2), [Methods](#methods-2) |
| [ElectrumTcp](#electrumtcp) | Standard TCP Electrum client. Implements `IBtcClient`. | [Constructor](#constructor-3) |
| [ElectrumTls](#electrumtls) | TLS Electrum client. Implements `IBtcClient`. | [Constructor](#constructor-4) |
| [ElectrumSsl](#electrumssl) | SSL Electrum client. Implements `IBtcClient`. | [Constructor](#constructor-5) |
| [ElectrumWs](#electrumws) | WebSocket Electrum client for browser environments. Implements `IBtcClient`. | [Constructor](#constructor-6), [Methods](#methods-3) |
## WalletManagerBtc
The main class for managing Bitcoin wallets.
Extends `WalletManager` from `@tetherto/wdk-wallet`.
#### Constructor
```javascript
new WalletManagerBtc(seed, config)
```
**Parameters:**
- `seed` (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
- `config` (BtcWalletConfig, optional): Configuration object
- `client` (`IBtcClient | BtcClientDescriptor | Array`, optional): Bitcoin client, descriptor, or ordered failover list
- `network` (string, optional): "bitcoin", "testnet", or "regtest" (default: "bitcoin")
- `bip` (number, optional): BIP address type - 44 (legacy) or 84 (native SegWit) (default: 84)
- `retries` (number, optional): Additional retry attempts when `client` is an array
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `getAccount(index)` | Returns a wallet account at the specified index | `Promise` |
| `getAccountByPath(path)` | Returns a wallet account at the specified derivation path | `Promise` |
| `getFeeRates()` | Returns current fee rates for transactions | `Promise<{normal: bigint, fast: bigint}>` |
| `dispose()` | Disposes all wallet accounts, clearing private keys from memory and closing internal Electrum connections | `void` |
##### `getAccount(index)`
Returns a wallet account at the specified index using BIP-84 (default) or BIP-44 derivation.
**Parameters:**
- `index` (number, optional): The index of the account to get (default: 0)
**Returns:** `Promise` - The wallet account
**Example:**
```javascript
// Returns the account with derivation path:
// For mainnet (bitcoin): m/84'/0'/0'/0/1
// For testnet or regtest: m/84'/1'/0'/0/1
const account = await wallet.getAccount(1)
```
##### `getAccountByPath(path)`
Returns a wallet account at the specified derivation path.
**Parameters:**
- `path` (string): The derivation path (e.g., "0'/0/0")
**Returns:** `Promise` - The wallet account
**Example:**
```javascript
// Returns the account with derivation path:
// For mainnet (bitcoin): m/84'/0'/0'/0/1
// For testnet or regtest: m/84'/1'/0'/0/1
const account = await wallet.getAccountByPath("0'/0/1")
```
##### `getFeeRates()`
Returns current fee rates from mempool.space API.
**Returns:** `Promise<{normal: bigint, fast: bigint}>` - Object containing fee rates in sat/vB
- `normal`: Standard fee rate for confirmation within ~1 hour
- `fast`: Higher fee rate for faster confirmation
**Example:**
```javascript
const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'sat/vB')
console.log('Fast fee rate:', feeRates.fast, 'sat/vB')
```
##### `dispose()`
Disposes all wallet accounts, clears sensitive data from memory, and closes internal Electrum connections.
**Returns:** `void`
**Example:**
```javascript
wallet.dispose()
```
## WalletAccountBtc
Represents an individual Bitcoin wallet account. Extends `WalletAccountReadOnlyBtc` and implements `IWalletAccount` from `@tetherto/wdk-wallet`.
#### Constructor
```javascript
new WalletAccountBtc(seed, path, config)
```
**Parameters:**
- `seed` (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
- `path` (string): Derivation path suffix (e.g., "0'/0/0")
- `config` (BtcWalletConfig, optional): Configuration object
- `client` (`IBtcClient | BtcClientDescriptor | Array`, optional): Bitcoin client, descriptor, or ordered failover list
- `network` (string, optional): "bitcoin", "testnet", or "regtest" (default: "bitcoin")
- `bip` (number, optional): BIP address type - 44 (legacy) or 84 (native SegWit) (default: 84)
- `retries` (number, optional): Additional retry attempts when `client` is an array
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `getAddress()` | Returns the account's Bitcoin address | `Promise` |
| `getBalance()` | Returns the total account balance in satoshis, including unconfirmed funds when present | `Promise` |
| `sendTransaction(options, timeoutMs?)` | Sends a Bitcoin transaction and optionally polls until spent inputs disappear from unspent outputs | `Promise<{hash: string, fee: bigint}>` |
| `signTransaction(options)` | Signs a Bitcoin transaction without broadcasting it | `Promise` |
| `quoteSendTransaction(options)` | Estimates the fee for a transaction | `Promise<{fee: bigint}>` |
| `getTransfers(options?)` | Returns the account's transfer history | `Promise` |
| `getTransactionReceipt(hash)` | Returns a transaction's receipt | `Promise` |
| `getMaxSpendable()` | Returns the maximum spendable amount | `Promise` |
| `sign(message)` | Signs a message with the account's private key | `Promise` |
| `verify(message, signature)` | Verifies a message signature | `Promise` |
| `toReadOnlyAccount()` | Creates a read-only version of this account | `Promise` |
| `dispose()` | Disposes the wallet account, clearing private keys from memory | `void` |
##### `getAddress()`
Returns the account's Bitcoin address (Native SegWit bech32 by default, or legacy if using BIP-44).
**Returns:** `Promise` - The Bitcoin address
**Example:**
```javascript
const address = await account.getAddress()
console.log('Address:', address) // bc1q... (BIP-84) or 1... (BIP-44)
```
##### `getBalance()`
Returns the account's total balance in satoshis, including unconfirmed funds when present.
**Returns:** `Promise` - Balance in satoshis
**Example:**
```javascript
const balance = await account.getBalance()
console.log('Balance:', balance, 'satoshis')
```
##### `sendTransaction(options, timeoutMs?)`
Sends a Bitcoin transaction to a single recipient and optionally polls after broadcast until spent inputs disappear from the unspent-output set.
**Parameters:**
- `options` (BtcTransaction): Transaction options
- `to` (string): Recipient's Bitcoin address
- `value` (number | bigint): Amount in satoshis
- `feeRate` (number | bigint, optional): Fee rate in sat/vB. If provided, overrides the fee rate estimated from the blockchain.
- `confirmationTarget` (number, optional): Target blocks for confirmation (default: 1)
- `timeoutMs` (number, optional): Maximum milliseconds to poll after broadcast before returning (default: 10000)
**Returns:** `Promise<{hash: string, fee: bigint}>`
- `hash`: Transaction hash
- `fee`: Transaction fee in satoshis
**Example:**
```javascript
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 50000n
})
console.log('Transaction hash:', result.hash)
console.log('Fee:', result.fee, 'satoshis')
```
##### `signTransaction(options)`
Signs a Bitcoin transaction and returns the signed raw transaction as a hex string. This method does not broadcast the transaction.
**Parameters:**
- `options` (BtcTransaction): Transaction options
- `to` (string): Recipient's Bitcoin address
- `value` (number | bigint): Amount in satoshis
- `feeRate` (number | bigint, optional): Fee rate in sat/vB. If provided, overrides the fee rate estimated from the blockchain.
- `confirmationTarget` (number, optional): Target blocks for confirmation (default: 1)
**Returns:** `Promise` - Signed raw transaction hex string
**Example:**
```javascript
const signedTransaction = await account.signTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 50000n,
feeRate: 10n
})
console.log('Signed transaction:', signedTransaction)
```
##### `quoteSendTransaction(options)`
Estimates the fee for a transaction without broadcasting it.
**Parameters:**
- `options` (BtcTransaction): Same as sendTransaction options
- `to` (string): Recipient's Bitcoin address
- `value` (number | bigint): Amount in satoshis
- `feeRate` (number | bigint, optional): Fee rate in sat/vB. If provided, overrides the fee rate estimated from the blockchain.
- `confirmationTarget` (number, optional): Target blocks for confirmation (default: 1)
**Returns:** `Promise<{fee: bigint}>`
- `fee`: Estimated transaction fee in satoshis
**Example:**
```javascript
const quote = await account.quoteSendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 50000n
})
console.log('Estimated fee:', quote.fee, 'satoshis')
```
##### `getTransfers(options?)`
Returns the account's transfer history with detailed transaction information.
**Parameters:**
- `options` (object, optional): Filter options
- `direction` (string, optional): 'incoming', 'outgoing', or 'all' (default: 'all')
- `limit` (number, optional): Maximum number of transfers (default: 10)
- `skip` (number, optional): Number of transfers to skip (default: 0)
**Returns:** `Promise` - Array of transfer objects
- `txid`: Transaction ID
- `address`: Account's own address
- `vout`: Output index in the transaction
- `height`: Block height (0 if unconfirmed)
- `value`: Transfer value in satoshis (bigint)
- `direction`: 'incoming' or 'outgoing'
- `fee`: Transaction fee in satoshis (bigint, for outgoing transfers)
- `recipient`: Receiving address (for outgoing transfers)
**Example:**
```javascript
const transfers = await account.getTransfers({
direction: 'incoming',
limit: 5
})
console.log('Recent incoming transfers:', transfers)
```
##### `getTransactionReceipt(hash)`
Returns a transaction's receipt if it has been included in a block.
**Parameters:**
- `hash` (string): The transaction hash (64 hex characters)
**Returns:** `Promise` - The receipt, or null if the transaction has not been included in a block yet.
**Example:**
```javascript
const receipt = await account.getTransactionReceipt('abc123...')
if (receipt) {
console.log('Transaction confirmed')
}
```
##### `getMaxSpendable()`
Returns the maximum spendable amount that can be sent in a single transaction. The maximum spendable amount can differ from the wallet's total balance for several reasons:
- **Transaction fees**: Fees are subtracted from the total balance
- **Uneconomic UTXOs**: Small UTXOs where the fee to spend them exceeds their value are excluded
- **UTXO limit**: A transaction can include at most 200 inputs. Wallets with more UTXOs cannot spend their full balance in a single transaction.
- **Dust limit**: Outputs below the dust threshold (294 sats for SegWit, 546 sats for legacy) cannot be created
**Returns:** `Promise` - Maximum spendable result
- `amount`: Maximum spendable amount in satoshis (bigint)
- `fee`: Estimated network fee in satoshis (bigint)
- `changeValue`: Estimated change value in satoshis (bigint)
**Example:**
```javascript
const { amount, fee } = await account.getMaxSpendable()
console.log('Max spendable:', amount, 'satoshis')
console.log('Estimated fee:', fee, 'satoshis')
```
##### `sign(message)`
Signs a message using the account's private key.
**Parameters:**
- `message` (string): Message to sign
**Returns:** `Promise` - Signature as base64 string
**Example:**
```javascript
const signature = await account.sign('Hello Bitcoin!')
console.log('Signature:', signature)
```
##### `verify(message, signature)`
Verifies a message signature using the account's public key.
**Parameters:**
- `message` (string): Original message
- `signature` (string): Signature as base64 string
**Returns:** `Promise` - True if signature is valid
**Example:**
```javascript
const isValid = await account.verify('Hello Bitcoin!', signature)
console.log('Signature valid:', isValid)
```
##### `toReadOnlyAccount()`
Creates a read-only version of this account that can query balances and transactions but cannot sign or send transactions.
**Returns:** `Promise` - Read-only account instance
**Example:**
```javascript
const readOnlyAccount = await account.toReadOnlyAccount()
const balance = await readOnlyAccount.getBalance()
```
##### `dispose()`
Disposes the wallet account, securely erasing the private key from memory and closing the Electrum connection.
**Returns:** `void`
**Example:**
```javascript
account.dispose()
// Private key is now securely wiped from memory
```
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `index` | `number` | The derivation path's index of this account |
| `path` | `string` | The full derivation path of this account |
| `keyPair` | `KeyPair` | The account's public and private key pair. Treat the returned `Uint8Array` values as read-only views because mutations affect the account's internal key material. |
## WalletAccountReadOnlyBtc
Represents a read-only Bitcoin wallet account. Extends `WalletAccountReadOnly` from `@tetherto/wdk-wallet`.
#### Constructor
```javascript
new WalletAccountReadOnlyBtc(address, config)
```
**Parameters:**
- `address` (string): The account's Bitcoin address
- `config` (object, optional): Configuration object (same as BtcWalletConfig but without `bip`)
- `client` (`IBtcClient | BtcClientDescriptor | Array`, optional): Bitcoin client, descriptor, or ordered failover list
- `network` (string, optional): "bitcoin", "testnet", or "regtest" (default: "bitcoin")
- `retries` (number, optional): Additional retry attempts when `client` is an array
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `getAddress()` | Returns the account's Bitcoin address | `Promise` |
| `getBalance()` | Returns the total account balance in satoshis, including unconfirmed funds when present | `Promise` |
| `quoteSendTransaction(options)` | Estimates the fee for a transaction | `Promise<{fee: bigint}>` |
| `getTransactionReceipt(hash)` | Returns a transaction's receipt | `Promise` |
| `getMaxSpendable()` | Returns the maximum spendable amount | `Promise` |
| `verify(message, signature)` | Verifies a message signature | `Promise` |
| `dispose()` | Closes any internal Electrum connection | `void` |
##### `getAddress()`
Returns the account's Bitcoin address.
**Returns:** `Promise` - The Bitcoin address
**Example:**
```javascript
const address = await readOnlyAccount.getAddress()
console.log('Address:', address)
```
##### `getBalance()`
Returns the account's confirmed balance in satoshis.
**Returns:** `Promise` - Balance in satoshis
**Example:**
```javascript
const balance = await readOnlyAccount.getBalance()
console.log('Balance:', balance, 'satoshis')
```
##### `quoteSendTransaction(options)`
Estimates the fee for a transaction without broadcasting it.
**Parameters:**
- `options` (BtcTransaction): Transaction options
- `to` (string): Recipient's Bitcoin address
- `value` (number | bigint): Amount in satoshis
- `feeRate` (number | bigint, optional): Fee rate in sat/vB
- `confirmationTarget` (number, optional): Target blocks for confirmation (default: 1)
**Returns:** `Promise<{fee: bigint}>` - Estimated fee in satoshis
**Example:**
```javascript
const quote = await readOnlyAccount.quoteSendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 50000n
})
console.log('Estimated fee:', quote.fee, 'satoshis')
```
##### `getTransactionReceipt(hash)`
Returns a transaction's receipt if it has been included in a block.
**Parameters:**
- `hash` (string): The transaction hash
**Returns:** `Promise` - The receipt, or null if not yet included
**Example:**
```javascript
const receipt = await readOnlyAccount.getTransactionReceipt('abc123...')
if (receipt) {
console.log('Transaction confirmed')
}
```
##### `getMaxSpendable()`
Returns the maximum spendable amount that can be sent in a single transaction.
**Returns:** `Promise` - Maximum spendable result
- `amount`: Maximum spendable amount in satoshis (bigint)
- `fee`: Estimated network fee in satoshis (bigint)
- `changeValue`: Estimated change value in satoshis (bigint)
**Example:**
```javascript
const { amount, fee } = await readOnlyAccount.getMaxSpendable()
console.log('Max spendable:', amount, 'satoshis')
```
##### `verify(message, signature)`
Verifies a message signature using the account's public key.
**Parameters:**
- `message` (string): Original message
- `signature` (string): Signature as base64 string
**Returns:** `Promise` - True if signature is valid
**Example:**
```javascript
const isValid = await readOnlyAccount.verify('Hello Bitcoin!', signature)
console.log('Signature valid:', isValid)
```
##### `dispose()`
Closes any internal Electrum connection owned by this account. If a [`client`](/sdk/wallet-modules/wallet-btc/configuration#client) was provided via config, the connection is left open (the caller manages its lifecycle).
**Returns:** `void`
**Example:**
```javascript
readOnlyAccount.dispose()
```
## ElectrumTcp
Electrum client using TCP transport. Standard for command-line and server-side environments.
Implements `IBtcClient`.
#### Constructor
```javascript
new ElectrumTcp(config)
```
**Parameters:**
- `config` (`Omit`): Configuration options
- `host` (string): Electrum server hostname
- `port` (number): Electrum server port
## ElectrumTls
Electrum client using TLS transport.
Implements `IBtcClient`.
#### Constructor
```javascript
new ElectrumTls(config)
```
**Parameters:**
- `config` (`Omit`): Configuration options
- `host` (string): Electrum server hostname
- `port` (number): Electrum server port
## ElectrumSsl
Electrum client using SSL transport.
Implements `IBtcClient`.
#### Constructor
```javascript
new ElectrumSsl(config)
```
**Parameters:**
- `config` (`Omit`): Configuration options
- `host` (string): Electrum server hostname
- `port` (number): Electrum server port
## ElectrumWs
Electrum client using WebSocket transport. Compatible with browser environments where TCP sockets are not available.
Implements `IBtcClient`.
#### Constructor
```javascript
new ElectrumWs(config)
```
**Parameters:**
- `config` (ElectrumWsConfig): Configuration options
- `url` (string): The WebSocket URL (e.g., 'wss://electrum.example.com:50004')
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `connect()` | Establishes connection to Electrum server | `Promise` |
| `close()` | Closes the connection | `Promise` |
| `reconnect()` | Recreates the underlying socket and reinitializes the session | `Promise` |
| `getBalance(scripthash)` | Returns balance for a script hash | `Promise` |
| `listUnspent(scripthash)` | Returns UTXOs for a script hash | `Promise` |
| `getHistory(scripthash)` | Returns transaction history | `Promise` |
| `getTransaction(txHash)` | Returns raw transaction hex | `Promise` |
| `broadcast(rawTx)` | Broadcasts raw transaction | `Promise` |
| `estimateFee(blocks)` | Returns estimated fee rate | `Promise` |
## Types
### BtcTransaction
```typescript
interface BtcTransaction {
to: string // The transaction's recipient
value: number | bigint // The amount of bitcoins to send to the recipient (in satoshis)
confirmationTarget?: number // Optional confirmation target in blocks (default: 1)
feeRate?: number | bigint // Optional fee rate in satoshis per virtual byte
}
```
### TransactionResult
```typescript
interface TransactionResult {
hash: string // Transaction hash/ID
fee: bigint // Transaction fee in satoshis
}
```
### FeeRates
```typescript
interface FeeRates {
normal: bigint // Standard fee rate (sat/vB) for ~1 hour confirmation
fast: bigint // Higher fee rate (sat/vB) for faster confirmation
}
```
### BtcTransfer
```typescript
interface BtcTransfer {
txid: string // The transaction's ID
address: string // The user's own address
vout: number // The index of the output in the transaction
height: number // The block height (if unconfirmed, 0)
value: bigint // The value of the transfer (in satoshis)
direction: 'incoming' | 'outgoing' // The direction of the transfer
fee?: bigint // The fee paid for the full transaction (in satoshis)
recipient?: string // The receiving address for outgoing transfers
}
```
### BtcMaxSpendableResult
```typescript
interface BtcMaxSpendableResult {
amount: bigint // The maximum spendable amount in satoshis
fee: bigint // The estimated network fee in satoshis
changeValue: bigint // The estimated change value in satoshis
}
```
### KeyPair
```typescript
interface KeyPair {
publicKey: Uint8Array // Public key bytes. Treat as read-only.
privateKey: Uint8Array | null // Private key bytes. Treat as read-only. Null after dispose.
}
```
### BtcWalletConfig
```typescript
interface BtcWalletConfig {
client?: IBtcClient | BtcClientDescriptor | Array // Client, descriptor, or failover list
network?: 'bitcoin' | 'testnet' | 'regtest' // Network to use (default: "bitcoin")
bip?: 44 | 84 // BIP address type - 44 (legacy) or 84 (native SegWit) (default: 84)
retries?: number // Additional retry attempts for client arrays
}
```
### BtcClientDescriptor
```typescript
type BtcClientDescriptor =
| { type: 'electrum'; clientConfig: MempoolElectrumConfig }
| { type: 'electrum-ws'; clientConfig: ElectrumWsConfig }
| { type: 'blockbook-http'; clientConfig: BlockbookClientConfig }
```
### IBtcClient
Interface for implementing custom Bitcoin network clients.
```typescript
interface IBtcClient {
connect(): Promise
close(): Promise
reconnect(): Promise
getBalance(scripthash: string): Promise
listUnspent(scripthash: string): Promise
getHistory(scripthash: string): Promise
getTransaction(txHash: string): Promise
broadcast(rawTx: string): Promise
estimateFee(blocks: number): Promise
}
```
### ElectrumBalance
```typescript
interface ElectrumBalance {
confirmed: number // Confirmed balance in satoshis
unconfirmed?: number // Unconfirmed balance in satoshis
}
```
### ElectrumUtxo
```typescript
interface ElectrumUtxo {
tx_hash: string // The transaction hash containing this UTXO
tx_pos: number // The output index within the transaction
value: number // The UTXO value in satoshis
height?: number // The block height (0 if unconfirmed)
}
```
### ElectrumHistoryItem
```typescript
interface ElectrumHistoryItem {
tx_hash: string // The transaction hash
height: number // The block height (0 or negative if unconfirmed)
}
```
### MempoolElectrumConfig
```typescript
interface MempoolElectrumConfig {
host: string // Electrum server hostname
port: number // Electrum server port
protocol?: 'tcp' | 'ssl' | 'tls' // Transport protocol (default: 'tcp')
maxRetry?: number // Maximum reconnection attempts (default: 2)
retryPeriod?: number // Delay between reconnection attempts in ms (default: 1000)
pingPeriod?: number // Delay between keep-alive pings in ms (default: 120000)
callback?: (err: Error | null) => void // Called when all retries are exhausted
}
```
Get started with WDK in a Node.js environment
Build mobile wallets with React Native Expo
Get started with WDK's Bitcoin Wallet Usage
Get started with WDK's Bitcoin Wallet Configuration
***
### Need Help?
***
## Configuration
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/configuration
Description: Configuration options and settings for @tetherto/wdk-wallet-btc
## Wallet Configuration
```javascript
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
const wallet = new WalletManagerBtc(seedPhrase, {
client: {
type: 'electrum',
clientConfig: {
host: 'electrum.blockstream.info',
port: 50002,
protocol: 'tls'
}
},
network: 'bitcoin'
})
```
## Account Creation
```javascript
// WalletAccountBtc is created by the WalletManagerBtc
// It takes the same configuration as the manager
const account = await wallet.getAccount(0) // Get account at index 0
const customAccount = await wallet.getAccountByPath("0'/0/5") // Custom path
```
## Configuration Options
### Client
The `client` option specifies how the wallet connects to Bitcoin network data. It accepts a pre-built `IBtcClient`, a client descriptor, or an ordered array of clients and descriptors for automatic failover.
**Type:** `IBtcClient | BtcClientDescriptor | Array`
**Default:** Uses an Electrum descriptor for `electrum.blockstream.info:50001`.
**Example:**
```javascript
const config = {
client: {
type: 'electrum',
clientConfig: {
host: 'fulcrum.frznode.com',
port: 50002,
protocol: 'tls'
}
}
}
```
`BtcClientDescriptor` supports:
| Type | Description |
|------|-------------|
| `electrum` | Creates a TCP, TLS, or SSL Electrum client from `clientConfig`. |
| `electrum-ws` | Creates a WebSocket Electrum client from `clientConfig`. |
| `blockbook-http` | Creates a stateless Blockbook HTTP client from `clientConfig`. |
#### Built-in Transport Clients
The package still exports built-in transport clients when you want to instantiate the client yourself:
```javascript
import {
ElectrumTcp, // TCP transport (default, port 50001)
ElectrumTls, // TLS transport (port 50002)
ElectrumSsl, // SSL transport (port 50002)
ElectrumWs // WebSocket transport
} from '@tetherto/wdk-wallet-btc'
// TCP (default)
const tcpClient = new ElectrumTcp({ host: 'electrum.blockstream.info', port: 50001 })
// TLS
const tlsClient = new ElectrumTls({ host: 'electrum.blockstream.info', port: 50002 })
// SSL
const sslClient = new ElectrumSsl({ host: 'electrum.blockstream.info', port: 50002 })
// WebSocket
const wsClient = new ElectrumWs({ url: 'wss://electrum.example.com:50004' })
```
#### Custom Bitcoin Client
You can implement your own client by implementing `IBtcClient`:
```typescript
import { IBtcClient } from '@tetherto/wdk-wallet-btc'
class MyCustomBitcoinClient implements IBtcClient {
// Implement the required interface methods
}
const wallet = new WalletManagerBtc(seedPhrase, {
client: new MyCustomBitcoinClient(params),
network: 'bitcoin'
})
```
#### Client Failover
Pass an ordered `client` array to retry connection failures against fallback clients. Set `retries` to control how many additional attempts can happen after the first failed call.
```javascript
const wallet = new WalletManagerBtc(seedPhrase, {
client: [
{
type: 'electrum',
clientConfig: {
host: 'primary-electrum.example',
port: 50002,
protocol: 'tls'
}
},
{
type: 'electrum',
clientConfig: {
host: 'secondary-electrum.example',
port: 50002,
protocol: 'tls'
}
}
],
retries: 1,
network: 'bitcoin'
})
```
### Host
The `host` value belongs inside an `electrum` descriptor's `clientConfig` or an `Electrum*` client constructor. It is not a top-level wallet config option.
**Type:** `string`
**Default:** `"electrum.blockstream.info"`
**Recommended:** Configure your own Electrum server for production use. Public servers can be 10-300x slower and may fail for addresses with many transactions.
**Example:**
```javascript
const config = {
client: {
type: 'electrum',
clientConfig: {
host: 'fulcrum.frznode.com',
port: 50002,
protocol: 'tls'
}
}
}
```
### Port
The `port` value belongs inside an `electrum` descriptor's `clientConfig` or an `Electrum*` client constructor. It is not a top-level wallet config option.
**Type:** `number`
**Default:** `50001`
**Common Ports:**
- `50001` - TCP (default)
- `50002` - TLS/SSL
- `50003` - WebSocket
**Example:**
```javascript
const config = {
client: {
type: 'electrum',
clientConfig: {
host: 'electrum.blockstream.info',
port: 50002,
protocol: 'tls'
}
}
}
```
### Protocol
The `protocol` value belongs inside an `electrum` descriptor's `clientConfig`. It is not a top-level wallet config option.
**Type:** `string`
**Values:**
- `"tcp"` - TCP transport (default)
- `"tls"` - TLS transport
- `"ssl"` - SSL transport
**Default:** `"tcp"`
**Example:**
```javascript
const config = {
client: {
type: 'electrum',
clientConfig: {
host: 'electrum.blockstream.info',
port: 50002,
protocol: 'tls'
}
}
}
```
### Retries
The `retries` option controls failover retry attempts when `client` is an array.
**Type:** `number` (optional)
**Example:**
```javascript
const config = {
client: [
{ type: 'electrum', clientConfig: { host: 'primary.example', port: 50002, protocol: 'tls' } },
{ type: 'electrum', clientConfig: { host: 'secondary.example', port: 50002, protocol: 'tls' } }
],
retries: 2
}
```
### Network
The `network` option specifies which Bitcoin network to use.
**Type:** `string`
**Values:**
- `"bitcoin"` - Bitcoin [mainnet](/resources/concepts#mainnet) (production)
- `"testnet"` - Bitcoin [testnet](/resources/concepts#testnet) (development)
- `"regtest"` - Bitcoin [regtest](/resources/concepts#regtest) (local testing)
**Default:** `"bitcoin"`
**Example:**
```javascript
const config = {
network: 'testnet' // Use testnet for development
}
```
### BIP
The `bip` option specifies the address type derivation standard to use.
**Type:** `number`
**Values:**
- `84` - [BIP-84](/resources/concepts#bip-84-native-segwit) (P2WPKH / Native SegWit) - addresses start with `bc1` (mainnet) or `tb1` (testnet)
- `44` - [BIP-44](/resources/concepts#bip-44-multi-account-hierarchy) (P2PKH / Legacy) - addresses start with `1` (mainnet) or `m`/`n` (testnet)
**Default:** `84`
**Example:**
```javascript
// Use legacy addresses
const config = {
bip: 44
}
```
## Electrum Server Configuration
**Important**: While the package defaults to `electrum.blockstream.info:50001` for convenience, **we strongly recommend configuring your own Electrum server** for production use.
### Recommended Approach
**For Production:**
- Set up your own Fulcrum server for optimal performance and reliability
- Use recent Fulcrum versions that support pagination for high-transaction addresses
**For Development/Testing:**
- `fulcrum.frznode.com:50001` - Generally faster than default
- `electrum.blockstream.info:50001` - Default fallback
### Configuration Examples
```javascript
import { ElectrumTcp, ElectrumTls } from '@tetherto/wdk-wallet-btc'
// Production with custom Fulcrum server
const productionClient = new ElectrumTls({
host: 'your-fulcrum-server.com',
port: 50002
})
const productionWallet = new WalletManagerBtc(seedPhrase, {
client: productionClient,
network: 'bitcoin'
})
// Development with alternative public server
const developmentClient = new ElectrumTcp({
host: 'fulcrum.frznode.com',
port: 50001
})
const developmentWallet = new WalletManagerBtc(seedPhrase, {
client: developmentClient,
network: 'bitcoin'
})
```
### Network-Specific Configuration
#### Bitcoin Mainnet
```javascript
import { ElectrumTcp } from '@tetherto/wdk-wallet-btc'
const client = new ElectrumTcp({
host: 'electrum.blockstream.info', // Or your own server
port: 50001
})
const wallet = new WalletManagerBtc(seedPhrase, {
client,
network: 'bitcoin'
})
```
#### Bitcoin Testnet
```javascript
import { ElectrumTcp } from '@tetherto/wdk-wallet-btc'
const client = new ElectrumTcp({
host: 'testnet.hsmiths.com', // Example testnet server
port: 53011
})
const wallet = new WalletManagerBtc(seedPhrase, {
client,
network: 'testnet'
})
```
#### Bitcoin Regtest
```javascript
import { ElectrumTcp } from '@tetherto/wdk-wallet-btc'
const client = new ElectrumTcp({
host: 'localhost', // Local regtest node
port: 50001
})
const wallet = new WalletManagerBtc(seedPhrase, {
client,
network: 'regtest'
})
```
## Derivation Paths
Bitcoin wallet addresses are derived using BIP-32 hierarchical deterministic paths:
### BIP-84 (Native SegWit) - Default
- `m/84'/0'/0'/0/0` for mainnet account 0, address 0
- `m/84'/1'/0'/0/0` for testnet/regtest account 0, address 0
Addresses start with `bc1` (mainnet) or `tb1` (testnet).
### BIP-44 (Legacy)
- `m/44'/0'/0'/0/0` for mainnet account 0, address 0
- `m/44'/1'/0'/0/0` for testnet/regtest account 0, address 0
Addresses start with `1` (mainnet) or `m`/`n` (testnet).
**Default Derivation Path Change in v1.0.0-beta.4+**
The default derivation path was updated in v1.0.0-beta.4 to use BIP-84 (Native SegWit) instead of BIP-44 (Legacy):
- **Previous path** (up to v1.0.0-beta.3): `m/44'/0'/0'/0/{index}` (Legacy addresses)
- **Current path** (v1.0.0-beta.4+): `m/84'/0'/0'/0/{index}` (Native SegWit addresses)
If you're upgrading from an earlier version, existing wallets created with the old path will generate different addresses. Make sure to migrate any existing wallets or use the old path explicitly if needed for compatibility.
Use [`getAccountByPath`](/sdk/wallet-modules/wallet-btc/api-reference#getaccountbypathpath) to supply an explicit derivation path when importing or recreating legacy wallets.
## Complete Configuration Example
```javascript
import WalletManagerBtc, { ElectrumTls } from '@tetherto/wdk-wallet-btc'
// Create Electrum client
const client = new ElectrumTls({
host: 'your-electrum-server.com', // Replace with your server
port: 50002
})
// Create wallet manager with configuration
const wallet = new WalletManagerBtc(seedPhrase, {
client,
network: 'bitcoin',
bip: 84 // Native SegWit (default)
})
// Get accounts (inherit configuration from manager)
const account0 = await wallet.getAccount(0)
const account1 = await wallet.getAccount(1)
const customAccount = await wallet.getAccountByPath("0'/0/5")
// Clean up when done
wallet.dispose()
```
## Performance Considerations
**Electrum Server Performance:**
- Public servers like Blockstream's can be significantly slower
- Addresses with many transactions may cause timeouts
- Custom Fulcrum servers provide better performance and reliability
- Consider server location and network latency
**Configuration Tips:**
- Use `fulcrum.frznode.com` for better development performance
- Set up your own Fulcrum server for production
- Monitor connection stability and implement retry logic
- Consider using multiple backup servers
Get started with WDK in a Node.js environment
Build mobile wallets with React Native Expo
Get started with WDK's BTC Wallet Usage
Get started with WDK's BTC Wallet API
***
### Need Help?
***
## Check Balances
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/check-balances
Description: Query native BTC balances for owned and read-only accounts.
This guide explains how to check [native BTC balances](#native-btc-balance), [maximum spendable amounts](#maximum-spendable-amount), and [read-only account balances](#read-only-account-balances).
## Native BTC Balance
You can retrieve the confirmed balance in satoshis using [`account.getBalance()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get Native BTC Balance"
const balance = await account.getBalance()
console.log('Total balance:', balance, 'satoshis')
```
On Bitcoin, balances are expressed in satoshis (1 BTC = 100,000,000 satoshis). The [`getBalance()`](/sdk/wallet-modules/wallet-btc/api-reference) method returns the total balance, including unconfirmed funds when present.
## Maximum Spendable Amount
You can check the maximum amount available to send in a single transaction using [`account.getMaxSpendable()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get Maximum Spendable"
const { amount, fee } = await account.getMaxSpendable()
console.log('Max spendable:', amount, 'satoshis')
console.log('Estimated fee:', fee, 'satoshis')
```
The maximum spendable amount can differ from the total balance due to transaction fees, uneconomic UTXOs, the 200-input limit per transaction, and the dust threshold (294 satoshis for SegWit, 546 for legacy).
## Read-Only Account Balances
You can check balances for any Bitcoin address without a seed phrase using [`WalletAccountReadOnlyBtc`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Create Read-Only Account"
import { WalletAccountReadOnlyBtc, ElectrumTcp } from '@tetherto/wdk-wallet-btc'
const client = new ElectrumTcp({
host: 'electrum.blockstream.info',
port: 50001
})
const readOnlyAccount = new WalletAccountReadOnlyBtc('bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', {
client,
network: 'bitcoin'
})
```
You can retrieve the balance from a read-only account using [`readOnlyAccount.getBalance()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Read-Only Balance"
const balance = await readOnlyAccount.getBalance()
console.log('Read-only account balance:', balance, 'satoshis')
```
Read-only accounts follow the same balance behavior as owned accounts: [`getBalance()`](/sdk/wallet-modules/wallet-btc/api-reference) includes unconfirmed funds when present.
You can also create a read-only account from an existing owned account using [`account.toReadOnlyAccount()`](/sdk/wallet-modules/wallet-btc/api-reference).
## Next Steps
With balance checks in place, learn how to [send BTC](/sdk/wallet-modules/wallet-btc/guides/send-transactions).
***
## Get Started
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/get-started
Description: Install and create your first Bitcoin wallet.
This guide explains how to [install the package](#1-install-the-package), [create a wallet](#2-create-a-wallet), [get your first account](#3-get-your-first-account), and optionally [convert to read-only](#4-optional-convert-to-read-only).
## 1. Install the Package
### Prerequisites
* **[Node.js](https://nodejs.org/)**: version 18 or higher.
* **[npm](https://www.npmjs.com/)**: usually comes with Node.js.
```bash title="Install @tetherto/wdk-wallet-btc"
npm install @tetherto/wdk-wallet-btc
```
## 2. Create a Wallet
You can create a new wallet instance using the [`WalletManagerBtc`](/sdk/wallet-modules/wallet-btc/api-reference) constructor with a BIP-39 seed phrase and an Electrum client:
```javascript title="Create Bitcoin Wallet"
import WalletManagerBtc, { ElectrumTcp } from '@tetherto/wdk-wallet-btc'
const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const client = new ElectrumTcp({
host: 'electrum.blockstream.info',
port: 50001
})
const wallet = new WalletManagerBtc(seedPhrase, {
client,
network: 'bitcoin'
})
```
**Secure the Seed Phrase:** You must securely store this seed phrase immediately. If it is lost, the user will permanently lose access to their funds.
**Electrum Server Performance:** Public servers like Blockstream's can be 10-300x slower than private servers. For production use, set up your own [Fulcrum](https://github.com/cculianu/Fulcrum) server. For development, consider `fulcrum.frznode.com` as a faster alternative.
## 3. Get Your First Account
You can retrieve an account at a given index using [`wallet.getAccount()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get Account"
const account = await wallet.getAccount(0)
const address = await account.getAddress()
console.log('Wallet address:', address)
```
This implementation uses BIP-84 derivation paths and generates Native SegWit (bech32) addresses by default. Addresses start with `bc1` on mainnet. Set `bip: 44` in config for legacy (P2PKH) addresses.
## 4. (optional) Convert to Read-Only
You can convert an owned account to a read-only account using [`account.toReadOnlyAccount()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Convert to Read-Only"
const readOnlyAccount = await account.toReadOnlyAccount()
```
## Next Steps
With your wallet ready, learn how to [manage multiple accounts](/sdk/wallet-modules/wallet-btc/guides/manage-accounts).
***
## Transaction History
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/get-transaction-history
Description: Retrieve and filter Bitcoin transfer history.
This guide explains how to [retrieve all transfers](#retrieve-all-transfers), [filter by direction](#filter-by-direction), [paginate results](#paginate-results), and [check transaction receipts](#check-transaction-receipts).
## Retrieve All Transfers
You can retrieve the account's transfer history using [`account.getTransfers()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get All Transfers"
const transfers = await account.getTransfers()
console.log('Recent transfers:', transfers)
```
The default limit is 10 transfers. Change outputs are automatically filtered out. Transfers are sorted by block height (newest first).
## Filter by Direction
You can filter transfers by direction using the `direction` option in [`account.getTransfers()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Incoming Transfers"
const incoming = await account.getTransfers({ direction: 'incoming' })
console.log('Incoming transfers:', incoming)
```
You can retrieve outgoing transfers with a custom limit using [`account.getTransfers()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Outgoing Transfers"
const outgoing = await account.getTransfers({
direction: 'outgoing',
limit: 5
})
console.log('Outgoing transfers:', outgoing)
```
## Paginate Results
You can paginate through transfer history using the `limit` and `skip` options in [`account.getTransfers()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Paginate Transfers"
const page = await account.getTransfers({
direction: 'all',
limit: 20,
skip: 10
})
console.log('Transfers 11-30:', page)
```
## Check Transaction Receipts
You can check whether a specific transaction has been confirmed using [`account.getTransactionReceipt()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get Transaction Receipt"
const receipt = await account.getTransactionReceipt('abc123...')
if (receipt) {
console.log('Transaction confirmed')
}
```
## Next Steps
Learn how to [sign and verify messages](/sdk/wallet-modules/wallet-btc/guides/sign-verify-messages).
***
## Handle Errors
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/handle-errors
Description: Handle errors, manage fees, and dispose of sensitive data.
This guide explains how to [handle transaction errors](#transaction-errors), [handle connection errors](#connection-errors), and follow [best practices](#best-practices) for fee management and memory cleanup.
## Transaction Errors
Transactions sent via [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference) can fail for several reasons. Wrap transaction calls in a `try/catch` block to handle specific error types:
```javascript title="Handle Transaction Errors"
try {
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n
})
console.log('Transaction hash:', result.hash)
} catch (error) {
if (error.message.includes('Insufficient balance')) {
console.error('Not enough funds in wallet')
} else if (error.message.includes('dust limit')) {
console.error('Amount is below the minimum dust limit')
} else if (error.message.includes('Invalid address')) {
console.error('Recipient address is invalid')
} else {
console.error('Transaction failed:', error.message)
}
}
```
## Connection Errors
Network issues with the Electrum server can cause failures across all operations. Handle connection errors at a higher level:
```javascript title="Handle Connection Errors"
try {
const balance = await account.getBalance()
console.log('Balance:', balance, 'satoshis')
} catch (error) {
if (error.message.includes('ECONNREFUSED') || error.message.includes('timeout')) {
console.error('Network error: check Electrum server connection')
} else if (error.message.includes('Invalid seed')) {
console.error('Invalid seed phrase provided')
} else {
console.error('Operation failed:', error.message)
}
}
```
## Best Practices
### Fee Management
You can retrieve current network fee rates using [`wallet.getFeeRates()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Get Fee Rates"
const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'sat/vB')
console.log('Fast fee rate:', feeRates.fast, 'sat/vB')
```
[`wallet.getFeeRates()`](/sdk/wallet-modules/wallet-btc/api-reference) fetches rates from the mempool.space API, while [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference) estimates fees from the connected Electrum server. Use [`getFeeRates()`](/sdk/wallet-modules/wallet-btc/api-reference) for display purposes.
### Dispose of Sensitive Data
For security, clear sensitive data from memory when a session is complete. Use [`account.dispose()`](/sdk/wallet-modules/wallet-btc/api-reference) and [`wallet.dispose()`](/sdk/wallet-modules/wallet-btc/api-reference) to securely wipe private keys:
```javascript title="Dispose Resources"
try {
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n
})
console.log('Transaction hash:', result.hash)
} finally {
account.dispose()
wallet.dispose()
}
```
Always call [`dispose()`](/sdk/wallet-modules/wallet-btc/api-reference) when finished with accounts. Private keys are securely wiped from memory using `sodium_memzero`. Electrum connections are automatically closed. Disposal is irreversible.
***
## Manage Accounts
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/manage-accounts
Description: Work with multiple accounts and custom derivation paths.
This guide explains how to [retrieve accounts by index](#retrieve-accounts-by-index) and [use custom derivation paths](#retrieve-account-by-custom-derivation-path).
## Retrieve Accounts by Index
You can retrieve multiple accounts using [`wallet.getAccount()`](/sdk/wallet-modules/wallet-btc/api-reference) with different index values:
```javascript title="Retrieve Multiple Accounts"
const account0 = await wallet.getAccount(0)
const address0 = await account0.getAddress()
console.log('Account 0 address:', address0)
const account1 = await wallet.getAccount(1)
const address1 = await account1.getAddress()
console.log('Account 1 address:', address1)
```
You can iterate through multiple accounts using [`wallet.getAccount()`](/sdk/wallet-modules/wallet-btc/api-reference) to inspect addresses and balances in bulk:
```javascript title="Iterate Over Accounts"
for (let i = 0; i < 5; i++) {
const account = await wallet.getAccount(i)
const address = await account.getAddress()
const balance = await account.getBalance()
console.log(`Account ${i}: ${address} (${balance} satoshis)`)
}
```
## Retrieve Account by Custom Derivation Path
You can retrieve an account at a specific derivation path using [`wallet.getAccountByPath()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Custom Derivation Path"
const customAccount = await wallet.getAccountByPath("0'/0/5")
const customAddress = await customAccount.getAddress()
console.log('Custom account address:', customAddress)
```
The default derivation scheme is BIP-84 (Native SegWit): `m/84'/0'/0'/0/{index}` on mainnet. Set `bip: 44` in the wallet configuration for legacy BIP-44 paths: `m/44'/0'/0'/0/{index}`.
## Next Steps
With accounts set up, learn how to [check balances](/sdk/wallet-modules/wallet-btc/guides/check-balances).
***
## Send Transactions
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/send-transactions
Description: Send BTC and estimate transaction fees.
This guide explains how to [send BTC](#send-btc), [extend post-broadcast polling](#extend-post-broadcast-polling), [sign without broadcasting](#sign-without-broadcasting), [estimate fees before sending](#estimate-fees), [use a custom fee rate](#send-with-custom-fee-rate), and [target a specific confirmation time](#send-with-confirmation-target).
## Send BTC
You can send Bitcoin to a recipient using [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#sendtransactionoptions-timeoutms):
```javascript title="Send BTC"
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n // 0.001 BTC in satoshis
})
console.log('Transaction hash:', result.hash)
console.log('Transaction fee:', result.fee, 'satoshis')
```
Bitcoin transactions support a single recipient only. Amounts and fees are always in satoshis (1 BTC = 100,000,000 satoshis). The minimum amount must be above the dust limit (294 satoshis for SegWit, 546 for legacy).
## Extend Post-Broadcast Polling
If you want [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#sendtransactionoptions-timeoutms) to keep polling after broadcast until spent inputs disappear from the unspent-output set, pass the optional `timeoutMs` argument:
```javascript title="Send BTC With Extended Polling"
const result = await account.sendTransaction(
{
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n,
},
30000
)
console.log('Transaction hash:', result.hash)
```
If you omit `timeoutMs`, the wallet uses the default post-broadcast polling window before returning.
## Sign Without Broadcasting
Use [`account.signTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#signtransactionoptions) when your app needs a signed raw Bitcoin transaction but does not want WDK to broadcast it immediately.
```javascript title="Sign BTC Transaction"
const signedTransaction = await account.signTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n,
feeRate: 10n
})
console.log('Signed transaction:', signedTransaction)
```
`signTransaction()` returns the signed transaction hex. Use `sendTransaction()` when WDK should sign, broadcast, and return the transaction hash.
## Estimate Fees
You can estimate the fee for a transaction without broadcasting it using [`account.quoteSendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#quotesendtransactionoptions):
```javascript title="Estimate Fee"
const quote = await account.quoteSendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n
})
console.log('Estimated fee:', quote.fee, 'satoshis')
```
## Send with Custom Fee Rate
You can override automatic fee estimation by providing a `feeRate` in sat/vB to [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#sendtransactionoptions-timeoutms):
```javascript title="Custom Fee Rate"
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n,
feeRate: 10n // sat/vB
})
```
When `feeRate` is provided, the `confirmationTarget` parameter is ignored.
## Send with Confirmation Target
You can target a specific number of blocks for confirmation using the `confirmationTarget` parameter in [`account.sendTransaction()`](/sdk/wallet-modules/wallet-btc/api-reference#sendtransactionoptions-timeoutms):
```javascript title="Confirmation Target"
const result = await account.sendTransaction({
to: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
value: 100000n,
confirmationTarget: 6 // target 6 blocks (~1 hour)
})
```
## Next Steps
Learn how to [view transaction history](/sdk/wallet-modules/wallet-btc/guides/get-transaction-history).
***
## Sign and Verify Messages
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/guides/sign-verify-messages
Description: Sign messages and verify signatures with Bitcoin accounts.
This guide explains how to [sign messages](#sign-a-message) and [verify signatures](#verify-a-signature).
## Sign a Message
You can sign a message with the account's private key using [`account.sign()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Sign Message"
const message = 'Hello, Bitcoin!'
const signature = await account.sign(message)
console.log('Signature:', signature)
```
The signature is returned as a base64-encoded string.
## Verify a Signature
You can verify that a signature was produced by the corresponding private key using [`account.verify()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Verify Signature"
const isValid = await account.verify(message, signature)
console.log('Signature valid:', isValid)
```
You can also verify signatures using a [read-only account](/sdk/wallet-modules/wallet-btc/api-reference). Use [`account.toReadOnlyAccount()`](/sdk/wallet-modules/wallet-btc/api-reference) to create one from an owned account, then call [`readOnlyAccount.verify()`](/sdk/wallet-modules/wallet-btc/api-reference):
```javascript title="Verify with Read-Only Account"
const readOnlyAccount = await account.toReadOnlyAccount()
const isValid = await readOnlyAccount.verify('Hello, Bitcoin!', signature)
console.log('Verified with read-only account:', isValid)
```
## Next Steps
Learn how to [handle errors and manage resources](/sdk/wallet-modules/wallet-btc/guides/handle-errors).
***
## Wallet BTC Usage
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-btc/usage
Description: Guide to using the @tetherto/wdk-wallet-btc module.
# Usage
The `@tetherto/wdk-wallet-btc` module provides wallet management for the Bitcoin blockchain.
Install the package and create your first wallet.
Work with multiple accounts and custom derivation paths.
Query native BTC balances for owned and read-only accounts.
Send Bitcoin and estimate transaction fees.
Retrieve and filter transfer history.
Sign messages and verify signatures.
Handle errors, manage fees, and dispose of sensitive data.
Get started with WDK in a Node.js environment
Build mobile wallets with React Native Expo
Get started with WDK's Bitcoin Wallet Configuration
Get started with WDK's Bitcoin Wallet API
***
### Need Help?
***
## Wallet EVM Overview
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm
Description: Overview of the @tetherto/wdk-wallet-evm module
A simple and secure package to manage BIP-44 wallets for EVM (Ethereum Virtual Machine) blockchains. This package provides a clean API for creating, managing, and interacting with Ethereum-compatible wallets using BIP-39 seed phrases and BIP-44 derivation paths.
## Features
- **BIP-39 Seed Phrase Support**: Generate and validate BIP-39 mnemonic seed phrases
- **EVM Derivation Paths**: Support for BIP-44 standard derivation paths for Ethereum (m/44'/60')
- **Multi-Account Management**: Create and manage multiple accounts from a single seed phrase
- **EVM Address Support**: Generate and manage Ethereum-compatible addresses using ethers.js
- **Message Signing**: Sign and verify messages using EVM cryptography
- **Offline Transaction Signing**: Sign EVM transactions with `signTransaction()` without broadcasting them
- **Transaction Management**: Send transactions and get fee estimates with EIP-1559 support
- **ERC20 Support**: Query native token and ERC20 token balances using smart contract interactions
- **Batch Token Balance Queries**: Fetch balances for multiple ERC20 tokens in one call with `getTokenBalances`
- **TypeScript Support**: Full TypeScript definitions included
- **Memory Safety**: Secure private key management with memory-safe HDNodeWallet implementation
- **Provider Flexibility**: Support for JSON-RPC URLs, EIP-1193 browser providers, and ordered failover provider lists
- **Gas Optimization**: Support for EIP-1559 maxFeePerGas and maxPriorityFeePerGas
- **Fee Estimation**: Dynamic fee calculation with normal (1.1x) and fast (2.0x) multipliers
## Supported Networks
This package works with any EVM-compatible blockchain, including:
- **Ethereum**: Mainnet, Sepolia
- **Polygon**: Mainnet, Amoy
- **Binance Smart Chain (BSC)**: Mainnet, Testnet
- **Arbitrum**: One, Nova
- **Optimism**: Mainnet, Sepolia
- **Avalanche C-Chain**: Mainnet, Fuji
- **And many more...**
## Next Steps
Get started with WDK in a Node.js environment
Get started with WDK's EVM Wallet configuration
Get started with WDK's EVM Wallet API
Get started with WDK's EVM Wallet usage
***
### Need Help?
***
## Wallet EVM ERC-4337 Overview
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm-erc-4337
Description: Overview of the @tetherto/wdk-wallet-evm-erc-4337 module
A simple and secure package to manage ERC-4337 compliant wallets for EVM-compatible blockchains. This package provides a clean API for creating, managing, and interacting with account abstraction wallets using BIP-39 seed phrases and EVM-specific derivation paths.
## Features
- **BIP-39 Seed Phrase Support**: Generate and validate BIP-39 mnemonic seed phrases
- **EVM Derivation Paths**: Support for BIP-44 standard derivation paths for Ethereum (m/44'/60')
- **Multi-Account Management**: Create and manage multiple account abstraction wallets from a single seed phrase
- **ERC-4337 Support**: Full implementation of ERC-4337 account abstraction standard
- **UserOperation Management**: Create and send UserOperations through bundlers
- **Message Signing**: Sign and verify messages using EVM cryptography
- **ERC20 Support**: Query native token and ERC20 token balances using smart contract interactions
- **TypeScript Support**: Full TypeScript definitions included
- **Memory Safety**: Secure private key management with memory-safe HDNodeWallet implementation
- **Bundler Integration**: Support for ERC-4337 bundler services
- **Gas Optimization**: Paymaster support and gas estimation for UserOperations
- **Fee Estimation**: Dynamic fee calculation with bundler-aware estimation
- **EIP-712 Typed Data Support**: Sign and verify EIP-712 structured typed data
- **Batch Token Balance Queries**: Query multiple ERC20 token balances in a single call
## Supported Networks
This package works with any EVM-compatible blockchain, including:
- **Ethereum Mainnet**
- **Ethereum Testnets** (Sepolia)
- **Other EVM Chains** (Polygon, Arbitrum, Avalanche C-chain, Plasma etc.)
## Next Steps
Get started with WDK in a Node.js environment
Get started with WDK's EVM with ERC-4337 Wallet configuration
Get started with WDK's EVM with ERC-4337 Wallet API
Get started with WDK's EVM with ERC-4337 Wallet usage
***
## Need Help?
***
## Wallet EVM ERC-4337 API Reference
URL: https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm-erc-4337/api-reference
Description: Complete API documentation for @tetherto/wdk-wallet-evm-erc-4337
## Table of Contents
| Class | Description | Methods |
|-------|-------------|---------|
| [WalletManagerEvmErc4337](#walletmanagerevmerc4337) | Main class for managing ERC-4337 EVM wallets. Extends `WalletManager` from `@tetherto/wdk-wallet`. | [Constructor](#constructor), [Methods](#methods) |
| [WalletAccountEvmErc4337](#walletaccountevmerc4337) | Individual ERC-4337 wallet account implementation. Extends `WalletAccountReadOnlyEvmErc4337` and implements `IWalletAccount`. | [Constructor](#constructor-1), [Methods](#methods-1), [Properties](#properties) |
| [WalletAccountReadOnlyEvmErc4337](#walletaccountreadonlyevmerc4337) | Read-only ERC-4337 wallet account. Extends `WalletAccountReadOnly` from `@tetherto/wdk-wallet`. | [Constructor](#constructor-2), [Methods](#methods-2) |
| [ConfigurationError](#configurationerror) | Error thrown when the wallet configuration is invalid or has missing required fields. | - |
## WalletManagerEvmErc4337
The main class for managing ERC-4337 EVM wallets. Extends `WalletManager` from `@tetherto/wdk-wallet`.
### Fee Rate Behavior
Internally, `getFeeRates()` applies these multipliers to the base fee:
- **Normal**: base fee × 110%
- **Fast**: base fee × 200%
These multipliers are internal (`protected static`) and cannot be imported or overridden.
### Constructor
```javascript
new WalletManagerEvmErc4337(seed, config)
```
**Parameters:**
- `seed` (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
- `config` (EvmErc4337WalletConfig): Configuration object with common fields and a gas payment mode
**Common config fields (required for all modes):**
- `chainId` (number): The blockchain's ID (e.g., 1 for Ethereum mainnet)
- `provider` (string | Eip1193Provider | Array\): RPC endpoint URL, EIP-1193 provider instance, or ordered failover list
- `bundlerUrl` (string): The URL of the bundler service
- `safeModulesVersion` (string): The Safe modules version (e.g., `'0.3.0'`)
**Gas payment mode** (one of the following):
Fees are paid using an ERC-20 token through a paymaster service.
- `paymasterUrl` (string): The URL of the paymaster service
- `paymasterAddress` (string): The address of the paymaster smart contract
- `paymasterToken` (object): The paymaster token configuration
- `address` (string): The address of the ERC-20 token used for fees
- `transferMaxFee` (number | bigint, optional): Maximum fee limit in paymaster token units
```javascript
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
chainId: 1,
provider: 'https://rpc.mevblocker.io/fast',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
safeModulesVersion: '0.3.0',
// Paymaster token mode
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7' // USD₮
},
transferMaxFee: 100000 // Optional: max fee in token units
})
```
Fees are sponsored by a third party via a sponsorship policy.
- `isSponsored` (true): Enables sponsorship mode
- `paymasterUrl` (string): The URL of the paymaster service
- `sponsorshipPolicyId` (string, optional): The sponsorship policy ID
```javascript
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
chainId: 1,
provider: 'https://rpc.mevblocker.io/fast',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
safeModulesVersion: '0.3.0',
// Sponsorship mode
isSponsored: true,
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
sponsorshipPolicyId: 'your-policy-id' // Optional
})
```
Fees are paid using the chain's native token (e.g., ETH).
- `useNativeCoins` (true): Enables native coin fee payment
- `transferMaxFee` (number | bigint, optional): Maximum fee limit in native token units
```javascript
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
chainId: 1,
provider: 'https://rpc.mevblocker.io/fast',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
safeModulesVersion: '0.3.0',
// Native coins mode
useNativeCoins: true,
transferMaxFee: 100000000000000n // Optional: max fee in wei
})
```
### Methods
| Method | Description | Returns | Throws |
|--------|-------------|---------|--------|
| `getRandomSeedPhrase(wordCount?)` | (static) Returns a random BIP-39 seed phrase | `string` | - |
| `isValidSeedPhrase(seedPhrase)` | (static) Checks if a seed phrase is valid | `boolean` | - |
| `getAccount(index?)` | Returns a wallet account at the specified index | `Promise\` | - |
| `getAccountByPath(path)` | Returns a wallet account at the specified BIP-44 derivation path | `Promise\` | - |
| `getFeeRates()` | Returns current fee rates for transactions | `Promise\<{normal: bigint, fast: bigint}\>` | If no provider |
| `dispose()` | Disposes all wallet accounts, clearing private keys from memory | `void` | - |
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `seed` | `Uint8Array` | The wallet's seed phrase as bytes |
#### `getRandomSeedPhrase(wordCount?)` (static)
Returns a random BIP-39 seed phrase.
**Parameters:**
- `wordCount` (12 | 24, optional): The number of words in the seed phrase (default: 12)
**Returns:** `string` - The seed phrase
**Example:**
```javascript
const seedPhrase = WalletManagerEvmErc4337.getRandomSeedPhrase()
console.log('Seed phrase:', seedPhrase) // 12 words
const longSeedPhrase = WalletManagerEvmErc4337.getRandomSeedPhrase(24)
console.log('Long seed phrase:', longSeedPhrase) // 24 words
```
#### `isValidSeedPhrase(seedPhrase)` (static)
Checks if a seed phrase is valid.
**Parameters:**
- `seedPhrase` (string): The seed phrase to validate
**Returns:** `boolean` - True if the seed phrase is valid
**Example:**
```javascript
const isValid = WalletManagerEvmErc4337.isValidSeedPhrase('abandon abandon abandon ...')
console.log('Valid:', isValid)
```
#### `getAccount(index)`
Returns a wallet account at the specified index using BIP-44 derivation.
**Parameters:**
- `index` (number, optional): The index of the account to get (default: 0)
**Returns:** `Promise\` - The wallet account
**Example:**
```javascript
// Get first account (index 0)
const account = await wallet.getAccount(0)
// Get default account
const defaultAccount = await wallet.getAccount()
```
#### `getAccountByPath(path)`
Returns a wallet account at the specified BIP-44 derivation path.
**Parameters:**
- `path` (string): The derivation path (e.g., "0'/0/0")
**Returns:** `Promise\` - The wallet account
**Example:**
```javascript
// Full derivation path: m/44'/60'/0'/0/1
const account = await wallet.getAccountByPath("0'/0/1")
```
#### `getFeeRates()`
Returns current fee rates with ERC-4337 specific multipliers.
**Returns:** `Promise\<{normal: bigint, fast: bigint}\>` - Fee rates in wei
**Throws:** Error if no provider is configured
**Example:**
```javascript
const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'wei') // base fee × 1.1
console.log('Fast fee rate:', feeRates.fast, 'wei') // base fee × 2.0
```
#### `dispose()`
Disposes all wallet accounts, clearing private keys from memory.
**Example:**
```javascript
// Clean up when done
wallet.dispose()
```
## WalletAccountEvmErc4337
Represents an individual ERC-4337 wallet account. Extends `WalletAccountReadOnlyEvmErc4337` and implements `IWalletAccount`.
### Constants
The following constant is used internally for Safe account address derivation:
```javascript
// Internal: used by predictSafeAddress() for deterministic address generation
const SALT_NONCE = '0x69b348339eea4ed93f9d11931c3b894c8f9d8c7663a053024b11cb7eb4e5a1f6'
```
> **Note:** This constant is not re-exported from the package entry point. Use `predictSafeAddress()` instead of referencing it directly.
### Constructor
```javascript
new WalletAccountEvmErc4337(seed, path, config)
```
**Parameters:**
- `seed` (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
- `path` (string): BIP-44 derivation path (e.g., "0'/0/0")
- `config` (EvmErc4337WalletConfig): Configuration object (same as [WalletManagerEvmErc4337](#constructor))
**Example:**
```javascript
const account = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 1,
provider: 'https://rpc.mevblocker.io/fast',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
safeModulesVersion: '0.3.0',
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
})
```
### Methods
| Method | Description | Returns | Throws |
|--------|-------------|---------|--------|
| `predictSafeAddress(owner, config)` | (static) Predicts the Safe address for a given owner | `string` | - |
| `getAddress()` | Returns the Safe account's address | `Promise\` | - |
| `sign(message)` | Signs a message using the account's private key | `Promise\` | - |
| `verify(message, signature)` | Verifies a message signature | `Promise\` | - |
| `sendTransaction(tx, config?)` | Sends a transaction via UserOperation | `Promise\<{hash: string, fee: bigint}\>` | If fee exceeds max |
| `quoteSendTransaction(tx, config?)` | Estimates the fee for a UserOperation | `Promise\<{fee: bigint}\>` | - |
| `transfer(options, config?)` | Transfers ERC20 tokens via UserOperation | `Promise\<{hash: string, fee: bigint}\>` | If fee exceeds max |
| `quoteTransfer(options, config?)` | Estimates the fee for an ERC20 transfer | `Promise\<{fee: bigint}\>` | - |
| `approve(options)` | Approves a spender to spend ERC20 tokens | `Promise\<{hash: string, fee: bigint}\>` | - |
| `getBalance()` | Returns the native token balance (in wei) | `Promise\` | - |
| `getTokenBalance(tokenAddress)` | Returns the balance of a specific ERC20 token | `Promise\` | - |
| `getPaymasterTokenBalance()` | Returns the paymaster token balance | `Promise\` | - |
| `getAllowance(token, spender)` | Returns current token allowance for a spender | `Promise\` | - |
| `getTransactionReceipt(hash)` | Returns a transaction receipt | `Promise\` | - |
| `getUserOperationReceipt(hash)` | Returns a UserOperation receipt | `Promise\` | - |
| `signTypedData(typedData)` | Signs EIP-712 typed structured data | `Promise\` | - |
| `verifyTypedData(typedData, signature)` | Verifies an EIP-712 typed data signature | `Promise\` | - |
| `getTokenBalances(tokenAddresses)` | Returns balances for multiple ERC20 tokens | `Promise\