The Connect SDK enables fast, cheap, native USDC bridging powered by Circle's Cross Chain Transfer Protocol. Using CCTP to transfer native USDC across chains with the Connect SDK works very much like a standard Token Transfer with the SDK.
First install the SDK package
npm install @wormhole-foundation/sdk
To use the CCTP bridge, the platform must be imported and registered
import { Wormhole } from "@wormhole-foundation/sdk";
import evm from "@wormhole-foundation/sdk/evm";
// ...
const wh = await wormhole("Testnet", [evm]);
const srcAddress = Wormhole.chainAddress("Ethereum", "0xdeadbeef...")
const dstAddress = Wormhole.chainAddress("Avalanche", "0xbeefdead...")
const xfer = await wh.circleTransfer(
1_000_000n, //
srcAddress,
dstAddress
);
console.log(xfer);
A Manual transfer has 3 steps:
- Initiate The transfer by calling
initiateTransfer
and passing a Signer to sign the transactions.
console.log("Starting Transfer");
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log(`Started Transfer: `, srcTxids);
- Wait for the Circle Attestation to be available, optionally passing a
// See https://developers.circle.com/stablecoins/docs/required-block-confirmations for reasonable timeout settings
// based on origin chain
const timeout = 60 * 1000;
console.log("Waiting for Attestation");
const attestIds = await xfer.fetchAttestation(timeout);
console.log(`Got Attestation: `, attestIds);
- Complete the transfer by calling, you guessed it,
completeTransfer
and again passing a Signer for the destination chain
console.log("Completing Transfer");
const dstTxids = await xfer.completeTransfer(dst.signer);
console.log(`Completed Transfer: `, dstTxids);
Using the Automatic Relaying feature is even easier and only involves initiating the transfer. The Relayer infrastructure will handle fetching and delivering the Attestation for you.
const xfer = await wh.circleTransfer(
amount,
srcAddress,
dstAddress,
true, // automatic transfer plz
undefined, // An arbitrary bytes payload if one is necessary
0n, // no native gas dropoff for this demo
);
console.log(xfer);
console.log("Starting Transfer");
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log(`Started Transfer: `, srcTxids);
In the case that a manual transfer is started but not finished, the transfer object can be reconstituted from only the source chain and transaction hash.
This is especially useful in cases where a user has terminated their session prior to completing the transfer or even for debugging.
const timeout = 60 * 1000
// Rebuild the transfer from the source txid
const xfer = await CircleTransfer.from(wh, {
chain: "Avalanche",
txid: "0x6b6d5f101a32aa6d2f7bf0bf14d72bfbf76a640e1b2fdbbeeac5b82069cda4dd",
}, timeout);
const dstTxIds = await xfer.completeTransfer(signer);
console.log("Completed transfer: ", dstTxIds);
The full source of a working example is available here