Hop
Search…
Getting started
⚠️ JavaScript SDK is in beta

kInstall module

Using NPM:
1
npm install @hop-protocol/sdk
Copied!
Using Yarn:
1
yarn add @hop-protocol/sdk
Copied!

Import module

Import as ES6 module (e.g. Using TypeScript, babel, webpack):
1
import { Hop } from '@hop-protocol/sdk'
Copied!
Import as commonJS module (e.g. Using Node.js directly or no ES6 modules):
1
const { Hop } = require('@hop-protocol/sdk')
Copied!

Instantiate SDK

1
import { Hop } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
Copied!
Supported networks are: mainnet, kovan, goerli

Instantiate with ethers Signer for sending transactions:

1
import { Hop } from '@hop-protocol/sdk'
2
import { Wallet } from 'ethers'
3
4
const signer = new Wallet(privateKey)
5
const hop = new Hop('mainnet', signer)
Copied!
Example: Using window web3 provider as signer:
1
import { Hop } from '@hop-protocol/sdk'
2
import { Wallet } from 'ethers'
3
4
const provider = new ethers.providers.Web3Provider(window.ethereum, 'any')
5
const signer = provider.getSigner()
6
7
const hop = new Hop('mainnet', signer)
Copied!

SDK with Node.js

Basic example that instantiates sdk with signer
1
require('dotenv').config()
2
const { Hop } = require('@hop-protocol/sdk')
3
const { Wallet } = require('ethers')
4
5
const privateKey = process.env.PRIVATE_KEY
6
const signer = new Wallet(privateKey)
7
8
const hop = new Hop('mainnet', signer)
9
console.log(hop.version)
Copied!
Create .env file
1
PRIVATE_KEY=<your private key>
Copied!
Running example
1
$ node example.js
2
0.0.1-beta.198
Copied!

Examples

Unit conversion using ethers

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.
1
import { parseUnits, formatUnits } from 'ethers/lib/utils'
2
3
const decimals = 6
4
5
const amountBN = parseUnits('1', decimals)
6
console.log(amountBN.toString()) // 1000000
7
8
const amount = formatUnits('1000000', decimals)
9
console.log(amount.toString()) // 1.0
Copied!

Token decimals

Symbol
Decimals
USDC
6
USDT
6
DAI
18
MATIC
18
ETH
18

Send tokens across chains

Send L1->L2

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Ethereum -> Polygon
7
const tx = await bridge.send('100000000', Chain.Ethereum, Chain.Polygon)
8
console.log(tx.hash)
Copied!

Send L2->L1

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Polygon -> Ethereum
7
const tx = await bridge.send('100000000', Chain.Polygon, Chain.Ethereum)
8
console.log(tx.hash)
Copied!

Send L2->L2

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Polygon -> xDai
7
const tx = await bridge.send('100000000', Chain.Polygon, Chain.xDai)
8
console.log(tx.hash)
Copied!

Using BigNumber as amount input

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
import { parseUnits } from 'ethers/lib/utils'
3
4
const hop = new Hop('mainnet')
5
const bridge = hop.connect(signer).bridge('USDC')
6
7
// send 100 USDC tokens from Ethereum -> Polygon
8
const decimals = 6
9
const amount = parseUnits('100', decimals)
10
const tx = await bridge.send(amount, Chain.Ethereum, Chain.Polygon)
11
console.log(tx.hash)
Copied!

Specifying custom bonder fee

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
const amountBN = '10000000'
7
const source = Chain.Polygon
8
const destination = Chain.xDai
9
10
// send 100 USDC tokens from Polygon -> xDai
11
const bonderFee = await bridge.getTotalFee(amountBN, source, destination)
12
const tx = await bridge.send(amountBN, source, destination, {
13
bonderFee
14
})
15
console.log(tx.hash)
Copied!

Sending to a custom recipient

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Polygon -> xDai
7
const tx = await bridge.send('100000000', Chain.Polygon, Chain.xDai, {
8
recipient: '0x123...'
9
})
10
console.log(tx.hash)
Copied!

Specifying custom min amount out

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Polygon -> xDai
7
const tx = await bridge.send('100000000', Chain.Polygon, Chain.xDai, {
8
amountOutMin: '99863953' // must take account fee and slippage
9
})
10
11
console.log(tx.hash)
Copied!

Specify custom deadline

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// send 100 USDC tokens from Polygon -> xDai
7
const deadline = Math.floor((Date.now() / 1000) + (24 * 60 * 60)) // expire after one day
8
const tx = await bridge.send('100000000', Chain.Polygon, Chain.xDai, {
9
deadline
10
})
11
12
console.log(tx.hash)
Copied!

Get approval address for sending over bridge

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
import { constants } from 'ethers'
3
4
const hop = new Hop('mainnet')
5
const bridge = hop.connect(signer).bridge('USDC')
6
7
// get address to approve for sending over Ethereum -> Polygon Hop bridge
8
const approvalAddress = await bridge.getSendApprovalAddress(Chain.Ethereum, Chain.Polygon)
9
console.log(approvalAddress)
10
11
const token = bridge.getCanonicalToken(Chain.Ethereum)
12
const amountToApprove = constants.MaxUint256
13
const tx = await token.approve(approvalAddress, amountToApprove)
14
console.log(tx.hash)
Copied!

