@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/solana/cleanup.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { AnchorProvider, Program } from '@coral-xyz/anchor';
|
|
3
|
+
import { AddressLookupTableProgram, PublicKey, SystemProgram, } from '@solana/web3.js';
|
|
3
4
|
import { dataSlice, hexlify } from 'ethers';
|
|
4
|
-
import
|
|
5
|
+
import { memoize } from 'micro-memoize';
|
|
5
6
|
import { sleep } from "../utils.js";
|
|
6
7
|
import { IDL as CCIP_OFFRAMP_IDL } from "./idl/1.6.0/CCIP_OFFRAMP.js";
|
|
7
|
-
import { simulateAndSendTxs } from "./
|
|
8
|
+
import { simulateAndSendTxs } from "./utils.js";
|
|
8
9
|
/**
|
|
9
|
-
* Clean up and recycle buffers and
|
|
10
|
-
*
|
|
11
|
-
* @param
|
|
12
|
-
* @param getLogs - SolanaChain-compatible getLogs function (to scan for Buffers and ALTs)
|
|
13
|
-
* @param opts
|
|
14
|
-
* (513 slots) to pass before closing; by default, we deactivate (if needed)
|
|
15
|
-
*
|
|
10
|
+
* Clean up and recycle buffers and Address Lookup Tables owned by wallet.
|
|
11
|
+
* @param ctx - Context object containing the Solana connection instance and logger.
|
|
12
|
+
* @param wallet - Wallet instance to sign txs.
|
|
13
|
+
* @param getLogs - SolanaChain-compatible getLogs function (to scan for Buffers and ALTs).
|
|
14
|
+
* @param opts - Optional parameters. Set `waitDeactivation` to wait for lookup table deactivation
|
|
15
|
+
* cool down period (513 slots) to pass before closing; by default, we deactivate (if needed)
|
|
16
|
+
* and leave close to be done in the future.
|
|
16
17
|
*/
|
|
17
|
-
export async function cleanUpBuffers(
|
|
18
|
-
const connection =
|
|
19
|
-
|
|
20
|
-
console.debug('Starting cleaning up buffers and lookup tables for account', wallet.publicKey.toString());
|
|
18
|
+
export async function cleanUpBuffers(ctx, wallet, getLogs, opts) {
|
|
19
|
+
const { connection, logger = console } = ctx;
|
|
20
|
+
logger.debug('Starting cleaning up buffers and lookup tables for account', wallet.publicKey.toString());
|
|
21
21
|
const seenAccs = new Set();
|
|
22
22
|
const pendingPromises = [];
|
|
23
|
-
const getCurrentSlot =
|
|
23
|
+
const getCurrentSlot = memoize(async () => {
|
|
24
24
|
let lastErr;
|
|
25
25
|
for (let i = 0; i < 10; i++) {
|
|
26
26
|
try {
|
|
@@ -28,23 +28,23 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
28
28
|
}
|
|
29
29
|
catch (err) {
|
|
30
30
|
lastErr = err;
|
|
31
|
-
|
|
31
|
+
logger.warn('Failed to get current slot', i, err);
|
|
32
32
|
await sleep(500);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
throw lastErr;
|
|
36
|
-
}, { maxAge: 1000,
|
|
36
|
+
}, { maxAge: 1000, async: true });
|
|
37
37
|
const closeAlt = async (lookupTable, deactivationSlot) => {
|
|
38
38
|
const altAddr = lookupTable.toBase58();
|
|
39
39
|
let sig;
|
|
40
40
|
while (!sig) {
|
|
41
41
|
const delta = deactivationSlot + 513 - (await getCurrentSlot());
|
|
42
42
|
if (delta > 0) {
|
|
43
|
-
if (opts?.
|
|
44
|
-
|
|
43
|
+
if (!opts?.waitDeactivation) {
|
|
44
|
+
logger.warn('Skipping: lookup table', altAddr, 'not yet ready for close until', 0.4 * delta, 'seconds');
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
logger.debug('Waiting for slot', deactivationSlot + 513, 'to be reached in', 0.4 * delta, 'seconds before closing lookup table', altAddr);
|
|
48
48
|
await sleep(400 * delta);
|
|
49
49
|
}
|
|
50
50
|
const closeIx = AddressLookupTableProgram.closeLookupTable({
|
|
@@ -53,8 +53,8 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
53
53
|
lookupTable,
|
|
54
54
|
});
|
|
55
55
|
try {
|
|
56
|
-
sig = await simulateAndSendTxs(
|
|
57
|
-
|
|
56
|
+
sig = await simulateAndSendTxs(ctx, wallet, { instructions: [closeIx] });
|
|
57
|
+
logger.info('🗑️ Closed lookup table', altAddr, ': tx =>', sig);
|
|
58
58
|
}
|
|
59
59
|
catch (err) {
|
|
60
60
|
const info = await connection.getAddressLookupTable(lookupTable);
|
|
@@ -62,7 +62,7 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
62
62
|
break;
|
|
63
63
|
else if (info.value.state.deactivationSlot < 2n ** 63n)
|
|
64
64
|
deactivationSlot = Number(info.value.state.deactivationSlot);
|
|
65
|
-
|
|
65
|
+
logger.warn('Failed to close lookup table', altAddr, err);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
};
|
|
@@ -85,14 +85,14 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
85
85
|
({ data }) => dataSlice(data, 0, 8 + 4) === '0x23cafcdc0252bd1720000000')
|
|
86
86
|
.map(({ data }) => Buffer.from(data.subarray(8 + 4, 8 + 4 + 32)));
|
|
87
87
|
for (const bufferId of bufferIds) {
|
|
88
|
-
const offrampProgram = new Program(CCIP_OFFRAMP_IDL, new PublicKey(log.address),
|
|
88
|
+
const offrampProgram = new Program(CCIP_OFFRAMP_IDL, new PublicKey(log.address), new AnchorProvider(connection, wallet, { commitment: 'confirmed' }));
|
|
89
89
|
const [executionReportBuffer] = PublicKey.findProgramAddressSync([Buffer.from('execution_report_buffer'), bufferId, wallet.publicKey.toBuffer()], offrampProgram.programId);
|
|
90
90
|
if (seenAccs.has(executionReportBuffer.toBase58()))
|
|
91
91
|
continue;
|
|
92
92
|
seenAccs.add(executionReportBuffer.toBase58());
|
|
93
93
|
const accInfo = await connection.getAccountInfo(executionReportBuffer);
|
|
94
94
|
if (!accInfo) {
|
|
95
|
-
|
|
95
|
+
logger.debug('Buffer with bufferId', hexlify(bufferId), 'at', executionReportBuffer.toBase58(), 'already closed');
|
|
96
96
|
continue;
|
|
97
97
|
}
|
|
98
98
|
const bufferingAccounts = {
|
|
@@ -106,10 +106,10 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
106
106
|
.closeExecutionReportBuffer(bufferId)
|
|
107
107
|
.accounts(bufferingAccounts)
|
|
108
108
|
.rpc();
|
|
109
|
-
|
|
109
|
+
logger.info('🗑️ Closed bufferId', hexlify(bufferId), 'at', executionReportBuffer.toBase58(), ': tx =>', sig);
|
|
110
110
|
}
|
|
111
111
|
catch (err) {
|
|
112
|
-
|
|
112
|
+
logger.warn('Failed to close bufferId', hexlify(bufferId), 'at', executionReportBuffer.toBase58(), err);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
break;
|
|
@@ -123,10 +123,10 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
123
123
|
const info = await connection.getAddressLookupTable(lookupTable);
|
|
124
124
|
if (!info?.value) {
|
|
125
125
|
alreadyClosed++; // assume we're done when we hit Nth closed ALT; maybe add an option to keep going?
|
|
126
|
-
|
|
126
|
+
logger.debug('Lookup table', lookupTable.toBase58(), 'already closed');
|
|
127
127
|
}
|
|
128
128
|
else if (info.value.state.authority?.toBase58() !== wallet.publicKey.toBase58()) {
|
|
129
|
-
|
|
129
|
+
logger.debug('Lookup table', lookupTable.toBase58(), 'not owned by us, but by', info.value.state.authority?.toBase58());
|
|
130
130
|
}
|
|
131
131
|
else if (info.value.state.deactivationSlot < 2n ** 63n) {
|
|
132
132
|
// non-deactivated have deactivationSlot=MAX_UINT64
|
|
@@ -140,12 +140,14 @@ export async function cleanUpBuffers(provider, getLogs, opts) {
|
|
|
140
140
|
lookupTable: lookupTable,
|
|
141
141
|
});
|
|
142
142
|
try {
|
|
143
|
-
const sig = await simulateAndSendTxs(
|
|
144
|
-
|
|
143
|
+
const sig = await simulateAndSendTxs(ctx, wallet, {
|
|
144
|
+
instructions: [deactivateIx],
|
|
145
|
+
});
|
|
146
|
+
logger.info('⤵️ Deactivated lookup table', lookupTable.toBase58(), ': tx =>', sig);
|
|
145
147
|
pendingPromises.push(closeAlt(lookupTable, await getCurrentSlot()));
|
|
146
148
|
}
|
|
147
149
|
catch (err) {
|
|
148
|
-
|
|
150
|
+
logger.warn('Failed to deactivate lookup table', lookupTable.toBase58(), err);
|
|
149
151
|
}
|
|
150
152
|
}
|
|
151
153
|
break; // case
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/solana/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/solana/cleanup.ts"],"names":[],"mappings":"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"}
|
package/dist/solana/exec.d.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { type Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { type ExecutionReport, type WithLogger } from '../types.ts';
|
|
3
|
+
import type { CCIPMessage_V1_6_Solana, UnsignedSolanaTx } from './types.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Generate unsigned tx to execute a CCIP report on Solana.
|
|
6
|
+
* @param ctx - Context containing connection and logger
|
|
7
|
+
* @param payer - Payer of the transaction.
|
|
8
|
+
* @param offramp - Address of the OffRamp contract.
|
|
9
|
+
* @param execReport - Execution report.
|
|
10
|
+
* @param opts - Options for txs to be generated
|
|
11
|
+
* - forceBuffer - Sends report in chunks for buffering in offRamp before execution
|
|
12
|
+
* - forceLookupTable - Creates lookup table for execution transaction, and deactivates in the end
|
|
13
|
+
* - clearLeftoverAccounts - Resets buffer before filling it in
|
|
14
|
+
* @returns Transaction hash of the execution.
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateUnsignedExecuteReport(ctx: {
|
|
17
|
+
connection: Connection;
|
|
18
|
+
} & WithLogger, payer: PublicKey, offramp: PublicKey, execReport: ExecutionReport<CCIPMessage_V1_6_Solana>, opts?: {
|
|
11
19
|
forceLookupTable?: boolean;
|
|
12
20
|
forceBuffer?: boolean;
|
|
13
21
|
clearLeftoverAccounts?: boolean;
|
|
14
|
-
}): Promise<
|
|
22
|
+
}): Promise<UnsignedSolanaTx>;
|
|
15
23
|
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/solana/exec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/solana/exec.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,UAAU,EAIf,SAAS,EAEV,MAAM,iBAAiB,CAAA;AAIxB,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,aAAa,CAAA;AAGhF,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAU3E;;;;;;;;;;;GAWG;AACH,wBAAsB,6BAA6B,CACjD,GAAG,EAAE;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,GAAG,UAAU,EAC5C,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,eAAe,CAAC,uBAAuB,CAAC,EACpD,IAAI,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5F,OAAO,CAAC,gBAAgB,CAAC,CA8F3B"}
|
package/dist/solana/exec.js
CHANGED
|
@@ -1,97 +1,64 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
1
2
|
import { Program } from '@coral-xyz/anchor';
|
|
2
|
-
import { AddressLookupTableAccount, AddressLookupTableProgram,
|
|
3
|
+
import { AddressLookupTableAccount, AddressLookupTableProgram, PublicKey, SystemProgram, } from '@solana/web3.js';
|
|
3
4
|
import BN from 'bn.js';
|
|
4
5
|
import { hexlify } from 'ethers';
|
|
6
|
+
import { ChainFamily } from "../types.js";
|
|
5
7
|
import { IDL as CCIP_OFFRAMP_IDL } from "./idl/1.6.0/CCIP_OFFRAMP.js";
|
|
6
8
|
import { encodeSolanaOffchainTokenData } from "./offchain.js";
|
|
7
|
-
import { getDataBytes,
|
|
8
|
-
import { bytesToBuffer
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
execTxSignature = signature;
|
|
25
|
-
}
|
|
26
|
-
catch (e) {
|
|
27
|
-
if (e instanceof SendTransactionError &&
|
|
28
|
-
e.logs?.some((log) => log.includes('Error Code: ExecutionReportBufferAlreadyContainsChunk.'))) {
|
|
29
|
-
console.warn(`Skipping tx ${i + 1} of ${execTxs.length} because a chunk is already in the buffer.`);
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
throw e;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
console.debug(`Confirming tx #${i + 1} of ${execTxs.length}: ${signature} (${reason})...`);
|
|
37
|
-
for (let currentAttempt = 0;; currentAttempt++) {
|
|
38
|
-
try {
|
|
39
|
-
const latestBlockhash = await connection.getLatestBlockhash();
|
|
40
|
-
await connection.confirmTransaction({
|
|
41
|
-
signature,
|
|
42
|
-
blockhash: latestBlockhash.blockhash,
|
|
43
|
-
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
|
44
|
-
}, 'confirmed');
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
if (currentAttempt < 5 && e instanceof TransactionExpiredBlockheightExceededError) {
|
|
49
|
-
await sleep(1000);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
throw e;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return { hash: execTxSignature };
|
|
58
|
-
}
|
|
59
|
-
async function buildExecTxToSolana(offrampProgram, execReport, computeUnitsOverride, opts) {
|
|
60
|
-
const provider = offrampProgram.provider;
|
|
61
|
-
offrampProgram = new Program(CCIP_OFFRAMP_IDL, offrampProgram.programId, provider);
|
|
62
|
-
const payerAddress = provider.wallet.publicKey;
|
|
9
|
+
import { getDataBytes, toLeArray } from "../utils.js";
|
|
10
|
+
import { bytesToBuffer } from "./utils.js";
|
|
11
|
+
/**
|
|
12
|
+
* Generate unsigned tx to execute a CCIP report on Solana.
|
|
13
|
+
* @param ctx - Context containing connection and logger
|
|
14
|
+
* @param payer - Payer of the transaction.
|
|
15
|
+
* @param offramp - Address of the OffRamp contract.
|
|
16
|
+
* @param execReport - Execution report.
|
|
17
|
+
* @param opts - Options for txs to be generated
|
|
18
|
+
* - forceBuffer - Sends report in chunks for buffering in offRamp before execution
|
|
19
|
+
* - forceLookupTable - Creates lookup table for execution transaction, and deactivates in the end
|
|
20
|
+
* - clearLeftoverAccounts - Resets buffer before filling it in
|
|
21
|
+
* @returns Transaction hash of the execution.
|
|
22
|
+
*/
|
|
23
|
+
export async function generateUnsignedExecuteReport(ctx, payer, offramp, execReport, opts) {
|
|
24
|
+
const { connection, logger = console } = ctx;
|
|
25
|
+
const program = new Program(CCIP_OFFRAMP_IDL, offramp, ctx);
|
|
63
26
|
let bufferId;
|
|
64
27
|
if (opts?.forceBuffer) {
|
|
65
28
|
// Use messageId for bufferId. This is arbitrary, but easy to track.
|
|
66
29
|
bufferId = bytesToBuffer(execReport.message.header.messageId);
|
|
67
30
|
}
|
|
68
31
|
const { executionReport: preparedReport, tokenIndexes, accounts, addressLookupTables, } = await getManuallyExecuteInputs({
|
|
32
|
+
payer,
|
|
33
|
+
offramp: program,
|
|
69
34
|
execReport,
|
|
70
|
-
offrampProgram,
|
|
71
|
-
transmitter: payerAddress.toBase58(),
|
|
72
35
|
bufferId,
|
|
36
|
+
logger,
|
|
73
37
|
});
|
|
74
38
|
const addressLookupTableAccounts = await Promise.all(addressLookupTables.map(async (acc) => {
|
|
75
|
-
const lookupTableAccountInfo = await
|
|
39
|
+
const lookupTableAccountInfo = await connection.getAddressLookupTable(acc);
|
|
76
40
|
if (!lookupTableAccountInfo.value) {
|
|
77
41
|
throw new Error(`Lookup table account not found: ${acc.toBase58()}`);
|
|
78
42
|
}
|
|
79
43
|
return lookupTableAccountInfo.value;
|
|
80
44
|
}));
|
|
81
|
-
let serializedReport =
|
|
82
|
-
const { blockhash: recentBlockhash } = await provider.connection.getLatestBlockhash();
|
|
45
|
+
let serializedReport = program.coder.types.encode('ExecutionReportSingleChain', preparedReport);
|
|
83
46
|
let alt;
|
|
84
47
|
if (opts?.forceLookupTable) {
|
|
85
|
-
alt = await
|
|
86
|
-
addressLookupTableAccounts.push(alt.
|
|
48
|
+
alt = await buildLookupTableIxs(ctx, payer, accounts.map((acc) => acc.pubkey));
|
|
49
|
+
addressLookupTableAccounts.push(alt.lookupTable);
|
|
87
50
|
}
|
|
88
|
-
const
|
|
51
|
+
const instructions = [];
|
|
89
52
|
if (bufferId) {
|
|
90
|
-
|
|
91
|
-
|
|
53
|
+
logger.info(`Execute report will be pre-buffered through the offramp. This may take some time.`);
|
|
54
|
+
const bufferingIxs = await bufferedTransactionData(payer, program, serializedReport, bufferId, {
|
|
55
|
+
logger,
|
|
56
|
+
...opts,
|
|
57
|
+
});
|
|
58
|
+
instructions.push(...bufferingIxs);
|
|
92
59
|
serializedReport = Buffer.from([]); // clear 1st param to manuallyExecute method if buffered
|
|
93
60
|
}
|
|
94
|
-
const
|
|
61
|
+
const execIx = await program.methods
|
|
95
62
|
.manuallyExecute(serializedReport, tokenIndexes)
|
|
96
63
|
.accounts({
|
|
97
64
|
config: accounts[0].pubkey,
|
|
@@ -108,39 +75,31 @@ async function buildExecTxToSolana(offrampProgram, execReport, computeUnitsOverr
|
|
|
108
75
|
rmnRemoteConfig: accounts[11].pubkey,
|
|
109
76
|
})
|
|
110
77
|
.remainingAccounts(accounts.slice(12))
|
|
111
|
-
.
|
|
112
|
-
computeUnitsOverride ||= Math.ceil(1.1 *
|
|
113
|
-
((await simulateTransaction({
|
|
114
|
-
instructions: execTx.instructions,
|
|
115
|
-
connection: provider.connection,
|
|
116
|
-
payerKey: provider.wallet.publicKey,
|
|
117
|
-
addressLookupTableAccounts,
|
|
118
|
-
computeUnitsOverride,
|
|
119
|
-
})).unitsConsumed || 0));
|
|
120
|
-
// Add compute budget instruction at the beginning of instructions
|
|
121
|
-
execTx.instructions.unshift(ComputeBudgetProgram.setComputeUnitLimit({
|
|
122
|
-
units: computeUnitsOverride,
|
|
123
|
-
}));
|
|
78
|
+
.instruction();
|
|
124
79
|
// actual exec tx
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
]);
|
|
80
|
+
let execIndex = instructions.length;
|
|
81
|
+
instructions.push(execIx);
|
|
82
|
+
// "sandwich" instructions with ALT create+extend, then deactivate
|
|
129
83
|
if (alt) {
|
|
130
|
-
|
|
131
|
-
|
|
84
|
+
instructions.unshift(...alt.initialIxs);
|
|
85
|
+
execIndex += alt.initialIxs.length;
|
|
86
|
+
instructions.push(...alt.finalIxs);
|
|
132
87
|
}
|
|
133
|
-
return
|
|
88
|
+
return {
|
|
89
|
+
family: ChainFamily.Solana,
|
|
90
|
+
instructions,
|
|
91
|
+
lookupTables: addressLookupTableAccounts,
|
|
92
|
+
mainIndex: execIndex,
|
|
93
|
+
};
|
|
134
94
|
}
|
|
135
|
-
async function
|
|
136
|
-
const recentSlot = await
|
|
95
|
+
async function buildLookupTableIxs({ connection, logger = console }, authority, addresses) {
|
|
96
|
+
const recentSlot = await connection.getSlot('confirmed');
|
|
137
97
|
const [createIx, altAddr] = AddressLookupTableProgram.createLookupTable({
|
|
138
|
-
authority
|
|
139
|
-
payer:
|
|
98
|
+
authority,
|
|
99
|
+
payer: authority,
|
|
140
100
|
recentSlot,
|
|
141
101
|
});
|
|
142
|
-
|
|
143
|
-
const addresses = accounts.map((a) => a.pubkey);
|
|
102
|
+
logger.info('Using Address Lookup Table', altAddr.toBase58());
|
|
144
103
|
if (addresses.length > 256) {
|
|
145
104
|
throw new Error(`The number of addresses (${addresses.length}) exceeds the maximum limit imposed by Solana of 256 for Address Lookup Tables`);
|
|
146
105
|
}
|
|
@@ -149,21 +108,19 @@ async function buildLookupTableTxs(provider, accounts) {
|
|
|
149
108
|
const firstChunkLength = 28;
|
|
150
109
|
const maxAddressesPerTx = 35;
|
|
151
110
|
const extendIxs = [];
|
|
152
|
-
const ranges = [];
|
|
153
111
|
for (let [start, end] = [0, firstChunkLength]; start < addresses.length; [start, end] = [end, end + maxAddressesPerTx]) {
|
|
154
112
|
const addressesChunk = addresses.slice(start, end);
|
|
155
113
|
const extendIx = AddressLookupTableProgram.extendLookupTable({
|
|
156
|
-
|
|
157
|
-
|
|
114
|
+
authority,
|
|
115
|
+
payer: authority,
|
|
158
116
|
lookupTable: altAddr,
|
|
159
117
|
addresses: addressesChunk,
|
|
160
118
|
});
|
|
161
119
|
extendIxs.push(extendIx);
|
|
162
|
-
ranges.push([start, start + addressesChunk.length - 1]);
|
|
163
120
|
}
|
|
164
121
|
const deactivateIx = AddressLookupTableProgram.deactivateLookupTable({
|
|
165
122
|
lookupTable: altAddr,
|
|
166
|
-
authority
|
|
123
|
+
authority,
|
|
167
124
|
});
|
|
168
125
|
// disable closeTx, to be cleaned in SolanaChain.cleanUpBuffers
|
|
169
126
|
// const closeIx = AddressLookupTableProgram.closeLookupTable({
|
|
@@ -171,82 +128,50 @@ async function buildLookupTableTxs(provider, accounts) {
|
|
|
171
128
|
// recipient: provider.wallet.publicKey,
|
|
172
129
|
// lookupTable: altAddr,
|
|
173
130
|
// })
|
|
174
|
-
const { blockhash: recentBlockhash } = await provider.connection.getLatestBlockhash();
|
|
175
131
|
return {
|
|
176
|
-
|
|
132
|
+
lookupTable: new AddressLookupTableAccount({
|
|
177
133
|
key: altAddr,
|
|
178
134
|
state: {
|
|
179
|
-
deactivationSlot:
|
|
135
|
+
deactivationSlot: 2n ** 64n - 1n,
|
|
180
136
|
lastExtendedSlot: recentSlot,
|
|
181
137
|
lastExtendedSlotStartIndex: 0,
|
|
182
138
|
addresses,
|
|
183
139
|
},
|
|
184
140
|
}),
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
[
|
|
188
|
-
`lookup[create + 0..${ranges[0][1]}]`,
|
|
189
|
-
toVersionedTransaction([createIx, extendIxs[0]], provider.wallet.publicKey, recentBlockhash),
|
|
190
|
-
],
|
|
191
|
-
...extendIxs
|
|
192
|
-
.slice(1)
|
|
193
|
-
.map((ix, i) => [
|
|
194
|
-
`lookup[${ranges[i + 1][0]}..${ranges[i + 1][1]}]`,
|
|
195
|
-
toVersionedTransaction([ix], provider.wallet.publicKey, recentBlockhash),
|
|
196
|
-
]),
|
|
197
|
-
],
|
|
198
|
-
finalTxs: [
|
|
199
|
-
[
|
|
200
|
-
`lookup[deactivate]`,
|
|
201
|
-
toVersionedTransaction([deactivateIx], provider.wallet.publicKey, recentBlockhash),
|
|
202
|
-
],
|
|
203
|
-
],
|
|
141
|
+
initialIxs: [createIx, ...extendIxs],
|
|
142
|
+
finalIxs: [deactivateIx],
|
|
204
143
|
};
|
|
205
144
|
}
|
|
206
|
-
async function bufferedTransactionData(
|
|
207
|
-
const
|
|
208
|
-
const [
|
|
209
|
-
|
|
210
|
-
console.log(`The bufferID is ${hexlify(bufferId)}, and the PDA address for the buffer is ${bufferAddress.toString()}\nIf this buffering process is aborted, remember to cleanUp the account to recover locked rent.`);
|
|
145
|
+
async function bufferedTransactionData(payer, offramp, serializedReport, bufferId, { logger = console, clearLeftoverAccounts, } = {}) {
|
|
146
|
+
const [bufferAddress] = PublicKey.findProgramAddressSync([Buffer.from('execution_report_buffer'), bufferId, payer.toBuffer()], offramp.programId);
|
|
147
|
+
const [configPDA] = PublicKey.findProgramAddressSync([Buffer.from('config')], offramp.programId);
|
|
148
|
+
logger.info(`The bufferID is ${hexlify(bufferId)}, and the PDA address for the buffer is ${bufferAddress.toString()}\nIf this buffering process is aborted, remember to cleanUp the account to recover locked rent.`);
|
|
211
149
|
const chunkSize = 800;
|
|
212
|
-
const
|
|
150
|
+
const bufferedExecIxs = [];
|
|
213
151
|
const bufferingAccounts = {
|
|
214
152
|
executionReportBuffer: bufferAddress,
|
|
215
153
|
config: configPDA,
|
|
216
|
-
authority:
|
|
154
|
+
authority: payer,
|
|
217
155
|
systemProgram: SystemProgram.programId,
|
|
218
156
|
};
|
|
219
|
-
if (
|
|
220
|
-
|
|
157
|
+
if (clearLeftoverAccounts) {
|
|
158
|
+
bufferedExecIxs.push(await offramp.methods
|
|
221
159
|
.closeExecutionReportBuffer(bufferId)
|
|
222
160
|
.accounts(bufferingAccounts)
|
|
223
|
-
.
|
|
224
|
-
bufferedExecTxs.push([
|
|
225
|
-
'buffering[clear]',
|
|
226
|
-
toVersionedTransaction(clearTx, provider.wallet.publicKey, recentBlockhash),
|
|
227
|
-
]);
|
|
161
|
+
.instruction());
|
|
228
162
|
}
|
|
229
163
|
const numChunks = Math.ceil(serializedReport.length / chunkSize);
|
|
230
164
|
for (let i = 0; i < serializedReport.length; i += chunkSize) {
|
|
231
165
|
const end = Math.min(i + chunkSize, serializedReport.length);
|
|
232
166
|
const chunk = serializedReport.subarray(i, end);
|
|
233
|
-
|
|
167
|
+
bufferedExecIxs.push(await offramp.methods
|
|
234
168
|
.bufferExecutionReport(bufferId, serializedReport.length, chunk, i / chunkSize, numChunks)
|
|
235
169
|
.accounts(bufferingAccounts)
|
|
236
|
-
.
|
|
237
|
-
bufferedExecTxs.push([
|
|
238
|
-
`buffering[${i / chunkSize}=${end - i}B]`,
|
|
239
|
-
toVersionedTransaction(appendTx, provider.wallet.publicKey, recentBlockhash),
|
|
240
|
-
]);
|
|
170
|
+
.instruction());
|
|
241
171
|
}
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
function toVersionedTransaction(input, payerKey, recentBlockhash, addressLookupTableAccounts) {
|
|
245
|
-
const instructions = Array.isArray(input) ? input : input.instructions;
|
|
246
|
-
const message = new TransactionMessage({ payerKey, recentBlockhash, instructions });
|
|
247
|
-
return new VersionedTransaction(message.compileToV0Message(addressLookupTableAccounts));
|
|
172
|
+
return bufferedExecIxs;
|
|
248
173
|
}
|
|
249
|
-
async function getManuallyExecuteInputs({
|
|
174
|
+
async function getManuallyExecuteInputs({ payer, offramp, execReport, bufferId, ...ctx }) {
|
|
250
175
|
const executionReport = prepareExecutionReport(execReport);
|
|
251
176
|
const messageAccountMetas = execReport.message.accounts.map((acc, index) => {
|
|
252
177
|
const bitmap = BigInt(execReport.message.accountIsWritableBitmap);
|
|
@@ -263,7 +188,6 @@ async function getManuallyExecuteInputs({ execReport, offrampProgram, transmitte
|
|
|
263
188
|
isSigner: false,
|
|
264
189
|
isWritable: false,
|
|
265
190
|
};
|
|
266
|
-
console.debug('Message receiver:', execReport.message.receiver);
|
|
267
191
|
// Prepend receiver to messaging accounts
|
|
268
192
|
const messagingAccounts = execReport.message.receiver !== PublicKey.default.toBase58()
|
|
269
193
|
? [receiverAccountMeta, ...messageAccountMetas]
|
|
@@ -281,15 +205,16 @@ async function getManuallyExecuteInputs({ execReport, offrampProgram, transmitte
|
|
|
281
205
|
},
|
|
282
206
|
}));
|
|
283
207
|
const { accounts, addressLookupTableAccounts: addressLookupTables, tokenIndexes, } = await autoDeriveExecutionAccounts({
|
|
284
|
-
|
|
208
|
+
offramp,
|
|
285
209
|
originalSender: bytesToBuffer(execReport.message.sender),
|
|
286
|
-
|
|
210
|
+
payer,
|
|
287
211
|
messagingAccounts,
|
|
288
212
|
sourceChainSelector: execReport.message.header.sourceChainSelector,
|
|
289
213
|
tokenTransferAndOffchainData,
|
|
290
214
|
merkleRoot: bytesToBuffer(execReport.merkleRoot),
|
|
291
215
|
bufferId,
|
|
292
216
|
tokenReceiver: new PublicKey(execReport.message.tokenReceiver),
|
|
217
|
+
...ctx,
|
|
293
218
|
});
|
|
294
219
|
return {
|
|
295
220
|
executionReport,
|
|
@@ -330,17 +255,17 @@ function prepareExecutionReport({ message, offchainTokenData, proofs, }) {
|
|
|
330
255
|
proofs: proofs.map((p) => Array.from(getDataBytes(p))),
|
|
331
256
|
};
|
|
332
257
|
}
|
|
333
|
-
async function autoDeriveExecutionAccounts({
|
|
258
|
+
async function autoDeriveExecutionAccounts({ offramp, originalSender, payer, messagingAccounts, sourceChainSelector, tokenTransferAndOffchainData, merkleRoot, tokenReceiver, bufferId, logger = console, }) {
|
|
334
259
|
const derivedAccounts = [];
|
|
335
260
|
const lookupTables = [];
|
|
336
261
|
const tokenIndices = [];
|
|
337
262
|
let askWith = [];
|
|
338
263
|
let stage = 'Start';
|
|
339
264
|
let tokenIndex = 0;
|
|
340
|
-
const [configPDA] = PublicKey.findProgramAddressSync([Buffer.from('config')],
|
|
265
|
+
const [configPDA] = PublicKey.findProgramAddressSync([Buffer.from('config')], offramp.programId);
|
|
341
266
|
while (true) {
|
|
342
267
|
const params = {
|
|
343
|
-
executeCaller:
|
|
268
|
+
executeCaller: payer,
|
|
344
269
|
messageAccounts: messagingAccounts,
|
|
345
270
|
sourceChainSelector: new BN(sourceChainSelector.toString()),
|
|
346
271
|
originalSender: originalSender,
|
|
@@ -359,10 +284,8 @@ async function autoDeriveExecutionAccounts({ offrampProgram, originalSender, tra
|
|
|
359
284
|
data: Buffer.from([]), // omit offchain token data
|
|
360
285
|
}));
|
|
361
286
|
}
|
|
362
|
-
// copy of Program which avoids signing every simulation
|
|
363
|
-
const readOnlyProgram = new Program(offrampProgram.idl, offrampProgram.programId, simulationProvider(offrampProgram.provider.connection, transmitter));
|
|
364
287
|
// Execute as a view call to get the response
|
|
365
|
-
const response = (await
|
|
288
|
+
const response = (await offramp.methods
|
|
366
289
|
.deriveAccountsExecute(params, stage)
|
|
367
290
|
.accounts({
|
|
368
291
|
config: configPDA,
|
|
@@ -370,8 +293,8 @@ async function autoDeriveExecutionAccounts({ offrampProgram, originalSender, tra
|
|
|
370
293
|
.remainingAccounts(askWith)
|
|
371
294
|
.view()
|
|
372
295
|
.catch((error) => {
|
|
373
|
-
|
|
374
|
-
|
|
296
|
+
logger.error('Error deriving accounts:', error);
|
|
297
|
+
logger.error('Params:', params);
|
|
375
298
|
throw error;
|
|
376
299
|
}));
|
|
377
300
|
// Check if we're at the start of a token transfer
|
|
@@ -382,7 +305,7 @@ async function autoDeriveExecutionAccounts({ offrampProgram, originalSender, tra
|
|
|
382
305
|
}
|
|
383
306
|
// Update token index
|
|
384
307
|
tokenIndex += response.accountsToSave.length;
|
|
385
|
-
|
|
308
|
+
logger.debug('After stage', stage, 'tokenIndices', tokenIndices, 'nextTokenIndex', tokenIndex);
|
|
386
309
|
// Collect the derived accounts
|
|
387
310
|
for (const meta of response.accountsToSave) {
|
|
388
311
|
derivedAccounts.push({
|
|
@@ -405,9 +328,9 @@ async function autoDeriveExecutionAccounts({ offrampProgram, originalSender, tra
|
|
|
405
328
|
}
|
|
406
329
|
stage = response.nextStage;
|
|
407
330
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
331
|
+
logger.debug('Resulting derived accounts:', derivedAccounts);
|
|
332
|
+
logger.debug('Resulting derived address lookup tables:', lookupTables);
|
|
333
|
+
logger.debug('Resulting derived token indexes:', tokenIndices);
|
|
411
334
|
return {
|
|
412
335
|
accounts: derivedAccounts,
|
|
413
336
|
addressLookupTableAccounts: lookupTables,
|