Skip to content

Commit 0697e78

Browse files
committed
additions
1 parent a0f1336 commit 0697e78

14 files changed

+714
-230
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const xfer = await wh.circleTransfer(
2+
// amount as bigint (base units)
3+
req.amount,
4+
// sender chain/address
5+
src.address,
6+
// receiver chain/address
7+
dst.address,
8+
// automatic delivery boolean
9+
req.automatic,
10+
// payload to be sent with the transfer
11+
undefined,
12+
// If automatic, native gas can be requested to be sent to the receiver
13+
req.nativeGas
14+
);
15+
16+
// Note, if the transfer is requested to be Automatic, a fee for performing the relay
17+
// will be present in the quote. The fee comes out of the amount requested to be sent.
18+
// If the user wants to receive 1.0 on the destination, the amount to send should be 1.0 + fee.
19+
// The same applies for native gas dropoff
20+
const quote = await CircleTransfer.quoteTransfer(
21+
src.chain,
22+
dst.chain,
23+
xfer.transfer
24+
);
25+
console.log('Quote', quote);
26+
27+
console.log('Starting Transfer');
28+
const srcTxids = await xfer.initiateTransfer(src.signer);
29+
console.log(`Started Transfer: `, srcTxids);
30+
31+
if (req.automatic) {
32+
const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
33+
console.log(`Finished relay: `, relayStatus);
34+
return;
35+
}
36+
37+
// Note: Depending on chain finality, this timeout may need to be increased.
38+
// See https://developers.circle.com/stablecoin/docs/cctp-technical-reference#mainnet for more
39+
console.log('Waiting for Attestation');
40+
const attestIds = await xfer.fetchAttestation(60_000);
41+
console.log(`Got Attestation: `, attestIds);
42+
43+
console.log('Completing Transfer');
44+
const dstTxids = await xfer.completeTransfer(dst.signer);
45+
console.log(`Completed Transfer: `, dstTxids);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import {
2+
Chain,
3+
CircleTransfer,
4+
Network,
5+
Signer,
6+
TransactionId,
7+
TransferState,
8+
Wormhole,
9+
amount,
10+
wormhole,
11+
} from "@wormhole-foundation/sdk";
12+
import evm from "@wormhole-foundation/sdk/evm";
13+
import solana from "@wormhole-foundation/sdk/solana";
14+
import { SignerStuff, getSigner, waitForRelay } from "./helpers/index.js";
15+
16+
/*
17+
Notes:
18+
Only a subset of chains are supported by Circle for CCTP, see core/base/src/constants/circle.ts for currently supported chains
19+
20+
AutoRelayer takes a 0.1usdc fee when xfering to any chain beside goerli, which is 1 usdc
21+
*/
22+
//
23+
24+
(async function () {
25+
// init Wormhole object, passing config for which network
26+
// to use (e.g. Mainnet/Testnet) and what Platforms to support
27+
const wh = await wormhole("Testnet", [evm, solana]);
28+
29+
// Grab chain Contexts
30+
const sendChain = wh.getChain("Avalanche");
31+
const rcvChain = wh.getChain("Solana");
32+
33+
// Get signer from local key but anything that implements
34+
// Signer interface (e.g. wrapper around web wallet) should work
35+
const source = await getSigner(sendChain);
36+
const destination = await getSigner(rcvChain);
37+
38+
// 6 decimals for USDC (except for bsc, so check decimals before using this)
39+
const amt = amount.units(amount.parse("0.2", 6));
40+
41+
// Choose whether or not to have the attestation delivered for you
42+
const automatic = false;
43+
44+
// If the transfer is requested to be automatic, you can also request that
45+
// during redemption, the receiver gets some amount of native gas transferred to them
46+
// so that they may pay for subsequent transactions
47+
// The amount specified here is denominated in the token being transferred (USDC here)
48+
const nativeGas = automatic ? amount.units(amount.parse("0.0", 6)) : 0n;
49+
50+
await cctpTransfer(wh, source, destination, {
51+
amount: amt,
52+
automatic,
53+
nativeGas,
54+
});
55+
56+
// Note: you can pick up a partial transfer from the origin chain name and txid
57+
// once created, you can call `fetchAttestations` and `completeTransfer` assuming its a manual transfer.
58+
// This is especially helpful for chains with longer time to finality where you don't want
59+
// to have to wait for the attestation to be generated.
60+
// await completeTransfer(
61+
// wh,
62+
// {
63+
// chain: sendChain.chain,
64+
// txid: "0x6b431a9172f6c672976294b3a3d6cd79f46a7d6247440c0934af4bfc2b5ad957",
65+
// },
66+
// destination.signer,
67+
// );
68+
})();
69+
70+
async function cctpTransfer<N extends Network>(
71+
wh: Wormhole<N>,
72+
src: SignerStuff<N, any>,
73+
dst: SignerStuff<N, any>,
74+
req: {
75+
amount: bigint;
76+
automatic: boolean;
77+
nativeGas?: bigint;
78+
},
79+
) {
80+
// EXAMPLE_CCTP_TRANSFER
81+
const xfer = await wh.circleTransfer(
82+
// amount as bigint (base units)
83+
req.amount,
84+
// sender chain/address
85+
src.address,
86+
// receiver chain/address
87+
dst.address,
88+
// automatic delivery boolean
89+
req.automatic,
90+
// payload to be sent with the transfer
91+
undefined,
92+
// If automatic, native gas can be requested to be sent to the receiver
93+
req.nativeGas,
94+
);
95+
96+
// Note, if the transfer is requested to be Automatic, a fee for performing the relay
97+
// will be present in the quote. The fee comes out of the amount requested to be sent.
98+
// If the user wants to receive 1.0 on the destination, the amount to send should be 1.0 + fee.
99+
// The same applies for native gas dropoff
100+
const quote = await CircleTransfer.quoteTransfer(src.chain, dst.chain, xfer.transfer);
101+
console.log("Quote", quote);
102+
103+
console.log("Starting Transfer");
104+
const srcTxids = await xfer.initiateTransfer(src.signer);
105+
console.log(`Started Transfer: `, srcTxids);
106+
107+
if (req.automatic) {
108+
const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
109+
console.log(`Finished relay: `, relayStatus);
110+
return;
111+
}
112+
113+
// Note: Depending on chain finality, this timeout may need to be increased.
114+
// See https://developers.circle.com/stablecoin/docs/cctp-technical-reference#mainnet for more
115+
console.log("Waiting for Attestation");
116+
const attestIds = await xfer.fetchAttestation(60_000);
117+
console.log(`Got Attestation: `, attestIds);
118+
119+
console.log("Completing Transfer");
120+
const dstTxids = await xfer.completeTransfer(dst.signer);
121+
console.log(`Completed Transfer: `, dstTxids);
122+
// EXAMPLE_CCTP_TRANSFER
123+
}
124+
125+
export async function completeTransfer(
126+
wh: Wormhole<Network>,
127+
txid: TransactionId,
128+
signer: Signer,
129+
): Promise<void> {
130+
// EXAMPLE_RECOVER_TRANSFER
131+
// Rebuild the transfer from the source txid
132+
const xfer = await CircleTransfer.from(wh, txid);
133+
134+
const attestIds = await xfer.fetchAttestation(60 * 60 * 1000);
135+
console.log("Got attestation: ", attestIds);
136+
137+
const dstTxIds = await xfer.completeTransfer(signer);
138+
console.log("Completed transfer: ", dstTxIds);
139+
// EXAMPLE_RECOVER_TRANSFER
140+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import {
2+
Chain,
3+
GatewayTransfer,
4+
GatewayTransferDetails,
5+
Network,
6+
TokenId,
7+
Wormhole,
8+
amount,
9+
wormhole,
10+
} from "@wormhole-foundation/sdk";
11+
12+
// Import the platform specific packages
13+
14+
import cosmwasm from "@wormhole-foundation/sdk/cosmwasm";
15+
import evm from "@wormhole-foundation/sdk/evm";
16+
import solana from "@wormhole-foundation/sdk/solana";
17+
import { SignerStuff, getSigner } from "./helpers/index.js";
18+
19+
// We're going to transfer into, around, and out of the Cosmos ecosystem
20+
// First on Avalanche, transparently through gateway and over IBC to Cosmoshub
21+
// Then over IBC, transparently through gateway and over IBC to Osmosis
22+
// Finally out of Osmosis, transparently through gateway, out to Avalanche
23+
24+
// eg:
25+
// Avalanche[avax] => {Gateway ->}Osmosis[gateway/wrapped avax]
26+
// Osmosis[gateway/wrapped avax] -> {Gateway ->} Cosmoshub[gateway/wrapped avax]
27+
// Cosmoshub[gateway/wrapped avax] -> {Gateway} => Avalanch[avax]
28+
29+
// Key:
30+
// => : Regular contract call
31+
// -> : IBC Transfer
32+
// {*}: Transparently handled by Gateway
33+
34+
(async function () {
35+
// init Wormhole object, passing config for which network
36+
// to use (e.g. Mainnet/Testnet) and what Platforms to support
37+
const wh = await wormhole("Mainnet", [evm, solana, cosmwasm]);
38+
// Pick up where you left off by updating the txids as you go
39+
let fakeIt = false;
40+
41+
// Grab chain Contexts for each leg of our journey
42+
const external = wh.getChain("Solana");
43+
const cosmos1 = wh.getChain("Dymension");
44+
const cosmos2 = wh.getChain("Injective");
45+
46+
// Get signer from local key but anything that implements
47+
// Signer interface (e.g. wrapper around web wallet) should work
48+
const leg1 = await getSigner(external);
49+
const leg2 = await getSigner(cosmos1);
50+
const leg3 = await getSigner(cosmos2);
51+
52+
// we'll use the native token on the source chain
53+
const token: TokenId = Wormhole.tokenId(external.chain, "native");
54+
const amt = amount.units(amount.parse("0.001", external.config.nativeTokenDecimals));
55+
56+
// Transfer native token from source chain, through gateway, to a cosmos chain
57+
let route1 = fakeIt
58+
? await GatewayTransfer.from(
59+
wh,
60+
{
61+
chain: external.chain,
62+
txid: "5y2BnJ1Nwqe4m6KTSrry5Ni88xqVrqo4jdbuNwAPDuXEonQRVLbALf7abViwucKKr8U8cDfJtDmqnuRAAC6i6wtb",
63+
},
64+
600_000,
65+
)
66+
: await transferIntoCosmos(wh, token, amt, leg1, leg2);
67+
console.log("Route 1 (External => Cosmos)", route1);
68+
69+
// Lookup the Gateway representation of the wrappd token
70+
const { denom } = route1.ibcTransfers![0]!.data;
71+
const cosmosTokenAddress = Wormhole.parseAddress("Wormchain", denom);
72+
73+
// Transfer Gateway factory tokens over IBC through gateway to another Cosmos chain
74+
let route2 = fakeIt
75+
? await GatewayTransfer.from(
76+
wh,
77+
{
78+
chain: cosmos1.chain,
79+
txid: "3014CABA727C8A1BFCBD282095C771ACBAB3B13CC595B702ABFD3A4502315FBD",
80+
},
81+
600_000,
82+
)
83+
: await transferBetweenCosmos(
84+
wh,
85+
{ chain: cosmos1.chain, address: cosmosTokenAddress },
86+
1000n,
87+
leg2,
88+
leg3,
89+
);
90+
console.log("Route 2 (Cosmos -> Cosmos): ", route2);
91+
92+
// Transfer Gateway factory token through gateway back to source chain
93+
let route3 = fakeIt
94+
? await GatewayTransfer.from(
95+
wh,
96+
{
97+
chain: cosmos2.chain,
98+
txid: "BEDD0CE2FEA8FF5DF81FCA5142E72745E154F87D496CDA147FC4D5D46A7C7D81",
99+
},
100+
600_000,
101+
)
102+
: await transferOutOfCosmos(
103+
wh,
104+
{ chain: cosmos2.chain, address: cosmosTokenAddress },
105+
1000n,
106+
leg3,
107+
leg1,
108+
);
109+
console.log("Route 3 (Cosmos => External): ", route3);
110+
})();
111+
112+
async function transferIntoCosmos(
113+
wh: Wormhole<Network>,
114+
token: TokenId,
115+
amount: bigint,
116+
src: SignerStuff<Network, Chain>,
117+
dst: SignerStuff<Network, Chain>,
118+
): Promise<GatewayTransfer<Network>> {
119+
// EXAMPLE_GATEWAY_INBOUND
120+
console.log(
121+
`Beginning transfer into Cosmos from ${src.chain.chain}:${src.address.address.toString()} to ${
122+
dst.chain.chain
123+
}:${dst.address.address.toString()}`,
124+
);
125+
126+
const xfer = await GatewayTransfer.from(wh, {
127+
token: token,
128+
amount: amount,
129+
from: src.address,
130+
to: dst.address,
131+
} as GatewayTransferDetails);
132+
console.log("Created GatewayTransfer: ", xfer.transfer);
133+
134+
const srcTxIds = await xfer.initiateTransfer(src.signer);
135+
console.log("Started transfer on source chain", srcTxIds);
136+
137+
const attests = await xfer.fetchAttestation(600_000);
138+
console.log("Got Attestations", attests);
139+
// EXAMPLE_GATEWAY_INBOUND
140+
141+
return xfer;
142+
}
143+
144+
async function transferBetweenCosmos<N extends Network>(
145+
wh: Wormhole<N>,
146+
token: TokenId,
147+
amount: bigint,
148+
src: SignerStuff<N, Chain>,
149+
dst: SignerStuff<N, Chain>,
150+
): Promise<GatewayTransfer<N>> {
151+
// EXAMPLE_GATEWAY_INTERCOSMOS
152+
console.log(
153+
`Beginning transfer within cosmos from ${
154+
src.chain.chain
155+
}:${src.address.address.toString()} to ${dst.chain.chain}:${dst.address.address.toString()}`,
156+
);
157+
158+
const xfer = await GatewayTransfer.from(wh, {
159+
token: token,
160+
amount: amount,
161+
from: src.address,
162+
to: dst.address,
163+
} as GatewayTransferDetails);
164+
console.log("Created GatewayTransfer: ", xfer.transfer);
165+
166+
const srcTxIds = await xfer.initiateTransfer(src.signer);
167+
console.log("Started transfer on source chain", srcTxIds);
168+
169+
const attests = await xfer.fetchAttestation(60_000);
170+
console.log("Got attests: ", attests);
171+
// EXAMPLE_GATEWAY_INTERCOSMOS
172+
173+
return xfer;
174+
}
175+
176+
async function transferOutOfCosmos<N extends Network>(
177+
wh: Wormhole<N>,
178+
token: TokenId,
179+
amount: bigint,
180+
src: SignerStuff<N, Chain>,
181+
dst: SignerStuff<N, Chain>,
182+
): Promise<GatewayTransfer<N>> {
183+
// EXAMPLE_GATEWAY_OUTBOUND
184+
console.log(
185+
`Beginning transfer out of cosmos from ${
186+
src.chain.chain
187+
}:${src.address.address.toString()} to ${dst.chain.chain}:${dst.address.address.toString()}`,
188+
);
189+
190+
const xfer = await GatewayTransfer.from(wh, {
191+
token: token,
192+
amount: amount,
193+
from: src.address,
194+
to: dst.address,
195+
} as GatewayTransferDetails);
196+
console.log("Created GatewayTransfer: ", xfer.transfer);
197+
const srcTxIds = await xfer.initiateTransfer(src.signer);
198+
console.log("Started transfer on source chain", srcTxIds);
199+
200+
const attests = await xfer.fetchAttestation(600_000);
201+
console.log("Got attests", attests);
202+
203+
// Since we're leaving cosmos, this is required to complete the transfer
204+
const dstTxIds = await xfer.completeTransfer(dst.signer);
205+
console.log("Completed transfer on destination chain", dstTxIds);
206+
// EXAMPLE_GATEWAY_OUTBOUND
207+
208+
return xfer;
209+
}

0 commit comments

Comments
 (0)