More Than Transfers: Give Any Wallet Swaps, Bridges, Lending, and Fiat capabilities.
By the end of this post, you'll understand what WDK protocol modules are, the three interface shapes they come in, and how to compose them into a real product.
What we've built so far
This series introduces complex blockchain interactions and makes them simple with WDK. If this is your first post, we recommend you explore the previous posts. The wallet layer is covered.
The wallet basics:
- Introduction to WDK: Tether's Wallet Development Kit: the what and the why: the vision, the six core principles, the four architectural pillars, and the module system that everything below depends on.
- Wallet Fundamentals: Build, Sign, and Send Your First Transaction in WDK: hands-on: one seed phrase, multiple chains, a working self-custodial wallet.
- Wallet Fundamentals: Sending USD₮ in WDK: how token transfers differ across blockchain models, and how WDK unifies them.
Gas abstraction:
- Gasless Transactions in WDK: A Chain-by-Chain Guide: the paymaster pattern, and why asking a user to buy ETH before sending USD₮ loses you that user.
- Chain by chain: EVM with ERC-4337 and EIP-7702, Solana, TON, and TRON.
Short on time? Read the introduction and the gasless overview. Come back to the chain-specific posts when you need them.
Transfers are not enough
Put it together, and you have a self-custodial wallet: one seed phrase, five chains, USD₮ transfers where the user never touches a native token. That's hard engineering, and most teams couldn't have shipped it a year ago without deep blockchain knowledge.
But compare it to the apps already on your user's phone: Revolut, Wise, PayPal, Pix... Sending money to another person (human to human) is a solved problem in most of the world, often with better UX than any crypto wallet. Every post above taught the wallet the same operation: send.
But, a transfer-only wallet isn't a product advantage. It's the baseline. Everything that makes blockchains interesting sits above it: DeFi, where the same wallet that sends money can also swap, lend, and borrow it, and AiFi, where that wallet is operated by an agent instead of a human.
The advantage of blockchain: permissionless composition. A fintech can't add a savings feature the way we're describing it, because the product doesn't exist on its side. Bank rates are set rates, not a market you can plug into. The best a fintech can do is find a partner, negotiate a revenue share, pass through whatever rate that partner offers, and ship it next year. With WDK, the lending market is already deployed, already liquid, and already callable, and WDK makes it as easy to integrate as one import and one registration line.
Note that that has nothing to do with transfers being faster or cheaper. On public blockchains, financial capability ships as a package, not a partnership. The lending market is already deployed, already liquid, and already callable by anyone. No business development cycle, no gatekeeper, no minimum volume.
Transfers get you parity. Protocols get you leverage.
One clarification, so this doesn't read as a sales pitch: the obligations don't disappear. Fiat on-ramps still require KYC; that's why a fiat module exists instead of a magic "add dollars" call. On-chain yield carries smart-contract and rate risk that an insured bank deposit doesn't. The rules stay. What changes is the cost of adding each capability, and that's the difference between a feature you cut and a feature you ship.
What a protocol module is
WDK's architecture has two layers of modules sitting on the same core.
Wallet modules speak blockchain. They derive addresses, sign transactions, read balances. One per chain, or per account model: wdk-wallet-btc, wdk-wallet-evm, wdk-wallet-solana-gasless.
Protocol modules speak everything above the chain. They wrap a protocol or service behind a normalized interface, reusing the accounts the wallet modules derive. A wallet module knows how to sign; a protocol module knows what to sign for. It wraps one protocol or service (a lending market, a router, an on-ramp, a swap...) and exposes it through an interface that doesn't change when you switch what's behind it.
But WDK, you register both the same way, on the same instance:
import WDK from '@tetherto/wdk'
import WalletManagerEvmErc4337 from '@tetherto/wdk-wallet-evm-erc-4337'
import LendingAaveEvm from '@tetherto/wdk-protocol-lending-aave-evm'
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvmErc4337, { /* config */ })
.registerProtocol('lending-aave-evm', LendingAaveEvm, { /* config */ })
As we have repeated in every blog post, WDK keeps a consistent API across wallets and across protocol types. registerWallet for chains, registerProtocol for capabilities, and the naming convention tells you what you're getting before you read a line of documentation:
@tetherto/wdk-protocol-<type>-<protocol>-<chain>wdk-protocol-lending-aave-evm. wdk-protocol-swap-velora-evm. wdk-protocol-bridge-usdt0-evm. Read the package name, know the shape.
Shaped by protocol type
WDK does not flatten every protocol into a single generic execute() call. That would be impossible, but it normalizes at the financial-primitive level between different protocol providers inside the same family.
WDK has the following protocol API standardizations:
Swidge (Swaps and bridges)
Moving value from one asset to another, or from one chain to another, is a routing problem. You ask what routes exist, you get a quote, you execute, and because the destination might be on another chain, you poll until it settles.
WDK expresses this as the Swidge interface (swap and bridge unified), because a real route is often both at once:
getSupportedChains()andgetSupportedTokens(): runtime discovery, no account requiredquoteSwidge(): what will this cost, what will I receiveswidge(): execute, approving and submitting one or more transactionsgetSwidgeStatus(): poll until done, because cross-chain isn't atomic
Four providers implement that interface today: Orchestra, Rhino.fi, Symbiosis, and LI.FI. The consequence is worth stating plainly: you can replace your router without touching your application code. Swap the registration line, keep everything else. Try that with four vendor SDKs.
Lending
Lending isn't an action; it's a position you hold over time, and you can earn a lending interest on it or borrow against it. The interface reflects that.
The Aave V3 module gives you four primitives: supply, withdraw, borrow, repay; each with a quote twin: quoteSupply, quoteWithdraw, quoteBorrow, quoteRepay. But the more important half is the read side: collateral, outstanding debt, and health factor, the number that tells you how close a borrowing position is to liquidation. Plus controls for toggling which assets count as collateral and setting eMode.
For a savings app you may only ever call supply, withdraw, and the account-data read. The borrowing half is there when you need it.
Fiat
On-ramps and off-ramps barely touch a blockchain, and pretending otherwise would be a bad abstraction. Buying crypto with a card involves a regulated provider, a KYC flow, and a payment session that lives entirely outside your app.
So the MoonPay module does something different: it generates signed widget URLs for buy and sell flows, alongside real-time price quotes, transaction status lookups, and discovery of which currencies and countries are actually supported. Your app opens the URL; MoonPay handles cards, bank transfers, Apple Pay, and identity verification.
One detail worth flagging early, because it's the thing people get wrong: signing those URLs requires a secret, which means it belongs on a server, not in your mobile app. The module takes a signUrl callback for exactly this. Unsigned URLs work for development. Don't ship them.
The comparison
Swidge | Lending | Fiat | |
|---|---|---|---|
Primitive | route | position | session |
Quote |
|
| price quotes |
Execute |
|
| open a widget URL |
Read state |
| collateral, debt, health factor | transaction lookup |
Settlement | asynchronous, poll it | on-chain, immediate | provider-side, out of band |
Notice the one thing all three columns share: every category has a quote. That's the same discipline we pushed throughout the wallet series: quote first, show the user the cost, then execute. It holds here without exception. If a protocol module offers you a quote method and you skip it, you are shipping a surprise to your user.
Who builds the modules?
WDK is open source, and the module system is what matters. A protocol module is a normal npm package implementing a documented interface; nothing about it is privileged, and nothing has to go through Tether.
That's why the table above lists both. Tether maintains the modules it has direct responsibility for. And protocols like Orchestra, Rhino.fi, Symbiosis, LI.FI, 0x were built and are maintained by the protocol teams themselves, alongside Morpho on the lending side. A protocol team that wants WDK support doesn't need to wait for us to prioritize it. They can ship it.
The create-wdk-module CLI scaffolds a complete package (source, tests, TypeScript definitions, CI workflows) in one command:
npx @tetherto/create-wdk-module@latest swap jupiter solanaIt supports seven module types: wallet, swap, bridge, lending, fiat, swidge, and sda. You fill in the integration logic; the template provides the interface, naming convention, and project structure.
The practical consequence for you as an integrator: the module you need may not exist yet, and that's a solvable problem. Following posts in this series will walk through building one.
What's available today
Category | Modules |
|---|---|
Swidge (swap + bridge routes) | Orchestra (Flashnet), Rhino.fi, Symbiosis, LI.FI |
Swap (standalone) | Velora EVM |
Bridge (standalone) | USDT0, EVM to EVM and non-EVM |
Lending | Aave V3 EVM · Morpho (Vault V2 and Blue) |
Fiat | MoonPay |
Pricing | CoinGecko, Bitfinex |
Pricing modules are the quiet enabler. That "earning 4.1% annually" line in our savings app needs a token price to render a fiat balance. PricingClient implementations for CoinGecko and Bitfinex handle current prices, batched lookups, and historical series, so you're not writing yet another price-fetching hack.The full list lives in the all modules reference.
Why this is the powerful part
The protocol abstraction removes scope. When integrating a lending protocol costs one import and one registration, it makes it accessible to every mobile developer.
Imagine. A remittance app can route through the cheapest corridor instead of hardcoding one. A payroll tool can hold treasury in a yield-bearing position between pay cycles. These aren't crypto products. They're ordinary products that happen to use crypto rails, which is the only version of this that ever reaches a billion people.
And it comprises everything from the wallet to the gasless wallet series. Gasless wallet plus protocol modules means a user can deposit fiat, move assets across chains, and earn yield without ever seeing, buying, or thinking about chains and their native token.
Key Insights
- Two layers, one core: wallet modules speak blockchain, protocol modules wrap everything above it. Both register on the same WDK instance, using accounts from the same seed phrase.
- Interface shapes: a single generic interface would have been a worse abstraction. An interface per protocol type keeps what matters visible.
- Always quote first: every category exposes a quote, the same discipline as wallet transactions. No surprises for the user.
- Providers are swappable: four routers implement one Swidge interface. Changing vendor is a config change, not a refactor.
- The type list is open: swap, bridge, lending, and fiat exist today. Privacy, perpetuals, and prediction markets don't. But any protocol with a stable interface can become a WDK module.
What's next
This post covered the what and the why. The rest of the series gets hands-on, one category at a time, in the same step-by-step format as the gasless wallet posts (including any necessary API keys and dashboard screenshots).
- Swap and Bridge in WDK: the Swidge interface in depth, provider selection, runtime route discovery, fee caps, and the configuration that keeps routes compatible with gasless execution.
- Lending in WDK: supply, withdraw, health factors, and turning a yield position into a product feature.
- Fiat On-Ramp and Off-Ramp in WDK: widget URLs, backend signing done properly, and the KYC handoff.
- Build a Savings App with WDK, End to End: all of it composed on a gasless wallet, as a working proof of concept.
- Build Your Own WDK Protocol Module: because the categories above and providers are a starting point, not a ceiling. Another lending protocol, or privacy, perpetuals, and prediction markets could become a WDK module. The naming convention is an open invitation.
Follow WDK's official X account for announcements, and join us on Discord, the best place to ask questions, share what you're building, and get help directly from the team.
Ready to explore?
All Modules Reference →
Swap and Bridge Modules →
Lending Modules →
Fiat Modules →
Contribute a Module →
GitHub →
Receive the latest WDK news
Click to subscribe to the WDK newsletter and stay updated!



