@across-protocol/contracts 3.0.18 → 3.0.19

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.
Files changed (74) hide show
  1. package/README.md +2 -0
  2. package/artifacts/build-info/9cb910e5bb5dd730cd01af84a0fb0466.json +1 -0
  3. package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.dbg.json +4 -0
  4. package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.json +2316 -0
  5. package/contracts/Ink_SpokePool.sol +72 -0
  6. package/dist/deploy/consts.js +8 -2
  7. package/dist/deployments/deployments.json +7 -1
  8. package/dist/hardhat.config.js +17 -0
  9. package/dist/scripts/svm/addressToPublicKey.js +2 -2
  10. package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +1 -4
  11. package/dist/scripts/svm/bridgeLiabilityToHubPool.js +5 -15
  12. package/dist/scripts/svm/closeRelayerPdas.js +3 -3
  13. package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +1 -4
  14. package/dist/scripts/svm/executeRebalanceToHubPool.js +6 -16
  15. package/dist/scripts/svm/executeRebalanceToSpokePool.js +14 -27
  16. package/dist/scripts/svm/fakeFillWithRandomDistribution.js +6 -7
  17. package/dist/scripts/svm/initialize.js +2 -2
  18. package/dist/scripts/svm/proposeRebalanceToSpokePool.js +11 -15
  19. package/dist/scripts/svm/publicKeyToAddress.js +2 -2
  20. package/dist/scripts/svm/queryDeposits.js +2 -2
  21. package/dist/scripts/svm/queryFills.js +10 -11
  22. package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +10 -24
  23. package/dist/scripts/svm/remoteHubPoolSetDepositRoute.js +16 -29
  24. package/dist/scripts/svm/remotePauseDeposits.js +21 -27
  25. package/dist/scripts/svm/simpleFakeRelayerRepayment.js +3 -3
  26. package/dist/scripts/svm/simpleFill.js +3 -4
  27. package/dist/scripts/svm/utils/helpers.d.ts +3 -1
  28. package/dist/scripts/svm/utils/helpers.js +13 -3
  29. package/dist/src/svm/coders.d.ts +37 -0
  30. package/dist/src/svm/coders.js +250 -0
  31. package/dist/src/svm/conversionUtils.d.ts +22 -0
  32. package/dist/src/svm/conversionUtils.js +73 -0
  33. package/dist/src/svm/index.d.ts +6 -0
  34. package/dist/src/svm/index.js +22 -0
  35. package/dist/src/svm/instructionParamsUtils.d.ts +31 -0
  36. package/dist/src/svm/instructionParamsUtils.js +128 -0
  37. package/dist/src/svm/relayHashUtils.d.ts +30 -0
  38. package/dist/src/svm/relayHashUtils.js +209 -0
  39. package/dist/src/svm/solanaProgramUtils.d.ts +38 -0
  40. package/dist/src/svm/solanaProgramUtils.js +147 -0
  41. package/dist/src/svm/transactionUtils.d.ts +8 -0
  42. package/dist/src/svm/transactionUtils.js +55 -0
  43. package/dist/src/types/svm.d.ts +118 -0
  44. package/dist/src/types/svm.js +2 -0
  45. package/dist/test/svm/MulticallHandler.js +2 -2
  46. package/dist/test/svm/SvmSpoke.Bundle.js +48 -48
  47. package/dist/test/svm/SvmSpoke.Deposit.js +13 -13
  48. package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +15 -17
  49. package/dist/test/svm/SvmSpoke.Fill.js +29 -30
  50. package/dist/test/svm/SvmSpoke.HandleReceiveMessage.js +2 -2
  51. package/dist/test/svm/SvmSpoke.Ownership.js +6 -6
  52. package/dist/test/svm/SvmSpoke.RefundClaims.js +5 -5
  53. package/dist/test/svm/SvmSpoke.Routes.js +3 -3
  54. package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +19 -20
  55. package/dist/test/svm/SvmSpoke.SlowFill.js +18 -18
  56. package/dist/test/svm/SvmSpoke.TokenBridge.js +13 -13
  57. package/dist/test/svm/SvmSpoke.common.d.ts +1 -49
  58. package/dist/test/svm/SvmSpoke.common.js +4 -4
  59. package/dist/test/svm/cctpHelpers.js +2 -2
  60. package/dist/test/svm/utils.d.ts +5 -66
  61. package/dist/test/svm/utils.js +10 -226
  62. package/dist/typechain/contracts/Ink_SpokePool.d.ts +1251 -0
  63. package/dist/typechain/contracts/Ink_SpokePool.js +2 -0
  64. package/dist/typechain/contracts/index.d.ts +1 -0
  65. package/dist/typechain/factories/contracts/Ink_SpokePool__factory.d.ts +1833 -0
  66. package/dist/typechain/factories/contracts/Ink_SpokePool__factory.js +2347 -0
  67. package/dist/typechain/factories/contracts/index.d.ts +1 -0
  68. package/dist/typechain/factories/contracts/index.js +3 -1
  69. package/dist/typechain/hardhat.d.ts +9 -0
  70. package/dist/typechain/index.d.ts +2 -0
  71. package/dist/typechain/index.js +5 -3
  72. package/package.json +2 -2
  73. package/dist/src/SvmUtils.d.ts +0 -72
  74. package/dist/src/SvmUtils.js +0 -496
