The ShibaSwap V1 SDK (@shibaswap/sdk
) is a TypeScript/JavaScript library that lets you build on top of ShibaSwap V1—a Uniswap V2 fork originally inherited via SushiSwap—using familiar abstractions like Token
, Pair
, Route
, and Trade
.
It runs in any JS environment (browsers, Node) and powers both quick hackathon prototypes and production-grade integrations.
Under the hood:
It swaps in ShibaSwap’s factory and router addresses
Computes CREATE2 pair addresses offline
Fetches on-chain reserves via ethers
Generates all parameters needed to craft router transactions
Quick Start & Installation
npm install @shibaswap/sdk
This pulls in @shibaswap/sdk-core
and ethers
as dependencies.
Imports & Initialization
import { ChainId } from '@shibaswap/sdk-core'
import { Pair } from '@shibaswap/sdk'
console . log ( `Mainnet chainId = ${ ChainId . MAINNET } ` )
Fetching On-Chain Data
You must supply on-chain data for tokens and pairs.
Case 1: Tokens
import { ChainId , Token } from '@shibaswap/sdk-core'
const DAI = new Token (
ChainId . MAINNET ,
'0x6B175474E89094C44Da98b954EedeAC495271d0F' ,
18 ,
'DAI' ,
'Dai Stablecoin'
)
To fetch decimals dynamically:
import { ethers } from 'ethers'
import erc20ABI from './erc20.json'
async function getDecimals ( chainId : ChainId , tokenAddress : string ) : Promise < number > {
const provider = new ethers . providers . JsonRpcProvider ( /* RPC URL */ )
const tokenContract = new ethers . Contract ( tokenAddress , erc20ABI , provider )
return tokenContract . decimals ()
}
Case 2: Pairs
import {
ChainId ,
Token ,
WETH9 ,
CurrencyAmount
} from '@shibaswap/sdk-core'
import { Pair } from '@shibaswap/sdk'
import { ethers } from 'ethers'
import poolABI from './V2Pool.json'
const DAI = new Token ( /* … */ )
const WETH = WETH9 [ ChainId . MAINNET ]
async function createDAIWethPair () : Promise < Pair > {
const pairAddress = Pair . getAddress ( DAI , WETH )
const provider = new ethers . providers . JsonRpcProvider ( /* RPC URL */ )
const pool = new ethers . Contract ( pairAddress , poolABI , provider )
const [ reserve0 , reserve1 ] = await pool . getReserves ()
const [ token0 , token1 ] = [ DAI , WETH ]. sort (( a , b ) => a . sortsBefore ( b ) ? - 1 : 1 )
return new Pair (
CurrencyAmount . fromRawAmount ( token0 , reserve0 . toString ()),
CurrencyAmount . fromRawAmount ( token1 , reserve1 . toString ())
)
}
Pricing
Mid Price (Direct & Indirect)
import { Route } from '@shibaswap/sdk'
const pair = await createDAIWethPair ()
const route = new Route ([ pair ], WETH , DAI )
console . log ( route . midPrice . toSignificant ( 6 ))
console . log ( route . midPrice . invert (). toSignificant ( 6 ))
For multi-hop (e.g., via USDC):
const USDC = new Token ( /* … */ )
const usdcWeth = await createPair ( USDC , WETH )
const daiUsdc = await createPair ( DAI , USDC )
const indirectRoute = new Route ([ usdcWeth , daiUsdc ], WETH , DAI )
console . log ( indirectRoute . midPrice . toSignificant ( 6 ))
Execution Price (with Slippage)
import { Trade , TradeType , CurrencyAmount } from '@shibaswap/sdk-core'
const trade = new Trade (
route ,
CurrencyAmount . fromRawAmount ( WETH , '1000000000000000000' ), // 1 WETH
TradeType . EXACT_INPUT
)
console . log ( trade . executionPrice . toSignificant ( 6 ))
Trading
The SDK does not send transactions. It generates transaction parameters for you to send manually via ethers
.
Router Address: 0x03f7724180aa6b939894b5ca4314783b0b36b329
Example: Swap 1 ETH → DAI
import { Percent } from '@shibaswap/sdk-core'
import routerABI from './V2Router02.json'
import { ethers } from 'ethers'
const provider = new ethers . providers . Web3Provider ( window . ethereum )
const signer = provider . getSigner ()
const router = new ethers . Contract (
'0x03f7724180aa6b939894b5ca4314783b0b36b329' ,
routerABI ,
signer
)
const slippageTolerance = new Percent ( '50' , '10000' ) // 0.50%
const amountOutMin = trade . minimumAmountOut ( slippageTolerance ). toExact ()
const path = [ WETH . address , DAI . address ]
const to = await signer . getAddress ()
const deadline = Math . floor ( Date . now () / 1000 ) + 60 * 20
const value = trade . inputAmount . toExact ()
await router . swapExactETHForTokens (
amountOutMin ,
path ,
to ,
deadline ,
{ value }
)
Pair Addresses (CREATE2 vs On-Chain)
On-chain :
factory. getPair (tokenA, tokenB)
Off-chain via CREATE2 :
import {
FACTORY_ADDRESS ,
INIT_CODE_HASH
} from '@shibaswap/sdk'
import { pack , keccak256 } from '@ethersproject/solidity'
import { getCreate2Address } from '@ethersproject/address'
const pairAddress = getCreate2Address (
FACTORY_ADDRESS ,
keccak256 ([ 'bytes' ], [ pack ([ 'address' , 'address' ], [ token0 , token1 ])]),
INIT_CODE_HASH
)
Technical Reference
Pair
class Pair {
constructor ( tokenAmountA : CurrencyAmount , tokenAmountB : CurrencyAmount )
static getAddress ( tokenA : Token , tokenB : Token ) : string
reserveOf ( token : Token ) : CurrencyAmount
getOutputAmount ( inputAmount : CurrencyAmount ) : [ CurrencyAmount , Pair ]
getInputAmount ( outputAmount : CurrencyAmount ) : [ CurrencyAmount , Pair ]
getLiquidityMinted (...) : CurrencyAmount
getLiquidityValue (...) : CurrencyAmount
}
Route
class Route {
constructor ( pairs : Pair [], input : Token , output : Token )
readonly midPrice : Price
}
Trade
class Trade {
constructor ( route : Route , amount : CurrencyAmount , tradeType : TradeType )
readonly inputAmount : CurrencyAmount
readonly outputAmount : CurrencyAmount
readonly executionPrice : Price
readonly priceImpact : Percent
minimumAmountOut ( slippageTolerance : Percent ) : CurrencyAmount
maximumAmountIn ( slippageTolerance : Percent ) : CurrencyAmount
worstExecutionPrice ( slippageTolerance : Percent ) : Price
static exactIn (...) : Trade
static exactOut (...) : Trade
static bestTradeExactIn (...) : Trade []
static bestTradeExactOut (...) : Trade []
}
Other Exports
FACTORY_ADDRESS
: ShibaSwap V1 Factory Address
INIT_CODE_HASH
: For CREATE2 address generation
MINIMUM_LIQUIDITY
: Protocol-reserved
Errors
: InsufficientReservesError
, InsufficientInputAmountError
Complete Example
Here’s a complete example showing how to use the SDK to perform a swap:
Complete Example
Router Integration
import {
ChainId ,
Token ,
WETH9 ,
CurrencyAmount ,
TradeType ,
Percent
} from '@shibaswap/sdk-core'
import { Pair , Route , Trade } from '@shibaswap/sdk'
import { ethers } from 'ethers'
// Define tokens
const WETH = WETH9 [ ChainId . MAINNET ]
const DAI = new Token (
ChainId . MAINNET ,
'0x6B175474E89094C44Da98b954EedeAC495271d0F' ,
18 ,
'DAI' ,
'Dai Stablecoin'
)
// Create pair and route
async function createSwap () {
const pair = await createDAIWethPair ()
const route = new Route ([ pair ], WETH , DAI )
// Create trade
const trade = new Trade (
route ,
CurrencyAmount . fromRawAmount ( WETH , '1000000000000000000' ), // 1 WETH
TradeType . EXACT_INPUT
)
// Set up transaction
const slippageTolerance = new Percent ( '50' , '10000' ) // 0.50%
const amountOutMin = trade . minimumAmountOut ( slippageTolerance ). toExact ()
console . log ( `Swapping 1 WETH for at least ${ amountOutMin } DAI` )
return {
amountOutMin ,
path: [ WETH . address , DAI . address ],
deadline: Math . floor ( Date . now () / 1000 ) + 60 * 20
}
}
Best Practices
Always use the SDK’s built-in functions for calculations rather than implementing your own. This ensures accuracy and consistency with the protocol.
Set appropriate slippage tolerance based on your use case. Lower values provide better prices but may fail more often.
Always verify token addresses and chain IDs before creating Token instances to avoid errors.
Never hardcode amounts or addresses in production code. Always fetch them dynamically from the blockchain or configuration.
Error Handling
The SDK provides specific error types for common scenarios:
import { InsufficientReservesError , InsufficientInputAmountError } from '@shibaswap/sdk'
try {
const trade = new Trade ( route , amount , TradeType . EXACT_INPUT )
} catch ( error ) {
if ( error instanceof InsufficientReservesError ) {
console . log ( 'Insufficient liquidity in the pool' )
} else if ( error instanceof InsufficientInputAmountError ) {
console . log ( 'Input amount too small' )
}
}