@across-protocol/sdk 4.3.71 → 4.3.73

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 (62) hide show
  1. package/dist/cjs/arch/svm/SpokeUtils.d.ts +2 -2
  2. package/dist/cjs/arch/svm/SpokeUtils.js +3 -3
  3. package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
  4. package/dist/cjs/arch/svm/provider.d.ts +12 -1
  5. package/dist/cjs/arch/svm/provider.js +17 -6
  6. package/dist/cjs/arch/svm/provider.js.map +1 -1
  7. package/dist/cjs/arch/svm/types.d.ts +5 -1
  8. package/dist/cjs/arch/svm/types.js.map +1 -1
  9. package/dist/cjs/arch/svm/utils.d.ts +4 -5
  10. package/dist/cjs/arch/svm/utils.js +19 -14
  11. package/dist/cjs/arch/svm/utils.js.map +1 -1
  12. package/dist/cjs/providers/solana/quorumFallbackRpcFactory.d.ts +1 -1
  13. package/dist/cjs/providers/solana/quorumFallbackRpcFactory.js +7 -3
  14. package/dist/cjs/providers/solana/quorumFallbackRpcFactory.js.map +1 -1
  15. package/dist/cjs/providers/solana/retryRpcFactory.d.ts +1 -2
  16. package/dist/cjs/providers/solana/retryRpcFactory.js +4 -16
  17. package/dist/cjs/providers/solana/retryRpcFactory.js.map +1 -1
  18. package/dist/cjs/providers/solana/utils.d.ts +1 -0
  19. package/dist/cjs/providers/solana/utils.js +15 -0
  20. package/dist/cjs/providers/solana/utils.js.map +1 -1
  21. package/dist/esm/arch/svm/SpokeUtils.d.ts +2 -2
  22. package/dist/esm/arch/svm/SpokeUtils.js +3 -3
  23. package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
  24. package/dist/esm/arch/svm/provider.d.ts +28 -1
  25. package/dist/esm/arch/svm/provider.js +29 -1
  26. package/dist/esm/arch/svm/provider.js.map +1 -1
  27. package/dist/esm/arch/svm/types.d.ts +5 -1
  28. package/dist/esm/arch/svm/types.js.map +1 -1
  29. package/dist/esm/arch/svm/utils.d.ts +4 -5
  30. package/dist/esm/arch/svm/utils.js +18 -12
  31. package/dist/esm/arch/svm/utils.js.map +1 -1
  32. package/dist/esm/providers/solana/quorumFallbackRpcFactory.d.ts +1 -1
  33. package/dist/esm/providers/solana/quorumFallbackRpcFactory.js +8 -3
  34. package/dist/esm/providers/solana/quorumFallbackRpcFactory.js.map +1 -1
  35. package/dist/esm/providers/solana/retryRpcFactory.d.ts +1 -8
  36. package/dist/esm/providers/solana/retryRpcFactory.js +4 -24
  37. package/dist/esm/providers/solana/retryRpcFactory.js.map +1 -1
  38. package/dist/esm/providers/solana/utils.d.ts +7 -0
  39. package/dist/esm/providers/solana/utils.js +22 -1
  40. package/dist/esm/providers/solana/utils.js.map +1 -1
  41. package/dist/types/arch/svm/SpokeUtils.d.ts +2 -2
  42. package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
  43. package/dist/types/arch/svm/provider.d.ts +28 -1
  44. package/dist/types/arch/svm/provider.d.ts.map +1 -1
  45. package/dist/types/arch/svm/types.d.ts +5 -1
  46. package/dist/types/arch/svm/types.d.ts.map +1 -1
  47. package/dist/types/arch/svm/utils.d.ts +4 -5
  48. package/dist/types/arch/svm/utils.d.ts.map +1 -1
  49. package/dist/types/providers/solana/quorumFallbackRpcFactory.d.ts +1 -1
  50. package/dist/types/providers/solana/quorumFallbackRpcFactory.d.ts.map +1 -1
  51. package/dist/types/providers/solana/retryRpcFactory.d.ts +1 -8
  52. package/dist/types/providers/solana/retryRpcFactory.d.ts.map +1 -1
  53. package/dist/types/providers/solana/utils.d.ts +7 -0
  54. package/dist/types/providers/solana/utils.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/arch/svm/SpokeUtils.ts +5 -4
  57. package/src/arch/svm/provider.ts +46 -1
  58. package/src/arch/svm/types.ts +6 -0
  59. package/src/arch/svm/utils.ts +17 -11
  60. package/src/providers/solana/quorumFallbackRpcFactory.ts +10 -4
  61. package/src/providers/solana/retryRpcFactory.ts +5 -27
  62. package/src/providers/solana/utils.ts +24 -0