@@ -1,496 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.AcrossPlusMessageCoder = exports.MulticallHandlerCoder = exports.LargeAccountsCoder = exports.readUInt256BE = exports.publicKeyToEvmAddress = exports.evmAddressToPublicKey = void 0;
30
- exports.findProgramAddress = findProgramAddress;
31
- exports.readEvents = readEvents;
32
- exports.readEventsUntilFound = readEventsUntilFound;
33
- exports.getEvent = getEvent;
34
- exports.readProgramEvents = readProgramEvents;
35
- exports.subscribeToCpiEventsForProgram = subscribeToCpiEventsForProgram;
36
- exports.calculateRelayHashUint8Array = calculateRelayHashUint8Array;
37
- exports.calculateRelayEventHashUint8Array = calculateRelayEventHashUint8Array;
38
- exports.sendTransactionWithLookupTable = sendTransactionWithLookupTable;
39
- exports.hashNonEmptyMessage = hashNonEmptyMessage;
40
- exports.strPublicKey = strPublicKey;
41
- //TODO: we will need to move this to a better location and integrate it more directly with other utils & files in time.
42
- // eslint-disable-next-line node/no-extraneous-import
43
- const borsh = __importStar(require("@coral-xyz/borsh"));
44
- const bs58_1 = __importDefault(require("bs58"));
45
- const anchor_1 = require("@coral-xyz/anchor");
46
- const idl_1 = require("@coral-xyz/anchor/dist/cjs/coder/borsh/idl");
47
- const ethers_1 = require("ethers");
48
- const web3_js_1 = require("@solana/web3.js");
49
- function findProgramAddress(label, program, extraSeeds) {
50
- const seeds = [Buffer.from(anchor_1.utils.bytes.utf8.encode(label))];
51
- if (extraSeeds) {
52
- for (const extraSeed of extraSeeds) {
53
- if (typeof extraSeed === "string") {
54
- seeds.push(Buffer.from(anchor_1.utils.bytes.utf8.encode(extraSeed)));
55
- }
56
- else if (Array.isArray(extraSeed)) {
57
- seeds.push(Buffer.from(extraSeed));
58
- }
59
- else if (Buffer.isBuffer(extraSeed)) {
60
- seeds.push(extraSeed);
61
- }
62
- else {
63
- seeds.push(extraSeed.toBuffer());
64
- }
65
- }
66
- }
67
- const res = web3_js_1.PublicKey.findProgramAddressSync(seeds, program);
68
- return { publicKey: res[0], bump: res[1] };
69
- }
70
- async function readEvents(connection, txSignature, programs, commitment = "confirmed") {
71
- const txResult = await connection.getTransaction(txSignature, { commitment, maxSupportedTransactionVersion: 0 });
72
- if (txResult === null)
73
- return [];
74
- return processEventFromTx(txResult, programs);
75
- }
76
- function processEventFromTx(txResult, programs) {
77
- const eventAuthorities = new Map();
78
- for (const program of programs) {
79
- eventAuthorities.set(program.programId.toString(), findProgramAddress("__event_authority", program.programId).publicKey);
80
- }
81
- const events = [];
82
- // Resolve any potential addresses that were passed from address lookup tables.
83
- const messageAccountKeys = txResult.transaction.message.getAccountKeys({
84
- accountKeysFromLookups: txResult.meta?.loadedAddresses,
85
- });
86
- for (const ixBlock of txResult.meta?.innerInstructions ?? []) {
87
- for (const ix of ixBlock.instructions) {
88
- for (const program of programs) {
89
- const ixProgramId = messageAccountKeys.get(ix.programIdIndex);
90
- const singleIxAccount = ix.accounts.length === 1 ? messageAccountKeys.get(ix.accounts[0]) : undefined;
91
- if (ixProgramId !== undefined &&
92
- singleIxAccount !== undefined &&
93
- program.programId.equals(ixProgramId) &&
94
- eventAuthorities.get(ixProgramId.toString())?.equals(singleIxAccount)) {
95
- const ixData = anchor_1.utils.bytes.bs58.decode(ix.data);
96
- const eventData = anchor_1.utils.bytes.base64.encode(Buffer.from(new Uint8Array(ixData).slice(8)));
97
- const event = program.coder.events.decode(eventData);
98
- events.push({
99
- program: program.programId,
100
- data: event?.data,
101
- name: event?.name,
102
- });
103
- }
104
- }
105
- }
106
- }
107
- return events;
108
- }
109
- // Helper function to wait for an event to be emitted. Should only be used in tests where txSignature is known to emit.
110
- async function readEventsUntilFound(connection, txSignature, programs) {
111
- const startTime = Date.now();
112
- let txResult = null;
113
- while (Date.now() - startTime < 5000) {
114
- // 5 seconds timeout to wait to find the event.
115
- txResult = await connection.getTransaction(txSignature, {
116
- commitment: "confirmed",
117
- maxSupportedTransactionVersion: 0,
118
- });
119
- if (txResult !== null)
120
- return processEventFromTx(txResult, programs);
121
- await new Promise((resolve) => setTimeout(resolve, 50)); // 50 ms delay between retries.
122
- }
123
- throw new Error("No event found within 5 seconds");
124
- }
125
- function getEvent(events, program, eventName) {
126
- for (const event of events) {
127
- if (event.name === eventName && program.toString() === event.program.toString()) {
128
- return event.data;
129
- }
130
- }
131
- throw new Error("Event " + eventName + " not found");
132
- }
133
- async function readProgramEvents(connection, program, finality = "confirmed", options = { limit: 1000 }) {
134
- const allSignatures = [];
135
- // Fetch all signatures in sequential batches
136
- while (true) {
137
- const signatures = await connection.getSignaturesForAddress(program.programId, options, finality);
138
- allSignatures.push(...signatures);
139
- // Update options for the next batch. Set before to the last fetched signature.
140
- if (signatures.length > 0) {
141
- options = { ...options, before: signatures[signatures.length - 1].signature };
142
- }
143
- if (options.limit && signatures.length < options.limit)
144
- break; // Exit early if the number of signatures < limit
145
- }
146
- // Fetch events for all signatures in parallel
147
- const eventsWithSlots = await Promise.all(allSignatures.map(async (signature) => {
148
- const events = await readEvents(connection, signature.signature, [program], finality);
149
- return events.map((event) => ({
150
- ...event,
151
- confirmationStatus: signature.confirmationStatus || "Unknown",
152
- blockTime: signature.blockTime || 0,
153
- signature: signature.signature,
154
- slot: signature.slot,
155
- name: event.name || "Unknown",
156
- }));
157
- }));
158
- return eventsWithSlots.flat(); // Flatten the array of events & return.
159
- }
160
- async function subscribeToCpiEventsForProgram(connection, program, callback) {
161
- const subscriptionId = connection.onLogs(new web3_js_1.PublicKey(findProgramAddress("__event_authority", program.programId).publicKey.toString()), async (logs) => {
162
- callback(await readEvents(connection, logs.signature, [program], "confirmed"));
163
- }, "confirmed");
164
- return subscriptionId;
165
- }
166
- const evmAddressToPublicKey = (address) => {
167
- const bytes32Address = `0x000000000000000000000000${address.replace("0x", "")}`;
168
- return new web3_js_1.PublicKey(ethers_1.ethers.utils.arrayify(bytes32Address));
169
- };
170
- exports.evmAddressToPublicKey = evmAddressToPublicKey;
171
- const publicKeyToEvmAddress = (publicKey) => {
172
- // Convert the input to a PublicKey if it's a string
173
- const pubKeyBuffer = typeof publicKey === "string" ? new web3_js_1.PublicKey(publicKey).toBuffer() : publicKey.toBuffer();
174
- // Extract the last 20 bytes to get the Ethereum address
175
- const addressBuffer = pubKeyBuffer.slice(-20);
176
- // Convert the buffer to a hex string and prepend '0x'
177
- return `0x${addressBuffer.toString("hex")}`;
178
- };
179
- exports.publicKeyToEvmAddress = publicKeyToEvmAddress;
180
- // TODO: we are inconsistant with where we are placing some utils. we have some stuff here, some stuff that we might
181
- // want to re-use within the test directory. more over, when moving things into the canonical across repo, we should
182
- // re-use the test utils there.
183
- function calculateRelayHashUint8Array(relayData, chainId) {
184
- const contentToHash = Buffer.concat([
185
- relayData.depositor.toBuffer(),
186
- relayData.recipient.toBuffer(),
187
- relayData.exclusiveRelayer.toBuffer(),
188
- relayData.inputToken.toBuffer(),
189
- relayData.outputToken.toBuffer(),
190
- relayData.inputAmount.toArrayLike(Buffer, "le", 8),
191
- relayData.outputAmount.toArrayLike(Buffer, "le", 8),
192
- relayData.originChainId.toArrayLike(Buffer, "le", 8),
193
- Buffer.from(relayData.depositId),
194
- new anchor_1.BN(relayData.fillDeadline).toArrayLike(Buffer, "le", 4),
195
- new anchor_1.BN(relayData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
196
- hashNonEmptyMessage(relayData.message), // Replace with hash of message, so that relay hash can be recovered from event.
197
- chainId.toArrayLike(Buffer, "le", 8),
198
- ]);
199
- const relayHash = ethers_1.ethers.utils.keccak256(contentToHash);
200
- const relayHashBuffer = Buffer.from(relayHash.slice(2), "hex");
201
- return new Uint8Array(relayHashBuffer);
202
- }
203
- // Same method as above, but message in the relayData is already hashed, as fetched from fill events.
204
- function calculateRelayEventHashUint8Array(relayEventData, chainId) {
205
- const contentToHash = Buffer.concat([
206
- relayEventData.depositor.toBuffer(),
207
- relayEventData.recipient.toBuffer(),
208
- relayEventData.exclusiveRelayer.toBuffer(),
209
- relayEventData.inputToken.toBuffer(),
210
- relayEventData.outputToken.toBuffer(),
211
- relayEventData.inputAmount.toArrayLike(Buffer, "le", 8),
212
- relayEventData.outputAmount.toArrayLike(Buffer, "le", 8),
213
- relayEventData.originChainId.toArrayLike(Buffer, "le", 8),
214
- Buffer.from(relayEventData.depositId),
215
- new anchor_1.BN(relayEventData.fillDeadline).toArrayLike(Buffer, "le", 4),
216
- new anchor_1.BN(relayEventData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
217
- Buffer.from(relayEventData.messageHash), // Renamed to messageHash in the event data.
218
- chainId.toArrayLike(Buffer, "le", 8),
219
- ]);
220
- const relayHash = ethers_1.ethers.utils.keccak256(contentToHash);
221
- const relayHashBuffer = Buffer.from(relayHash.slice(2), "hex");
222
- return new Uint8Array(relayHashBuffer);
223
- }
224
- const readUInt256BE = (buffer) => {
225
- let result = BigInt(0);
226
- for (let i = 0; i < buffer.length; i++) {
227
- result = (result << BigInt(8)) + BigInt(buffer[i]);
228
- }
229
- return result;
230
- };
231
- exports.readUInt256BE = readUInt256BE;
232
- // This is extended Anchor accounts coder to handle large account data that is required when passing instruction
233
- // parameters from prefilled data account. Base implementation restricts the buffer to only 1000 bytes.
234
- class LargeAccountsCoder extends anchor_1.BorshAccountsCoder {
235
- // Getter to access the private accountLayouts property from base class.
236
- getAccountLayouts() {
237
- return this.accountLayouts;
238
- }
239
- async encode(accountName, account) {
240
- const buffer = Buffer.alloc(10240); // We don't currently need anything above instruction data account reallocation limit.
241
- const layout = this.getAccountLayouts().get(accountName);
242
- if (!layout) {
243
- throw new Error(`Unknown account: ${accountName}`);
244
- }
245
- const len = layout.encode(account, buffer);
246
- const accountData = buffer.slice(0, len);
247
- const discriminator = this.accountDiscriminator(accountName);
248
- return Buffer.concat([discriminator, accountData]);
249
- }
250
- }
251
- exports.LargeAccountsCoder = LargeAccountsCoder;
252
- // Modified version of CompiledKeys to handle compilation of unsigned transactions. Original implementation is here:
253
- // https://github.com/solana-labs/solana-web3.js/blob/v1.95.3/src/message/compiled-keys.ts
254
- class UnsignedCompiledKeys {
255
- constructor(keyModeMap, payer) {
256
- this.keyModeMap = keyModeMap;
257
- this.payer = payer;
258
- }
259
- static compileUnsigned(instructions, payer) {
260
- const keyModeMap = new Map();
261
- const getOrInsertDefault = (pubkey) => {
262
- const address = pubkey.toBase58();
263
- let keyMode = keyModeMap.get(address);
264
- if (keyMode === undefined) {
265
- keyMode = {
266
- isWritable: false,
267
- };
268
- keyModeMap.set(address, keyMode);
269
- }
270
- return keyMode;
271
- };
272
- if (payer !== undefined) {
273
- const payerKeyMode = getOrInsertDefault(payer);
274
- payerKeyMode.isWritable = true;
275
- }
276
- for (const ix of instructions) {
277
- getOrInsertDefault(ix.programId);
278
- for (const accountMeta of ix.keys) {
279
- const keyMode = getOrInsertDefault(accountMeta.pubkey);
280
- keyMode.isWritable ||= accountMeta.isWritable;
281
- }
282
- }
283
- return new UnsignedCompiledKeys(keyModeMap, payer);
284
- }
285
- getMessageComponents() {
286
- const mapEntries = [...this.keyModeMap.entries()];
287
- if (mapEntries.length > 256)
288
- throw new Error("Max static account keys length exceeded");
289
- const writableNonSigners = mapEntries.filter(([, mode]) => mode.isWritable);
290
- const readonlyNonSigners = mapEntries.filter(([, mode]) => !mode.isWritable);
291
- const header = {
292
- numRequiredSignatures: 0,
293
- numReadonlySignedAccounts: 0,
294
- numReadonlyUnsignedAccounts: readonlyNonSigners.length,
295
- };
296
- const staticAccountKeys = [
297
- ...writableNonSigners.map(([address]) => new web3_js_1.PublicKey(address)),
298
- ...readonlyNonSigners.map(([address]) => new web3_js_1.PublicKey(address)),
299
- ];
300
- return [header, staticAccountKeys];
301
- }
302
- }
303
- // Extended version of legacy Message to handle compilation of unsigned transactions. Base implementation is here:
304
- // https://github.com/solana-labs/solana-web3.js/blob/v1.95.3/src/message/legacy.ts
305
- class UnsignedMessage extends web3_js_1.Message {
306
- static compileUnsigned(instructions, payer) {
307
- const compiledKeys = UnsignedCompiledKeys.compileUnsigned(instructions, payer);
308
- const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
309
- const accountKeys = new web3_js_1.MessageAccountKeys(staticAccountKeys);
310
- const compiledInstructions = accountKeys.compileInstructions(instructions).map((ix) => ({
311
- programIdIndex: ix.programIdIndex,
312
- accounts: ix.accountKeyIndexes,
313
- data: bs58_1.default.encode(ix.data),
314
- }));
315
- return new web3_js_1.Message({
316
- header,
317
- accountKeys: staticAccountKeys,
318
- recentBlockhash: "", // Not used as we are not signing the transaction.
319
- instructions: compiledInstructions,
320
- });
321
- }
322
- }
323
- // Helper to encode message compiled transactions for Across+ multicall handler.
324
- class MulticallHandlerCoder {
325
- constructor(instructions, payerKey) {
326
- // Compile transaction message and keys.
327
- this.compiledMessage = UnsignedMessage.compileUnsigned(instructions, payerKey);
328
- // Setup the layout for the encoder.
329
- const fieldLayouts = [idl_1.IdlCoder.fieldLayout(MulticallHandlerCoder.coderArg, MulticallHandlerCoder.coderTypes)];
330
- this.layout = borsh.struct(fieldLayouts);
331
- }
332
- get readOnlyLen() {
333
- return (this.compiledMessage.header.numReadonlySignedAccounts + this.compiledMessage.header.numReadonlyUnsignedAccounts);
334
- }
335
- get compiledKeyMetas() {
336
- return this.compiledMessage.accountKeys.map((key, index) => {
337
- return {
338
- pubkey: key,
339
- isSigner: this.compiledMessage.isAccountSigner(index),
340
- isWritable: this.compiledMessage.isAccountWritable(index),
341
- };
342
- });
343
- }
344
- encode() {
345
- const buffer = Buffer.alloc(1280);
346
- const len = this.layout.encode({ compiledIxs: this.compiledMessage.compiledInstructions }, buffer);
347
- return buffer.slice(0, len);
348
- }
349
- }
350
- exports.MulticallHandlerCoder = MulticallHandlerCoder;
351
- MulticallHandlerCoder.coderArg = {
352
- name: "compiledIxs",
353
- type: {
354
- vec: {
355
- defined: {
356
- name: "compiledIx",
357
- },
358
- },
359
- },
360
- };
361
- MulticallHandlerCoder.coderTypes = [
362
- {
363
- name: "compiledIx",
364
- type: {
365
- kind: "struct",
366
- fields: [
367
- {
368
- name: "programIdIndex",
369
- type: "u8",
370
- },
371
- {
372
- name: "accountKeyIndexes",
373
- type: {
374
- vec: "u8",
375
- },
376
- },
377
- {
378
- name: "data",
379
- type: "bytes",
380
- },
381
- ],
382
- },
383
- },
384
- ];
385
- class AcrossPlusMessageCoder {
386
- constructor(acrossPlusMessage) {
387
- this.acrossPlusMessage = acrossPlusMessage;
388
- }
389
- encode() {
390
- const fieldLayouts = [idl_1.IdlCoder.fieldLayout(AcrossPlusMessageCoder.coderArg, AcrossPlusMessageCoder.coderTypes)];
391
- const layout = borsh.struct(fieldLayouts);
392
- const buffer = Buffer.alloc(12800);
393
- const len = layout.encode({ message: this.acrossPlusMessage }, buffer);
394
- return buffer.slice(0, len);
395
- }
396
- }
397
- exports.AcrossPlusMessageCoder = AcrossPlusMessageCoder;
398
- AcrossPlusMessageCoder.coderArg = {
399
- name: "message",
400
- type: {
401
- defined: {
402
- name: "acrossPlusMessage",
403
- },
404
- },
405
- };
406
- AcrossPlusMessageCoder.coderTypes = [
407
- {
408
- name: "acrossPlusMessage",
409
- type: {
410
- kind: "struct",
411
- fields: [
412
- {
413
- name: "handler",
414
- type: "pubkey",
415
- },
416
- {
417
- name: "readOnlyLen",
418
- type: "u8",
419
- },
420
- {
421
- name: "valueAmount",
422
- type: "u64",
423
- },
424
- {
425
- name: "accounts",
426
- type: {
427
- vec: "pubkey",
428
- },
429
- },
430
- {
431
- name: "handlerMessage",
432
- type: "bytes",
433
- },
434
- ],
435
- },
436
- },
437
- ];
438
- // Helper to send instructions using Address Lookup Table (ALT) for large number of accounts.
439
- async function sendTransactionWithLookupTable(connection, instructions, sender) {
440
- // Maximum number of accounts that can be added to Address Lookup Table (ALT) in a single transaction.
441
- const maxExtendedAccounts = 30;
442
- // Consolidate addresses from all instructions into a single array for the ALT.
443
- const lookupAddresses = Array.from(new Set(instructions.flatMap((instruction) => [
444
- instruction.programId,
445
- ...instruction.keys.map((accountMeta) => accountMeta.pubkey),
446
- ])));
447
- // Create instructions for creating and extending the ALT.
448
- const [lookupTableInstruction, lookupTableAddress] = await web3_js_1.AddressLookupTableProgram.createLookupTable({
449
- authority: sender.publicKey,
450
- payer: sender.publicKey,
451
- recentSlot: await connection.getSlot(),
452
- });
453
- // Submit the ALT creation transaction
454
- await anchor_1.web3.sendAndConfirmTransaction(connection, new anchor_1.web3.Transaction().add(lookupTableInstruction), [sender], {
455
- skipPreflight: true, // Avoids recent slot mismatch in simulation.
456
- });
457
- // Extend the ALT with all accounts making sure not to exceed the maximum number of accounts per transaction.
458
- for (let i = 0; i < lookupAddresses.length; i += maxExtendedAccounts) {
459
- const extendInstruction = web3_js_1.AddressLookupTableProgram.extendLookupTable({
460
- lookupTable: lookupTableAddress,
461
- authority: sender.publicKey,
462
- payer: sender.publicKey,
463
- addresses: lookupAddresses.slice(i, i + maxExtendedAccounts),
464
- });
465
- await anchor_1.web3.sendAndConfirmTransaction(connection, new anchor_1.web3.Transaction().add(extendInstruction), [sender], {
466
- skipPreflight: true, // Avoids recent slot mismatch in simulation.
467
- });
468
- }
469
- // Avoids invalid ALT index as ALT might not be active yet on the following tx.
470
- await new Promise((resolve) => setTimeout(resolve, 1000));
471
- // Fetch the AddressLookupTableAccount
472
- const lookupTableAccount = (await connection.getAddressLookupTable(lookupTableAddress)).value;
473
- if (lookupTableAccount === null)
474
- throw new Error("AddressLookupTableAccount not fetched");
475
- // Create the versioned transaction
476
- const versionedTx = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({
477
- payerKey: sender.publicKey,
478
- recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
479
- instructions,
480
- }).compileToV0Message([lookupTableAccount]));
481
- // Sign and submit the versioned transaction.
482
- versionedTx.sign([sender]);
483
- const txSignature = await connection.sendTransaction(versionedTx);
484
- return { txSignature, lookupTableAddress };
485
- }
486
- function hashNonEmptyMessage(message) {
487
- if (message.length > 0) {
488
- const hash = ethers_1.ethers.utils.keccak256(message);
489
- return Uint8Array.from(Buffer.from(hash.slice(2), "hex"));
490
- }
491
- // else return zeroed bytes32
492
- return new Uint8Array(32);
493
- }
494
- function strPublicKey(publicKey) {
495
- return new web3_js_1.PublicKey(publicKey).toString();
496
- }