@wormhole-foundation/sdk-connect
Version:
The core package for the Connect SDK, used in conjunction with 1 or more of the chain packages
122 lines • 4.82 kB
JavaScript
import { amount, circle, contracts } from "@wormhole-foundation/sdk-base";
import { CircleBridge, isSameToken } from "@wormhole-foundation/sdk-definitions";
import { signSendWait } from "../../common.js";
import { CircleTransfer } from "../../protocols/cctp/cctpTransfer.js";
import { TransferState, isAttested } from "../../types.js";
import { Wormhole } from "../../wormhole.js";
import { ManualRoute } from "../route.js";
export class CCTPRoute extends ManualRoute {
static meta = {
name: "ManualCCTP",
provider: "Circle",
};
static supportedNetworks() {
return ["Mainnet", "Testnet"];
}
// get the list of chains this route supports
static supportedChains(network) {
if (contracts.circleContractChains.has(network)) {
return contracts.circleContractChains.get(network);
}
return [];
}
// get the list of destination tokens that may be received on the destination chain
static async supportedDestinationTokens(sourceToken, fromChain, toChain) {
// Ensure the source token is USDC
const sourceChainUsdcContract = circle.usdcContract.get(fromChain.network, fromChain.chain);
if (!sourceChainUsdcContract)
return [];
if (!isSameToken(sourceToken, Wormhole.tokenId(fromChain.chain, sourceChainUsdcContract))) {
return [];
}
const { network, chain } = toChain;
if (!circle.usdcContract.has(network, chain))
return [];
return [Wormhole.chainAddress(chain, circle.usdcContract.get(network, chain))];
}
getDefaultOptions() {
return {
payload: undefined,
};
}
async validate(request, params) {
const amount = request.parseAmount(params.amount);
const validatedParams = {
normalizedParams: {
amount,
},
options: params.options ?? this.getDefaultOptions(),
...params,
};
return { valid: true, params: validatedParams };
}
async quote(request, params) {
try {
return request.displayQuote(await CircleTransfer.quoteTransfer(request.fromChain, request.toChain, {
automatic: false,
amount: amount.units(params.normalizedParams.amount),
...params.options,
}), params);
}
catch (e) {
return {
success: false,
error: e,
};
}
}
async initiate(request, signer, quote, to) {
const { params } = quote;
const transfer = await CircleTransfer.destinationOverrides(request.fromChain, request.toChain, this.toTransferDetails(params, Wormhole.chainAddress(signer.chain(), signer.address()), to));
const txids = await CircleTransfer.transfer(request.fromChain, transfer, signer);
const msg = await CircleTransfer.getTransferMessage(request.fromChain, txids[txids.length - 1].txid);
return {
from: transfer.from.chain,
to: transfer.to.chain,
state: TransferState.SourceFinalized,
originTxs: txids,
attestation: { id: msg.id, attestation: { message: msg.message } },
};
}
async complete(signer, receipt) {
if (!isAttested(receipt))
throw new Error("The source must be finalized in order to complete the transfer");
const { id, attestation: att } = receipt.attestation;
if (CircleBridge.isCircleAttestation(att)) {
const { message, attestation } = att;
if (!attestation)
throw new Error(`No Circle attestation for ${id}`);
const toChain = this.wh.getChain(receipt.to);
const cb = await toChain.getCircleBridge();
const sender = Wormhole.parseAddress(signer.chain(), signer.address());
const xfer = cb.redeem(sender, message, attestation);
const dstTxids = await signSendWait(toChain, xfer, signer);
return {
...receipt,
state: TransferState.DestinationInitiated,
destinationTxs: dstTxids,
};
}
else {
//
return receipt;
}
}
async resume(txid) {
const xfer = await CircleTransfer.from(this.wh, txid, 10 * 1000);
return CircleTransfer.getReceipt(xfer);
}
async *track(receipt, timeout) {
yield* CircleTransfer.track(this.wh, receipt, timeout);
}
toTransferDetails(params, from, to) {
return {
from,
to,
amount: amount.units(params.normalizedParams.amount),
automatic: false,
...params.options,
};
}
}
//# sourceMappingURL=manual.js.map