Skip to main content

Example Code

Example SDK & API implementations

Basic Implementation

// app.js

import { JsonRpcProvider } from '@ethersproject/providers'
import { Provider } from '@ethersproject/abstract-provider'
import { SynapseSDK } from '@synapsecns/sdk-router'
import { BigNumber } from '@ethersproject/bignumber'

//Set up providers (RPCs) for each chain desired**
const arbitrumProvider: Provider = new JsonRpcProvider('https://arb1.arbitrum.io/rpc')
const avalancheProvider: Provider = new JsonRpcProvider('https://api.avax.network/ext/bc/C/rpc')

//Structure arguments properly
const chainIds = [42161, 43114]
const providers = [arbitrumProvider, avalancheProvider]

//Set up a SynapseSDK instance
const Synapse = new SynapseSDK(chainIds, providers)

// quote
const quote = await Synapse.bridgeQuote(
42161, // From Chain
43114, // To Chain
'0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', // From Token
'0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664', // To Token
BigNumber.from('20000000'), // Amount
{
deadline: 1234567890,
excludedModules: ['SynapseRFQ'],
originUserAddress: '0x1234567890abcdef1234567890abcdef12345678',
}
)

// bridge
await Synapse.bridge(
'0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9', // To Address
quote.routerAddress, // bridge router contract address
42161, // Origin Chain
43114, // Destination Chain
'0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', // Origin Token Address
BigNumber.from('20000000'), // Amount
quote.originQuery, // Origin query from bridgeQuote()
quote.destQuery // Destination query from bridgeQuote()
)

NextJS Implementation

Dependencies

Wagmi, RainbowKit

App

// app.tsx

import '@styles/global.css'
import '@rainbow-me/rainbowkit/styles.css'
import { SynapseProvider } from '@/utils/SynapseProvider'
import type { AppProps } from 'next/app'
import { Provider as EthersProvider } from '@ethersproject/abstract-provider'
import { JsonRpcProvider } from '@ethersproject/providers'
import { configureChains, createClient, WagmiConfig } from 'wagmi'
import {
mainnet,
arbitrum,
aurora,
avalanche,
bsc,
canto,
fantom,
harmonyOne,
metis,
moonbeam,
moonriver,
optimism,
polygon,
} from 'wagmi/chains'

import {
getDefaultWallets,
RainbowKitProvider,
darkTheme,
} from '@rainbow-me/rainbowkit'
import { alchemyProvider } from 'wagmi/providers/alchemy'
import { publicProvider } from 'wagmi/providers/public'

export default function App({ Component, pageProps }: AppProps) {
const { chains, provider } = configureChains([mainnet,
arbitrum,
aurora,
avalanche,
bsc,
canto,
fantom,
harmonyOne,
metis,
moonbeam,
moonriver,
optimism,
polygon], [
alchemyProvider({ apiKey: 'API_KEY' }),
publicProvider(),
])

const { connectors } = getDefaultWallets({
appName: 'ExampleApp',
chains,
})

const wagmiClient = createClient({
autoConnect: true,
connectors,
provider,
})

// Synapse client params setup example
let synapseProviders: EthersProvider[] = []
chains.map((chain) => {
let rpc: EthersProvider = new JsonRpcProvider(chain.rpcUrls.default.http[0])
synapseProviders.push(rpc)
})

return (
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains} theme={darkTheme()}>
<SynapseProvider
chainIds={chains.map((chain) => chain.id)}
providers={synapseProviders}
>
<Component {...pageProps} />
</SynapseProvider>
</RainbowKitProvider>
</WagmiConfig>
)
}

Provider

// `@/utils/SynapseProvider.tsx`

import { createContext, useContext } from 'react'
import { SynapseSDK } from '@synapsecns/sdk-router'
import { Provider } from '@ethersproject/abstract-provider'

export const SynapseContext = createContext<SynapseSDK>(null)

export const SynapseProvider = ({
children,
chainIds,
providers,
}: {
children: React.ReactNode
chainIds: number[]
providers: Provider[]
}) => {
const sdk = new SynapseSDK(chainIds, providers)
return (
<SynapseContext.Provider value={sdk}>{children}</SynapseContext.Provider>
)
}

export const useSynapseContext = () => useContext(SynapseContext)

Homepage

// `/homepage/index.tsx`