Get approval address for sending hTokens over bridge

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
import { constants } from 'ethers'
3
4
const hop = new Hop('mainnet')
5
const bridge = hop.connect(signer).bridge('USDC')
6
7
// get address to approve for sending over Ethereum -> Polygon Hop bridge
8
const isHToken = true
9
const approvalAddress = await bridge.getSendApprovalAddress(Chain.Ethereum, Chain.Polygon, isHToken)
10
console.log(approvalAddress)
Copied!

Send tokens over canonical bridge

Deposit tokens (L1 -> L2):

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('kovan')
4
const bridge = hop.connect(signer).canonicalBridge('USDC', Chain.xDai)
5
6
// send 1 USDC tokens from Ethereum -> xDai
7
const tx = await bridge.deposit('100000000')
8
console.log(tx.hash)
Copied!

Withdraw tokens (L2 -> L1):

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('kovan')
4
const bridge = hop.connect(signer).canonicalBridge('USDC', Chain.xDai)
5
6
// send 100 USDC tokesn from xDai -> Ethereum
7
const tx = await bridge.withdraw('100000000')
8
console.log(tx.hash)
Copied!

Estimate tokens amount out from swap

Call this to estimate how many tokens the swap will provide (does not take account slippage or bonder fee):
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// estimate tokens amount out for 100 USDC
7
const amountOut = await bridge.getAmountOut('1000000', Chain.Polygon, Chain.xDai)
8
console.log(amountOut) // 998608
Copied!

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.
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// get estimated tokens out when sending 100 USDC Polygon -> xDai
7
const { estimatedReceived } = await bridge.getSendData('10000000', Chain.Polygon, Chain.xDai)
8
console.log(estimatedReceived.toString()) // 98866001
Copied!

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.
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// estimate total bonder fee for sending 100 UDSC Polygon -> xDai
7
const totalBonderFee = await bridge.getTotalFee('10000000', Chain.Polygon, Chain.xDai)
8
console.log(toalBonderFee.toString()) // 998239
Copied!
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.
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// estimate base bonder fee for sending 100 UDSC Polygon -> xDai
7
const totalBonderFee = await bridge.getBonderFee('10000000', Chain.Polygon, Chain.xDai)
8
console.log(toalBonderFee.toString()) // 1000000
Copied!

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.
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// estimate bonder destination tx fee for sending USDC Polygon -> xDai
7
const destinationTxFee = await bridge.getBonderFee(Chain.Polygon, Chain.xDai)
8
console.log(destinationTxFee.toString()) // 772
Copied!

Get all send data info:

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// get all send data info for sending 100 USDC Polygon -> xDai
7
const sendData = await bridge.getSendData('10000000', Chain.Polygon, Chain.xDai)
8
console.log(sendData)
9
/*
10
{ amountOut: BigNumber { _hex: '0x05f3cd91', _isBigNumber: true },
11
rate: 0.998639,
12
priceImpact: -0.06402805611223007,
13
requiredLiquidity: BigNumber { _hex: '0x05f7a763', _isBigNumber: true },
14
lpFees: BigNumber { _hex: '0x013880', _isBigNumber: true },
15
adjustedBonderFee: BigNumber { _hex: '0x0f386a', _isBigNumber: true },
16
adjustedDestinationTxFee: BigNumber { _hex: '0x01d6', _isBigNumber: true },
17
totalFee: BigNumber { _hex: '0x0f3a40', _isBigNumber: true },
18
estimatedReceived: BigNumber { _hex: '0x05e49351', _isBigNumber: true } }
19
}
20
*/
Copied!

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.
1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('kovan')
4
const bridge = hop.connect(signer).bridge('USDC')
5
6
// get total available liquidity for Polygon -> xDai
7
const availableLiquidity = await bridge.getFrontendAvailableLiquidity(Chain.Polygon, Chain.xDai)
8
console.log(availableLiquidity.toString()) // 38142941773
Copied!

Watch for receipt events

1
import { Hop, Chain } from '@hop-protocol/sdk'
2
3
const hop = new Hop('kovan')
4
const bridge = hop.connect(signer).bridge('USDC')
5
const tx = await bridge.send('1000000', Chain.Kovan, Chain.xDai)
6
7
hop
8
.watch(tx.hash, Token.USDC, Chain.Kovan, Chain.xDai)
9
.on('receipt', data => {
10
const { receipt, chain } = data
11
console.log(receipt, chain)
12
})
13
})
Copied!

Set custom provider RPC URLs

1
import { Hop } from '@hop-protocol/sdk'
2
3
const hop = new Hop('mainnet')
4
5
hop.setChainProviders({
6
ethereum: new providers.StaticJsonRpcProvider('https://mainnet.infura.io/v3/84842078b09946638c03157f83405213'),
7
polygon: new providers.StaticJsonRpcProvider('https://polygon-rpc.com'),
8
xdai: new providers.StaticJsonRpcProvider('https://rpc.xdaichain.com'),
9
optimism: new providers.StaticJsonRpcProvider('https://mainnet.optimism.io'),
10
arbitrum: new providers.StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc'),
11
})
Copied!

More examples

If you'd like to see more examples or have any feedback, message us on Discord!

SDK API Reference

Contract addresses

Last modified 2mo ago