@chainlink/ccip-sdk 0.90.2 → 0.91.0
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/README.md +35 -26
- package/dist/aptos/exec.d.ts +4 -5
- package/dist/aptos/exec.d.ts.map +1 -1
- package/dist/aptos/exec.js +5 -14
- package/dist/aptos/exec.js.map +1 -1
- package/dist/aptos/hasher.d.ts +18 -0
- package/dist/aptos/hasher.d.ts.map +1 -1
- package/dist/aptos/hasher.js +18 -0
- package/dist/aptos/hasher.js.map +1 -1
- package/dist/aptos/index.d.ts +127 -28
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +199 -70
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/logs.d.ts +18 -0
- package/dist/aptos/logs.d.ts.map +1 -1
- package/dist/aptos/logs.js +21 -3
- package/dist/aptos/logs.js.map +1 -1
- package/dist/aptos/send.d.ts +22 -5
- package/dist/aptos/send.d.ts.map +1 -1
- package/dist/aptos/send.js +23 -15
- package/dist/aptos/send.js.map +1 -1
- package/dist/aptos/token.d.ts +6 -0
- package/dist/aptos/token.d.ts.map +1 -1
- package/dist/aptos/token.js +6 -0
- package/dist/aptos/token.js.map +1 -1
- package/dist/aptos/types.d.ts +16 -1
- package/dist/aptos/types.d.ts.map +1 -1
- package/dist/aptos/types.js +13 -0
- package/dist/aptos/types.js.map +1 -1
- package/dist/aptos/utils.d.ts +1 -1
- package/dist/aptos/utils.js +1 -1
- package/dist/chain.d.ts +185 -99
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +38 -15
- package/dist/chain.js.map +1 -1
- package/dist/commits.d.ts +4 -10
- package/dist/commits.d.ts.map +1 -1
- package/dist/commits.js +2 -1
- package/dist/commits.js.map +1 -1
- package/dist/evm/const.d.ts +5 -0
- package/dist/evm/const.d.ts.map +1 -1
- package/dist/evm/const.js +5 -0
- package/dist/evm/const.js.map +1 -1
- package/dist/evm/errors.d.ts +5 -0
- package/dist/evm/errors.d.ts.map +1 -1
- package/dist/evm/errors.js +6 -1
- package/dist/evm/errors.js.map +1 -1
- package/dist/evm/hasher.d.ts +16 -2
- package/dist/evm/hasher.d.ts.map +1 -1
- package/dist/evm/hasher.js +17 -3
- package/dist/evm/hasher.js.map +1 -1
- package/dist/evm/index.d.ts +176 -31
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +312 -154
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/logs.d.ts +20 -0
- package/dist/evm/logs.d.ts.map +1 -0
- package/dist/evm/logs.js +194 -0
- package/dist/evm/logs.js.map +1 -0
- package/dist/evm/messages.d.ts +11 -2
- package/dist/evm/messages.d.ts.map +1 -1
- package/dist/evm/messages.js +4 -2
- package/dist/evm/messages.js.map +1 -1
- package/dist/evm/offchain.d.ts +7 -2
- package/dist/evm/offchain.d.ts.map +1 -1
- package/dist/evm/offchain.js +12 -7
- package/dist/evm/offchain.js.map +1 -1
- package/dist/execution.d.ts +19 -62
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +28 -31
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +35 -5
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +10 -5
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +6 -8
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +7 -9
- package/dist/gas.js.map +1 -1
- package/dist/hasher/common.d.ts +3 -2
- package/dist/hasher/common.d.ts.map +1 -1
- package/dist/hasher/common.js +2 -2
- package/dist/hasher/common.js.map +1 -1
- package/dist/hasher/hasher.d.ts +8 -2
- package/dist/hasher/hasher.d.ts.map +1 -1
- package/dist/hasher/hasher.js +8 -3
- package/dist/hasher/hasher.js.map +1 -1
- package/dist/hasher/merklemulti.d.ts +11 -9
- package/dist/hasher/merklemulti.d.ts.map +1 -1
- package/dist/hasher/merklemulti.js +17 -16
- package/dist/hasher/merklemulti.js.map +1 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/requests.d.ts +39 -25
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +42 -35
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts +1 -1
- package/dist/solana/cleanup.d.ts +14 -10
- package/dist/solana/cleanup.d.ts.map +1 -1
- package/dist/solana/cleanup.js +35 -33
- package/dist/solana/cleanup.js.map +1 -1
- package/dist/solana/exec.d.ts +19 -11
- package/dist/solana/exec.d.ts.map +1 -1
- package/dist/solana/exec.js +86 -163
- package/dist/solana/exec.js.map +1 -1
- package/dist/solana/hasher.d.ts +7 -2
- package/dist/solana/hasher.d.ts.map +1 -1
- package/dist/solana/hasher.js +7 -2
- package/dist/solana/hasher.js.map +1 -1
- package/dist/solana/index.d.ts +202 -84
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +367 -252
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/offchain.d.ts +8 -18
- package/dist/solana/offchain.d.ts.map +1 -1
- package/dist/solana/offchain.js +29 -83
- package/dist/solana/offchain.js.map +1 -1
- package/dist/solana/patchBorsh.d.ts +5 -1
- package/dist/solana/patchBorsh.d.ts.map +1 -1
- package/dist/solana/patchBorsh.js +57 -46
- package/dist/solana/patchBorsh.js.map +1 -1
- package/dist/solana/send.d.ts +28 -10
- package/dist/solana/send.d.ts.map +1 -1
- package/dist/solana/send.js +44 -77
- package/dist/solana/send.js.map +1 -1
- package/dist/solana/types.d.ts +22 -1
- package/dist/solana/types.d.ts.map +1 -1
- package/dist/solana/types.js +12 -1
- package/dist/solana/types.js.map +1 -1
- package/dist/solana/utils.d.ts +58 -4
- package/dist/solana/utils.d.ts.map +1 -1
- package/dist/solana/utils.js +110 -7
- package/dist/solana/utils.js.map +1 -1
- package/dist/sui/hasher.d.ts +18 -0
- package/dist/sui/hasher.d.ts.map +1 -1
- package/dist/sui/hasher.js +18 -0
- package/dist/sui/hasher.js.map +1 -1
- package/dist/sui/index.d.ts +99 -12
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +108 -19
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/types.d.ts +6 -0
- package/dist/sui/types.d.ts.map +1 -1
- package/dist/sui/types.js +5 -0
- package/dist/sui/types.js.map +1 -1
- package/dist/supported-chains.d.ts +2 -1
- package/dist/supported-chains.d.ts.map +1 -1
- package/dist/supported-chains.js.map +1 -1
- package/dist/types.d.ts +127 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +67 -46
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +143 -21
- package/dist/utils.js.map +1 -1
- package/package.json +13 -9
- package/src/aptos/exec.ts +7 -18
- package/src/aptos/hasher.ts +18 -0
- package/src/aptos/index.ts +288 -110
- package/src/aptos/logs.ts +21 -3
- package/src/aptos/send.ts +25 -22
- package/src/aptos/token.ts +6 -0
- package/src/aptos/types.ts +26 -2
- package/src/aptos/utils.ts +1 -1
- package/src/chain.ts +243 -108
- package/src/commits.ts +6 -7
- package/src/evm/const.ts +5 -0
- package/src/evm/errors.ts +6 -1
- package/src/evm/hasher.ts +20 -4
- package/src/evm/index.ts +416 -214
- package/src/evm/logs.ts +255 -0
- package/src/evm/messages.ts +11 -5
- package/src/evm/offchain.ts +13 -4
- package/src/execution.ts +40 -32
- package/src/extra-args.ts +38 -6
- package/src/gas.ts +7 -9
- package/src/hasher/common.ts +3 -2
- package/src/hasher/hasher.ts +12 -4
- package/src/hasher/merklemulti.ts +17 -16
- package/src/index.ts +29 -23
- package/src/requests.ts +64 -46
- package/src/selectors.ts +1 -1
- package/src/solana/cleanup.ts +49 -34
- package/src/solana/exec.ts +128 -272
- package/src/solana/hasher.ts +13 -4
- package/src/solana/index.ts +483 -356
- package/src/solana/offchain.ts +32 -102
- package/src/solana/patchBorsh.ts +65 -50
- package/src/solana/send.ts +52 -111
- package/src/solana/types.ts +44 -3
- package/src/solana/utils.ts +143 -19
- package/src/sui/hasher.ts +18 -0
- package/src/sui/index.ts +143 -31
- package/src/sui/types.ts +6 -0
- package/src/supported-chains.ts +2 -1
- package/src/types.ts +130 -18
- package/src/utils.ts +168 -26
- package/tsconfig.json +2 -1
package/dist/evm/index.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import util from 'util';
|
|
2
1
|
import { parseAbi } from 'abitype';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import { Chain
|
|
2
|
+
import { Contract, JsonRpcProvider, Result, WebSocketProvider, ZeroAddress, concat, dataSlice, encodeBase58, getAddress, getBytes, hexlify, isBytesLike, isHexString, toBeHex, toBigInt, zeroPadValue, } from 'ethers';
|
|
3
|
+
import { memoize } from 'micro-memoize';
|
|
4
|
+
import { Chain } from "../chain.js";
|
|
6
5
|
import { EVMExtraArgsV1Tag, EVMExtraArgsV2Tag, SVMExtraArgsV1Tag, SuiExtraArgsV1Tag, } from "../extra-args.js";
|
|
7
6
|
import { supportedChains } from "../supported-chains.js";
|
|
8
|
-
import { CCIPVersion, } from "../types.js";
|
|
9
|
-
import {
|
|
7
|
+
import { CCIPVersion, ChainFamily, } from "../types.js";
|
|
8
|
+
import { decodeAddress, decodeOnRampAddress, getAddressBytes, getDataBytes, networkInfo, parseTypeAndVersion, util, } from "../utils.js";
|
|
10
9
|
import EVM2EVMOffRamp_1_2_ABI from "./abi/OffRamp_1_2.js";
|
|
11
10
|
import EVM2EVMOffRamp_1_5_ABI from "./abi/OffRamp_1_5.js";
|
|
12
11
|
import OffRamp_1_6_ABI from "./abi/OffRamp_1_6.js";
|
|
13
12
|
import EVM2EVMOnRamp_1_2_ABI from "./abi/OnRamp_1_2.js";
|
|
14
13
|
import EVM2EVMOnRamp_1_5_ABI from "./abi/OnRamp_1_5.js";
|
|
15
14
|
import OnRamp_1_6_ABI from "./abi/OnRamp_1_6.js";
|
|
16
|
-
import {
|
|
15
|
+
import { DEFAULT_GAS_LIMIT, commitsFragments, defaultAbiCoder, interfaces, receiptsFragments, requestsFragments, } from "./const.js";
|
|
17
16
|
import { parseData } from "./errors.js";
|
|
18
17
|
import { getV12LeafHasher, getV16LeafHasher } from "./hasher.js";
|
|
18
|
+
import { getEvmLogs } from "./logs.js";
|
|
19
19
|
import { parseSourceTokenData, } from "./messages.js";
|
|
20
20
|
import { encodeEVMOffchainTokenData, fetchEVMOffchainTokenData } from "./offchain.js";
|
|
21
|
+
import { fetchAllMessagesInBatch, fetchCCIPRequestById, fetchCCIPRequestsInTx, } from "../requests.js";
|
|
21
22
|
const VersionedContractABI = parseAbi(['function typeAndVersion() view returns (string)']);
|
|
22
23
|
const EVMExtraArgsV1 = 'tuple(uint256 gasLimit)';
|
|
23
24
|
const EVMExtraArgsV2 = 'tuple(uint256 gasLimit, bool allowOutOfOrderExecution)';
|
|
@@ -42,68 +43,58 @@ function resultsToMessage(result) {
|
|
|
42
43
|
...(result.header ? { header: result.header.toObject() } : {}),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
46
|
+
/** typeguard for ethers Signer interface (used for `wallet`s) */
|
|
47
|
+
function isSigner(wallet) {
|
|
48
|
+
return (typeof wallet === 'object' &&
|
|
49
|
+
wallet !== null &&
|
|
50
|
+
'signTransaction' in wallet &&
|
|
51
|
+
'getAddress' in wallet);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* EVM chain implementation supporting Ethereum-compatible networks.
|
|
55
|
+
*/
|
|
45
56
|
export class EVMChain extends Chain {
|
|
57
|
+
static {
|
|
58
|
+
supportedChains[ChainFamily.EVM] = EVMChain;
|
|
59
|
+
}
|
|
46
60
|
static family = ChainFamily.EVM;
|
|
47
61
|
static decimals = 18;
|
|
48
|
-
network;
|
|
49
62
|
provider;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
destroy$;
|
|
64
|
+
/**
|
|
65
|
+
* Creates a new EVMChain instance.
|
|
66
|
+
* @param provider - JSON-RPC provider for the EVM network.
|
|
67
|
+
* @param network - Network information for this chain.
|
|
68
|
+
*/
|
|
69
|
+
constructor(provider, network, ctx) {
|
|
70
|
+
super(network, ctx);
|
|
55
71
|
this.provider = provider;
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
72
|
+
this.destroy$ = new Promise((resolve) => (this.destroy = resolve));
|
|
73
|
+
void this.destroy$.finally(() => provider.destroy());
|
|
74
|
+
this.typeAndVersion = memoize(this.typeAndVersion.bind(this));
|
|
75
|
+
this.provider.getBlock = memoize(provider.getBlock.bind(provider), {
|
|
58
76
|
maxSize: 100,
|
|
59
|
-
|
|
77
|
+
maxArgs: 1,
|
|
78
|
+
async: true,
|
|
79
|
+
forceUpdate: ([block]) => typeof block !== 'number',
|
|
60
80
|
});
|
|
61
|
-
this.getTransaction =
|
|
81
|
+
this.getTransaction = memoize(this.getTransaction.bind(this), {
|
|
62
82
|
maxSize: 100,
|
|
63
|
-
|
|
83
|
+
transformKey: (args) => typeof args[0] !== 'string'
|
|
64
84
|
? [args[0].hash]
|
|
65
85
|
: args,
|
|
66
86
|
});
|
|
67
|
-
this.getTokenForTokenPool =
|
|
68
|
-
this.getNativeTokenForRouter =
|
|
87
|
+
this.getTokenForTokenPool = memoize(this.getTokenForTokenPool.bind(this));
|
|
88
|
+
this.getNativeTokenForRouter = memoize(this.getNativeTokenForRouter.bind(this), {
|
|
69
89
|
maxArgs: 1,
|
|
70
|
-
|
|
90
|
+
async: true,
|
|
71
91
|
});
|
|
72
|
-
this.getTokenInfo =
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
isPromise: true,
|
|
92
|
+
this.getTokenInfo = memoize(this.getTokenInfo.bind(this));
|
|
93
|
+
this.getTokenAdminRegistryFor = memoize(this.getTokenAdminRegistryFor.bind(this), {
|
|
94
|
+
async: true,
|
|
76
95
|
maxArgs: 1,
|
|
77
96
|
});
|
|
78
|
-
|
|
79
|
-
// overwrite EVMChain.getWallet to implement custom wallet loading
|
|
80
|
-
// some signers don't like to be `.connect`ed, so pass provider as first param
|
|
81
|
-
static getWallet(_provider, _opts) {
|
|
82
|
-
throw new Error('static EVM wallet loading not available');
|
|
83
|
-
}
|
|
84
|
-
// cached wallet/signer getter
|
|
85
|
-
async getWallet(opts = {}) {
|
|
86
|
-
if (typeof opts.wallet === 'number' ||
|
|
87
|
-
(typeof opts.wallet === 'string' && opts.wallet.match(/^(\d+|0x[a-fA-F0-9]{40})$/))) {
|
|
88
|
-
// if given a number, numeric string or address, use ethers `provider.getSigner` (e.g. geth or MM)
|
|
89
|
-
return this.provider.getSigner(typeof opts.wallet === 'string' && opts.wallet.match(/^0x[a-fA-F0-9]{40}$/)
|
|
90
|
-
? opts.wallet
|
|
91
|
-
: Number(opts.wallet));
|
|
92
|
-
}
|
|
93
|
-
else if (typeof opts.wallet === 'string') {
|
|
94
|
-
// support receiving private key directly (not recommended)
|
|
95
|
-
try {
|
|
96
|
-
return Promise.resolve(new BaseWallet(new SigningKey((opts.wallet.startsWith('0x') ? '' : '0x') + opts.wallet), this.provider));
|
|
97
|
-
}
|
|
98
|
-
catch (_) {
|
|
99
|
-
// pass
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else if (opts.wallet instanceof AbstractSigner) {
|
|
103
|
-
// if given a signer, return/cache it
|
|
104
|
-
return opts.wallet;
|
|
105
|
-
}
|
|
106
|
-
return this.constructor.getWallet(this.provider, opts);
|
|
97
|
+
this.getFeeTokens = memoize(this.getFeeTokens.bind(this), { async: true, maxArgs: 1 });
|
|
107
98
|
}
|
|
108
99
|
/**
|
|
109
100
|
* Expose ethers provider's `listAccounts`, if provider supports it
|
|
@@ -111,9 +102,11 @@ export class EVMChain extends Chain {
|
|
|
111
102
|
async listAccounts() {
|
|
112
103
|
return (await this.provider.listAccounts()).map(({ address }) => address);
|
|
113
104
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Creates a JSON-RPC provider from a URL.
|
|
107
|
+
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
108
|
+
* @returns A ready JSON-RPC provider.
|
|
109
|
+
*/
|
|
117
110
|
static async _getProvider(url) {
|
|
118
111
|
let provider;
|
|
119
112
|
let providerReady;
|
|
@@ -137,28 +130,38 @@ export class EVMChain extends Chain {
|
|
|
137
130
|
}
|
|
138
131
|
return providerReady;
|
|
139
132
|
}
|
|
140
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Creates an EVMChain instance from an existing provider.
|
|
135
|
+
* @param provider - JSON-RPC provider instance.
|
|
136
|
+
* @param ctx - context containing logger.
|
|
137
|
+
* @returns A new EVMChain instance.
|
|
138
|
+
*/
|
|
139
|
+
static async fromProvider(provider, ctx) {
|
|
141
140
|
try {
|
|
142
|
-
return new EVMChain(provider, networkInfo(Number((await provider.getNetwork()).chainId)));
|
|
141
|
+
return new EVMChain(provider, networkInfo(Number((await provider.getNetwork()).chainId)), ctx);
|
|
143
142
|
}
|
|
144
143
|
catch (err) {
|
|
145
144
|
provider.destroy();
|
|
146
145
|
throw err;
|
|
147
146
|
}
|
|
148
147
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Creates an EVMChain instance from an RPC URL.
|
|
150
|
+
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
151
|
+
* @param ctx - context containing logger.
|
|
152
|
+
* @returns A new EVMChain instance.
|
|
153
|
+
*/
|
|
154
|
+
static async fromUrl(url, ctx) {
|
|
155
|
+
return this.fromProvider(await this._getProvider(url), ctx);
|
|
155
156
|
}
|
|
157
|
+
/** {@inheritDoc Chain.getBlockTimestamp} */
|
|
156
158
|
async getBlockTimestamp(block) {
|
|
157
|
-
const res = await this.provider.getBlock(block);
|
|
159
|
+
const res = await this.provider.getBlock(block); // cached
|
|
158
160
|
if (!res)
|
|
159
161
|
throw new Error(`Block not found: ${block}`);
|
|
160
162
|
return res.timestamp;
|
|
161
163
|
}
|
|
164
|
+
/** {@inheritDoc Chain.getTransaction} */
|
|
162
165
|
async getTransaction(hash) {
|
|
163
166
|
const tx = typeof hash === 'string' ? await this.provider.getTransactionReceipt(hash) : hash;
|
|
164
167
|
if (!tx)
|
|
@@ -166,7 +169,6 @@ export class EVMChain extends Chain {
|
|
|
166
169
|
const timestamp = await this.getBlockTimestamp(tx.blockNumber);
|
|
167
170
|
const chainTx = {
|
|
168
171
|
...tx,
|
|
169
|
-
chain: this,
|
|
170
172
|
timestamp,
|
|
171
173
|
logs: [],
|
|
172
174
|
};
|
|
@@ -174,39 +176,40 @@ export class EVMChain extends Chain {
|
|
|
174
176
|
chainTx.logs = logs;
|
|
175
177
|
return chainTx;
|
|
176
178
|
}
|
|
179
|
+
/** {@inheritDoc Chain.getLogs} */
|
|
177
180
|
async *getLogs(filter) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (
|
|
192
|
-
filter
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
...(filter.address ? { address: filter.address } : {}),
|
|
198
|
-
...(filter.topics?.length ? { topics: filter.topics } : {}),
|
|
199
|
-
});
|
|
200
|
-
const logs = await this.provider.getLogs({
|
|
201
|
-
...blockRange,
|
|
202
|
-
...(filter.address ? { address: filter.address } : {}),
|
|
203
|
-
...(filter.topics?.length ? { topics: filter.topics } : {}),
|
|
204
|
-
});
|
|
205
|
-
if (!filter.startBlock)
|
|
206
|
-
logs.reverse();
|
|
207
|
-
yield* logs;
|
|
181
|
+
yield* getEvmLogs(filter, this);
|
|
182
|
+
}
|
|
183
|
+
/** {@inheritDoc Chain.fetchRequestsInTx} */
|
|
184
|
+
async fetchRequestsInTx(tx) {
|
|
185
|
+
return fetchCCIPRequestsInTx(this, typeof tx === 'string' ? await this.getTransaction(tx) : tx);
|
|
186
|
+
}
|
|
187
|
+
/** {@inheritDoc Chain.fetchRequestById} */
|
|
188
|
+
fetchRequestById(messageId, onRamp, opts) {
|
|
189
|
+
return fetchCCIPRequestById(this, messageId, { address: onRamp, ...opts });
|
|
190
|
+
}
|
|
191
|
+
/** {@inheritDoc Chain.fetchAllMessagesInBatch} */
|
|
192
|
+
async fetchAllMessagesInBatch(request, commit, opts) {
|
|
193
|
+
let opts_;
|
|
194
|
+
if (request.lane.version >= CCIPVersion.V1_6) {
|
|
195
|
+
// specialized getLogs filter for v1.6 CCIPMessageSent events, to filter by dest
|
|
196
|
+
opts_ = {
|
|
197
|
+
...opts,
|
|
198
|
+
topics: [[request.log.topics[0]], [toBeHex(request.lane.destChainSelector, 32)]],
|
|
199
|
+
};
|
|
208
200
|
}
|
|
201
|
+
return fetchAllMessagesInBatch(this, request, commit, opts_);
|
|
202
|
+
}
|
|
203
|
+
/** {@inheritDoc Chain.typeAndVersion} */
|
|
204
|
+
async typeAndVersion(address) {
|
|
205
|
+
const contract = new Contract(address, VersionedContractABI, this.provider);
|
|
206
|
+
return parseTypeAndVersion(await contract.typeAndVersion());
|
|
209
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Decodes a CCIP message from a log event.
|
|
210
|
+
* @param log - Log event with topics and data.
|
|
211
|
+
* @returns Decoded CCIPMessage or undefined if not a valid CCIP message.
|
|
212
|
+
*/
|
|
210
213
|
static decodeMessage(log) {
|
|
211
214
|
if (!isBytesLike(log.data))
|
|
212
215
|
throw new Error(`invalid data=${util.inspect(log.data)}`);
|
|
@@ -259,7 +262,7 @@ export class EVMChain extends Chain {
|
|
|
259
262
|
};
|
|
260
263
|
}
|
|
261
264
|
catch (_) {
|
|
262
|
-
|
|
265
|
+
// legacy sourceTokenData
|
|
263
266
|
}
|
|
264
267
|
}
|
|
265
268
|
if (typeof tokenAmount.destExecData === 'string' && tokenAmount.destGasAmount == null) {
|
|
@@ -294,6 +297,12 @@ export class EVMChain extends Chain {
|
|
|
294
297
|
}
|
|
295
298
|
return message;
|
|
296
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Decodes commit reports from a log event.
|
|
302
|
+
* @param log - Log event with topics and data.
|
|
303
|
+
* @param lane - Lane info (required for CCIP v1.5 and earlier).
|
|
304
|
+
* @returns Array of CommitReport or undefined if not a valid commit event.
|
|
305
|
+
*/
|
|
297
306
|
static decodeCommits(log, lane) {
|
|
298
307
|
if (!isBytesLike(log.data))
|
|
299
308
|
throw new Error(`invalid data=${util.inspect(log.data)}`);
|
|
@@ -348,6 +357,11 @@ export class EVMChain extends Chain {
|
|
|
348
357
|
}
|
|
349
358
|
}
|
|
350
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Decodes an execution receipt from a log event.
|
|
362
|
+
* @param log - Log event with topics and data.
|
|
363
|
+
* @returns ExecutionReceipt or undefined if not a valid execution event.
|
|
364
|
+
*/
|
|
351
365
|
static decodeReceipt(log) {
|
|
352
366
|
if (!isBytesLike(log.data))
|
|
353
367
|
throw new Error(`invalid data=${util.inspect(log.data)}`);
|
|
@@ -373,6 +387,11 @@ export class EVMChain extends Chain {
|
|
|
373
387
|
}
|
|
374
388
|
}
|
|
375
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Decodes extra arguments from a CCIP message.
|
|
392
|
+
* @param extraArgs - Encoded extra arguments bytes.
|
|
393
|
+
* @returns Decoded extra arguments with tag, or undefined if unknown format.
|
|
394
|
+
*/
|
|
376
395
|
static decodeExtraArgs(extraArgs) {
|
|
377
396
|
const data = getDataBytes(extraArgs), tag = dataSlice(data, 0, 4);
|
|
378
397
|
switch (tag) {
|
|
@@ -404,6 +423,11 @@ export class EVMChain extends Chain {
|
|
|
404
423
|
return undefined;
|
|
405
424
|
}
|
|
406
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* Encodes extra arguments for a CCIP message.
|
|
428
|
+
* @param args - Extra arguments to encode.
|
|
429
|
+
* @returns Encoded extra arguments as hex string.
|
|
430
|
+
*/
|
|
407
431
|
static encodeExtraArgs(args) {
|
|
408
432
|
if (!args)
|
|
409
433
|
return '0x';
|
|
@@ -441,6 +465,11 @@ export class EVMChain extends Chain {
|
|
|
441
465
|
}
|
|
442
466
|
return '0x';
|
|
443
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Converts bytes to a checksummed EVM address.
|
|
470
|
+
* @param bytes - Bytes to convert (must be 20 bytes or 32 bytes with leading zeros).
|
|
471
|
+
* @returns Checksummed EVM address.
|
|
472
|
+
*/
|
|
444
473
|
static getAddress(bytes) {
|
|
445
474
|
bytes = getBytes(bytes);
|
|
446
475
|
if (bytes.length < 20)
|
|
@@ -455,10 +484,11 @@ export class EVMChain extends Chain {
|
|
|
455
484
|
}
|
|
456
485
|
return getAddress(hexlify(bytes));
|
|
457
486
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
487
|
+
/**
|
|
488
|
+
* Gets lane configuration from an OnRamp contract.
|
|
489
|
+
* @param onRamp - OnRamp contract address.
|
|
490
|
+
* @returns Lane configuration.
|
|
491
|
+
*/
|
|
462
492
|
async getLaneForOnRamp(onRamp) {
|
|
463
493
|
const [, version] = await this.typeAndVersion(onRamp);
|
|
464
494
|
const onRampABI = version === CCIPVersion.V1_2 ? EVM2EVMOnRamp_1_2_ABI : EVM2EVMOnRamp_1_5_ABI;
|
|
@@ -474,6 +504,7 @@ export class EVMChain extends Chain {
|
|
|
474
504
|
onRamp,
|
|
475
505
|
};
|
|
476
506
|
}
|
|
507
|
+
/** {@inheritDoc Chain.getRouterForOnRamp} */
|
|
477
508
|
async getRouterForOnRamp(onRamp, destChainSelector) {
|
|
478
509
|
const [, version] = await this.typeAndVersion(onRamp);
|
|
479
510
|
let onRampABI;
|
|
@@ -497,6 +528,7 @@ export class EVMChain extends Chain {
|
|
|
497
528
|
throw new Error(`Unsupported version: ${version}`);
|
|
498
529
|
}
|
|
499
530
|
}
|
|
531
|
+
/** {@inheritDoc Chain.getRouterForOffRamp} */
|
|
500
532
|
async getRouterForOffRamp(offRamp, sourceChainSelector) {
|
|
501
533
|
const [, version] = await this.typeAndVersion(offRamp);
|
|
502
534
|
let offRampABI, router;
|
|
@@ -521,10 +553,12 @@ export class EVMChain extends Chain {
|
|
|
521
553
|
}
|
|
522
554
|
return router;
|
|
523
555
|
}
|
|
556
|
+
/** {@inheritDoc Chain.getNativeTokenForRouter} */
|
|
524
557
|
async getNativeTokenForRouter(router) {
|
|
525
558
|
const contract = new Contract(router, interfaces.Router, this.provider);
|
|
526
559
|
return contract.getWrappedNative();
|
|
527
560
|
}
|
|
561
|
+
/** {@inheritDoc Chain.getOffRampsForRouter} */
|
|
528
562
|
async getOffRampsForRouter(router, sourceChainSelector) {
|
|
529
563
|
const contract = new Contract(router, interfaces.Router, this.provider);
|
|
530
564
|
const offRamps = await contract.getOffRamps();
|
|
@@ -532,10 +566,12 @@ export class EVMChain extends Chain {
|
|
|
532
566
|
.filter((offRamp) => offRamp.sourceChainSelector === sourceChainSelector)
|
|
533
567
|
.map(({ offRamp }) => offRamp);
|
|
534
568
|
}
|
|
569
|
+
/** {@inheritDoc Chain.getOnRampForRouter} */
|
|
535
570
|
async getOnRampForRouter(router, destChainSelector) {
|
|
536
571
|
const contract = new Contract(router, interfaces.Router, this.provider);
|
|
537
572
|
return contract.getOnRamp(destChainSelector);
|
|
538
573
|
}
|
|
574
|
+
/** {@inheritDoc Chain.getOnRampForOffRamp} */
|
|
539
575
|
async getOnRampForOffRamp(offRamp, sourceChainSelector) {
|
|
540
576
|
const [, version] = await this.typeAndVersion(offRamp);
|
|
541
577
|
let offRampABI;
|
|
@@ -559,6 +595,7 @@ export class EVMChain extends Chain {
|
|
|
559
595
|
throw new Error(`Unsupported version: ${version}`);
|
|
560
596
|
}
|
|
561
597
|
}
|
|
598
|
+
/** {@inheritDoc Chain.getCommitStoreForOffRamp} */
|
|
562
599
|
async getCommitStoreForOffRamp(offRamp) {
|
|
563
600
|
const [, version] = await this.typeAndVersion(offRamp);
|
|
564
601
|
let offRampABI;
|
|
@@ -579,10 +616,12 @@ export class EVMChain extends Chain {
|
|
|
579
616
|
throw new Error(`Unsupported version: ${version}`);
|
|
580
617
|
}
|
|
581
618
|
}
|
|
619
|
+
/** {@inheritDoc Chain.getTokenForTokenPool} */
|
|
582
620
|
async getTokenForTokenPool(tokenPool) {
|
|
583
621
|
const contract = new Contract(tokenPool, interfaces.TokenPool_v1_6, this.provider);
|
|
584
622
|
return contract.getToken();
|
|
585
623
|
}
|
|
624
|
+
/** {@inheritDoc Chain.getTokenInfo} */
|
|
586
625
|
async getTokenInfo(token) {
|
|
587
626
|
const contract = new Contract(token, interfaces.Token, this.provider);
|
|
588
627
|
const [symbol, decimals, name] = await Promise.all([
|
|
@@ -592,7 +631,13 @@ export class EVMChain extends Chain {
|
|
|
592
631
|
]);
|
|
593
632
|
return { symbol, decimals: Number(decimals), name };
|
|
594
633
|
}
|
|
595
|
-
|
|
634
|
+
/**
|
|
635
|
+
* Gets the leaf hasher for computing Merkle proofs on the destination chain.
|
|
636
|
+
* @param lane - Lane configuration.
|
|
637
|
+
* @param ctx - Context object containing logger.
|
|
638
|
+
* @returns Leaf hasher function.
|
|
639
|
+
*/
|
|
640
|
+
static getDestLeafHasher({ sourceChainSelector, destChainSelector, onRamp, version }, ctx) {
|
|
596
641
|
switch (version) {
|
|
597
642
|
case CCIPVersion.V1_2:
|
|
598
643
|
case CCIPVersion.V1_5:
|
|
@@ -600,11 +645,16 @@ export class EVMChain extends Chain {
|
|
|
600
645
|
throw new Error(`Unsupported source chain: ${sourceChainSelector}`);
|
|
601
646
|
return getV12LeafHasher(sourceChainSelector, destChainSelector, onRamp);
|
|
602
647
|
case CCIPVersion.V1_6:
|
|
603
|
-
return getV16LeafHasher(sourceChainSelector, destChainSelector, onRamp);
|
|
648
|
+
return getV16LeafHasher(sourceChainSelector, destChainSelector, onRamp, ctx);
|
|
604
649
|
default:
|
|
605
650
|
throw new Error(`Unsupported hasher version for EVM: ${version}`);
|
|
606
651
|
}
|
|
607
652
|
}
|
|
653
|
+
/**
|
|
654
|
+
* Gets any available OnRamp for the given router.
|
|
655
|
+
* @param router - Router contract address.
|
|
656
|
+
* @returns OnRamp contract address.
|
|
657
|
+
*/
|
|
608
658
|
async _getSomeOnRampFor(router) {
|
|
609
659
|
// when given a router, we take any onRamp we can find, as usually they all use same registry
|
|
610
660
|
const someOtherNetwork = this.network.isTestnet
|
|
@@ -616,6 +666,7 @@ export class EVMChain extends Chain {
|
|
|
616
666
|
: 'ethereum-mainnet';
|
|
617
667
|
return this.getOnRampForRouter(router, networkInfo(someOtherNetwork).chainSelector);
|
|
618
668
|
}
|
|
669
|
+
/** {@inheritDoc Chain.getTokenAdminRegistryFor} */
|
|
619
670
|
async getTokenAdminRegistryFor(address) {
|
|
620
671
|
let [type, version, typeAndVersion] = await this.typeAndVersion(address);
|
|
621
672
|
if (type === 'TokenAdminRegistry') {
|
|
@@ -638,6 +689,11 @@ export class EVMChain extends Chain {
|
|
|
638
689
|
const { tokenAdminRegistry } = await contract.getStaticConfig();
|
|
639
690
|
return tokenAdminRegistry;
|
|
640
691
|
}
|
|
692
|
+
/**
|
|
693
|
+
* Gets the FeeQuoter contract address for a given Router or Ramp.
|
|
694
|
+
* @param address - Router or Ramp contract address.
|
|
695
|
+
* @returns FeeQuoter contract address.
|
|
696
|
+
*/
|
|
641
697
|
async getFeeQuoterFor(address) {
|
|
642
698
|
let [type, version, typeAndVersion] = await this.typeAndVersion(address);
|
|
643
699
|
if (type === 'FeeQuoter') {
|
|
@@ -656,6 +712,7 @@ export class EVMChain extends Chain {
|
|
|
656
712
|
const { feeQuoter } = await contract.getDynamicConfig();
|
|
657
713
|
return feeQuoter;
|
|
658
714
|
}
|
|
715
|
+
/** {@inheritDoc Chain.getFee} */
|
|
659
716
|
async getFee(router_, destChainSelector, message) {
|
|
660
717
|
const router = new Contract(router_, interfaces.Router, this.provider);
|
|
661
718
|
return router.getFee(destChainSelector, {
|
|
@@ -666,7 +723,19 @@ export class EVMChain extends Chain {
|
|
|
666
723
|
extraArgs: hexlify(this.constructor.encodeExtraArgs(message.extraArgs)),
|
|
667
724
|
});
|
|
668
725
|
}
|
|
669
|
-
|
|
726
|
+
/**
|
|
727
|
+
* Generate unsigned txs for ccipSend'ing a message
|
|
728
|
+
* @param sender - sender address
|
|
729
|
+
* @param router - address of the Router contract
|
|
730
|
+
* @param destChainSelector - chainSelector of destination chain
|
|
731
|
+
* @param message - AnyMessage to send; if `fee` is not present, it'll be calculated
|
|
732
|
+
* @param approveMax - if tokens approvals are needed, opt into approving maximum allowance
|
|
733
|
+
* @returns Array containing 0 or more unsigned token approvals txs (if needed at the time of
|
|
734
|
+
* generation), followed by a ccipSend TransactionRequest
|
|
735
|
+
*/
|
|
736
|
+
async generateUnsignedSendMessage(sender, router, destChainSelector, message, opts) {
|
|
737
|
+
if (!message.fee)
|
|
738
|
+
message.fee = await this.getFee(router, destChainSelector, message);
|
|
670
739
|
const feeToken = message.feeToken ?? ZeroAddress;
|
|
671
740
|
const receiver = zeroPadValue(getAddressBytes(message.receiver), 32);
|
|
672
741
|
const data = hexlify(message.data);
|
|
@@ -675,52 +744,85 @@ export class EVMChain extends Chain {
|
|
|
675
744
|
const amountsToApprove = (message.tokenAmounts ?? []).reduce((acc, { token, amount }) => ({ ...acc, [token]: (acc[token] ?? 0n) + amount }), {});
|
|
676
745
|
if (feeToken !== ZeroAddress)
|
|
677
746
|
amountsToApprove[feeToken] = (amountsToApprove[feeToken] ?? 0n) + message.fee;
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
const tx = await contract.approve(router_, amnt, {
|
|
689
|
-
nonce: nonce++,
|
|
690
|
-
gasLimit: DEFAULT_APPROVE_GAS_LIMIT,
|
|
691
|
-
});
|
|
692
|
-
console.info('=>', tx.hash);
|
|
693
|
-
await tx.wait(1, 60_000);
|
|
694
|
-
}
|
|
695
|
-
}));
|
|
696
|
-
const router = new Contract(router_, interfaces.Router, wallet);
|
|
697
|
-
const tx = await router.ccipSend(destChainSelector, {
|
|
747
|
+
const approveTxs = (await Promise.all(Object.entries(amountsToApprove).map(async ([token, amount]) => {
|
|
748
|
+
const contract = new Contract(token, interfaces.Token, this.provider);
|
|
749
|
+
const allowance = await contract.allowance(sender, router);
|
|
750
|
+
if (allowance >= amount)
|
|
751
|
+
return;
|
|
752
|
+
const amnt = opts?.approveMax ? 2n ** 256n - 1n : amount;
|
|
753
|
+
return contract.approve.populateTransaction(router, amnt, { from: sender });
|
|
754
|
+
}))).filter((tx) => tx != null);
|
|
755
|
+
const contract = new Contract(router, interfaces.Router, this.provider);
|
|
756
|
+
const sendTx = await contract.ccipSend.populateTransaction(destChainSelector, {
|
|
698
757
|
receiver,
|
|
699
758
|
data,
|
|
700
759
|
tokenAmounts: message.tokenAmounts ?? [],
|
|
701
760
|
extraArgs,
|
|
702
761
|
feeToken,
|
|
703
762
|
}, {
|
|
704
|
-
|
|
763
|
+
from: sender,
|
|
705
764
|
// if native fee, include it in value; otherwise, it's transferedFrom feeToken
|
|
706
|
-
...(feeToken === ZeroAddress
|
|
765
|
+
...(feeToken === ZeroAddress && { value: message.fee }),
|
|
707
766
|
});
|
|
708
|
-
const
|
|
709
|
-
return
|
|
767
|
+
const txRequests = [...approveTxs, sendTx];
|
|
768
|
+
return {
|
|
769
|
+
family: ChainFamily.EVM,
|
|
770
|
+
transactions: txRequests,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
/** {@inheritDoc Chain.sendMessage} */
|
|
774
|
+
async sendMessage(router_, destChainSelector, message, opts) {
|
|
775
|
+
const wallet = opts.wallet;
|
|
776
|
+
if (!isSigner(wallet))
|
|
777
|
+
throw new Error(`Wallet must be a Signer, got=${util.inspect(wallet)}`);
|
|
778
|
+
const sender = await wallet.getAddress();
|
|
779
|
+
const txs = await this.generateUnsignedSendMessage(sender, router_, destChainSelector, message, opts);
|
|
780
|
+
const approveTxs = txs.transactions.slice(0, txs.transactions.length - 1);
|
|
781
|
+
let sendTx = txs.transactions[txs.transactions.length - 1];
|
|
782
|
+
// approve all tokens (including feeToken, if needed) in parallel
|
|
783
|
+
let nonce = await this.provider.getTransactionCount(sender);
|
|
784
|
+
const responses = await Promise.all(approveTxs.map(async (tx) => {
|
|
785
|
+
tx.nonce = nonce++;
|
|
786
|
+
tx = await wallet.populateTransaction(tx);
|
|
787
|
+
tx.from = undefined;
|
|
788
|
+
const signed = await wallet.signTransaction(tx);
|
|
789
|
+
const response = await this.provider.broadcastTransaction(signed);
|
|
790
|
+
this.logger.debug('approve =>', response.hash);
|
|
791
|
+
return response;
|
|
792
|
+
}));
|
|
793
|
+
if (responses.length)
|
|
794
|
+
await responses[responses.length - 1].wait(1, 60_000); // wait last tx nonce to be mined
|
|
795
|
+
sendTx.nonce = nonce++;
|
|
796
|
+
// sendTx.gasLimit = await this.provider.estimateGas(sendTx)
|
|
797
|
+
sendTx = await wallet.populateTransaction(sendTx);
|
|
798
|
+
sendTx.from = undefined; // some signers don't like receiving pre-populated `from`
|
|
799
|
+
const signed = await wallet.signTransaction(sendTx);
|
|
800
|
+
const response = await this.provider.broadcastTransaction(signed);
|
|
801
|
+
this.logger.debug('ccipSend =>', response.hash);
|
|
802
|
+
await response.wait(1, 60_000);
|
|
803
|
+
return (await this.fetchRequestsInTx(await this.getTransaction(response.hash)))[0];
|
|
710
804
|
}
|
|
805
|
+
/** {@inheritDoc Chain.fetchOffchainTokenData} */
|
|
711
806
|
fetchOffchainTokenData(request) {
|
|
712
|
-
return fetchEVMOffchainTokenData(request);
|
|
807
|
+
return fetchEVMOffchainTokenData(request, this);
|
|
713
808
|
}
|
|
714
|
-
|
|
809
|
+
/**
|
|
810
|
+
* Generate unsigned tx to manuallyExecute a message
|
|
811
|
+
* @param _payer - not used in EVM
|
|
812
|
+
* @param offRamp - address of the OffRamp contract
|
|
813
|
+
* @param execReport - execution report
|
|
814
|
+
* @param opts - gas limit overrides for ccipReceive and tokenPool calls options
|
|
815
|
+
* @returns array containing one unsigned `manuallyExecute` TransactionRequest object
|
|
816
|
+
*/
|
|
817
|
+
async generateUnsignedExecuteReport(_payer, offRamp, execReport, opts) {
|
|
715
818
|
const [_, version] = await this.typeAndVersion(offRamp);
|
|
716
|
-
const wallet = await this.getWallet(opts);
|
|
717
819
|
let manualExecTx;
|
|
718
820
|
const offchainTokenData = execReport.offchainTokenData.map(encodeEVMOffchainTokenData);
|
|
719
821
|
switch (version) {
|
|
720
822
|
case CCIPVersion.V1_2: {
|
|
721
|
-
const contract = new Contract(offRamp, EVM2EVMOffRamp_1_2_ABI,
|
|
823
|
+
const contract = new Contract(offRamp, EVM2EVMOffRamp_1_2_ABI, this.provider);
|
|
722
824
|
const gasOverride = BigInt(opts?.gasLimit ?? 0);
|
|
723
|
-
manualExecTx = await contract.manuallyExecute({
|
|
825
|
+
manualExecTx = await contract.manuallyExecute.populateTransaction({
|
|
724
826
|
...execReport,
|
|
725
827
|
proofs: execReport.proofs.map((d) => hexlify(d)),
|
|
726
828
|
messages: [execReport.message],
|
|
@@ -729,8 +831,8 @@ export class EVMChain extends Chain {
|
|
|
729
831
|
break;
|
|
730
832
|
}
|
|
731
833
|
case CCIPVersion.V1_5: {
|
|
732
|
-
const contract = new Contract(offRamp, EVM2EVMOffRamp_1_5_ABI,
|
|
733
|
-
manualExecTx = await contract.manuallyExecute({
|
|
834
|
+
const contract = new Contract(offRamp, EVM2EVMOffRamp_1_5_ABI, this.provider);
|
|
835
|
+
manualExecTx = await contract.manuallyExecute.populateTransaction({
|
|
734
836
|
...execReport,
|
|
735
837
|
proofs: execReport.proofs.map((d) => hexlify(d)),
|
|
736
838
|
messages: [execReport.message],
|
|
@@ -756,8 +858,8 @@ export class EVMChain extends Chain {
|
|
|
756
858
|
sender,
|
|
757
859
|
tokenAmounts,
|
|
758
860
|
};
|
|
759
|
-
const contract = new Contract(offRamp, OffRamp_1_6_ABI,
|
|
760
|
-
manualExecTx = await contract.manuallyExecute([
|
|
861
|
+
const contract = new Contract(offRamp, OffRamp_1_6_ABI, this.provider);
|
|
862
|
+
manualExecTx = await contract.manuallyExecute.populateTransaction([
|
|
761
863
|
{
|
|
762
864
|
...execReport,
|
|
763
865
|
proofs: execReport.proofs.map((p) => hexlify(p)),
|
|
@@ -778,20 +880,38 @@ export class EVMChain extends Chain {
|
|
|
778
880
|
default:
|
|
779
881
|
throw new Error(`Unsupported version: ${version}`);
|
|
780
882
|
}
|
|
781
|
-
|
|
883
|
+
return { family: ChainFamily.EVM, transactions: [manualExecTx] };
|
|
884
|
+
}
|
|
885
|
+
/** {@inheritDoc Chain.executeReport} */
|
|
886
|
+
async executeReport(offRamp, execReport, opts) {
|
|
887
|
+
const wallet = opts.wallet;
|
|
888
|
+
if (!isSigner(wallet))
|
|
889
|
+
throw new Error(`Wallet must be a Signer, got=${util.inspect(wallet)}`);
|
|
890
|
+
const unsignedTxs = await this.generateUnsignedExecuteReport(await wallet.getAddress(), offRamp, execReport, opts);
|
|
891
|
+
const unsignedTx = await wallet.populateTransaction(unsignedTxs.transactions[0]);
|
|
892
|
+
unsignedTx.from = undefined; // some signers don't like receiving pre-populated `from`
|
|
893
|
+
const signed = await wallet.signTransaction(unsignedTx);
|
|
894
|
+
const response = await this.provider.broadcastTransaction(signed);
|
|
895
|
+
this.logger.debug('ccipSend =>', response.hash);
|
|
896
|
+
const receipt = await response.wait(1, 60_000);
|
|
782
897
|
if (!receipt?.hash)
|
|
783
|
-
throw new Error(`Could not confirm exec tx: ${
|
|
898
|
+
throw new Error(`Could not confirm exec tx: ${response.hash}`);
|
|
784
899
|
if (!receipt.status)
|
|
785
|
-
throw new Error(`Exec transaction reverted: ${
|
|
900
|
+
throw new Error(`Exec transaction reverted: ${response.hash}`);
|
|
786
901
|
return this.getTransaction(receipt);
|
|
787
902
|
}
|
|
903
|
+
/**
|
|
904
|
+
* Parses raw data into typed structures.
|
|
905
|
+
* @param data - Raw data to parse.
|
|
906
|
+
* @returns Parsed data.
|
|
907
|
+
*/
|
|
788
908
|
static parse(data) {
|
|
789
909
|
return parseData(data);
|
|
790
910
|
}
|
|
791
911
|
/**
|
|
792
|
-
* Get the supported tokens for a given contract address
|
|
793
|
-
*
|
|
794
|
-
* @param
|
|
912
|
+
* Get the supported tokens for a given contract address.
|
|
913
|
+
* @param registry - Router, OnRamp, OffRamp or TokenAdminRegistry contract address.
|
|
914
|
+
* @param opts - Optional parameters.
|
|
795
915
|
* @returns An array of supported token addresses.
|
|
796
916
|
*/
|
|
797
917
|
async getSupportedTokens(registry, opts) {
|
|
@@ -805,6 +925,7 @@ export class EVMChain extends Chain {
|
|
|
805
925
|
} while (page.length === limit);
|
|
806
926
|
return res;
|
|
807
927
|
}
|
|
928
|
+
/** {@inheritDoc Chain.getRegistryTokenConfig} */
|
|
808
929
|
async getRegistryTokenConfig(registry, token) {
|
|
809
930
|
const contract = new Contract(registry, interfaces.TokenAdminRegistry, this.provider);
|
|
810
931
|
const config = (await resultToObject(contract.getTokenConfig(token)));
|
|
@@ -819,6 +940,7 @@ export class EVMChain extends Chain {
|
|
|
819
940
|
administrator: config.administrator,
|
|
820
941
|
};
|
|
821
942
|
}
|
|
943
|
+
/** {@inheritDoc Chain.getTokenPoolConfigs} */
|
|
822
944
|
async getTokenPoolConfigs(tokenPool) {
|
|
823
945
|
const [_, , typeAndVersion] = await this.typeAndVersion(tokenPool);
|
|
824
946
|
const contract = new Contract(tokenPool, interfaces.TokenPool_v1_6, this.provider);
|
|
@@ -832,6 +954,7 @@ export class EVMChain extends Chain {
|
|
|
832
954
|
};
|
|
833
955
|
});
|
|
834
956
|
}
|
|
957
|
+
/** {@inheritDoc Chain.getTokenPoolRemotes} */
|
|
835
958
|
async getTokenPoolRemotes(tokenPool, remoteChainSelector) {
|
|
836
959
|
const [_, version] = await this.typeAndVersion(tokenPool);
|
|
837
960
|
let supportedChains;
|
|
@@ -870,22 +993,30 @@ export class EVMChain extends Chain {
|
|
|
870
993
|
},
|
|
871
994
|
])));
|
|
872
995
|
}
|
|
873
|
-
|
|
996
|
+
/** {@inheritDoc Chain.getFeeTokens} */
|
|
997
|
+
async getFeeTokens(router) {
|
|
874
998
|
const onRamp = await this._getSomeOnRampFor(router);
|
|
875
999
|
const [_, version] = await this.typeAndVersion(onRamp);
|
|
876
1000
|
let tokens;
|
|
877
|
-
let
|
|
1001
|
+
let onRampIface;
|
|
878
1002
|
switch (version) {
|
|
879
1003
|
case CCIPVersion.V1_2:
|
|
880
|
-
|
|
1004
|
+
onRampIface = interfaces.EVM2EVMOnRamp_v1_2;
|
|
881
1005
|
// falls through
|
|
882
1006
|
case CCIPVersion.V1_5: {
|
|
883
|
-
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1007
|
+
onRampIface ??= interfaces.EVM2EVMOnRamp_v1_5;
|
|
1008
|
+
const fragment = onRampIface.getEvent('FeeConfigSet');
|
|
1009
|
+
const tokens_ = new Set();
|
|
1010
|
+
for await (const log of this.getLogs({
|
|
1011
|
+
address: onRamp,
|
|
1012
|
+
topics: [fragment.topicHash],
|
|
1013
|
+
startBlock: 1,
|
|
1014
|
+
onlyFallback: true,
|
|
1015
|
+
})) {
|
|
1016
|
+
;
|
|
1017
|
+
onRampIface.decodeEventLog(fragment, log.data, log.topics).feeConfig.forEach(({ token, enabled }) => enabled ? tokens_.add(token) : tokens_.delete(token));
|
|
1018
|
+
}
|
|
1019
|
+
tokens = Array.from(tokens_);
|
|
889
1020
|
break;
|
|
890
1021
|
}
|
|
891
1022
|
case CCIPVersion.V1_6: {
|
|
@@ -899,6 +1030,33 @@ export class EVMChain extends Chain {
|
|
|
899
1030
|
}
|
|
900
1031
|
return Object.fromEntries(await Promise.all(tokens.map(async (token) => [token, await this.getTokenInfo(token)])));
|
|
901
1032
|
}
|
|
1033
|
+
/** {@inheritDoc Chain.fetchExecutionReceipts} */
|
|
1034
|
+
async *fetchExecutionReceipts(offRamp, request, commit, opts) {
|
|
1035
|
+
let opts_ = opts;
|
|
1036
|
+
if (request.lane.version < CCIPVersion.V1_6) {
|
|
1037
|
+
opts_ = {
|
|
1038
|
+
...opts,
|
|
1039
|
+
topics: [
|
|
1040
|
+
interfaces.EVM2EVMOffRamp_v1_5.getEvent('ExecutionStateChanged').topicHash,
|
|
1041
|
+
null,
|
|
1042
|
+
request.message.header.messageId,
|
|
1043
|
+
],
|
|
1044
|
+
// onlyFallback: false,
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
else /* >= V1.6 */ {
|
|
1048
|
+
opts_ = {
|
|
1049
|
+
...opts,
|
|
1050
|
+
topics: [
|
|
1051
|
+
interfaces.OffRamp_v1_6.getEvent('ExecutionStateChanged').topicHash,
|
|
1052
|
+
toBeHex(request.lane.sourceChainSelector, 32),
|
|
1053
|
+
null,
|
|
1054
|
+
request.message.header.messageId,
|
|
1055
|
+
],
|
|
1056
|
+
// onlyFallback: false,
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
yield* super.fetchExecutionReceipts(offRamp, request, commit, opts_);
|
|
1060
|
+
}
|
|
902
1061
|
}
|
|
903
|
-
supportedChains[ChainFamily.EVM] = EVMChain;
|
|
904
1062
|
//# sourceMappingURL=index.js.map
|