@@ -26,11 +26,8 @@ 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
-
32
- export { isSolanaError } from "@solana/kit";
33
-
34
31
  /**
35
32
  * Basic void TransactionSigner type
36
33
  */
@@ -397,12 +394,16 @@ export function getRandomSvmAddress() {
397
394
  * @param signer - The signer of the transaction.
398
395
  * @returns The default transaction.
399
396
  */
400
- export const createDefaultTransaction = async (rpcClient: SVMProvider, signer: TransactionSigner) => {
401
- const { value: latestBlockhash } = await rpcClient.getLatestBlockhash().send();
397
+ export const createDefaultTransaction = async (
398
+ rpcClient: SVMProvider,
399
+ signer: TransactionSigner,
400
+ latestBlockhash?: LatestBlockhash
401
+ ) => {
402
+ latestBlockhash = isDefined(latestBlockhash) ? latestBlockhash : (await rpcClient.getLatestBlockhash().send()).value;
402
403
  return pipe(
403
404
  createTransactionMessage({ version: 0 }),
404
405
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
405
- (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
406
+ (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash!, tx)
406
407
  );
407
408
  };
408
409
 
@@ -418,9 +419,13 @@ export const simulateAndDecode = async <P extends (buf: Buffer) => unknown>(
418
419
  solanaClient: SVMProvider,
419
420
  ix: IInstruction,
420
421
  signer: KeyPairSigner,
421
- parser: P
422
+ parser: P,
423
+ latestBlockhash?: LatestBlockhash
422
424
  ): Promise<ReturnType<P>> => {
423
- const simulationTx = appendTransactionMessageInstruction(ix, await createDefaultTransaction(solanaClient, signer));
425
+ const simulationTx = appendTransactionMessageInstruction(
426
+ ix,
427
+ await createDefaultTransaction(solanaClient, signer, latestBlockhash)
428
+ );
424
429
 
425
430
  const simulationResult = await solanaClient
426
431
  .simulateTransaction(getBase64EncodedWireTransaction(await signTransactionMessageWithSigners(simulationTx)), {
@@ -470,7 +475,8 @@ export const getCCTPNoncePda = async (
470
475
  solanaClient: SVMProvider,
471
476
  signer: KeyPairSigner,
472
477
  nonce: number,
473
- sourceDomain: number
478
+ sourceDomain: number,
479
+ latestBlockhash?: LatestBlockhash
474
480
  ) => {
475
481
  const [messageTransmitterPda] = await getProgramDerivedAddress({
476
482
  programAddress: MessageTransmitterClient.MESSAGE_TRANSMITTER_PROGRAM_ADDRESS,
@@ -489,7 +495,7 @@ export const getCCTPNoncePda = async (
489
495
  throw new Error("Invalid buffer");
490
496
  };
491
497
 
492
- return await simulateAndDecode(solanaClient, getNonceIx, signer, parserFunction);
498
+ return await simulateAndDecode(solanaClient, getNonceIx, signer, parserFunction, latestBlockhash);
493
499
  };
494
500
 
495
501
  /**
@@ -1,9 +1,10 @@
1
+ import { Logger } from "winston";
1
2
  import { RpcFromTransport, RpcResponse, RpcTransport, SolanaRpcApiFromTransport } from "@solana/kit";
2
- import { CachedSolanaRpcFactory } from "./cachedRpcFactory";
3
- import { SolanaBaseRpcFactory, SolanaClusterRpcFactory } from "./baseRpcFactories";
4
3
  import { isPromiseFulfilled, isPromiseRejected } from "../../utils/TypeGuards";
5
4
  import { compareSvmRpcResults, createSendErrorWithMessage } from "../utils";
6
- import { Logger } from "winston";
5
+ import { CachedSolanaRpcFactory } from "./cachedRpcFactory";
6
+ import { SolanaBaseRpcFactory, SolanaClusterRpcFactory } from "./baseRpcFactories";
7
+ import { shouldFailImmediate } from "./utils";
7
8
 
8
9
  // This factory stores multiple Cached RPC factories so that users of this factory can specify multiple RPC providers
9
10
  // and the factory will fallback through them if any RPC calls fail. This factory also implements quorum logic amongst
@@ -64,13 +65,18 @@ export class QuorumFallbackSolanaRpcFactory extends SolanaBaseRpcFactory {
64
65
  throw error;
65
66
  }
66
67
 
68
+ // If one RPC provider reverted, others likely will too. Skip them.
69
+ if (quorumThreshold === 1 && shouldFailImmediate(method, error)) {
70
+ throw error;
71
+ }
72
+
67
73
  const currentFactory = factory.rpcFactory.clusterUrl;
68
74
  const nextFactory = fallbackFactories.shift()!;
69
75
  this.logger.debug({
70
76
  at: "FallbackSolanaRpcFactory#createTransport::tryWithFallback",
71
77
  message: `[${method}] ${currentFactory} failed, falling back to ${nextFactory.rpcFactory.clusterUrl}, new fallback providers length: ${fallbackFactories.length}`,
72
78
  method,
73
- error,
79
+ jsonError: error,
74
80
  });
75
81
  return tryWithFallback(nextFactory, ...args);
76
82
  });
@@ -1,10 +1,11 @@
1
+ import { Logger } from "winston";
1
2
  import { RpcTransport, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR } from "@solana/kit";
2
3
  import { getThrowSolanaErrorResponseTransformer } from "@solana/rpc-transformers";
4
+ import { isSolanaError } from "../../arch/svm";
5
+ import { delay } from "../../utils";
3
6
  import { SolanaClusterRpcFactory } from "./baseRpcFactories";
4
7
  import { RateLimitedSolanaRpcFactory } from "./rateLimitedRpcFactory";
5
- import { isSolanaError, SVM_SLOT_SKIPPED, SVM_LONG_TERM_STORAGE_SLOT_SKIPPED } from "../../arch/svm";
6
- import { delay } from "../../utils";
7
- import { Logger } from "winston";
8
+ import { shouldFailImmediate } from "./utils";
8
9
 
9
10
  // This factory adds retry logic on top of the RateLimitedSolanaRpcFactory.
10
11
  // It follows the same composition pattern as other factories in this module.
@@ -67,7 +68,7 @@ export class RetrySolanaRpcFactory extends SolanaClusterRpcFactory {
67
68
  getThrowSolanaErrorResponseTransformer()(response, { methodName: method, params });
68
69
  return response;
69
70
  } catch (error) {
70
- if (retryAttempt++ >= this.retries || this.shouldFailImmediate(method, error)) {
71
+ if (retryAttempt++ >= this.retries || shouldFailImmediate(method, error)) {
71
72
  throw error;
72
73
  }
73
74
 
@@ -82,29 +83,6 @@ export class RetrySolanaRpcFactory extends SolanaClusterRpcFactory {
82
83
  }
83
84
  }
84
85
 
85
- /**
86
- * Determine whether a Solana RPC error indicates an unrecoverable error that should not be retried.
87
- * @param method RPC method name
88
- * @param error Error object from the RPC call
89
- * @returns True if the request should be aborted immediately, otherwise false
90
- */
91
- private shouldFailImmediate(method: string, error: unknown): boolean {
92
- if (!isSolanaError(error)) {
93
- return false;
94
- }
95
-
96
- // JSON-RPC errors: https://www.quicknode.com/docs/solana/error-references
97
- const { __code: code } = error.context;
98
- switch (method) {
99
- case "getBlock":
100
- case "getBlockTime":
101
- // No block at the requested slot. This may not be correct for blocks > 1 year old.
102
- return [SVM_SLOT_SKIPPED, SVM_LONG_TERM_STORAGE_SLOT_SKIPPED].includes(code);
103
- default:
104
- return false;
105
- }
106
- }
107
-
108
86
  /**
109
87
  * Identify whether an error thrown was the result of an RPC provider 429 response.
110
88
  * @param error Error object from the RPC query.
@@ -1,4 +1,5 @@
1
1
  import { RpcTransport } from "@solana/rpc-spec";
2
+ import { isSolanaError, SVM_SLOT_SKIPPED, SVM_LONG_TERM_STORAGE_SLOT_SKIPPED } from "../../arch/svm";
2
3
 
3
4
  /**
4
5
  * This is the type we pass to define a Solana RPC request "task".
@@ -12,3 +13,26 @@ export interface SolanaRateLimitTask {
12
13
  resolve: (result: unknown) => void;
13
14
  reject: (err: unknown) => void;
14
15
  }
16
+
17
+ /**
18
+ * Determine whether a Solana RPC error indicates an unrecoverable error that should not be retried.
19
+ * @param method RPC method name.
20
+ * @param error Error object from the RPC call.
21
+ * @returns True if the request should be aborted immediately, otherwise false.
22
+ */
23
+ export function shouldFailImmediate(method: string, error: unknown): boolean {
24
+ if (!isSolanaError(error)) {
25
+ return false;
26
+ }
27
+
28
+ // JSON-RPC errors: https://www.quicknode.com/docs/solana/error-references
29
+ const { __code: code } = error.context;
30
+ switch (method) {
31
+ case "getBlock":
32
+ case "getBlockTime":
33
+ // No block at the requested slot. This may not be correct for blocks > 1 year old.
34
+ return [SVM_SLOT_SKIPPED, SVM_LONG_TERM_STORAGE_SLOT_SKIPPED].includes(code);
35
+ default:
36
+ return false;
37
+ }
38
+ }