The SDK accepts amounts as inputs as big number and most SDK methods return outputs as big numbers, so it's important to know how to convert to and from big numbers.
Note: a bonder fee is required when sending L2->L1. It'll calculate it the bonder fee if don't is not explicitly specified. See specifying a custom fee for more info.
Note: a bonder fee is required when sending L2->L2. It'll calculate it the bonder fee if don't is not explicitly specified. See specifying a custom fee for more info.
Send ETH
Sending ETH is the same as sending any other ERC-20. The sdk handles inputting the tx value based on input amount.
Example
constbridge=hop.connect(signer).bridge('ETH')// send 1 ETH from Polygon -> Gnosisconsttx=awaitbridge.send('1000000000000000000',Chain.Polygon,Chain.Gnosis)
Get send calldata only
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// get tx calldata for sending 100 USDC tokens from Polygon -> Gnosisconsttx=awaitbridge.populateSendTx('100000000',Chain.Polygon,Chain.Gnosis)console.log(tx) // { data: '0xdeace8f5000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000002a6303e6b99d451df3566068ebb110708335658f00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006227bdad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', to: '0x3666f603Cc164936C1b87e207F36BEBa4AC5f18a' }
By default, the sdk will use the recommended bonder fee if one is not specified. You can set a custom bonder fee in the bonderFee field. See getSendData(...) for more info on the fee breakdown.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// send 100 USDC tokens from Polygon -> Gnosisconsttx=awaitbridge.send('100000000',Chain.Polygon,Chain.Gnosis, { amountOutMin:'99863953'// must take account fee and slippage})console.log(tx.hash)
Note: The amountOutMin will be 0 if one is not specified. You can use the result from getSendData(...) to calculate the estimated amountOutMin value.
Note: Do not set destinationAmountOutMin and destinationDeadline when sending to L1. There is no AMM on L1 so these parameters should not be used, otherwise the calculated transferId will be invalid the transfer will be unbondable.
Specify custom deadline
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// send 100 USDC tokens from Polygon -> Gnosisconstdeadline=Math.floor((Date.now() /1000) + (24*60*60)) // expire after one dayconsttx=awaitbridge.send('100000000',Chain.Polygon,Chain.Gnosis, { deadline})console.log(tx.hash)
Note: the deadline will be 7 days if one is not specified. The deadline is required for L2->L1 transfers and L2->L2 transfers for the AMM swap at the origin chain. Additionally, destinationDeadline is also required for L2->L2 transfers to swap the hTokens for the canonical tokens at the destination.
Note: Do not set destinationDeadline and destinationAmountOutMin for L2->L1 since there is no L1 AMM at the destination.
Get approval address for sending over bridge
import { Hop, Chain } from'@hop-protocol/sdk'import { constants } from'ethers'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// get address to approve for sending over Ethereum -> Polygon Hop bridgeconstapprovalAddress=awaitbridge.getSendApprovalAddress(Chain.Ethereum)console.log(approvalAddress)consttoken=bridge.getCanonicalToken(Chain.Ethereum)constamountToApprove=constants.MaxUint256consttx=awaittoken.approve(approvalAddress, amountToApprove)console.log(tx.hash)
Get approval address for sending hTokens over bridge
import { Hop, Chain } from'@hop-protocol/sdk'import { constants } from'ethers'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// get address to approve for sending over Ethereum -> Polygon Hop bridgeconstisHToken=trueconstapprovalAddress=awaitbridge.getSendApprovalAddress(Chain.Ethereum, isHToken)console.log(approvalAddress)
Call this to estimate how many tokens the swap will provide (does not take account slippage or bonder fee):
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// estimate tokens amount out for 100 USDCconstamountOut=awaitbridge.getAmountOut('1000000',Chain.Polygon,Chain.Gnosis)console.log(amountOut) // 998608
Estimate tokens that will be received at destination
Call this to estimate how you'll receive at the destination. This is what the UI uses to show user the estimated tokens amount out.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// get estimated tokens out when sending 100 USDC Polygon -> Gnosisconst { estimatedReceived } =awaitbridge.getSendData('10000000',Chain.Polygon,Chain.Gnosis)console.log(estimatedReceived.toString()) // 98866001
The estimatedReceived value takes account the bonder fee and destination transaction fee.
Estimate amountOutMin
Call this to estimate the minimum amount of tokens you should receive at the destination when including slippage.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.bridge('USDC')// get estimated min tokens out with slippage of 0.5% when sending 100 USDC Polygon -> Gnosisconstdata=awaitbridge.getSendData('10000000','polygon','gnosis')const { amountOut } = dataconstslippage=0.5constamountOutMin=bridge.calcAmountOutMin(amountOut, slippage)console.log(amountOutMin.toString()) // 9935445
Note: Do not set destinationAmountOutMin and destinationDeadline when sending to L1 because there's is no AMM on L1.
Estimate total bonder fee
The total bonder fee is bonderFee+ destinationTxFee
Make sure to use the total bonder fee when sending a transfer over the Hop bridge.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// estimate total bonder fee for sending 100 UDSC Polygon -> GnosisconsttotalBonderFee=awaitbridge.getTotalFee('10000000',Chain.Polygon,Chain.Gnosis)console.log(toalBonderFee.toString()) // 998239
The method bridge.getTotalFee(...) is a simple wrapper for const { totalFee } = await bridge.getSendData(...).
The following examples below are for retrieving the individual fees if you're interested in the breakdown of the total bonder fee.
Estimate base bonder fee:
The base bonder fee is the fee the bonder takes for fronting liquidity at the destination. The bonder receives this fee when bonding the transfer at the destination.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// estimate base bonder fee for sending 100 UDSC Polygon -> GnosisconsttotalBonderFee=awaitbridge.getBonderFee('10000000',Chain.Polygon,Chain.Gnosis)console.log(toalBonderFee.toString()) // 1000000
Estimate bonder destination transaction fee:
The bonder destination transaction fee is the regular chain transaction fee that the bonder pays to get transaction included in block. The sender of the transfer must compensate the bonder for this fee which is why this fee exists. The destination transaction fee returned here is in terms of the asset being transferred.
The estimated amount out but without taking account slippage or fees. Use the value estimatedReceived if you're looking for the final estimated out amount which takes account fees.
rate
Number
The ratio between amountIn and amountOut
priceImpact
Number
Price impact percentage. Depositing underpooled assets will give you bonus LP tokens. Depositing overpooled assets will give you less LP tokens (shown as negative price impact).
requiredLiquidity
BigNumber
The amount of required liquidity the bonder must have in order for this transfer to go through. Use getFrontendAvailableLiquidity(...) to check total available liquidity before sending.
lpFees
BigNumber
The AMM swap fees for amountIn
adjustedBonderFee
BigNumber
Small fee bonder takes for fronting liquidity at the destination when bonding transfer. There is a bonderFee going L2->L2 or L2->L1. There is no bonder fee going L1->L2.
adjustedDestinationTxFee
BigNumber
The destination transaction fee that the bonder has to pay when bonding transfer. The sender pays this fee in terms of the token being sent.
totalFee
BigNumber
The total fee consists of bonderFee + destinationTxFee. Use this totalFee value for the bonderFee parameter when sending transfer going L2->L2 or L2->L1.
estimatedReceived
BigNumber
The estimated amount that will be received at destination when slippage and all fees (bonderFee + destinationTxfee) are accounted for. This is what the UI displays.
The getSendData logic can viewed in github here if you would like to know how it works or implement in another language.
Get available liquidity for transfer
A transfer can only be bonded if the availale liquidity amount is greater than or equal to the transfer amount. The transfer bond at the destination may be delayed if it is sent when there is low or no available liquidity.
import { Hop, Chain } from'@hop-protocol/sdk'consthop=newHop('mainnet')constbridge=hop.connect(signer).bridge('USDC')// get total available liquidity for Polygon -> GnosisconstavailableLiquidity=awaitbridge.getFrontendAvailableLiquidity(Chain.Polygon,Chain.Gnosis)console.log(availableLiquidity.toString()) // 38142941773
Depositing underpooled assets will give you bonus LP tokens. Depositing overpooled assets will give you less LP tokens (shown as negative price impact).
import { Hop } from'@hop-protocol/sdk'constsourceChain='optimism'constdestinationChain='ethereum'consttransferIdOrTxHash='0xbc24dd151ced6ad0d725c753b513a2164e669868faeebea8224dd0b92e751df7'constsdk=newHop('mainnet')constbridge=sdk.bridge('ETH')consttx=awaitbridge.withdrawTransfer(sourceChain, destinationChain, transferIdOrTxHash)console.log(tx.hash)
Note: A transfer can be withdrawn only after the transfer root has been set at the destination chain, which may take a few hours or days depending on the chain.