@across-protocol/sdk 4.3.70 → 4.3.72

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.
@@ -58,7 +58,6 @@ import {
58
58
  chainIsProd,
59
59
  chainIsSvm,
60
60
  chunk,
61
- delay,
62
61
  getMessageHash,
63
62
  isDefined,
64
63
  isUnsafeDepositId,
@@ -87,7 +86,7 @@ import {
87
86
  } from "./";
88
87
  import { SvmCpiEventsClient } from "./eventsClient";
89
88
  import { SVM_LONG_TERM_STORAGE_SLOT_SKIPPED, SVM_SLOT_SKIPPED, isSolanaError } from "./provider";
90
- import { AttestedCCTPMessage, SVMEventNames, SVMProvider } from "./types";
89
+ import { AttestedCCTPMessage, SVMEventNames, SVMProvider, LatestBlockhash } from "./types";
91
90
  import {
92
91
  getEmergencyDeleteRootBundleRootBundleId,
93
92
  getNearestSlotTime,
@@ -1261,21 +1260,18 @@ export async function getFillRelayDelegatePda(
1261
1260
  * @param nonce The nonce to check.
1262
1261
  * @param sourceDomain The source domain.
1263
1262
  * @returns True if the message has been processed, false otherwise.
1263
+ * @dev This function intentionally does not have error handling for `getCCTPNoncePda` nor `simulateAndDecode` since
1264
+ * the error handling would have to account for the asynchronous opening/closing of PDAs, which is better handled downstream,
1265
+ * where the caller of this function has more context.
1264
1266
  */
1265
1267
  export const hasCCTPV1MessageBeenProcessed = async (
1266
1268
  solanaClient: SVMProvider,
1267
1269
  signer: KeyPairSigner,
1268
1270
  nonce: number,
1269
1271
  sourceDomain: number,
1270
- nRetries: number = 0,
1271
- maxRetries: number = 2
1272
+ latestBlockhash?: LatestBlockhash
1272
1273
  ): Promise<boolean> => {
1273
- let noncePda: Address;
1274
- try {
1275
- noncePda = await getCCTPNoncePda(solanaClient, signer, nonce, sourceDomain);
1276
- } catch (e) {
1277
- return false;
1278
- }
1274
+ const noncePda = await getCCTPNoncePda(solanaClient, signer, nonce, sourceDomain);
1279
1275
  const isNonceUsedIx = MessageTransmitterClient.getIsNonceUsedInstruction({
1280
1276
  nonce: nonce,
1281
1277
  usedNonces: noncePda,
@@ -1286,19 +1282,7 @@ export const hasCCTPV1MessageBeenProcessed = async (
1286
1282
  }
1287
1283
  return Boolean(buf[0]);
1288
1284
  };
1289
- // If the nonce PDA was found, we should be able to query the isNonceUsed parameter. If we can't then assume it is a transient RPC error
1290
- // and retry, and throw if the error persists.
1291
- try {
1292
- return await simulateAndDecode(solanaClient, isNonceUsedIx, signer, parserFunction);
1293
- } catch (e) {
1294
- if (nRetries < maxRetries) {
1295
- const delaySeconds = 2 ** nRetries + Math.random();
1296
- await delay(delaySeconds);
1297
-
1298
- return hasCCTPV1MessageBeenProcessed(solanaClient, signer, nonce, sourceDomain, ++nRetries);
1299
- }
1300
- throw e;
1301
- }
1285
+ return await simulateAndDecode(solanaClient, isNonceUsedIx, signer, parserFunction, latestBlockhash);
1302
1286
  };
1303
1287
 
1304
1288
  /**
@@ -9,6 +9,7 @@ import {
9
9
  SlotNotificationsApi,
10
10
  SolanaRpcApiFromTransport,
11
11
  UnixTimestamp,
12
+ type Blockhash,
12
13
  } from "@solana/kit";
13
14
 
14
15
  export type EventData =
@@ -69,3 +70,8 @@ export type AttestedCCTPMessage = {
69
70
  attestation: string;
70
71
  type: "transfer" | "message";
71
72
  };
73
+
74
+ export type LatestBlockhash = {
75
+ blockhash: Blockhash;
76
+ lastValidBlockHeight: bigint;
77
+ };
@@ -26,7 +26,7 @@ import { ethers } from "ethers";
26
26
  import { FillType, RelayData, RelayDataWithMessageHash } from "../../interfaces";
27
27
  import { BigNumber, Address as SdkAddress, biMin, getMessageHash, isDefined, isUint8Array } from "../../utils";
28
28
  import { getTimestampForSlot, getSlot, getRelayDataHash } from "./SpokeUtils";
29
- import { AttestedCCTPMessage, EventName, SVMEventNames, SVMProvider } from "./types";
29
+ import { AttestedCCTPMessage, EventName, SVMEventNames, SVMProvider, LatestBlockhash } from "./types";
30
30
  import winston from "winston";
31
31
 
32
32
  export { isSolanaError } from "@solana/kit";
@@ -397,12 +397,16 @@ export function getRandomSvmAddress() {
397
397
  * @param signer - The signer of the transaction.
398
398
  * @returns The default transaction.
399
399
  */
400
- export const createDefaultTransaction = async (rpcClient: SVMProvider, signer: TransactionSigner) => {
401
- const { value: latestBlockhash } = await rpcClient.getLatestBlockhash().send();
400
+ export const createDefaultTransaction = async (
401
+ rpcClient: SVMProvider,
402
+ signer: TransactionSigner,
403
+ latestBlockhash?: LatestBlockhash
404
+ ) => {
405
+ latestBlockhash = isDefined(latestBlockhash) ? latestBlockhash : (await rpcClient.getLatestBlockhash().send()).value;
402
406
  return pipe(
403
407
  createTransactionMessage({ version: 0 }),
404
408
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
405
- (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
409
+ (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash!, tx)
406
410
  );
407
411
  };
408
412
 
@@ -418,9 +422,13 @@ export const simulateAndDecode = async <P extends (buf: Buffer) => unknown>(
418
422
  solanaClient: SVMProvider,
419
423
  ix: IInstruction,
420
424
  signer: KeyPairSigner,
421
- parser: P
425
+ parser: P,
426
+ latestBlockhash?: LatestBlockhash
422
427
  ): Promise<ReturnType<P>> => {
423
- const simulationTx = appendTransactionMessageInstruction(ix, await createDefaultTransaction(solanaClient, signer));
428
+ const simulationTx = appendTransactionMessageInstruction(
429
+ ix,
430
+ await createDefaultTransaction(solanaClient, signer, latestBlockhash)
431
+ );
424
432
 
425
433
  const simulationResult = await solanaClient
426
434
  .simulateTransaction(getBase64EncodedWireTransaction(await signTransactionMessageWithSigners(simulationTx)), {
@@ -470,7 +478,8 @@ export const getCCTPNoncePda = async (
470
478
  solanaClient: SVMProvider,
471
479
  signer: KeyPairSigner,
472
480
  nonce: number,
473
- sourceDomain: number
481
+ sourceDomain: number,
482
+ latestBlockhash?: LatestBlockhash
474
483
  ) => {
475
484
  const [messageTransmitterPda] = await getProgramDerivedAddress({
476
485
  programAddress: MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
@@ -489,7 +498,7 @@ export const getCCTPNoncePda = async (
489
498
  throw new Error("Invalid buffer");
490
499
  };
491
500
 
492
- return await simulateAndDecode(solanaClient, getNonceIx, signer, parserFunction);
501
+ return await simulateAndDecode(solanaClient, getNonceIx, signer, parserFunction, latestBlockhash);
493
502
  };
494
503
 
495
504
  /**
@@ -108,7 +108,7 @@ function _getEthersGasPriceEstimate(
108
108
  [CHAIN_IDs.ARBITRUM]: arbitrum.eip1559,
109
109
  [CHAIN_IDs.BSC]: ethereum.legacy,
110
110
  [CHAIN_IDs.MAINNET]: ethereum.eip1559,
111
- // [CHAIN_IDs.PLASMA]: ethereum.eip1559, @todo: Pending RPC support
111
+ [CHAIN_IDs.PLASMA]: ethereum.eip1559,
112
112
  [CHAIN_IDs.POLYGON]: polygon.gasStation,
113
113
  [CHAIN_IDs.SCROLL]: ethereum.legacy,
114
114
  [CHAIN_IDs.ZK_SYNC]: ethereum.legacy,