Skip to content

Repository files navigation

@0x/wdk-protocol-swidge-0x

Built with WDK License: Apache 2.0

WDK Swidge protocol module for EVM token swaps via the 0x Swap API v2.

This module implements the SwidgeProtocol interface from @tetherto/wdk-wallet, letting any WDK-based wallet perform same-chain EVM swaps through 0x's aggregated liquidity — with automatic ERC-20 approval handling and on-chain status tracking.

Note: Cross-chain bridging via 0x is not yet supported. toChain must equal the source chain.


Installation

npm install @0x/wdk-protocol-swidge-0x

Configuration

Option Type Required Description
chainId number | string EVM chain ID of the bound wallet account
apiKey string 0x API key — get one at dashboard.0x.org
baseUrl string API base URL. Defaults to https://api.0x.org
defaultSlippage number Default slippage as a decimal (e.g. 0.005 = 0.5%). Defaults to no slippage param sent
skipApproval boolean Skip automatic ERC-20 approval before swapping
maxNetworkFeeBps number | bigint Maximum network fee in basis points of the input amount
maxProtocolFeeBps number | bigint Maximum protocol fee in basis points of the input amount

Store your API key in an environment variable — never commit it to source control:

# .env
ZERO_EX_API_KEY=your_api_key_here

Usage

import ZeroExProtocol from '@0x/wdk-protocol-swidge-0x'

const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'

// ── 1. Get an indicative quote (no wallet needed) ──────────────────────────

const protocol = new ZeroExProtocol(undefined, {
  chainId: 1, // Ethereum mainnet
  apiKey: process.env.ZERO_EX_API_KEY,
  defaultSlippage: 0.005 // 0.5%
})

const quote = await protocol.quoteSwidge({
  fromToken: USDC,
  toToken: WETH,
  fromTokenAmount: 100_000_000n // 100 USDC (6 decimals)
})

console.log('Estimated WETH out:', quote.toTokenAmount)
console.log('Minimum WETH out:  ', quote.toTokenAmountMin)

// ── 2. Execute (requires a full WDK EVM wallet account) ───────────────────

import WalletManagerEvm from '@tetherto/wdk-wallet-evm'

const manager = new WalletManagerEvm(process.env.MNEMONIC, {
  provider: process.env.ETH_RPC,
  chainId: 1
})
const account = await manager.getAccount(0)

const execProtocol = new ZeroExProtocol(account, {
  chainId: 1,
  apiKey: process.env.ZERO_EX_API_KEY,
  defaultSlippage: 0.005
})

const result = await execProtocol.swidge({
  fromToken: USDC,
  toToken: WETH,
  fromTokenAmount: 100_000_000n
})

console.log('Swap submitted:', result.hash)

// ── 3. Poll for status ────────────────────────────────────────────────────

let status
do {
  await new Promise(r => setTimeout(r, 3000))
  const s = await execProtocol.getSwidgeStatus(result.id)
  status = s.status
  console.log('Status:', status)
} while (status === 'pending')

See examples/swap-usdc-to-weth.js for a runnable example.


Supported chains

Chain Chain ID
Abstract 2741
Arbitrum One 42161
Avalanche C-Chain 43114
Base 8453
Berachain 80094
BNB Smart Chain 56
Ethereum 1
HyperEVM 999
Ink 57073
Linea 59144
Mantle 5000
Monad 143
OP Mainnet 10
Plasma 9745
Polygon 137
Scroll 534352
Sonic 146
Tempo 4217
Unichain 130
World Chain 480

Call getSupportedChains() to retrieve the full list at runtime.


Token discovery

The 0x Swap API accepts any liquid ERC-20 token by contract address. There is no supported token list — getSupportedTokens() throws NotImplementedError. Pass token addresses directly to quoteSwidge and swidge.