import { useSynapseContext } from '@/utils/SynapseProvider'
import { Zero } from '@ethersproject/constants'
import { useState, useEffect } from 'react'
import { getNetwork } from '@wagmi/core'
import {
DEFAULT_FROM_CHAIN,
DEFAULT_TO_CHAIN,
DEFAULT_FROM_TOKEN,
DEFAULT_TO_TOKEN,
} from '@/constants/bridge'

export default function HomePage({ address }: { address: `0x${string}` }) {
// Get the synapse sdk
const SynapseSDK = useSynapseContext()

// Get the current time
const time = // add logic to get the current unix timestamp
// Example state hooks
const [fromToken, setFromToken] = useState(DEFAULT_FROM_TOKEN)
const [toToken, setToToken] = useState(DEFAULT_TO_TOKEN)
const [fromChainId, setFromChainId] = useState(DEFAULT_FROM_CHAIN)
const [toChainId, setToChainId] = useState(DEFAULT_TO_CHAIN)
const [amount, setAmount] = useState(Zero)
const [bridgeQuote, setBridgeQuote] = useState({
outputAmountString: '',
quotes: { originQuery: null, destQuery: null },
})

// Set connected network when component is mounted
useEffect(() => {
const { chain: fromChainIdRaw } = getNetwork()
setFromChainId(fromChainIdRaw ? fromChainIdRaw?.id : DEFAULT_FROM_CHAIN)
}, [])

// Get Quote function
// Suggestion: this function should be triggered from an useEffect when amount or to/from token/chain is altered
const getQuote = async () = {
SynapseSDK.bridgeQuote(
fromChainId,
toChainId,
fromToken,
toToken,
amount,
{
deadline: time + 10000,
excludedModules: [],
originUserAddress: address,
}
)
.then(
({ feeAmount, bridgeFee, maxAmountOut, originQuery, destQuery }) => {
let toValueBigNum = maxAmountOut ?? Zero
let toValueBase = toValueBigNum.div(toDecimals).toString()
let toValueMantissa = toValueBigNum.mod(toDecimals).toString()

setBridgeQuote({
outputAmountString: toValueBase + '.' + toValueMantissa,
quotes: {
originQuery,
destQuery,
},
})
// do something
}
)
.catch((err) => {
alert('error getting quote', err)
// do something
})

}

// Execute bridge function
const executeBridge = async () = {
await Synapse.bridge(
toAddress, // To Address
bridgeQuote.routerAddress, // bridge router contract address
fromChainId, // Origin Chain
toChainId, // Destination Chain
fromToken, // Origin Token Address
amount, // Amount
bridgeQuote.quotes.originQuery, // Origin query from bridgeQuote()
bridgeQuote.quotes.destQuery // Destination query from bridgeQuote()
).then(({to, data}) => {
// do something
}
)
.catch((err) => {
alert('error bridging', err)
// do something
})
}

// ...

}

API Functions

Estimate bridge output

async function estimateBridgeOutput(
fromChain,
toChain,
fromToken,
toToken,
amountFrom
) {
const query_string = `fromChain=${fromChain}&toChain=${toChain}&fromToken=${fromToken}&toToken=${toToken}&amountFrom=${amountFrom}`;
const response = await fetch(
`https://api.synapseprotocol.com/bridge?${query_string}`
);

const response_json = await response.json();
// Check if the response is an array and has at least one item
if (Array.isArray(response_json) && response_json.length > 0) {
return response_json[0]; // Return the first item
} else {
throw new Error('No bridge quotes available');
}
}

estimateBridgeOutput(
1, // Ethereum
42161, // Arbitrum
"USDC",
"USDC",
"1000"
).then(firstQuote => {
console.log('First bridge quote:', firstQuote);
}).catch(error => {
console.error('Error:', error.message);
});

Generate unsigned bridge transaction

async function generateUnsignedBridgeTxn(
fromChain,
toChain,
fromToken,
toToken,
amountFrom,
destAddress
) {
const query_string = `fromChain=${fromChain}&toChain=${toChain}&fromToken=${fromToken}&toToken=${toToken}&amount=${amountFrom}&destAddress=${addressTo}`;
const response = await fetch(
`https://api.synapseprotocol.com/bridgeTxInfo?${query_string}`
);
const response_json = await response.json();
return await response_json;
}

generateUnsignedBridgeTxn(
1, // Ethereum
42161, // Arbitrum
"USDC",
"USDC",
"1000"
"0x2D2c027E0d1A899a1965910Dd272bcaE1cD03c22"
);