npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lifi/wdk-protocol-swidge-lifi

v0.5.1

Published

WDK Swidge module for LI.FI — lets any WDK wallet account swap and bridge tokens via LI.FI using the ISwidgeProtocol interface.

Readme

@lifi/wdk-protocol-swidge-lifi

Powered by WDK License: Apache 2.0

WDK Swidge module for LI.FI — lets any WDK wallet account swap and bridge tokens across chains via LI.FI using the ISwidgeProtocol interface.

Implements ISwidgeProtocol from @tetherto/wdk-wallet >= 1.0.0-beta.9. By implementing SwidgeProtocol, this module automatically satisfies both ISwapProtocol and IBridgeProtocol — one module, every route LI.FI supports.

Install

npm install @lifi/wdk-protocol-swidge-lifi

Peer dependencies (install the ones you need):

npm install @tetherto/wdk-wallet-evm          # EOA accounts
npm install @tetherto/wdk-wallet-evm-erc-4337  # ERC-4337 smart accounts (optional)

Usage

Quote and bridge USDT from Ethereum to Arbitrum

import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
import { LifiSwidgeProtocol } from '@lifi/wdk-protocol-swidge-lifi'

const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
  provider: 'https://mainnet.infura.io/v3/YOUR_KEY'
})

const protocol = new LifiSwidgeProtocol(account, {
  integrator: 'your-integrator-id',  // optional
  order: 'RECOMMENDED'
})

// Non-binding quote
const quote = await protocol.quoteSwidge({
  fromToken: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT on Ethereum
  toToken:   '0xdAC17F958D2ee523a2206206994597C13D831ec7', // same — resolved to symbol cross-chain
  toChain: 'arbitrum',
  fromTokenAmount: 10_000_000n // 10 USDT (6 decimals)
})

console.log(`Receive ~${quote.toTokenAmount} USDT on Arbitrum`)

// Execute
const result = await protocol.swidge({
  fromToken: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  toToken:   '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  toChain: 'arbitrum',
  fromTokenAmount: 10_000_000n
})

console.log(`Bridge tx: ${result.hash}`)

// Poll status
let { status } = await protocol.getSwidgeStatus(result.id, { fromChain: 1, toChain: 42161 })

Same-chain swap

const result = await protocol.swidge({
  fromToken: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
  toToken:   '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
  // toChain omitted → same chain as wallet
  fromTokenAmount: 10_000_000n
})

Discovery (no account needed)

const protocol = new LifiSwidgeProtocol(undefined, {
  provider: 'https://mainnet.infura.io/v3/YOUR_KEY'
})

const chains = await protocol.getSupportedChains()
const tokens = await protocol.getSupportedTokens({ fromChain: 1 })

Configuration

new LifiSwidgeProtocol(account, {
  // WDK fee caps (basis points of input amount)
  maxNetworkFeeBps: 100,       // reject if gas > 1% of input (USD-based for cross-token)
  maxProtocolFeeBps: 50,       // reject if LI.FI fee > 0.5% of input (source token units)

  // LI.FI options
  integrator: 'my-app',        // integrator identifier header
  apiKey: 'sk-...',            // API key for higher rate limits — server-side only
  order: 'RECOMMENDED',        // 'RECOMMENDED' | 'FASTEST' | 'CHEAPEST'
  allowBridges: ['stargate'],  // whitelist specific bridges
  denyBridges: ['across'],     // blacklist specific bridges
  allowDestinationCall: true,  // include routes with a destination-chain call/swap (LI.FI default)
  allowNativeValue: true,      // set false to reject routes that require native token value (gasless)

  // Reliability (defaults shown — modeled on the LI.FI SDK)
  timeout: 30_000,             // ms per API request attempt
  retries: 1,                  // extra attempts on 5xx / 429 / network errors / timeouts; 0 disables
  retryDelay: 500,             // base backoff in ms, doubled per attempt, capped at 5000

  // Security (opt-in)
  trustedContracts: true,      // require quote tx target + approval address to be known LI.FI contracts
})

Fee caps can also be overridden per call:

await protocol.swidge(options, { maxProtocolFeeBps: 20 })

Quote-first flows: minAmountOut

swidge() always fetches a fresh quote at execution time, so in a quote-first UI the route the user accepted can differ from the route that executes if the market moves in between. Pass the displayed quote's toTokenAmountMin as the minAmountOut option (WDK-standard SwidgeOptions field since @tetherto/wdk-wallet 1.0.0-beta.14): if the fresh execution quote's worst-case output falls below it, swidge() throws before any approval or transaction is sent, and the app can re-quote and ask the user again.

const quote = await protocol.quoteSwidge(options)
// ... user reviews and accepts the displayed quote ...
const result = await protocol.swidge({ ...options, minAmountOut: quote.toTokenAmountMin })

minAmountOut is enforced at execution only — quoteSwidge() ignores it and always returns the quoted amounts, so the app can display the fresh numbers when re-quoting. It is not forwarded to LI.FI. When omitted, behavior is unchanged.

By default the module mirrors LI.FI's own routing behavior: no bridges are denied, routes with a destination-chain call are allowed (allowDestinationCall is only forwarded when explicitly set), and quotes whose transaction carries native token value are executed as-is. Setting allowDestinationCall: false excludes routes that need a destination-chain call, such as a swap after bridging, avoiding PARTIAL outcomes where the bridge succeeds but the destination swap cannot complete and the user receives an intermediary token.

