A powerful and flexible toolkit designed for seamless integration with multiple decentralized exchanges (DEXs) across various blockchain networks. It simplifies complex trading operations by providing advanced routing algorithms, real-time pricing, and streamlined transaction management, making it an essential tool for developers looking to enhance their DEX interactions effortlessly.
NOTE: WIP. V2 is fully functional on most DEXs. V3 is a WIP/Untested.
Architecture may change in the future to instead use each DEXs official SDK with a standardized interface.
- Features
- Supported Libraries
- Installation
- Packages
- Import Examples
- Initialization
- Trade
- Getting a Quote
- Multi-DEX Quote
- Trade Directions
- Trade with Custom Settings
- Trade with Price Context
- Custom Network
- Custom DEX and Network
- Trade with Quote Changed Subscription
- Manual Requote
- Executing a Trade with Approve and Swap
- Approving Custom Router Allowance
- Approving Max Router Allowance
- Get Versioned Route Paths by DEX
- Get Route Quotes
- Get Pool Reserves
- Liquidity
- Provider (Dex Provider)
- Number (Dex Number)
- Token Contract
- Tokens
- Token List
- Contracts
- Supported DEXes and Chains
- Tests
- Related Toolkits
- Issues
- Contributing
- License
💕 Multi-DEX Support: Seamlessly interact with various decentralized exchanges like Uniswap, SushiSwap, PancakeSwap, PulseX, and others.
⛓️ Multi-Chain Compatibility: Trade with multiple blockchains such as Ethereum, Binance Smart Chain, PulseChain, and others.
🔮 Auto-Routing and Aggregation: Execute token swaps with the best rates using optimized multi-route algorithms, supporting both v2 and v3 routes together while aggregating across multiple DEXes for the most efficient trades.
🐸 Multi-Hop Routing: Optimize trades with multi-hop routing to achieve the best prices.
🔍 Transparent Routing: Get detailed insights into the routes and pricing calculations for your trades.
💰 Price Impact Calculation: Predict how your trades affect token prices and make informed decisions.
⚙️ Customizable Trade Settings: Modify slippage, recipient addresses, and other parameters to suit your trading strategy.
🕹️ Plug-n-Play: Easily configure any Uniswap compatible DEX on any EVM compatible network.
💸 Transaction Ready: Generate the transaction data, simply fill in gas details, and send it with ease, streamlining the entire process.
🔄 Auto-Refreshing Quotes: Ensure your trade quotes remain up-to-date with block-based automatic updates.
📝 Pre-Formatted Figures: Token balances and trade amounts come ready for direct UI rendering.
🧳 Wallet Integration: Check balances, generate transactions, and interact seamlessly with your wallet.
🧩 Token Metadata Retrieval: Fetch comprehensive token information like name, symbol, decimals, and more.
📡 Efficient Multicall Queries: Uses multicall to reduce JSON-RPC requests and fetch on-chain data quickly and efficiently.
🦎 Custom Price Sources: Leverage external price feeds like CoinGecko or CoinMarketCap for enriched price contexts.
📦 Optimized Bundle Size: Keep your project lightweight.
💯 Full TypeScript Support: Built with TypeScript for a seamless and type-safe development experience.
💎 Open Source and Community-Driven: Join the community on GitHub to contribute, report issues, or request features.
✨ And much more!
- Ethers.js 4.x and 5.x
npm install @dex-toolkit/core
# or
yarn add @dex-toolkit/core
# or
pnpm add @dex-toolkit/core
# or
bun add @dex-toolkit/core
Package | Description |
---|---|
@dex-toolkit/core |
Core module for seamless interaction with various decentralized exchanges, supporting trades, liquidity pools, and more. |
@dex-toolkit/types |
Comprehensive TypeScript type definitions for the entire toolkit, ensuring type safety and better developer experience. |
@dex-toolkit/utils |
A collection of helper functions and utilities for streamlining on-chain interactions, data formatting, and token management. |
@dex-toolkit/provider |
A wrapper around a provider that allows for multicall requests. |
@dex-toolkit/contracts |
A centralized repository of smart contract ABIs and addresses for supported DEXes across various networks. It provides easy access to contract interfaces and network-specific deployments. |
@dex-toolkit/number |
Numeric class extending BigNumber.js that manages decimal arithmetic with state-aware precision, primarily for blockchain and DeFi applications. It handles automatic decimal scaling, maintains atomic/decimal state tracking, and provides consistent conversion between common blockchain numeric representations (wei/ether, decimal/atomic, etc). Built for scenarios requiring high-precision decimal math with proper decimal place management |
var dexToolkit = require('@dex-toolkit/core')
const dexToolkit = require('@dex-toolkit/core')
import { DexFactory } from '@dex-toolkit/core'
There are multiple ways to initialize the library
import { DexFactory } from '@dex-toolkit/core'
const ethersProvider = new ethers.providers.JsonRpcProvider(
'https://rpc.example.com',
1,
)
const dexFactory = new DexFactory({
providerContext: { ethersProvider },
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
Provide an Ethers signer to:
- Execute transactions on behalf of the user
- Sign messages like permits
import { DexFactory } from '@dex-toolkit/core'
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.example.com',
1,
)
const signer = new ethers.Wallet('0xPrivateKey', provider)
const walletAddress = await signer.getAddress()
const dexFactory = new DexFactory({
providerContext: { ethersSigner: signer },
walletAddress,
dexContext: 'UNISWAP',
})
Simply provide the chainId and DexType
Will use Ethers.js behind the scenes
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
If the library doesn't support the chain you're using, you can provide a custom RPC URL to the providerContext
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: {
chainId: 1
rpcUrl: 'https://rpc.example.com'
},
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
If the RPC URL requires authentication, you can provide the authentication details to the providerContext
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: {
chainId: 1,
providerType: 'infura',
apiKey: 'a0123456789abcdef0123456789abcdef',
},
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
import { DexFactory } from '@dex-toolkit/core'
import { DexProvider } from '@dex-toolkit/provider'
const dexProvider = new DexProvider({
chainId: 1,
rpcUrl: 'https://rpc.example.com',
})
const dexFactory = new DexFactory({
providerContext: dexProvider,
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
You can get a quote with a few lines of code.
import { DexFactory } from '@dex-toolkit/core'
// Create a factory which can be used to create a swap, liquidity pool, etc for the given configuration.
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: ['PULSEX'], // Pass in one or multiple DEXes
/**
* The format in which the trade context's number values will be returned.
*
* - `'readable'`: Returns a human-readable string with grouping (thousands separators) and specified decimal places (e.g., "1,234.567").
* - `'decimal'`: Outputs a precise decimal string representation without grouping, maintaining the decimal places specified (e.g., "1234.567").
* - `'wei'`: Outputs the value in its smallest unit, suitable for precise blockchain interactions (e.g., "1000000000000000000" for 1 Ether).
* - `'hex'`: Returns a hexadecimal string representation, useful for encoding values in blockchain transactions (e.g., "0x158e460913d000000000").
* - `'dexnumber'`: Returns the current instance as a `DexNumber` object.
* - `'bignumber'`: Returns an instance of `BigNumber` from `bignumber.js`.
* - `'ethers'`: Returns a `BigNumber` instance from `ethers.js`.
* - `'bigint'`: Converts and returns the value as a native JavaScript `BigInt`.
*/
format: { type: 'readable' },
})
// Create a trade from the factory
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
toTokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
})
// Generate a trade quote
const quote = await trade.quote('100')
console.log(quote)
// Example of the trade quote containing various information about the swap,
// including `transaction` which can be used to execute the swap.
const exampleConsoleLog = {
/**
* The unique ID for the context
*/
id: 'f358a3a6-a6be-4eaf-a407-4f10fe76131b',
/**
* The tag of the DEX used for the trade.
*/
dexTag: 'PULSEX',
/**
* The protocol of the DEX used for the trade.
*/
protocol: 'protocolV2',
/**
* The version of the DEX used for the trade.
*/
version: { major: 1, minor: 0, patch: 0 },
/**
* The direction of the trade, indicating whether the trade is an input (buy) or output (sell) operation.
*/
tradeDirection: 'input',
/**
* The base amount to be converted in the trade, represented as a string.
*/
baseConvertRequest: '100',
/**
* The minimum amount to receive from the trade, accounting for slippage.
* Undefined when the trade direction is output.
*/
minAmountConvertQuote: '1032.042070',
/**
* The maximum amount that can be sent for the trade.
* Undefined when the trade direction is input.
*/
maximumSent: undefined,
/**
* The expected amount to be received or converted from the trade.
*/
expectedConvertQuote: '1037.228211',
/**
* The liquidity provider fee for the trade, which can be a single number (v2) or an array of numbers (v3).
* Undefined when wrapping/unwrapping tokens.
*/
liquidityProviderFee: '0.300000000000000000',
/**
* The liquidity provider fee as a percentage for the trade, which can be a single number (v2) or an array of numbers (v3).
* Undefined when wrapping/unwrapping tokens.
*/
liquidityProviderFeePercent: 0.003,
/**
* The Unix timestamp indicating when the trade expires.
*/
tradeExpires: 1726098260,
/**
* The impact of the trade on the price of the assets being traded.
* Undefined when price impact is disabled in the trade settings.
*/
priceImpact: {
/**
* The 100-based percentage representing the price impact of the trade.
* Undefined when price impact is disabled in the trade settings.
*/
percentage: '0.32',
/**
* Whether the price impact is considered minimal, less than "0.01%".
*/
isMinimal: false,
},
/**
* The tokens involved in the route path of the trade.
*/
routePathTokens: [
{
name: 'Uniswap token',
symbol: 'UNI',
decimals: 18,
color: 'rgb(247, 30, 185)',
chainId: 943,
contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png',
},
{
name: 'Wrapped Pulse',
symbol: 'WPLS',
decimals: 18,
color: 'rgb(5, 185, 213)',
chainId: 943,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x70499adEBB11Efd915E3b69E700c331778628707/logo.png',
},
{
name: 'Tether USD',
symbol: 'USDT',
decimals: 6,
color: '',
chainId: 943,
contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png',
},
],
/**
* A human-readable representation of the route path for the trade.
*/
routePathText: 'UNI > WPLS > USDT',
/**
* The addresses of the tokens involved in the route path of the trade.
*/
routePathAddresses: [
'0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
'0x70499adEBB11Efd915E3b69E700c331778628707',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
],
/**
* The addresses of the pairs involved in the trade.
*/
pairAddresses: [
'0x7b813BB8df019Cb351CdD31151C208E9c02885A1',
'0x362289D3Cf77BdD4c2523C83d0d6DB49231b5290',
],
/**
* A collection of attempted route quotes categorized by DEX type.
*/
attemptedRouteQuotes: {
PULSEX: [
{
expectedConvertQuote: '1037.228211',
expectedConvertQuoteOrTokenAmountInMaxWithSlippage: '1032.042070',
transaction: {
to: '0xDaE9dd3d1A52CfCe9d5F2fAC7fDe164D500E50f7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x38ed17390000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000000000000003d83b65600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000acae34847ab1c58e61f7caa8a5f7e755a08195b10000000000000000000000000000000000000000000000000000000066e2413700000000000000000000000000000000000000000000000000000000000000030000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000070499adebb11efd915e3b69e700c331778628707000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7',
value: '0x00',
},
tradeExpires: 1726103863,
routePathTokens: [
{
name: 'Uniswap token',
symbol: 'UNI',
decimals: 18,
color: 'rgb(247, 30, 185)',
chainId: 943,
contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png',
},
{
name: 'Wrapped Pulse',
symbol: 'WPLS',
decimals: 18,
color: 'rgb(5, 185, 213)',
chainId: 943,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x70499adEBB11Efd915E3b69E700c331778628707/logo.png',
},
{
name: 'Tether USD',
symbol: 'USDT',
decimals: 6,
color: '',
chainId: 943,
contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png',
},
],
routePathText: 'UNI > WPLS > USDT',
routePathAddresses: [
'0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
'0x70499adEBB11Efd915E3b69E700c331778628707',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
],
pairAddresses: [
'0x7b813BB8df019Cb351CdD31151C208E9c02885A1',
'0x362289D3Cf77BdD4c2523C83d0d6DB49231b5290',
],
dexTag: 'PULSEX',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
liquidityProviderFeePercent: 0.003,
tradeDirection: 'input',
},
{
expectedConvertQuote: '1033.150867',
expectedConvertQuoteOrTokenAmountInMaxWithSlippage: '1027.985113',
transaction: {
to: '0xDaE9dd3d1A52CfCe9d5F2fAC7fDe164D500E50f7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x38ed17390000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000000000000003d45ced900000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000acae34847ab1c58e61f7caa8a5f7e755a08195b10000000000000000000000000000000000000000000000000000000066e2413700000000000000000000000000000000000000000000000000000000000000040000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000070499adebb11efd915e3b69e700c331778628707000000000000000000000000826e4e896cc2f5b371cd7bb0bd929db3e3db67c0000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7',
value: '0x00',
},
tradeExpires: 1726103863,
routePathTokens: [
{
name: 'Uniswap token',
symbol: 'UNI',
decimals: 18,
color: 'rgb(247, 30, 185)',
chainId: 943,
contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png',
},
{
name: 'Wrapped Pulse',
symbol: 'WPLS',
decimals: 18,
color: 'rgb(5, 185, 213)',
chainId: 943,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x70499adEBB11Efd915E3b69E700c331778628707/logo.png',
},
{
name: 'Dai Stablecoin',
symbol: 'tDAI',
decimals: 18,
color: '',
chainId: 943,
contractAddress: '0x826e4e896CC2f5B371Cd7Bb0bd929DB3e3DB67c0',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x826e4e896CC2f5B371Cd7Bb0bd929DB3e3DB67c0/logo.png',
},
{
name: 'Tether USD',
symbol: 'USDT',
decimals: 6,
color: '',
chainId: 943,
contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png',
},
],
routePathText: 'UNI > WPLS > tDAI > USDT',
routePathAddresses: [
'0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
'0x70499adEBB11Efd915E3b69E700c331778628707',
'0x826e4e896CC2f5B371Cd7Bb0bd929DB3e3DB67c0',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
],
pairAddresses: [
'0x7b813BB8df019Cb351CdD31151C208E9c02885A1',
'0xA2D510bf42D2B9766DB186F44a902228E76ef262',
'0xDfB8224F112a5500306Df87a18Eec140332ee1Dd',
],
dexTag: 'PULSEX',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
liquidityProviderFeePercent: 0.003,
tradeDirection: 'input',
},
],
},
/**
* The transaction required for approving the maximum allowance.
* Undefined when no approval is needed.
*/
approvalTransaction: {
to: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x095ea7b3000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
value: '0x00',
},
/**
* The info for the token being traded from (the input token).
*/
fromTokenInfo: {
token: {
name: 'Uniswap token',
symbol: 'UNI',
decimals: 18,
color: 'rgb(247, 30, 185)',
chainId: 943,
contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png',
},
balance: '0',
hasEnoughBalance: false,
allowance: '79228162514264337593543950335',
hasEnoughAllowance: true,
isMaxAllowance: false,
value: 0,
},
/**
* The info for the token being traded to (the output token).
*/
toTokenInfo: {
token: {
name: 'Tether USD',
symbol: 'USDT',
decimals: 6,
color: '',
chainId: 943,
contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png',
},
balance: '0.042585',
value: 0,
},
/**
* The transaction object representing the trade.
*/
transaction: {
to: '0xDaE9dd3d1A52CfCe9d5F2fAC7fDe164D500E50f7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x38ed17390000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000000000000003d83b65600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000acae34847ab1c58e61f7caa8a5f7e755a08195b10000000000000000000000000000000000000000000000000000000066e22b5400000000000000000000000000000000000000000000000000000000000000030000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000070499adebb11efd915e3b69e700c331778628707000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7',
value: '0x00',
},
/**
* The source of the estimated gas price for the trade.
* Undefined when gas settings were not set in the trade settings.
*/
gasPriceEstimatedBy: undefined,
}
Provide multiple DEX configurations and get the best quote possible.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: [
'UNISWAP',
'SUSHISWAP',
'PANCAKESWAP',
{ YOUR_CUSTOM_DEX_CONFIG },
],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote('100')
console.log(quote)
There are two trade directions input
and output
.
input
: The amount of the input token is known and the amount of the output token is unknown.output
: The amount of the output token is known and the amount of the input token is unknown.
import { DexFactory } from '@dex-toolkit/core'
import { tradeDirectionMap } from '@dex-toolkit/utils'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: ['UNISWAP', 'SUSHISWAP', 'PANCAKESWAP'],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const fromTokenAmount = '100'
// By default the trade direction is input
let quote = await trade.quote(fromTokenAmount)
// You may also specify it explicitly
quote = await trade.quote({
direction: 'input',
fromAmount: fromTokenAmount,
})
// The quote will return the amount of the output tokens expected
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: ['UNISWAP', 'SUSHISWAP', 'PANCAKESWAP'],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote({
direction: 'output',
toAmount: '100',
})
// The quote will return the amount of the input tokens needed to output 100 tokens
Create a trade quote with custom settings.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
// Turn off price context
multiPriceContext: undefined,
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
// All settings are optional
settings: {
/**
* The address that will receive the output tokens from the swap.
* If not provided, the default is to send the output tokens to the address initiating the swap.
*
* @default ''
*/
recipient: '0x1234...',
/**
* Slippage in percentage
* For example, a value of 0.005 will be 0.5% or 50 bips.
*
* @default 0.005
*/
slippage: 0.005,
/**
* The number of minutes before the transaction expires.
*
* @default 20
*/
deadlineMinutes: 20,
/**
* Disable multihops, forcing direct routes.
*
* @default false
*/
disableMultihops: false,
/**
* Prevent the built-in block listener from observing changes.
*
* @default false
*/
disableObserver: false,
/**
* Number of blocks to skip between each quote, reducing the number of calls to the node.
*
* @default 0
*/
observerBlockSkip: 3,
/**
* When `true`, disables the price impact calculation for the trade.
*
* @default false
*/
disablePriceImpact: false,
/**
* When `true`, enables support for fee-on-transfer tokens (commonly used by deflationary tokens).
* Fee-on-transfer tokens automatically deduct a percentage as a fee upon each transfer.
*
* @default false
*/
hasFeeOnTransfer: false,
/**
* Filter to choose which DEX versions to use. Defaults to all.
*
* @default All protocols of targeted DEXs
*/
protocolSettings: {
protocolV2: {
// Enables/disables all versions of the protocol
enabled: true,
// Optionally include/exclude versions
includeVersions: [{ major: 1, minor: 0, patch: 0 }],
excludeVersions: [{ major: 2, minor: 0, patch: 0 }],
},
protocolV3: {
enabled: true,
includeVersions: [{ major: 1, minor: 0, patch: 0 }],
excludeVersions: [{ major: 2, minor: 0, patch: 0 }],
},
},
/**
* Gas price settings, where the `getGasPrice` function returns the gas price in GWEI.
*
* @default undefined
*/
gasSettings: {
getGasPrice: async () => '90',
},
/**
* Whether to approve the the maximum token amount, or the exact token amount.
*
* @default true
*/
approveMax: true,
/**
* Multiplier for the token approval amount to add a buffer.
* Only applies when `approveMax` is false.
* For example, a value of 1.05 represents a 5% buffer.
*
* @default 1.05
*/
approvalBufferFactor: 1.05
},
})
const quote = await trade.quote('100')
console.log(quote)
Execute a trade with multi-source price context.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
multiPriceContext: {
priceCtxs: [
{ sourceType: 'coingecko', apiKey: 'your-api-key' },
{ sourceType: 'coinmarketcap', apiKey: 'your-api-key' },
{ sourceType: 'cryptocompare', apiKey: 'your-api-key' },
],
/**
* Describes the methods for calculating price from multiple sources.
* - `min`: Select the minimum price.
* - `max`: Select the maximum price.
* - `median`: Select the median price.
*/
calculationMethod: 'median',
},
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote('100')
console.log(quote)
You can initialize a provider in various ways, and provide a custom network if not supported out of the box.
import { DexFactory } from '@dex-toolkit/core'
import type { DexCustomNetwork, DexChainIdAndProviderContext } from '@dex-toolkit/types'
const chainId = 943
const rpcUrl = 'https://rpc.v4.testnet.pulsechain.com'
// Custom Network example (Optional)
const customNetwork: DexCustomNetwork = {
name: 'PulseChain Testnet',
multicallContractAddress: '0xcA11bde05977b3631167028862bE2a173976CA11',
nativeCurrency: {
name: 'Pulse',
symbol: 'tPLS',
},
nativeWrappedTokenInfo: {
name: 'Wrapped PLS',
symbol: 'WPLS',
decimals: 18,
chainId,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
},
}
const providerChainIdContext: DexChainIdAndProviderContext = {
chainId,
// Optional. Provide if chainId is not supported out of the box, or you want to override the default rpc url
rpcUrl: rpcUrl,
// Optional. Provide if you want to use a custom network not supported out of the box, or you want to override the default network
customNetwork,
}
const dexFactory = new DexFactory({
providerContext: providerChainIdContext,
walletAddress: '0x1234...',
dexContext: ['PULSEX'],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote('100')
console.log(quote)
Use a custom DEX and network configuration.
import { DexFactory } from '@dex-toolkit/core'
import { tradeDirectionMap } from '@dex-toolkit/utils'
import { providers } from 'ethers'
const chainId = 943
const ethersProvider = new ethers.providers.JsonRpcProvider(
'https://rpc.v4.testnet.pulsechain.com',
chainId,
)
const dexFactory = new DexFactory({
// You could also use a chainId and an optional custom rpc url instead of an ethers provider
providerContext: {
ethersProvider,
customNetwork: {
name: 'PulseChain Testnet',
multicallContractAddress: '0xcA11bde05977b3631167028862bE2a173976CA11',
nativeCurrency: { name: 'Pulse', symbol: 'tPLS' },
nativeWrappedTokenInfo: {
name: 'Wrapped PLS',
symbol: 'WPLS',
decimals: 18,
chainId,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
},
},
},
walletAddress: '0x1234...',
dexContext: [
{
dexType: 'CUSTOM',
dexTag: 'CUSTOM_DEX_NAME',
protocols: {
protocolV2: {
'1-0-0': {
feePercent: 0.003,
router: {
address: '0x1715a3E4A142d8b698131108995174F37aEBA10D',
abi: pulseXRouterV2ABI,
methods: {
...defaultRouterMethodMapV2,
// You can map custom method names to keep contracts compatible with other dexes
WETH: 'WPLS',
},
},
factory: {
address: '0x29eA7545DEf87022BAdc76323F373EA1e707C523',
abi: uniswapFactoryV2ABI,
},
pair: {
abi: uniswapPairV2ABI,
},
},
'2-0-0': {
feePercent: 0.003,
router: {
address: '0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02',
abi: pulseXRouterV2ABI,
methods: {
...defaultRouterMethodMapV2,
WETH: 'WPLS',
},
},
factory: {
address: '0x29eA7545DEf87022BAdc76323F373EA1e707C523',
abi: uniswapFactoryV2ABI,
},
pair: {
abi: uniswapPairV2ABI,
},
},
},
},
},
],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote('100')
console.log('Custom DEX Quote:', quote)
Subscribe to quote changes during a trade.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
format: { type: 'dexnumber' },
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
settings: {
/**
* Number of blocks to skip between each quote, reducing the number of calls to the node.
*
* @default 0
*/
observerBlockSkip: 3,
},
})
const quote = await trade.quote('100')
const targetAmount = '2000'
// Listen for changes in our quote
const subscription = quote.observer$.subscribe(
async ({ blockNumber, latestQuote }) => {
const hitTargetAmount = latestQuote.expectedConvertQuote.gte(
DexNumber.fromUnshifted(
targetAmount,
latestQuote.toTokenInfo.token.decimals,
),
)
if (hitTargetAmount) {
subscription.unsubscribe()
// Or call unsubscribe from the quote
// quote.unsubscribe()
// Or call destroy to clean up all trade quotes and subscriptions
// trade.destroy()
const wallet = new Wallet('0xPrivateKey', trade.dexProvider.provider)
if (latestQuote.approvalTransaction) {
try {
const response = await wallet.sendTransaction(
latestQuote.approvalTransaction,
)
const receipt = await response.wait(1)
console.log('Approval receipt', receipt)
} catch (error) {
console.log(error)
}
}
const response = await wallet.sendTransaction(latestQuote.transaction)
const receipt = await response.wait(1)
console.log({ blockNumber, receipt })
}
},
)
Manually update trade quotes.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
settings: {
// Disable the built in quote observer
disableObserver: true,
},
})
const quote = await trade.quote('100')
// Here we use a block event to trigger the requote, but you can use any trigger you want
trade.dexProvider.provider.on('block', async () => {
console.log('Requoting...')
await trade.requote(quote.id)
})
// When ever `requote` is executed, the stream will update if there are any changes to the quote
const subscription = quote.observer$.subscribe(({ blockNumber, latestQuote }) => {
subscription.unsubscribe()
// Or call unsubscribe from the quote
// quote.unsubscribe()
// Or call destroy to clean up all trade quotes and subscriptions
// trade.destroy()
console.log(
`Quote changed (${blockNumber}): ${latestQuote.expectedConvertQuote} ${latestQuote.toTokenInfo.token.symbol}`,
)
})
Execute a trade with token approval and swap.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const quote = await trade.quote('100')
const wallet = new Wallet('0xPrivateKey', trade.dexProvider.provider)
if (quote.approvalTransaction) {
try {
const response = await wallet.sendTransaction(quote.approvalTransaction)
const receipt = await response.wait(1)
console.log('Approval receipt', receipt)
} catch (error) {
console.log(error)
}
}
const response = await wallet.sendTransaction(quote.transaction)
const receipt = await response.wait(1)
console.log('Swap receipt', receipt)
Generate and send a transaction to approve a custom router allowance without using the trade context.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: ['UNISWAP', 'SUSHISWAP', 'PANCAKESWAP'],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const transaction = await trade.generateApproveRouterAllowanceTransaction({
dexTag: 'UNISWAP',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
amount: '0.1',
})
console.log(transaction)
const wallet = new Wallet('0xPrivateKey', trade.dexProvider.provider)
const response = await wallet.sendTransaction(transaction)
const receipt = await response.wait(1)
console.log('Approval receipt', receipt)
Generate and send a transaction to approve maximum router allowance without using the trade context.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: ['UNISWAP', 'SUSHISWAP', 'PANCAKESWAP'],
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const transaction = await trade.generateApproveRouterAllowanceTransaction({
dexTag: 'UNISWAP',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
// Omit amount to use the max allowance
})
console.log(transaction)
const wallet = new Wallet('0xPrivateKey', trade.dexProvider.provider)
const response = await wallet.sendTransaction(transaction)
const receipt = await response.wait(1)
console.log('Approval receipt', receipt)
Retrieve versioned route paths for a specific DEX.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const versionedRoutePathsByDex = await trade.getVersionedRoutePathsByDex()
console.log(versionedRoutePathsByDex)
Obtain route quotes for a trade.
import { DexFactory } from '@dex-toolkit/core'
import BigNumber from 'bignumber.js'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const routeQuotes = await trade.getRouteQuotes({
amountToTrade: '100',
tradeDirection: tradeDirectionMap.input,
})
console.log(routeQuotes)
Retrieve pool reserves for a specific pair.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0x1234...',
dexContext: 'PULSEX',
})
const trade = await dexFactory.createTrade({
fromTokenAddress: '0x1234...',
toTokenAddress: '0x5678...',
})
const reserves = await trade.getPoolReserves({
pairAddresses: ['0x7b813BB8df019Cb351CdD31151C208E9c02885A1'],
protocol: 'protocolV2',
dexTag: 'PULSEX',
version: { major: 1, minor: 0, patch: 0 },
})
console.log(reserves)
You can get a quote for adding liquidity with a few lines of code.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
dexContext: ['PULSEX'],
format: { type: 'readable' },
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
tokenBAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
})
const quote = await liquidity.addLiquidity({
dexTag: 'PULSEX',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
// Provide either the tokenA or tokenB amount and the other will be calculated automatically.
// Provide both to override the calculated values.
tokenAAmount: '100',
})
console.log(quote)
// Example of the liquidity quote containing various information for adding liquidity.
const exampleConsoleLog = {
/** The unique ID for the context */
id: 'f358a3a6-a6be-4eaf-a407-4f10fe76131b',
/** The tag of the decentralized exchange (DEX) being used */
dexTag: 'PULSEX',
/** The protocol of the DEX being used */
protocol: 'protocolV2',
/** The version of the DEX used for liquidity */
version: { major: 1, minor: 0, patch: 0 },
/** The direction of the liquidity operation (add or remove) */
liquidityDirection: 'add',
/** The slippage tolerance for the liquidity operation, expressed as a decimal (e.g., 0.01 for 1%) */
slippage: 0.005,
/** The Unix timestamp after which the transaction will revert */
deadline: 1731353101,
/**
* Set of transactions needed to enable token spending, if required.
* V2: If removing liquidity and permit data is passed in, this will be set to undefined.
*/
enableTransactions: {
/** The transaction needed to enable spending of tokenA, if required */
tokenA: {
to: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x095ea7b3000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
value: '0x00',
},
/** The transaction needed to enable spending of tokenB, if required */
tokenB: {
to: '0x70499adEBB11Efd915E3b69E700c331778628707',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0x095ea7b3000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
value: '0x00',
},
},
/** The main transaction that will perform the liquidity operation */
transaction: {
to: '0xDaE9dd3d1A52CfCe9d5F2fAC7fDe164D500E50f7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0xe8e337000000000000000000000000008a810ea8b121d08342e9e7696f4a9915cbe494b700000000000000000000000070499adebb11efd915e3b69e700c3317786287070000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000011e3644c037c1858b00000000000000000000000000000000000000000000000564d702d38f5e00000000000000000000000000000000000000000000000000011cc7eace9de08dd5000000000000000000000000acae34847ab1c58e61f7caa8a5f7e755a08195b10000000000000000000000000000000000000000000000000000000067325a0d',
value: '0x00',
},
/** Information about the first token in the liquidity pair */
tokenAInfo: {
token: {
name: 'PulseX',
symbol: 'PLSX',
decimals: 18,
color: 'rgb(0, 254, 112)',
chainId: 943,
contractAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x8a810ea8B121d08342E9e7696f4a9915cBE494B7/logo.png',
},
amount: '100.000000000000000000',
balance: '9.250263818388626889',
allowance: '9.250263818388626889',
hasEnoughBalance: false,
hasEnoughAllowance: false,
isMaxAllowance: false,
isCoin: false,
},
/** Information about the second token in the liquidity pair */
tokenBInfo: {
token: {
name: 'Wrapped Pulse',
symbol: 'WPLS',
decimals: 18,
color: 'rgb(5, 185, 213)',
chainId: 943,
contractAddress: '0x70499adEBB11Efd915E3b69E700c331778628707',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x70499adEBB11Efd915E3b69E700c331778628707/logo.png',
},
amount: '20.623747135949604235',
balance: '0.511553843587478274',
allowance: '0.000000000000000000',
hasEnoughBalance: false,
hasEnoughAllowance: false,
isMaxAllowance: false,
isCoin: false,
},
/** Information about the liquidity pool (LP) token */
lpTokenInfo: {
token: {
chainId: 943,
contractAddress: '0xFfd1fD891301D347ECaf4fC76866030387e97ED4',
symbol: 'PLP',
decimals: 18,
name: 'PulseX LP',
standard: 'PRC20',
},
amount: undefined,
balance: '0.000000000000000000',
allowance: '0.000000000000000000',
hasEnoughBalance: undefined,
hasEnoughAllowance: undefined,
totalSupply: '173,485,006,421.031475748512189402',
isCoin: false,
},
/** The current share of the pool */
shareOfPool: '0.000000000000000000',
/** The expected share of the pool after the liquidity operation */
expectedShareOfPool: '0.000000026177118500',
/** The current prices between the two tokens in the pool */
prices: {
aTokenPerBToken: '4.848779387218547690',
bTokenPerAToken: '0.206237471359496042',
},
/** The expected amount of liquidity to be added or removed */
expectedLiquidity: '45.413375890979069836',
/** The minimum amount of liquidity acceptable for the operation, considering slippage */
minLiquidity: '45.186309011524174486',
}
You can get a quote for removing liquidity with a few lines of code.
import { DexFactory } from '@dex-toolkit/core'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
dexContext: ['PULSEX'],
format: { type: 'readable' },
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
tokenBAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
})
const quote = await liquidity.removeLiquidity({
dexTag: 'PULSEX',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
lpTokenAmount: '0.1',
minTokenAAmount: '1',
minTokenBAmount: '5',
permit: false,
supportFeeOnTransferTokens: false,
})
console.log(quote)
// Example of the liquidity quote containing various information for removing liquidity.
const exampleConsoleLog = {
/** The unique ID for the context */
id: '8cad521b-02ec-45d7-b20e-45f3f2d8ddbf',
/** The tag of the decentralized exchange (DEX) being used */
dexTag: 'PULSEX',
/** The protocol of the DEX being used */
protocol: 'protocolV2',
/** The version of the DEX used for liquidity */
version: { major: 1, minor: 0, patch: 0 },
/** The direction of the liquidity operation (add or remove) */
liquidityDirection: 'remove',
/** The slippage tolerance for the liquidity operation, expressed as a decimal (e.g., 0.01 for 1%) */
slippage: 0.005,
/** The Unix timestamp after which the transaction will revert */
deadline: 1731353870,
/** The main transaction that will perform the liquidity operation */
transaction: {
to: '0xDaE9dd3d1A52CfCe9d5F2fAC7fDe164D500E50f7',
from: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
data: '0xbaa2abde0000000000000000000000008a810ea8b121d08342e9e7696f4a9915cbe494b70000000000000000000000002b591e99afe9f32eaa6214f7b7629768c40eeb39000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000001dcd6500000000000000000000000000acae34847ab1c58e61f7caa8a5f7e755a08195b10000000000000000000000000000000000000000000000000000000067325d0d',
value: '0x00',
},
/** Information about the first token in the liquidity pair */
tokenAInfo: {
token: {
name: 'PulseX',
symbol: 'PLSX',
decimals: 18,
color: 'rgb(0, 254, 112)',
chainId: 943,
contractAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x8a810ea8B121d08342E9e7696f4a9915cBE494B7/logo.png',
},
amount: undefined,
balance: '9.250263818388626889',
allowance: '9.250263818388626889',
hasEnoughBalance: undefined,
hasEnoughAllowance: undefined,
isCoin: false,
},
/** Information about the second token in the liquidity pair */
tokenBInfo: {
token: {
name: 'HEX',
symbol: 'HEX',
decimals: 8,
color: 'rgb(255, 7, 184)',
chainId: 943,
contractAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39',
standard: 'PRC20',
logoUri:
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/pulse/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png',
},
amount: undefined,
balance: '0.00000000',
allowance: '0.00000000',
hasEnoughBalance: undefined,
hasEnoughAllowance: undefined,
isCoin: false,
},
/** Information about the liquidity pool (LP) token */
lpTokenInfo: {
token: {
chainId: 943,
contractAddress: '0xf96B8c17610F379C021EC5565E45AF82AA6391b2',
symbol: 'PLP',
decimals: 18,
name: 'PulseX LP',
standard: 'PRC20',
},
amount: undefined,
balance: '0.000000000000000000',
allowance: '0.000000000000000000',
hasEnoughBalance: undefined,
hasEnoughAllowance: undefined,
totalSupply: '3,571.226502511590054385',
isCoin: false,
},
/** The current share of the pool */
shareOfPool: '0.000000000000000000',
/** The expected share of the pool after the liquidity operation */
expectedShareOfPool: '0.000000000000000000',
/** The current prices between the two tokens in the pool */
prices: {
aTokenPerBToken: '12,302,743,272,666.837920566679339782',
bTokenPerAToken: '0.000000000000081282',
},
/** The expected amount of liquidity to be added or removed */
expectedLiquidity: '0.100000000000000000',
/** The minimum amount of liquidity acceptable for the operation, considering slippage */
minLiquidity: '0.099500000000000000',
}
Remove liquidity with token approval in one transaction.
import { DexFactory } from '@dex-toolkit/core'
import ethers from 'ethers'
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.example.com',
1,
)
const signer = new ethers.Wallet('0xPrivateKey', provider)
const walletAddress = await signer.getAddress()
const dexFactory = new DexFactory({
// Must provide a signer for permit generation
providerContext: { ethersSigner: signer },
walletAddress,
dexContext: ['UNISWAP', 'SUSHISWAP', 'PANCAKESWAP'],
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
tokenBAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
settings: {
// Set this to true if you want the permit to approve the max amount
approveMax: true,
},
})
const quote = await liquidity.removeLiquidity({
dexTag: 'UNISWAP',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
lpTokenAmount: '0.1',
minTokenAAmount: '1',
minTokenBAmount: '5',
// Set this to true if you want to auto generate the permit signature
// Or set to false or omit if you don't want to use permit
permit: true,
// If you want to manually provide the permit signature
// permit: {
// approveMax: false,
// permitData: {
// v: 2,
// r: '0xYourPermitSignature',
// s: '0xYourPermitSignature',
// },
// },
supportFeeOnTransferTokens: false, // Deflationary tokens
})
console.log(quote)
const { approvalReceipts, transactionReceipt } = await quote.execute({
approvalConfirmations: 1,
transactionConfirmations: 1,
})
console.log('Approval receipts', approvalReceipts)
console.log('Remove liquidity receipt', transactionReceipt)
Add liquidity with an automatic approval process. This example also demonstrates how to send transactions for the approvals and liquidity addition.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
dexContext: 'PULSEX',
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
tokenBAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
})
const quote = await liquidity.addLiquidity({
dexTag: 'PULSEX',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
tokenAAmount: '100',
})
const wallet = new Wallet('0xPrivateKey', liquidity.dexProvider.provider)
if (quote.enableTransactions) {
const approvalResults = await Promise.all(
Object.values(quote.enableTransactions).map((tx) => wallet.sendTransaction(tx).then(res => res.wait(1)))
)
console.log('Approval receipts:', approvalResults)
}
if (quote.transaction) {
const response = await wallet.sendTransaction(quote.transaction)
const receipt = await response.wait(1)
console.log('Add liquidity receipt:', receipt)
}
Remove liquidity with token approvals. This example handles the approval transaction for the LP token before executing the removal.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const dexFactory = new DexFactory({
providerContext: { chainId: 943 },
walletAddress: '0xAcAe34847aB1c58E61f7CAA8a5f7e755a08195b1',
dexContext: 'PULSEX',
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
tokenBAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
})
const quote = await liquidity.removeLiquidity({
lpTokenAmount: '0.1',
minTokenAAmount: '1',
minTokenBAmount: '5',
protocol: 'protocolV2',
dexTag: 'PULSEX',
version: { major: 1, minor: 0, patch: 0 },
supportFeeOnTransferTokens: false,
})
const wallet = new Wallet('0xPrivateKey', liquidity.dexProvider.provider)
if (quote.enableTransactions?.lpToken) {
const approvalResponse = await wallet.sendTransaction(quote.enableTransactions.lpToken)
const approvalReceipt = await approvalResponse.wait(1)
console.log('Approval receipt:', approvalReceipt)
}
if (quote.transaction) {
const response = await wallet.sendTransaction(quote.transaction)
const receipt = await response.wait(1)
console.log('Remove liquidity receipt:', receipt)
}
Add liquidity with an automatic approval process. This example also demonstrates how to send transactions for the approvals and liquidity addition.
import { DexFactory } from '@dex-toolkit/core'
import { Wallet } from 'ethers'
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.example.com',
1,
)
const signer = new ethers.Wallet('0xPrivateKey', provider)
const walletAddress = await signer.getAddress()
const dexFactory = new DexFactory({
// Must provide a signer to use the execute function
providerContext: { ethersSigner: signer },
walletAddress,
dexContext: 'UNISWAP',
format: { type: 'readable' },
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x1dA01e84F3d4e6716F274c987Ae4bEE5DC3C8288', // BID
tokenBAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
})
const quote = await liquidity.addLiquidity({
dexTag: 'UNISWAP',
protocol: 'protocolV2',
version: { major: 1, minor: 0, patch: 0 },
tokenAAmount: '4000',
})
const { approvalReceipts, transactionReceipt } = await quote.execute({
approvalConfirmations: 1,
transactionConfirmations: 1,
})
console.log('Approval receipts', approvalReceipts)
console.log('Add liquidity receipt', transactionReceipt)
Create a liquidity quote with custom settings.
import { DexFactory } from '@dex-toolkit/core'
const customSettingsFactory = new DexFactory({
providerContext: { chainId: 1 },
walletAddress: '0x1234...',
dexContext: 'UNISWAP',
})
const liquidity = await customSettingsFactory.createLiquidity({
tokenAAddress: '0x1234...',
tokenBAddress: '0x5678...',
// All settings are optional
settings: {
/**
* The address that will receive the output tokens from the swap.
* If not provided, the default is to send the output tokens to the address initiating the swap.
*
* @default ''
*/
recipient: '0x1234...',
/**
* Slippage in percentage
* For example, a value of 0.005 will be 0.5% or 50 bips.
*
* @default 0.005
*/
slippage: 0.005,
/**
* The number of minutes before the transaction expires.
*
* @default 20
*/
deadlineMinutes: 20,
/**
* Disable multihops, forcing direct routes.
*
* @default false
*/
disableMultihops: false,
/**
* Prevent the built-in block listener from observing changes.
*
* @default false
*/
disableObserver: false,
/**
* Number of blocks to skip between each quote, reducing the number of calls to the node.
*
* @default 0
*/
observerBlockSkip: 3,
/**
* Filter to choose which DEX versions to use. Defaults to all.
*
* @default All protocols of targeted DEXs
*/
protocolSettings: {
protocolV2: {
// Enables/disables all versions of the protocol
enabled: true,
// Optionally include/exclude versions
includeVersions: [{ major: 1, minor: 0, patch: 0 }],
excludeVersions: [{ major: 2, minor: 0, patch: 0 }],
},
protocolV3: {
enabled: true,
includeVersions: [{ major: 1, minor: 0, patch: 0 }],
excludeVersions: [{ major: 2, minor: 0, patch: 0 }],
},
},
/**
* Gas price settings, where the `getGasPrice` function returns the gas price in GWEI.
*
* @default undefined
*/
gasSettings: {
getGasPrice: async () => '90',
},
/**
* Whether to approve the the maximum token amount, or the exact token amount.
*
* @default true
*/
approveMax: true,
/**
* Multiplier for the token approval amount to add a buffer.
* Only applies when `approveMax` is false.
* For example, a value of 1.05 represents a 5% buffer.
*
* @default 1.05
*/
approvalBufferFactor: 1.05,
// V3 Only settings
/**
* When `true`, enables the use of a price limit during the trade.
* A price limit helps protect against unfavorable price movements during trade execution.
*
* @default false
*/
enablePriceLimit: false,
/**
* When `true`, enables the use of a price limit during the trade.
* A price limit helps protect against unfavorable price movements during trade execution.
*
* @default undefined
*/
priceRange: {
tickLower: 0,
tickUpper: 10000,
},
/**
* The fee tier for the trade.
*
* @default undefined
*/
feeTier: 3_000,
},
})
const quote = await liquidity.addLiquidity({
protocol: 'protocolV3',
dexTag: 'UNISWAP',
version: { major: 1, minor: 0, patch: 0 },
tokenAAmount: '100',
feeTier: 3_000,
priceRange: {
tickLower: -60,
tickUpper: 60,
},
})
console.log('Custom settings liquidity quote:', quote)
You can subscribe to a liquidity quote, which will automatically update when the blockchain state changes.
import { DexFactory } from '@dex-toolkit/core'
import ethers from 'ethers'
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.v4.testnet.pulsechain.com',
943,
)
const signer = new ethers.Wallet(walletPk, provider)
const walletAddress = await signer.getAddress()
const dexFactory = new DexFactory({
// Must provide a signer to use the execute function
providerContext: { ethersSigner: signer },
walletAddress,
dexContext: 'UNISWAP',
format: { type: 'readable' },
})
const liquidity = await dexFactory.createLiquidity({
tokenAAddress: '0x1dA01e84F3d4e6716F274c987Ae4bEE5DC3C8288', // BID
tokenBAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
settings: {
/**
* Number of blocks to skip between each quote, reducing the number of calls to the node.
*
* @default 0
*/
observerBlockSkip: 3,
},
})
const quote = await liquidity.addLiquidity({
tokenAAmount: '4000',
protocol: 'protocolV2',
dexTag: 'UNISWAP',
version: { major: 1, minor: 0, patch: 0 },
})
console.log(quote)
// Listen for changes in our quote
const subscription = quote.observer$.subscribe(async ({ blockNumber, latestQuote }) => {
console.log(
'New quote generated for block number',
blockNumber,
latestQuote,
)
if (blockNumber && blockNumber > 9876543210) {
subscription.unsubscribe()
// Or call unsubscribe from the quote
// quote.unsubscribe()
// Or call destroy to clean up all liquidity quotes and subscriptions
// trade.destroy()
// Execute will use the latest quote data
const { approvalReceipts, transactionReceipt } = await quote.execute({
approvalConfirmations: 1,
transactionConfirmations: 1,
})
console.log('Approval receipts', approvalReceipts)
console.log('Add liquidity receipt', transactionReceipt)
}
})
Dex Provider is a wrapper around Ethers.js provider that adds multicall support, and some additional helpers.
You can provide your own Ethers.js provider.
import { DexProvider } from '@dex-toolkit/provider'
const ethersProvider = new ethers.providers.JsonRpcProvider(
'https://rpc.example.com',
1,
)
const dexProvider = new DexProvider({
ethersProvider,
})
console.log(dexProvider)
Simply provide the chainId.
import { DexProvider } from '@dex-toolkit/provider'
const dexProvider = new DexProvider({
chainId,
})
console.log(dexProvider)
If you want to override the RPC URL, or the network isn't pre-configured, you can provide a custom RPC URL.
import { DexProvider } from '@dex-toolkit/provider'
const dexProvider = new DexProvider({
chainId,
rpcUrl: 'https://rpc.example.com',
})
console.log(dexProvider)
import { DexProvider } from '@dex-toolkit/provider'
const dexProvider = new DexProvider({
chainId,
/**
* Represents a custom network configuration.
*/
customNetwork: {
/** The name of the custom network. */
name: 'Name of network',
/** The address of the multicall contract for the network. */
multicallContractAddress: '0x1234...',
},
/**
* Whether to use the `tryAggregate` function for error handling.
* If `true`, individual call failures do not cause the entire batch to fail.
* Defaults to `false`.
*/
tryAggregate: true,
/**
* Whether to enable batching when calls exceed configured size or count limits.
* When enabled, calls that exceed `maxCallDataSize` or `maxCallsPerBatch` are split into multiple batches, resulting in multiple calls to the blockchain.
* Defaults to `true`.
*/
enableBatching: true,
/**
* Maximum allowed call data size (in bytes) for a single batch of calls.
* Batches are split if the combined return data size exceeds this limit.
* Defaults to `100000` bytes.
*/
maxCallDataSize: 100_000,
/**
* Maximum number of calls allowed in a single batch.
* Ensures that each batch stays within a manageable number of calls.
* Defaults to `500` calls.
*/
maxCallsPerBatch: 100,
})
console.log(dexProvider)
Refer to the Preparing a multicall ContractContext with the ERC20 Contract example.
DexNumber is a powerful and flexible numeric class built on top of BigNumber.js, designed specifically for handling decimal numbers in decentralized finance (DeFi) applications. It provides seamless conversion between different number representations and supports shifting operations for easy manipulation of token amounts.
View the readme for DexNumber
Fetch token information:
import { TokenContract } from '@dex-toolkit/core'
const contract = new TokenContract({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
})
const token = await contract.getToken()
console.log(token)
Fetch token information using a custom token list.
import { TokenContract, TokenList } from '@dex-toolkit/core'
import { getAllTokenListSources } from '@dex-toolkit/utils'
const chainId = 943
const customTokenList = new TokenList({
chainId,
tokenListSources: [
{
name: 'Uniswap Labs Default',
url: 'https://tokens.uniswap.org/',
chainIds: [], // Filter by chainId, or leave empty to include all chains
},
// You could also extend the defaults by spreading the `getAllTokenListSources` from the utils package
...getAllTokenListSources(),
],
})
const contract = new TokenContract({
dexProviderContext: {
chainId,
},
dexContext: 'PULSEX',
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
tokenList: customTokenList,
})
const token = await contract.getToken()
console.log(token)
Retrieve the balance of a native coin.
import { TokenContract } from '@dex-toolkit/core'
import { PLSCoin } from '@dex-toolkit/utils'
const chainId = 943
const contract = new TokenContract({
dexProviderContext: {
chainId,
},
dexContext: 'PULSEX',
tokenContractAddress: PLSCoin.getTokenForChainId(chainId)!.contractAddress,
})
const balance = await contract.balanceOf({
walletAddress: '0x1234...',
format: { type: 'readable' },
})
console.log(balance)
Retrieve the balance of a specific token:
import { TokenContract } from '@dex-toolkit/core'
const contract = new TokenContract({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
})
const balance = await contract.balanceOf({
walletAddress: '0x1234...',
format: { type: 'readable' },
})
console.log(balance)
Generate transaction data for approving token allowance.
import { TokenContract } from '@dex-toolkit/core'
import { MAX_HEX_STRING } from '@dex-toolkit/utils'
const dexTag = 'PULSEX'
const contract = new TokenContract({
dexProviderContext: {
chainId: 943,
},
dexContext: dexTag,
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
})
const versionTag = getVersionTagFromVersion({
major: 1,
minor: 0,
patch: 0,
})
const routerAddress =
contract.dexConfigsByDex[dexTag]?.protocols.protocolV2?.[versionTag]?.router
.address
if (!routerAddress) {
throw new Error('No router address found')
}
const data = contract.encodeApproveAllowanceData({
spender: routerAddress,
amount: DexNumber.fromShifted(MAX_HEX_STRING, 18),
})
console.log(data)
Directly interact with the underlying token contract.
import { TokenContract } from '@dex-toolkit/core'
const contract = new TokenContract({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
})
const totalSupply = await contract.tokenContract.totalSupply()
console.log(totalSupply)
Use multicall to batch multiple contract calls.
import { TokenContract } from '@dex-toolkit/core'
const contract = new TokenContract({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
tokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNIToken
})
// Get the underlying token contract
const tokenContract = contract.tokenContract
const { blockNumber, results } = await tokenContract.call({
name: tokenContract.nameCallContext(),
decimals: tokenContract.decimalsCallContext(),
symbol: tokenContract.symbolCallContext(),
totalSupply: tokenContract.totalSupplyCallContext(),
balanceOf: tokenContract.balanceOfCallContext('0x1234...'),
})
console.log('Multicall results:', {
blockNumber,
balance: results.balanceOf.value,
name: results.name.value,
symbol: results.symbol.value,
totalSupply: results.totalSupply.value,
})
Fetch information for multiple tokens in one call.
import { Tokens } from '@dex-toolkit/core'
const tokens = new Tokens({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
})
const results = await tokens.getTokens([
'0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
'0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
'0x1da01e84f3d4e6716f274c987ae4bee5dc3c8288', // BID
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
'0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
])
console.log(results)
Fetch multiple tokens using a custom token list:
import { Tokens, TokenList } from '@dex-toolkit/core'
import { getAllTokenListSources } from '@dex-toolkit/utils'
const customTokenList = new TokenList({
chainId: 943,
tokenListSources: [
{
name: 'Uniswap Labs Default',
url: 'https://tokens.uniswap.org/',
chainIds: [], // Filter by chainId, or leave empty to include all chains
},
// You could also extend the defaults by spreading the `getAllTokenListSources` from the utils package
...getAllTokenListSources(),
],
})
const tokens = new Tokens({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
tokenList: customTokenList,
})
const results = await tokens.getTokens([
'0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
'0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
'0x1da01e84f3d4e6716f274c987ae4bee5dc3c8288', // BID
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
'0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
])
console.log(results)
Retrieve allowance and balance information for multiple tokens in one call.
import { Tokens } from '@dex-toolkit/core'
const tokenContract = new Tokens({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
})
const multiTokenAllowanceAndBalance = await tokenContract.getAllowancesAndBalanceOf({
walletAddress: '0x1234...',
tokenContractAddresses: [
'0x8a810ea8B121d08342E9e7696f4a9915cBE494B7', // PLSX
'0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', // HEX
'0x1da01e84f3d4e6716f274c987ae4bee5dc3c8288', // BID
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
'0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
],
format: { type: 'readable' },
})
console.log(multiTokenAllowanceAndBalance)
Retrieve the full token list with allowances and balances.
import { Tokens } from '@dex-toolkit/core'
const tokenContract = new Tokens({
dexProviderContext: {
chainId: 943,
},
dexContext: 'PULSEX',
})
const tokenListWithAllowancesAndBalance = await tokenContract.getTokenListWithAllowancesAndBalance({
walletAddress: '0x1234...',
includeAllowance: true,
format: { type: 'readable' },
})
console.log(tokenListWithAllowancesAndBalance)
Retrieve all tokens from the token list.
import { TokenList } from '@dex-toolkit/core'
const tokenList = new TokenList({
chainId: 943,
})
const tokens = await tokenList.getTokens()
console.log('All tokens from token list:', tokens)
Retrieve a single token from the token list.
import { TokenList } from '@dex-toolkit/core'
const tokenList = new TokenList({
chainId: 943,
})
const token = tokenList.getPredefinedToken({
contractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
})
console.log('Single token from token list:', token)
Create a TokenList with a custom token list.
import { TokenList } from '@dex-toolkit/core'
import { plsTestChainId, getAllTokenListSources } from '@dex-toolkit/utils'
const tokenList = new TokenList({
chainId: plsTestChainId,
tokenListSources: [
{
name: 'Uniswap Labs Default',
url: 'https://tokens.uniswap.org/',
chainIds: [], // Filter by chainId, or leave empty to include all chains
},
// You could also extend the defaults by spreading the `getAllTokenListSources` from the utils package
...getAllTokenListSources(),
],
})
const tokens = await tokenList.getTokens()
console.log('Tokens from custom token list sources:', tokens)
Directly interact with an ERC20 token contract.
import { Erc20Contract } from '@dex-toolkit/contracts'
const tokenContract = new Erc20Contract(
{
chainId: 943,
},
{
address: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
}
)
const totalSupply = await tokenContract.totalSupply()
console.log(totalSupply)
Use multicall to batch multiple ERC20 contract calls.
import { Erc20Contract } from '@dex-toolkit/contracts'
const tokenContract = new Erc20Contract(
{
chainId: 943,
},
{
address: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNI
}
)
const { blockNumber, results, originContext } = await tokenContract.call({
// You can define the method calls explicitly like this...
balanceOf: {
methodName: 'balanceOf',
methodParameters: ['0x1234...'],
},
// Or use the helpers from the contract
balanceOfFriend: tokenContract.balanceOfCallContext('0x5678...'),
name: tokenContract.nameCallContext(),
symbol: tokenContract.symbolCallContext(),
totalSupply: tokenContract.totalSupplyCallContext(),
})
const balanceOf = results.balanceOf.value
const balanceOfFriend = results.balanceOfFriend.value
const name = results.name.value
const symbol = results.symbol.value
const totalSupply = results.totalSupply.value
console.log({
originContext,
blockNumber,
balanceOf,
balanceOfFriend,
name,
symbol,
totalSupply,
})
Use multicall to batch multiple ERC20 contract calls.
import { Erc20Contract, PairContract } from '@dex-toolkit/contracts'
import { DexProvider } from '@dex-toolkit/provider'
const dexProvider = new DexProvider({
chainId,
tryAggregate: true,
enableBatching: true,
maxCallDataSize: 100_000,
})
const tokenContract = new Erc20Contract(dexProvider, {
address: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', // UNIToken
})
const tokenContractCallContext = tokenContract.prepareContractContext({
balanceOf: tokenContract.balanceOfCallContext(walletAddress),
name: tokenContract.nameCallContext(),
symbol: tokenContract.symbolCallContext(),
totalSupply: tokenContract.totalSupplyCallContext(),
})
const pairContract = new PairContract(dexProvider, {
address: '0xBa2dEE2861ddEAecd0ff1bAC44bc1f5DfCD35C0c', // AAVE/DAI pair
abi: uniswapPairV2ABI,
})
const pairContractCallContext = pairContract.prepareContractContext({
token0: pairContract.token0CallContext(),
token1: pairContract.token1CallContext(),
getReserves: pairContract.getReservesCallContext(),
})
const { blockNumber, contracts } = await dexProvider.call({
tokenContract: tokenContractCallContext,
pairContract: pairContractCallContext,
})
const { results: tokenResults, originContext } = contracts.tokenContract
const { results: pairContractResults } = contracts.pairContract
const balanceOf = tokenResults.balanceOf.value
const name = tokenResults.name.value
const symbol = tokenResults.symbol.value
const totalSupply = tokenResults.totalSupply.value
const token0 = pairContractResults.token0.value
const token1 = pairContractResults.token1.value
const reserves = pairContractResults.getReserves.value
const { _reserve0, _reserve1, _blockTimestampLast } = reserves
console.log({
// Multicall results
originContext,
blockNumber,
// Token results
balanceOf,
name,
symbol,
totalSupply,
// Pair results
token0,
token1,
_reserve0,
_reserve1,
_blockTimestampLast,
})
If the Dex/Chain combination is not listed, you can use a CustomNetwork and DexContext on the Trade to support it. You may also make a PR to add it to the library.
- Total DEXs: 10
- Total DEX Configs: 51
DEX | Chain | Chain ID |
---|---|---|
DoveSwap | ||
zkEVM Mainnet | 1101 | |
Energiswap | ||
Energi Mainnet | 39797 | |
PancakeSwap | ||
Arbitrum Mainnet | 42161 | |
Base Mainnet | 8453 | |
Binance Smart Chain Mainnet | 56 | |
Binance Smart Chain Testnet | 97 | |
Ethereum Mainnet | 1 | |
zkEVM Mainnet | 1101 | |
zkSync Mainnet | 324 | |
Pangolin | ||
Avalanche Mainnet | 43114 | |
Avalanche Fuji Testnet | 43113 | |
PulseX | ||
PulseChain Mainnet | 369 | |
PulseChain Testnet | 943 | |
QuickSwap | ||
Polygon Mainnet | 137 | |
zkEVM Mainnet | 1101 | |
SushiSwap | ||
Arbitrum Mainnet | 42161 | |
Avalanche Mainnet | 43114 | |
Avalanche Fuji Testnet | 43113 | |
Base Mainnet | 8453 | |
Blast Mainnet | 81457 | |
Binance Smart Chain Mainnet | 56 | |
Binance Smart Chain Testnet | 97 | |
Celo Mainnet | 42220 | |
Celo Alfajores Testnet | 44787 | |
Ethereum Mainnet | 1 | |
Ethereum Sepolia Testnet | 11155111 | |
Optimism Mainnet | 10 | |
Polygon Mainnet | 137 | |
zkEVM Mainnet | 1101 | |
Trader Joe | ||
Avalanche Mainnet | 43114 | |
Avalanche Fuji Testnet | 43113 | |
Arbitrum Mainnet | 42161 | |
Binance Smart Chain Mainnet | 56 | |
Binance Smart Chain Testnet | 97 | |
Ethereum Mainnet | 1 | |
Uniswap | ||
Arbitrum Mainnet | 42161 | |
Arbitrum Sepolia Testnet | 421614 | |
Avalanche Mainnet | 43114 | |
Base Mainnet | 8453 | |
Base Sepolia Testnet | 84532 | |
Blast Mainnet | 81457 | |
Celo Mainnet | 42220 | |
Celo Alfajores Testnet | 44787 | |
Ethereum Mainnet | 1 | |
Ethereum Sepolia Testnet | 11155111 | |
Polygon Mainnet | 137 | |
Zora Mainnet | 7777777 | |
Zora Sepolia Testnet | 999999999 | |
zkSync Mainnet | 324 | |
YetiSwap | ||
Avalanche Mainnet | 43114 |
The whole repo is covered in tests output below.
V2 Protocol
// TODO
V3 Protocol
// TODO
Check out my other projects and forks for blockchain development!
Toolkit | Description |
---|---|
abi-toolkit | TypeScript ABI generation and conversion utilities |
provider-toolkit | Web3 provider management and configuration tools |
multicall-toolkit | Batch contract calls and state aggregation utilities |
transaction-toolkit | Transaction building, simulation, and management tools |
connector-toolkit | Wallet connection and account management utilities |
Please raise any issues in the GitHub repository.
Contributions are welcome! Please feel free to submit a Pull Request.
Check out the TODO.md file for a list of future features and improvements.
This project is licensed under the ISC License - see the LICENSE file for details.