@wormhole-foundation/sdk-connect
Version:
The core package for the Connect SDK, used in conjunction with 1 or more of the chain packages
146 lines • 6.38 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutomaticCCTPRoute = void 0;
const sdk_base_1 = require("@wormhole-foundation/sdk-base");
const sdk_definitions_1 = require("@wormhole-foundation/sdk-definitions");
const cctpTransfer_js_1 = require("../../protocols/cctp/cctpTransfer.js");
const types_js_1 = require("../../types.js");
const wormhole_js_1 = require("../../wormhole.js");
const route_js_1 = require("../route.js");
const types_js_2 = require("../types.js");
class AutomaticCCTPRoute extends route_js_1.AutomaticRoute {
static NATIVE_GAS_DROPOFF_SUPPORTED = true;
static meta = {
name: "AutomaticCCTP",
provider: "Circle",
};
static supportedNetworks() {
return ["Mainnet", "Testnet"];
}
// get the list of chains this route supports
static supportedChains(network) {
if (sdk_base_1.contracts.circleContractChains.has(network)) {
const circleSupportedChains = sdk_base_1.contracts.circleContractChains.get(network);
return circleSupportedChains.filter((c) => {
return sdk_base_1.contracts.circleContracts.get(network, c)?.wormholeRelayer;
});
}
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 = sdk_base_1.circle.usdcContract.get(fromChain.network, fromChain.chain);
if (!sourceChainUsdcContract)
return [];
if (!(0, sdk_definitions_1.isSameToken)(sourceToken, wormhole_js_1.Wormhole.tokenId(fromChain.chain, sourceChainUsdcContract))) {
return [];
}
const { network, chain } = toChain;
if (!sdk_base_1.circle.usdcContract.has(network, chain))
return [];
return [wormhole_js_1.Wormhole.chainAddress(chain, sdk_base_1.circle.usdcContract.get(network, chain))];
}
getDefaultOptions() {
return {
nativeGas: 0.0,
};
}
async validate(request, params) {
try {
const options = params.options ?? this.getDefaultOptions();
const normalizedParams = await this.normalizeTransferParams(request, params);
const validatedParams = {
normalizedParams,
options,
...params,
};
return { valid: true, params: validatedParams };
}
catch (e) {
return {
valid: false,
params,
error: e,
};
}
}
async quote(request, params) {
try {
return request.displayQuote(await cctpTransfer_js_1.CircleTransfer.quoteTransfer(request.fromChain, request.toChain, {
automatic: true,
amount: sdk_base_1.amount.units(params.normalizedParams.amount),
nativeGas: sdk_base_1.amount.units(params.normalizedParams.nativeGasAmount),
}), params);
}
catch (e) {
return {
success: false,
error: e,
};
}
}
async normalizeTransferParams(request, params) {
const amt = request.parseAmount(params.amount);
const ctb = await request.fromChain.getAutomaticCircleBridge();
const fee = await ctb.getRelayerFee(request.toChain.chain);
const minAmount = (fee * 105n) / 100n;
if (sdk_base_1.amount.units(amt) < minAmount) {
throw new types_js_2.MinAmountError(sdk_base_1.amount.fromBaseUnits(minAmount, amt.decimals));
}
const redeemableAmount = sdk_base_1.amount.units(amt) - fee;
const options = params.options ?? this.getDefaultOptions();
const nativeGasPerc = options.nativeGas ?? 0.0;
if (nativeGasPerc > 1.0 || nativeGasPerc < 0.0)
throw new Error("Native gas must be between 0.0 and 1.0 (0% and 100%)");
let nativeGasAmount = 0n;
if (nativeGasPerc > 0.0) {
const dcb = await request.toChain.getAutomaticCircleBridge();
let maxSwapAmount = await dcb.maxSwapAmount();
if (redeemableAmount < maxSwapAmount) {
// can't swap more than the receivable amount
maxSwapAmount = redeemableAmount;
}
const scale = 10000;
const scaledGas = BigInt(Math.floor(nativeGasPerc * scale));
// the native gas percentage is applied to the max swap amount
nativeGasAmount = (maxSwapAmount * scaledGas) / BigInt(scale);
if (nativeGasAmount === redeemableAmount && nativeGasAmount > 0n) {
// edge case: transfer will revert if the native gas amount is equal to the redeemable amount
nativeGasAmount -= 1n;
}
}
return {
fee: request.amountFromBaseUnits(fee),
amount: amt,
nativeGasAmount: request.amountFromBaseUnits(nativeGasAmount),
};
}
toTransferDetails(params, from, to) {
return {
from,
to,
amount: sdk_base_1.amount.units(params.normalizedParams.amount),
automatic: true,
nativeGas: sdk_base_1.amount.units(params.normalizedParams.nativeGasAmount),
};
}
async initiate(request, signer, quote, to) {
const { params } = quote;
let transfer = this.toTransferDetails(params, wormhole_js_1.Wormhole.chainAddress(signer.chain(), signer.address()), to);
let txids = await cctpTransfer_js_1.CircleTransfer.transfer(request.fromChain, transfer, signer);
const msg = await cctpTransfer_js_1.CircleTransfer.getTransferMessage(request.fromChain, txids[txids.length - 1].txid);
return {
from: transfer.from.chain,
to: transfer.to.chain,
state: types_js_1.TransferState.SourceFinalized,
originTxs: txids,
attestation: { id: msg.id, attestation: { message: msg.message } },
};
}
async *track(receipt, timeout) {
yield* cctpTransfer_js_1.CircleTransfer.track(this.wh, receipt, timeout);
}
}
exports.AutomaticCCTPRoute = AutomaticCCTPRoute;
//# sourceMappingURL=automatic.js.map
;