Gasless integrations

Wallets that cannot spend native tokens (e.g. ERC-4337 accounts with a paymaster) should opt into gasless mode explicitly:

import LifiSwidgeProtocol, { NATIVE_VALUE_BRIDGE_DENY_LIST } from '@lifi/wdk-protocol-swidge-lifi'

new LifiSwidgeProtocol(account, {
  denyBridges: NATIVE_VALUE_BRIDGE_DENY_LIST, // filter out native-fee bridges at quote time
  allowNativeValue: false                     // reject any remaining native-value quote before execution
})

NATIVE_VALUE_BRIDGE_DENY_LIST is the maintained list of bridges known to require native token value in the source transaction (glacis, stargateV2, stargateV2Bus, squid, arbitrum, and gasZipBridge). With allowNativeValue: false, swidge() rejects any quote whose transactionRequest.value is greater than zero before sending approvals or the bridge transaction.

Reliability

All LI.FI API calls go through a central request layer modeled on the LI.FI SDK:

  • Timeouts — every request is aborted after timeout ms (default 30s) instead of hanging.
  • Retries — transient failures (5xx, network errors, timeouts) are retried with exponential backoff. 429 responses honor the Retry-After header when present.
  • Error classification — HTTP statuses map to typed errors: 409 → LifiSlippageError (stale quote, request a new one), 429 → LifiRateLimitError, timeouts → LifiTimeoutError, persistent network failures → LifiNetworkError.

When polling getSwidgeStatus(), a LifiStatusError with err.lifiStatus === 'NOT_FOUND' means the transaction is not indexed yet — treat it as still pending (see examples/bridge-usdt.js).

Security

The transaction data returned by the LI.FI quote API is always structurally validated (valid target address, hex calldata, parseable amounts) before being forwarded to the wallet.

Setting trustedContracts additionally requires the transaction target and approval address to be known LI.FI contracts, rejecting with LifiUntrustedContractError before any approval is granted:

// Built-in allowlist: per-chain LI.FI Diamond deployments + Permit2
new LifiSwidgeProtocol(account, { trustedContracts: true })

// Extend the built-ins with additional trusted addresses per chain ID
new LifiSwidgeProtocol(account, { trustedContracts: { 137: '0x...' } })

This check is opt-in to match LI.FI SDK behavior and because some chains use non-canonical Diamond deployments. The built-in allowlist covers the canonical address and known exceptions (e.g. zkSync Era); verify against LI.FI deployments before enabling on uncommon chains.

Supported chains

All chains supported by LI.FI — call getSupportedChains() for the live list. Common string aliases for toChain: ethereum, arbitrum, base, optimism, polygon, bsc, avalanche, scroll, zksync, and 60+ more. Raw numeric chain IDs are also accepted.

Status mapping

| LI.FI status | Substatus | SwidgeStatus | |---|---|---| | PENDING | — | pending | | DONE | COMPLETED | completed | | DONE | PARTIAL | partial | | DONE | REFUNDED | refunded | | DONE | NOT_PROCESSABLE_REFUND_NEEDED | refund-pending | | FAILED | — | failed | | any | requiredActions non-empty | action-required |

Fee mapping

| LI.FI cost type | SwidgeFeeType | Legacy field | |---|---|---| | gasCosts[].type === 'SEND' | network | fee | | feeCosts[] | protocol | bridgeFee |

Each fee uses its LI.FI cost token's chainId when available. This identifies the chain where the fee token is charged or denominated, which may differ from the chain where the underlying execution or gas consumption occurs. If LI.FI does not identify the token chain, the optional chain field is omitted rather than inferred from the route.

Error types

| Class | When thrown | |---|---| | LifiConfigurationError | Missing or invalid provider/config | | LifiQuoteError | LI.FI quote or token API error | | LifiExecutionError | Fee cap exceeded before any transaction | | LifiStatusError | LI.FI status API error or unknown id | | LifiReadOnlyAccountError | swidge() called with read-only or absent account | | LifiUnsupportedChainError | Unknown chain name string passed as toChain | | LifiTimeoutError | API request exceeded the configured timeout | | LifiNetworkError | Network-level failure persisted after all retries | | LifiRateLimitError | 429 from the API after retries were exhausted | | LifiSlippageError | 409 from the quote API — stale quote, request a new one (subclass of LifiQuoteError) | | LifiValidationError | Invalid user input or malformed API response, thrown before execution | | LifiUntrustedContractError | Quote target/approval address not in the trustedContracts allowlist (subclass of LifiExecutionError) |

All errors extend LifiProtocolError which extends Error.

TypeScript

Type declarations are generated from JSDoc and shipped in types/. Consumers get full typings for the protocol class, config, and all error classes. After changing public JSDoc, regenerate with:

npm run build:types

Publishing

This package does not bundle or transpile its runtime JavaScript. It ships ESM source files directly from index.js, src/, and bare.js, plus generated type declarations in types/. Before handing off a release, run:

npm run lint
npm test
npm run build:types
npm audit --omit=dev
npm publish --dry-run

The actual npm release command is:

npm publish --access public

Support

  • Integration questions: open an issue on GitHub or reach the LI.FI developer relations team at help.li.fi/hc/en-us.
  • WDK-specific questions: use your assigned Tether partner Slack channel.

Security

See SECURITY.md for the vulnerability disclosure process.

License

Apache 2.0 — see LICENSE.