WDK logoWDK documentation
Core SDKGuides

Integrate Protocols

Register and access WDK protocol providers from wallet accounts.

Source preview — unreleased: The protocol construction and policy-context changes on this page describe approved Core source 342fb4e, from open PR #117. They are not part of the verified npm 1.0.0-beta.19 artifact. The release version and installed-package validation are pending.

The WDK Core module supports registering external protocol providers. This lets you extend wallet accounts with protocol-specific discovery, quote, and write operations.

Register Protocols

You can register protocols globally (for all new accounts).

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 exact wallet and protocol releases used by the direct-account compatibility flows later in this guide:

npm install --save-exact @tetherto/wdk-wallet-evm@1.0.0-beta.19 @tetherto/wdk-protocol-swap-velora-evm@1.0.0-beta.8 @tetherto/wdk-protocol-bridge-usdt0-evm@1.0.0-beta.10

2. Register in Code

Register a compatible protocol class for the specific chains it supports. This makes its methods available to accounts derived from that WDK instance.

Register Protocols
const wdk = new WDK(seedPhrase)
  .registerWallet('ethereum', WalletManagerEvm, ethConfig)
  .registerProtocol('ethereum', 'swap', MySwapProtocol, swapProtocolConfig)

MySwapProtocol is an illustrative class that extends SwapProtocol. Replace it with a provider whose constructor supports the manager account's provider shape.

Do not register Velora beta.8, USD₮0 bridge beta.10, or Aave beta.7 on a wallet-evm beta.19 manager account. These protocol constructors treat the manager's shared ethers Provider as EIP-1193 and reject it. Use a direct standard account with its original RPC URL or EIP-1193 provider for these exact combinations; never replace the account's internal provider field. For Aave, follow the direct-account configuration.

Source Preview: Account-Scoped Registration

In the approved source preview, register a provider on one resolved account when its constructor supports the account's public interface:

Preview Account-Scoped Registration
const account = await wdk.getAccount('ethereum', 0)

// MySdaProtocol is an application-supplied class extending SdaProtocol.
account.registerProtocol('deposits', MySdaProtocol, sdaProtocolConfig)

// Registration stores the class and config; this getter constructs the provider.
const deposits = account.getSdaProtocol('deposits')

WDK retains the supplied configuration arguments for later construction; it does not snapshot their objects. Avoid changing a config object between registration and retrieval. Each getter constructs a fresh provider, so retrieve it once when you need to retain instance-local state. Re-registering the same type and label changes future retrievals; it does not replace an instance your application already holds. A global registration with the same type and label takes precedence. Catch provider-constructor and configuration errors at retrieval rather than account-level registration.

On a governed account, account-scoped providers receive the policy proxy, which hides keyPair and _-prefixed members. A constructor that requires account._config is incompatible with this context. Global registration keeps the raw account available to the constructor, but the provider's internal calls on that account bypass account-method policies. This choice does not establish compatibility with the wallet's provider type; the exact-release compatibility warnings in this guide still apply.

For an account-scoped provider holding the governed account, a real governed protocol call evaluates its outer operation and any governed calls it makes through that account. For example, allowing swap does not also allow an internal sendTransaction: both need applicable rules. Calls within the underlying wallet implementation, or through separately retained raw references, remain outside that interception path. See Transaction Policies for simulation limits.

Use Protocols

Once registered, access the protocol instance with its typed getter, such as getSwapProtocol(), getBridgeProtocol(), getLendingProtocol(), getFiatProtocol(), getSwidgeProtocol(), or getSdaProtocol().

Smart Deposit Addresses

WDK Core beta.15 registers and retrieves SDA providers through the same account protocol surface. The concrete provider must extend SdaProtocol; MySdaProtocol below is illustrative.

Register And Access An SDA Provider
const wdk = new WDK(seedPhrase)
  .registerWallet('ethereum', WalletManagerEvm, ethConfig)
  .registerProtocol('ethereum', 'deposits', MySdaProtocol, sdaProtocolConfig)

const account = await wdk.getAccount('ethereum', 0)
const deposits = account.getSdaProtocol('deposits')

const routes = await deposits.getSupportedRoutes({
  sourceChain: 'ethereum',
  outputAsset: 'USDT'
})

Every SDA provider implements route discovery and deposit-address creation. Quote, derivation, renewal, lookup, history, recovery, and disable operations are optional. Check the concrete provider's contract before calling them; the base implementations throw UnsupportedOperationError. Output assets are route-specific, with USD₮ shown only as an example. See Smart Deposit Address Modules for concrete providers and their setup requirements.

Swidge Routes

Use a swidge provider module for new swap, bridge, or combined route integrations. Retrieve a registered provider with getSwidgeProtocol(). 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.

Swidge route flow
const account = await wdk.getAccount('ethereum', 0)
const swidge = account.getSwidgeProtocol('swidge')

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. Choose a released Swidge provider module for new protocol integrations because the standalone swap and bridge interfaces are expected to be deprecated after Swidge provider coverage is available.

Swapping Tokens

Velora beta.8 requires a directly constructed standard account that retains its RPC URL or EIP-1193 provider when paired with wallet-evm beta.19. Approve the input token for the current Velora spender before running this example; see Execute Swaps.

This compatibility path does not use wdk.getAccount(), so WDK transaction policies and middleware do not decorate swapAccount. Keep required application checks before approval and swap execution. The account-level transactionMaxFee and protocol-level swapMaxFee caps remain available, but they do not replace WDK policy rules.

Swap Tokens
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'

const swapAccount = new WalletAccountEvm(seedPhrase, "0'/0/0", {
  provider: 'https://eth.drpc.org',
  transactionMaxFee: 5000000000000000n
})
const velora = new VeloraProtocolEvm(swapAccount, {
  swapMaxFee: 200000000000000n
})

try {
  const result = await velora.swap({
    tokenIn: '0x...', // Address of the approved token to sell
    tokenOut: '0x...', // Address of token to buy
    tokenInAmount: 1000000n // Amount to swap
  })
} finally {
  swapAccount.dispose()
}

Bridging Assets

Bridge beta.10 requires a directly constructed standard account that retains its RPC URL or EIP-1193 provider. Instantiate the bridge with that account. Before calling bridge(), prepare and confirm a bounded allowance for the same source token, spender, and amount. Reuse that confirmed allowance in the example below.

This compatibility path does not use wdk.getAccount(), so WDK transaction policies and middleware do not decorate bridgeAccount. Keep required application checks before approval and bridge execution. Account-level options such as transactionMaxFee remain available, but they do not replace WDK policy rules.

Bridge Assets
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'

const bridgeAccount = new WalletAccountEvm(seedPhrase, "0'/0/0", {
  provider: 'https://eth.drpc.org',
  transactionMaxFee: 5000000000000000n
})
const usdt0 = new Usdt0ProtocolEvm(bridgeAccount)

try {
  const result = await usdt0.bridge({
    targetChain: 'ton',
    recipient: 'UQBla...', // TON address
    token: '0x...', // Same ERC20 token address
    amount: 1000000n,
    oftContractAddress: '0x...' // Same address used as approval spender
  })
} finally {
  bridgeAccount.dispose()
}

Protocol Availability: If you try to access a protocol that has not been registered (for example, getSwapProtocol('uniswap')), the SDK throws an error. Always ensure registration matches the ID you request.

Next Steps

Learn how to configure middleware to add logging or failover protection to your wallet interactions.

On this page