@aptos-labs/cross-chain-core 4.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/CrossChainCore.d.ts +36 -0
- package/dist/CrossChainCore.d.ts.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/mainnet/chains.d.ts +17 -0
- package/dist/config/mainnet/chains.d.ts.map +1 -0
- package/dist/config/mainnet/index.d.ts +3 -0
- package/dist/config/mainnet/index.d.ts.map +1 -0
- package/dist/config/mainnet/tokens.d.ts +4 -0
- package/dist/config/mainnet/tokens.d.ts.map +1 -0
- package/dist/config/testnet/chains.d.ts +19 -0
- package/dist/config/testnet/chains.d.ts.map +1 -0
- package/dist/config/testnet/index.d.ts +3 -0
- package/dist/config/testnet/index.d.ts.map +1 -0
- package/dist/config/testnet/tokens.d.ts +4 -0
- package/dist/config/testnet/tokens.d.ts.map +1 -0
- package/dist/config/types.d.ts +41 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +989 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +957 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/wormhole/index.d.ts +5 -0
- package/dist/providers/wormhole/index.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +18 -0
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts +5 -0
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/Signer.d.ts +17 -0
- package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts +28 -0
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/types.d.ts +39 -0
- package/dist/providers/wormhole/types.d.ts.map +1 -0
- package/dist/providers/wormhole/wormhole.d.ts +35 -0
- package/dist/providers/wormhole/wormhole.d.ts.map +1 -0
- package/dist/utils/getUsdcBalance.d.ts +5 -0
- package/dist/utils/getUsdcBalance.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +83 -0
- package/src/CrossChainCore.ts +130 -0
- package/src/config/index.ts +3 -0
- package/src/config/mainnet/chains.ts +64 -0
- package/src/config/mainnet/index.ts +2 -0
- package/src/config/mainnet/tokens.ts +43 -0
- package/src/config/testnet/chains.ts +69 -0
- package/src/config/testnet/index.ts +2 -0
- package/src/config/testnet/tokens.ts +43 -0
- package/src/config/types.ts +45 -0
- package/src/index.ts +5 -0
- package/src/providers/wormhole/index.ts +4 -0
- package/src/providers/wormhole/signers/AptosLocalSigner.ts +136 -0
- package/src/providers/wormhole/signers/EthereumSigner.ts +49 -0
- package/src/providers/wormhole/signers/Signer.ts +102 -0
- package/src/providers/wormhole/signers/SolanaSigner.ts +418 -0
- package/src/providers/wormhole/types.ts +59 -0
- package/src/providers/wormhole/wormhole.ts +320 -0
- package/src/utils/getUsdcBalance.ts +82 -0
- package/src/utils/logger.ts +17 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chainToPlatform,
|
|
3
|
+
routes,
|
|
4
|
+
TokenId,
|
|
5
|
+
Wormhole,
|
|
6
|
+
wormhole,
|
|
7
|
+
PlatformLoader,
|
|
8
|
+
TransferState,
|
|
9
|
+
} from "@wormhole-foundation/sdk";
|
|
10
|
+
import { Network, sleep } from "@aptos-labs/ts-sdk";
|
|
11
|
+
import aptos from "@wormhole-foundation/sdk/aptos";
|
|
12
|
+
import solana from "@wormhole-foundation/sdk/solana";
|
|
13
|
+
import evm from "@wormhole-foundation/sdk/evm";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
Chain,
|
|
17
|
+
CrossChainProvider,
|
|
18
|
+
CrossChainCore,
|
|
19
|
+
} from "../../CrossChainCore";
|
|
20
|
+
import { logger } from "../../utils/logger";
|
|
21
|
+
import { AptosLocalSigner } from "./signers/AptosLocalSigner";
|
|
22
|
+
import { Signer } from "./signers/Signer";
|
|
23
|
+
import { ChainConfig } from "../../config";
|
|
24
|
+
import {
|
|
25
|
+
WormholeQuoteRequest,
|
|
26
|
+
WormholeQuoteResponse,
|
|
27
|
+
WormholeInitiateTransferRequest,
|
|
28
|
+
WormholeInitiateTransferResponse,
|
|
29
|
+
WormholeRouteResponse,
|
|
30
|
+
WormholeRequest,
|
|
31
|
+
WormholeSubmitTransferRequest,
|
|
32
|
+
WormholeStartTransferResponse,
|
|
33
|
+
WormholeClaimTransferRequest,
|
|
34
|
+
} from "./types";
|
|
35
|
+
import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
|
|
36
|
+
import { EIP1193DerivedWallet } from "@aptos-labs/derived-wallet-ethereum";
|
|
37
|
+
|
|
38
|
+
export class WormholeProvider
|
|
39
|
+
implements
|
|
40
|
+
CrossChainProvider<
|
|
41
|
+
WormholeQuoteRequest,
|
|
42
|
+
WormholeQuoteResponse,
|
|
43
|
+
WormholeInitiateTransferRequest,
|
|
44
|
+
WormholeInitiateTransferResponse
|
|
45
|
+
>
|
|
46
|
+
{
|
|
47
|
+
private crossChainCore: CrossChainCore;
|
|
48
|
+
|
|
49
|
+
private _wormholeContext: Wormhole<"Mainnet" | "Testnet"> | undefined;
|
|
50
|
+
|
|
51
|
+
private wormholeRoute: WormholeRouteResponse | undefined;
|
|
52
|
+
private wormholeRequest: WormholeRequest | undefined;
|
|
53
|
+
private wormholeQuote: WormholeQuoteResponse | undefined;
|
|
54
|
+
|
|
55
|
+
constructor(core: CrossChainCore) {
|
|
56
|
+
this.crossChainCore = core;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get wormholeContext(): Wormhole<"Mainnet" | "Testnet"> | undefined {
|
|
60
|
+
return this._wormholeContext;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async setWormholeContext(sourceChain: Chain) {
|
|
64
|
+
const dappNetwork = this.crossChainCore._dappConfig?.aptosNetwork;
|
|
65
|
+
if (dappNetwork === Network.DEVNET) {
|
|
66
|
+
throw new Error("Devnet is not supported on Wormhole");
|
|
67
|
+
}
|
|
68
|
+
if (!sourceChain) {
|
|
69
|
+
throw new Error("Origin chain not selected");
|
|
70
|
+
}
|
|
71
|
+
const isMainnet = dappNetwork === Network.MAINNET;
|
|
72
|
+
const platforms: PlatformLoader<any>[] = [aptos, solana, evm];
|
|
73
|
+
const wh = await wormhole(isMainnet ? "Mainnet" : "Testnet", platforms);
|
|
74
|
+
this._wormholeContext = wh;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getRoute(sourceChain: Chain): Promise<{
|
|
78
|
+
route: WormholeRouteResponse;
|
|
79
|
+
request: WormholeRequest;
|
|
80
|
+
}> {
|
|
81
|
+
if (!this._wormholeContext) {
|
|
82
|
+
throw new Error("Wormhole context not initialized");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const { sourceToken, destToken } = this.getTokenInfo(sourceChain);
|
|
86
|
+
|
|
87
|
+
const sourceContext = this._wormholeContext
|
|
88
|
+
.getPlatform(chainToPlatform(sourceChain))
|
|
89
|
+
.getChain(sourceChain);
|
|
90
|
+
|
|
91
|
+
logger.log("sourceContext", sourceContext);
|
|
92
|
+
|
|
93
|
+
const destContext = this._wormholeContext
|
|
94
|
+
.getPlatform(chainToPlatform("Aptos"))
|
|
95
|
+
.getChain("Aptos");
|
|
96
|
+
|
|
97
|
+
logger.log("destContext", destContext);
|
|
98
|
+
|
|
99
|
+
const request = await routes.RouteTransferRequest.create(
|
|
100
|
+
this._wormholeContext,
|
|
101
|
+
{
|
|
102
|
+
source: sourceToken,
|
|
103
|
+
destination: destToken,
|
|
104
|
+
},
|
|
105
|
+
sourceContext,
|
|
106
|
+
destContext
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const resolver = this._wormholeContext.resolver([
|
|
110
|
+
routes.CCTPRoute, // manual CCTP
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const route = await resolver.findRoutes(request);
|
|
114
|
+
const cctpRoute = route[0];
|
|
115
|
+
|
|
116
|
+
this.wormholeRoute = cctpRoute;
|
|
117
|
+
this.wormholeRequest = request;
|
|
118
|
+
|
|
119
|
+
return { route: cctpRoute, request };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async getQuote(input: WormholeQuoteRequest): Promise<WormholeQuoteResponse> {
|
|
123
|
+
const { amount, sourceChain } = input;
|
|
124
|
+
|
|
125
|
+
if (!this._wormholeContext) {
|
|
126
|
+
await this.setWormholeContext(sourceChain);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const { route, request } = await this.getRoute(sourceChain);
|
|
130
|
+
|
|
131
|
+
// TODO what is nativeGas for?
|
|
132
|
+
const transferParams = {
|
|
133
|
+
amount: amount,
|
|
134
|
+
options: { nativeGas: 0 },
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const validated = await route.validate(request, transferParams);
|
|
138
|
+
if (!validated.valid) {
|
|
139
|
+
logger.log("invalid", validated.valid);
|
|
140
|
+
throw new Error(`Invalid quote: ${validated.error}`).message;
|
|
141
|
+
}
|
|
142
|
+
const quote = await route.quote(request, validated.params);
|
|
143
|
+
if (!quote.success) {
|
|
144
|
+
logger.log("quote failed", quote.success);
|
|
145
|
+
throw new Error(`Invalid quote: ${quote.error}`).message;
|
|
146
|
+
}
|
|
147
|
+
this.wormholeQuote = quote;
|
|
148
|
+
logger.log("quote", quote);
|
|
149
|
+
return quote;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async submitCCTPTransfer(
|
|
153
|
+
input: WormholeSubmitTransferRequest
|
|
154
|
+
): Promise<WormholeStartTransferResponse> {
|
|
155
|
+
const { sourceChain, wallet, destinationAddress } = input;
|
|
156
|
+
|
|
157
|
+
if (!this._wormholeContext) {
|
|
158
|
+
await this.setWormholeContext(sourceChain);
|
|
159
|
+
}
|
|
160
|
+
if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
|
|
161
|
+
throw new Error("Wormhole route, request, or quote not initialized");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let signerAddress: string;
|
|
165
|
+
|
|
166
|
+
const chainContext = this.getChainConfig(sourceChain).context;
|
|
167
|
+
|
|
168
|
+
//const currentAccount = await wallet.getAccount();
|
|
169
|
+
if (chainContext === "Solana") {
|
|
170
|
+
signerAddress =
|
|
171
|
+
(wallet as SolanaDerivedWallet).solanaWallet.publicKey?.toBase58() ||
|
|
172
|
+
"";
|
|
173
|
+
} else {
|
|
174
|
+
// is Ethereum
|
|
175
|
+
[signerAddress] = await (
|
|
176
|
+
wallet as EIP1193DerivedWallet
|
|
177
|
+
).eip1193Provider.request({
|
|
178
|
+
method: "eth_requestAccounts",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
logger.log("signerAddress", signerAddress);
|
|
182
|
+
|
|
183
|
+
const signer = new Signer(
|
|
184
|
+
this.getChainConfig(sourceChain),
|
|
185
|
+
signerAddress,
|
|
186
|
+
{},
|
|
187
|
+
wallet
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
let receipt = await this.wormholeRoute.initiate(
|
|
191
|
+
this.wormholeRequest,
|
|
192
|
+
signer,
|
|
193
|
+
this.wormholeQuote,
|
|
194
|
+
Wormhole.chainAddress("Aptos", destinationAddress.toString())
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const originChainTxnId =
|
|
198
|
+
"originTxs" in receipt
|
|
199
|
+
? receipt.originTxs[receipt.originTxs.length - 1].txid
|
|
200
|
+
: undefined;
|
|
201
|
+
|
|
202
|
+
return { originChainTxnId: originChainTxnId || "", receipt };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async claimCCTPTransfer(
|
|
206
|
+
input: WormholeClaimTransferRequest
|
|
207
|
+
): Promise<{ destinationChainTxnId: string }> {
|
|
208
|
+
let { receipt, mainSigner, sponsorAccount } = input;
|
|
209
|
+
if (!this.wormholeRoute) {
|
|
210
|
+
throw new Error("Wormhole route not initialized");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
logger.log("mainSigner", mainSigner.accountAddress.toString());
|
|
214
|
+
|
|
215
|
+
let retries = 0;
|
|
216
|
+
const maxRetries = 5;
|
|
217
|
+
const baseDelay = 1000; // Initial delay of 1 second
|
|
218
|
+
|
|
219
|
+
while (retries < maxRetries) {
|
|
220
|
+
try {
|
|
221
|
+
for await (receipt of this.wormholeRoute.track(receipt, 120 * 1000)) {
|
|
222
|
+
if (receipt.state >= TransferState.SourceInitiated) {
|
|
223
|
+
logger.log("Receipt is on track ", receipt);
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const signer = new AptosLocalSigner(
|
|
227
|
+
"Aptos",
|
|
228
|
+
{},
|
|
229
|
+
mainSigner, // the account that signs the "claim" transaction
|
|
230
|
+
sponsorAccount ? sponsorAccount : undefined // the fee payer account
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (routes.isManual(this.wormholeRoute)) {
|
|
234
|
+
const circleAttestationReceipt =
|
|
235
|
+
await this.wormholeRoute.complete(signer, receipt);
|
|
236
|
+
logger.log("Claim receipt: ", circleAttestationReceipt);
|
|
237
|
+
const destinationChainTxnId = signer.claimedTransactionHashes();
|
|
238
|
+
return { destinationChainTxnId };
|
|
239
|
+
} else {
|
|
240
|
+
// Should be unreachable
|
|
241
|
+
return { destinationChainTxnId: "" };
|
|
242
|
+
}
|
|
243
|
+
} catch (e) {
|
|
244
|
+
console.error("Failed to claim", e);
|
|
245
|
+
return { destinationChainTxnId: "" };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
} catch (e) {
|
|
250
|
+
console.error(
|
|
251
|
+
`Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
|
|
252
|
+
e
|
|
253
|
+
);
|
|
254
|
+
const delay = baseDelay * Math.pow(2, retries); // Exponential backoff
|
|
255
|
+
await sleep(delay);
|
|
256
|
+
retries++;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Should be unreachable
|
|
260
|
+
return { destinationChainTxnId: "" };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Initiates a transfer of USDC funds from the source chain wallet to the destination chain wallet
|
|
265
|
+
* @param args
|
|
266
|
+
* @returns
|
|
267
|
+
*/
|
|
268
|
+
async initiateCCTPTransfer(
|
|
269
|
+
input: WormholeInitiateTransferRequest
|
|
270
|
+
): Promise<WormholeInitiateTransferResponse> {
|
|
271
|
+
if (this.crossChainCore._dappConfig?.aptosNetwork === Network.DEVNET) {
|
|
272
|
+
throw new Error("Devnet is not supported on Wormhole");
|
|
273
|
+
}
|
|
274
|
+
// if amount is provided, it is expected to get the quote internally
|
|
275
|
+
// and initiate a transfer automatically
|
|
276
|
+
if (input.amount) {
|
|
277
|
+
await this.getQuote({
|
|
278
|
+
amount: input.amount,
|
|
279
|
+
sourceChain: input.sourceChain,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Submit transfer transaction from origin chain
|
|
283
|
+
let { originChainTxnId, receipt } = await this.submitCCTPTransfer(input);
|
|
284
|
+
// Claim transfer transaction on destination chain
|
|
285
|
+
const { destinationChainTxnId } = await this.claimCCTPTransfer({
|
|
286
|
+
receipt,
|
|
287
|
+
mainSigner: input.mainSigner,
|
|
288
|
+
sponsorAccount: input.sponsorAccount,
|
|
289
|
+
});
|
|
290
|
+
return { originChainTxnId, destinationChainTxnId };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
getChainConfig(chain: Chain): ChainConfig {
|
|
294
|
+
const chainConfig =
|
|
295
|
+
this.crossChainCore.CHAINS[
|
|
296
|
+
chain as keyof typeof this.crossChainCore.CHAINS
|
|
297
|
+
];
|
|
298
|
+
if (!chainConfig) {
|
|
299
|
+
throw new Error(`Chain config not found for chain: ${chain}`);
|
|
300
|
+
}
|
|
301
|
+
return chainConfig;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
getTokenInfo(sourceChain: Chain): {
|
|
305
|
+
sourceToken: TokenId;
|
|
306
|
+
destToken: TokenId;
|
|
307
|
+
} {
|
|
308
|
+
const sourceToken: TokenId = Wormhole.tokenId(
|
|
309
|
+
this.crossChainCore.TOKENS[sourceChain].tokenId.chain as Chain,
|
|
310
|
+
this.crossChainCore.TOKENS[sourceChain].tokenId.address
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const destToken: TokenId = Wormhole.tokenId(
|
|
314
|
+
this.crossChainCore.APTOS_TOKEN.tokenId.chain as Chain,
|
|
315
|
+
this.crossChainCore.APTOS_TOKEN.tokenId.address
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
return { sourceToken, destToken };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
|
+
import {
|
|
4
|
+
AptosMainnetUSDCToken,
|
|
5
|
+
AptosTestnetUSDCToken,
|
|
6
|
+
mainnetTokens,
|
|
7
|
+
testnetTokens,
|
|
8
|
+
} from "../config";
|
|
9
|
+
import { ethers, JsonRpcProvider } from "ethers";
|
|
10
|
+
|
|
11
|
+
export const getSolanaWalletUSDCBalance = async (
|
|
12
|
+
walletAddress: string,
|
|
13
|
+
aptosNetwork: Network,
|
|
14
|
+
rpc: string
|
|
15
|
+
): Promise<string> => {
|
|
16
|
+
const address = new PublicKey(walletAddress);
|
|
17
|
+
const tokenAddress =
|
|
18
|
+
aptosNetwork === Network.MAINNET
|
|
19
|
+
? mainnetTokens["Solana"].tokenId.address
|
|
20
|
+
: testnetTokens["Solana"].tokenId.address;
|
|
21
|
+
|
|
22
|
+
const connection = new Connection(rpc);
|
|
23
|
+
// Check to see if we were passed wallet address or token account
|
|
24
|
+
const splToken = await connection.getTokenAccountsByOwner(address, {
|
|
25
|
+
mint: new PublicKey(tokenAddress),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Use the first token account if it exists, otherwise fall back to wallet address
|
|
29
|
+
const checkAddress =
|
|
30
|
+
splToken.value.length > 0 ? splToken.value[0]!.pubkey : address;
|
|
31
|
+
|
|
32
|
+
const balance = await connection.getTokenAccountBalance(checkAddress);
|
|
33
|
+
console.log("balance", balance);
|
|
34
|
+
return (
|
|
35
|
+
balance.value.uiAmountString ??
|
|
36
|
+
(Number(balance.value.amount) / 10 ** balance.value.decimals).toString()
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const getEthereumWalletUSDCBalance = async (
|
|
41
|
+
walletAddress: string,
|
|
42
|
+
aptosNetwork: Network,
|
|
43
|
+
rpc: string
|
|
44
|
+
): Promise<string> => {
|
|
45
|
+
const token =
|
|
46
|
+
aptosNetwork === Network.MAINNET
|
|
47
|
+
? mainnetTokens["Ethereum"]
|
|
48
|
+
: testnetTokens["Sepolia"];
|
|
49
|
+
|
|
50
|
+
const tokenAddress = token.tokenId.address;
|
|
51
|
+
const connection = new JsonRpcProvider(rpc);
|
|
52
|
+
const abi = ["function balanceOf(address owner) view returns (uint256)"];
|
|
53
|
+
const contract = new ethers.Contract(tokenAddress, abi, connection);
|
|
54
|
+
const balance = await contract.balanceOf(walletAddress);
|
|
55
|
+
return ethers.formatUnits(balance, token.decimals).toString();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const getAptosWalletUSDCBalance = async (
|
|
59
|
+
walletAddress: string,
|
|
60
|
+
aptosNetwork: Network
|
|
61
|
+
): Promise<string> => {
|
|
62
|
+
const token =
|
|
63
|
+
aptosNetwork === Network.MAINNET
|
|
64
|
+
? AptosMainnetUSDCToken
|
|
65
|
+
: AptosTestnetUSDCToken;
|
|
66
|
+
const tokenAddress = token.tokenId.address;
|
|
67
|
+
const aptosConfig = new AptosConfig({ network: aptosNetwork });
|
|
68
|
+
const connection = new Aptos(aptosConfig);
|
|
69
|
+
const response = await connection.getCurrentFungibleAssetBalances({
|
|
70
|
+
options: {
|
|
71
|
+
where: {
|
|
72
|
+
owner_address: { _eq: walletAddress },
|
|
73
|
+
asset_type: { _eq: tokenAddress },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const balance = (
|
|
78
|
+
Number(response[0].amount) /
|
|
79
|
+
10 ** token.decimals
|
|
80
|
+
).toString();
|
|
81
|
+
return balance;
|
|
82
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const logger = {
|
|
2
|
+
log: (...args: any[]) => {
|
|
3
|
+
if (process.env.NODE_ENV === "development") {
|
|
4
|
+
console.log(...args);
|
|
5
|
+
}
|
|
6
|
+
},
|
|
7
|
+
warn: (...args: any[]) => {
|
|
8
|
+
if (process.env.NODE_ENV === "development") {
|
|
9
|
+
console.warn(...args);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
error: (...args: any[]) => {
|
|
13
|
+
if (process.env.NODE_ENV === "development") {
|
|
14
|
+
console.error(...args);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
};
|
package/src/version.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CROSS_CHAIN_CORE_VERSION = "4.23.1";
|