For native ETH (or any chain's native token), use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE or one of the aliases 'native', 'eth', '', or the zero address. Aliases are matched case-insensitively and rewritten to the sentinel before the request is sent. Native tokens are supported as both the sell token and the buy token.

Note that 'eth' and '' mean the chain's native token on every supported chain — on Polygon, 'eth' resolves to POL. Any other value is forwarded to the 0x API unchanged; the module does not validate or checksum non-native token addresses.


Status mapping

On-chain state SwidgeStatus
Transaction unknown to the network throws ZeroExUnknownTransactionError
Transaction known, no receipt yet pending
Receipt with success status completed
Receipt with reverted status failed

The module has no server-side status endpoint; status is resolved from on-chain state via the bound wallet account.

When the account exposes getTransactionByHash, transaction existence is checked first so a well-formed id that the network has no record of throws ZeroExUnknownTransactionError instead of reporting pending forever. The receipt then resolves completed / failed, or pending while in-flight.

Fallback: if the account exposes only getTransactionReceipt, an unknown transaction cannot be distinguished from an in-flight one, so status is derived from the receipt alone and reported as pending when no receipt exists yet. If the account exposes neither method, status is always pending.


Fee mapping

0x response field SwidgeFeeType Notes Legacy mapping
totalNetworkFee network Denominated in the chain's native token (e.g. ETH) fee
fees.zeroExFee protocol 0x protocol fee bridgeFee
fees.integratorFee affiliate Integrator / referral fee not visible

Fee caps (maxNetworkFeeBps, maxProtocolFeeBps) are expressed in basis points of the sell-token input amount and enforced fail-closed — a configured cap that cannot be evaluated rejects the swap with ZeroExFeeLimitExceededError:

  • maxNetworkFeeBps — the network fee is always denominated in the chain's native token. When the sell token is the native token the comparison is direct; otherwise the fee is converted into sell-token terms via one extra 0x /price request (native → sell token). If no conversion route is available, the swap is rejected.
  • maxProtocolFeeBps — compared directly when the protocol fee token matches the sell token (the common case). If the fee comes back denominated in another token it cannot be compared and the swap is rejected.

Error types

Class When thrown
ZeroExApiError The 0x API returned a non-2xx response
ZeroExInsufficientLiquidityError liquidityAvailable: false in the price response
ZeroExFeeLimitExceededError A quoted fee exceeds a configured maxNetworkFeeBps / maxProtocolFeeBps cap, or a configured cap cannot be evaluated (fail-closed)
ZeroExReadOnlyError swidge is called without a full signing account
ZeroExValidationError Invalid or missing input parameters
ZeroExUnsupportedOperationError An unsupported operation is requested (e.g. cross-chain toChain)
ZeroExUnknownTransactionError getSwidgeStatus is called for a transaction the network has no record of
ZeroExTransactionRevertedError The swap transaction reverted on-chain
ZeroExTimeoutError Timed out waiting for transaction confirmation
NotImplementedError getSupportedTokens() is called

WDK interface

This module implements SwidgeProtocol from @tetherto/wdk-wallet ^1.0.0-beta.11.

The swap, quoteSwap, bridge, and quoteBridge methods are inherited from the base class and delegate to swidge / quoteSwidge respectively.


Development

npm install       # install dependencies
npm test          # run unit tests
npm run lint      # check code style (JavaScript Standard Style)
npm run build:types  # generate TypeScript declarations in types/

End-to-end test against the live 0x API (read-only, no wallet needed):

ZERO_EX_API_KEY=... npm run e2e

To test real swap execution, add a BIP-39 mnemonic:

ZERO_EX_API_KEY=... MNEMONIC="word word ..." npm run e2e

Verified on mainnet

End-to-end tested against the live 0x API on Base mainnet (chain 8453):

Swap Chain Tx
1 USDC → WETH Base 0x87afe3…704ec

Unsupported options

The following fields from SwidgeCommonOptions are accepted by the interface but not supported by this module:

Option Reason
toChain Cross-chain bridging is not implemented. Passing a toChain that differs from the configured chainId throws an error.
refundAddress The 0x AllowanceHolder flow has no refund path. This field is silently ignored.

Rate limits

The 0x Swap API enforces rate limits based on your plan tier:

Plan Rate limit
Standard (free) 5 requests per second
Custom Higher limits available on request

Limits are enforced on fixed 1-second windows across all endpoints combined. The API returns HTTP 429 Too Many Requests when the limit is exceeded.

See the 0x rate limits documentation for details and to discuss higher limits.


Support

Open an issue at github.com/0xProject/wdk-protocol-swidge-0x/issues.


Security

See SECURITY.md for the vulnerability disclosure process.


License

Apache 2.0 — see LICENSE.

About

WDK module to swap tokens on EVM blockchains using 0x DEX aggregator.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages