Quickstart & Examples
Additional Examples

Transaction Creation

As the SDK wraps all Synapse Protocol on-chain contracts, all transaction submission is handled through the end users wallet provider (through MetaMask, WalletConnect, etc). Below, the quickstart example is extended to include full transaction creation, including token approvals.
1
import {
2
Bridge,
3
Tokens,
4
ChainId,
5
Networks,
6
swappableTokens,
7
NetworkSwappableTokensMap
8
} from "@synapseprotocol/sdk";
9
10
import {JsonRpcProvider} from "@ethersproject/providers";
11
import {ContractTransaction, PopulatedTransaction} from "@ethersproject/contracts";
12
import {parseUnits, formatUnits} from "@ethersproject/units";
13
import {BigNumber} from "@ethersproject/bignumber";
14
15
16
// Initialize dummy Ethers Provider
17
const AVAX_PROVIDER = new JsonRpcProvider("https://api.avax.network/ext/bc/C/rpc");
18
// Use SDK Data about different chains
19
const AVAX_NETWORK = Networks.AVALANCHE;
20
21
// Initialize Bridge
22
const SYNAPSE_BRIDGE = new Bridge.SynapseBridge({
23
network: AVAX_NETWORK,
24
provider: AVAX_PROVIDER
25
});
26
27
// Set up some variables to prepare a Avalanche USDC -> BSC USDT quote
28
const
29
TOKEN_IN = Tokens.USDC,
30
TOKEN_OUT = Tokens.USDT,
31
CHAIN_OUT = ChainId.BSC,
32
INPUT_AMOUNT: BigNumber = parseUnits("1000", tokenIn.decimals(NETWORK.chainId));
33
34
// Use the following flow to handle
35
// 1) Receiving a bridge quote
36
// 2) Submitting an approval TX on the specific Token
37
// 3) Initiating a bridge transaction
38
39
async function submitBridgeTransaction_manual() {
40
// get estimated output
41
const { amountToReceive } = await SYNAPSE_BRIDGE.estimateBridgeTokenOutput({
42
tokenFrom: TOKEN_IN, // token to send from the source chain, in this case USDT on Avalanche
43
chainIdTo: CHAIN_OUT, // Chain ID of the destination chain, in this case BSC
44
tokenTo: TOKEN_OUT, // Token to be received on the destination chain, in this case USDC
45
amountFrom: INPUT_AMOUNT,
46
});
47
48
let
49
populatedApproveTxn: PopulatedTransaction,
50
populatedBridgeTokenTxn: PopulatedTransaction;
51
52
// build an ERC20 Approve() TX to have the user submit so that the Bridge contract
53
// can handle the cross-chain swap
54
// If desired, `amount` can be passed in the args object, which overrides
55
// the default behavior of "infinite approval" for the token.
56
try {
57
populatedApproveTxn = await SYNAPSE_BRIDGE.buildApproveTransaction({token: TOKEN_IN});
58
} catch (e) {
59
// handle error if one occurs
60
}
61
62
// submit populatedApproveTx via your web3/ethers pkg
63
64
// Once confirmed, build the bridge TX
65
66
try {
67
populatedBridgeTokenTxn = await SYNAPSE_BRIDGE.buildBridgeTokenTransaction({
68
tokenFrom: TOKEN_IN, // token to send from the source chain, in this case nUSD on Avalanche
69
chainIdTo: CHAIN_OUT, // Chain ID of the destination chain, in this case BSC
70
tokenTo: TOKEN_OUT, // Token to be received on the destination chain, in this case USDC
71
amountFrom: INPUT_AMOUNT, // Amount of `tokenFrom` being sent
72
amountTo: amountToReceive, // minimum desired amount of `tokenTo` to receive on the destination chain
73
});
74
} catch (e) {
75
// handle error if one occurs
76
}
77
78
// Submit bridge TX via your web3/ethers pkg
79
}
Copied!
Just like that, your application initiated a cross-chain transfer. The Synapse Network will then respond to the user submitted bridge transaction, and complete the token transfer on BSC within a few minutes.

Full example in React

A minimal viable example is located in the SDK Repo here. This is a barebones implementation displaying functionality of the SDK.

Automatic Transaction Submission

While in the first example the SDK handled creation of the data needed to be submitted on-chain through the connected wallet provider, in the following example, the SDK will both create the data needed, as well as initiate the transactions through the connected wallet for the user to submit on chain.
Use the following flow if having the SDK take care of Approval and Bridge "magically" is desired.
Note that in this flow, a valid ethersjs Signer instance must be passed to executeApproveTransaction and executeBridgeTokenTransaction so that they're able to send/execute their respective transactions on behalf of the user.
If your project maintains some sort of storage for contract approvals such that it's able to determine that an approval transaction isn't necessary in a given context, then there's obviously no need to send an otherwise unnecessary approval transaction.
1
async function doBridgeTransaction_magic() {
2
// This should not be null in practice, but it is such here for the purposes of example documentation.
3
let signer: Signer = null;
4
5
// get minimum desired output
6
const { amountToReceive } = await SYNAPSE_BRIDGE.estimateBridgeTokenOutput({
7
tokenFrom: TOKEN_IN, // token to send from the source chain, in this case nUSD on Avalanche
8
chainIdTo: CHAIN_OUT, // Chain ID of the destination chain, in this case BSC
9
tokenTo: TOKEN_OUT, // Token to be received on the destination chain, in this case USDC
10
amountFrom: INPUT_AMOUNT, // Amount of `tokenFrom` being sent
11
});
12
13
try {
14
// build and execute an ERC20 Approve transaction so that the Synapse Bridge contract
15
// can do its thing.
16
// If desired, `amount` can be passed in the args object, which overrides
17
// the default behavior of "infinite approval" for the token.
18
let approveTxn: ContractTransaction = await SYNAPSE_BRIDGE.executeApproveTransaction({
19
token: TOKEN_IN
20
}, signer);
21
22
// Wait for at least one confirmation on the sending chain, this is an optional
23
// step and can be either omitted or implemented in a custom manner.
24
await approveTxn.wait(1);
25
26
console.log(`ERC20 Approve transaction hash: ${approveTxn.hash}`);
27
console.log(`ERC20 Approve transaction block number: ${approveTxn.blockNumber}`);
28
} catch (err) {
29
// deal with the caught error accordingly
30
}
31
32
try {
33
// executeBridgeTokenTransaction requires an ethers Signer instance to be
34
// passed to it in order to actually do the bridge transaction.
35
// An optional field `addressTo` can be passed, which will send tokens
36
// on the output chain to an address other than the address of the Signer instance.
37
//
38
// NOTE: executeBridgeTokenTransaction performs the step of actually sending/broadcasting the signed
39
// transaction on the source chain.
40
let bridgeTxn: ContractTransaction = await SYNAPSE_BRIDGE.executeBridgeTokenTransaction({
41
tokenFrom: TOKEN_IN, // token to send from the source chain, in this case nUSD on Avalanche
42
chainIdTo: CHAIN_OUT, // Chain ID of the destination chain, in this case BSC
43
tokenTo: TOKEN_OUT, // Token to be received on the destination chain, in this case USDC
44
amountFrom: INPUT_AMOUNT, // Amount of `tokenFrom` being sent
45
amountTo: amountToReceive, // minimum desired amount of `tokenTo` to receive on the destination chain
46
}, signer);
47
48
// Wait for at least one confirmation on the sending chain, this is an optional
49
// step and can be either omitted or implemented in a custom manner.
50
await bridgeTxn.wait(1);
51
52
console.log(`Bridge transaction hash: ${bridgeTxn.hash}`);
53
console.log(`Bridge transaction block number: ${bridgeTxn.blockNumber}`);
54
} catch (err) {
55
// deal with the caught error accordingly
56
}
57
58
// You're done!
59
}
Copied!