@across-protocol/sdk 4.3.104 → 4.3.106-beta.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.
Files changed (41) hide show
  1. package/dist/cjs/arch/svm/SpokeUtils.d.ts +8 -1
  2. package/dist/cjs/arch/svm/SpokeUtils.js +26 -3
  3. package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
  4. package/dist/cjs/arch/svm/encoders.d.ts +1 -0
  5. package/dist/cjs/arch/svm/encoders.js +4 -0
  6. package/dist/cjs/arch/svm/encoders.js.map +1 -1
  7. package/dist/cjs/arch/svm/eventsClient.js +9 -11
  8. package/dist/cjs/arch/svm/eventsClient.js.map +1 -1
  9. package/dist/cjs/providers/solana/utils.d.ts +13 -0
  10. package/dist/cjs/providers/solana/utils.js.map +1 -1
  11. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +6 -0
  12. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +77 -27
  13. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  14. package/dist/esm/arch/svm/SpokeUtils.d.ts +27 -1
  15. package/dist/esm/arch/svm/SpokeUtils.js +44 -3
  16. package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
  17. package/dist/esm/arch/svm/encoders.d.ts +1 -0
  18. package/dist/esm/arch/svm/encoders.js +3 -0
  19. package/dist/esm/arch/svm/encoders.js.map +1 -1
  20. package/dist/esm/arch/svm/eventsClient.js +10 -12
  21. package/dist/esm/arch/svm/eventsClient.js.map +1 -1
  22. package/dist/esm/providers/solana/utils.d.ts +13 -0
  23. package/dist/esm/providers/solana/utils.js.map +1 -1
  24. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +6 -0
  25. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +82 -31
  26. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  27. package/dist/types/arch/svm/SpokeUtils.d.ts +27 -1
  28. package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
  29. package/dist/types/arch/svm/encoders.d.ts +1 -0
  30. package/dist/types/arch/svm/encoders.d.ts.map +1 -1
  31. package/dist/types/arch/svm/eventsClient.d.ts.map +1 -1
  32. package/dist/types/providers/solana/utils.d.ts +13 -0
  33. package/dist/types/providers/solana/utils.d.ts.map +1 -1
  34. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +6 -0
  35. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/src/arch/svm/SpokeUtils.ts +50 -1
  38. package/src/arch/svm/encoders.ts +4 -0
  39. package/src/arch/svm/eventsClient.ts +3 -4
  40. package/src/providers/solana/utils.ts +14 -0
  41. package/src/relayFeeCalculator/chain-queries/svmQuery.ts +80 -5
@@ -4,13 +4,27 @@ import {
4
4
  TransactionSigner,
5
5
  fetchEncodedAccount,
6
6
  isSome,
7
+ Rpc,
8
+ pipe,
9
+ appendTransactionMessageInstruction,
7
10
  } from "@solana/kit";
8
- import { SVMProvider, SolanaVoidSigner, getFillRelayTx, toAddress, getAssociatedTokenAddress } from "../../arch/svm";
11
+ import {
12
+ SVMProvider,
13
+ SolanaVoidSigner,
14
+ getFillRelayTx,
15
+ getIPFillRelayTx,
16
+ getFillRelayViaInstructionParamsInstructions,
17
+ toAddress,
18
+ createDefaultTransaction,
19
+ getAssociatedTokenAddress,
20
+ isSVMFillTooLarge,
21
+ } from "../../arch/svm";
22
+ import { JitoInterface } from "../../providers/solana";
9
23
  import { Coingecko } from "../../coingecko";
10
24
  import { CHAIN_IDs } from "../../constants";
11
25
  import { getGasPriceEstimate } from "../../gasPriceOracle";
12
26
  import { RelayData } from "../../interfaces";
13
- import { Address, BigNumber, BigNumberish, SvmAddress, TransactionCostEstimate, toBN } from "../../utils";
27
+ import { Address, BigNumber, BigNumberish, SvmAddress, TransactionCostEstimate, toBN, mapAsync } from "../../utils";
14
28
  import { Logger, QueryInterface, getDefaultRelayer } from "../relayFeeCalculator";
15
29
  import { SymbolMappingType } from "./";
16
30
  import { TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
@@ -77,15 +91,35 @@ export class SvmQuery implements QueryInterface {
77
91
  assert(relayer.isSVM());
78
92
 
79
93
  const [repaymentChainId, repaymentAddress] = [destinationChainId, relayer]; // These are not important for gas cost simulation.
80
- const fillRelayTx = await this.getFillRelayTx(
94
+
95
+ // For solana, we algorithmically estimate gas based on the size of the message.
96
+ const _fillRelayTx = await this.getFillRelayTx(
81
97
  { ...relayData, recipient, outputToken, exclusiveRelayer },
82
98
  SolanaVoidSigner(relayer.toBase58()),
83
99
  repaymentChainId,
84
100
  repaymentAddress
85
101
  );
86
102
 
87
- const [computeUnitsConsumed, gasPriceEstimate, tokenAccountInfo] = await Promise.all([
88
- toBN(await this.computeUnitEstimator(fillRelayTx)),
103
+ const fillTooLarge = isSVMFillTooLarge(_fillRelayTx);
104
+ // If the fill is too large, we need to construct a dummy fill relay transaction which estimates the priority fee of the fillRelay instruction call. To guarantee
105
+ // that the transaction won't be too large, we overwrite the message with empty bytes.
106
+ const fillRelayTx = fillTooLarge.tooLarge
107
+ ? await this.getFillRelayTx(
108
+ { ...relayData, recipient, outputToken, exclusiveRelayer, message: "0x" },
109
+ SolanaVoidSigner(relayer.toBase58()),
110
+ repaymentChainId,
111
+ repaymentAddress
112
+ )
113
+ : _fillRelayTx;
114
+ const [_computeUnitsConsumed, gasPriceEstimate, tokenAccountInfo] = await Promise.all([
115
+ fillTooLarge.tooLarge
116
+ ? this.estimateComputeUnits(
117
+ { ...relayData, recipient, outputToken, exclusiveRelayer },
118
+ relayer,
119
+ repaymentChainId,
120
+ repaymentAddress
121
+ )
122
+ : this.computeUnitEstimator(fillRelayTx),
89
123
  getGasPriceEstimate(this.provider, {
90
124
  unsignedTx: fillRelayTx,
91
125
  baseFeeMultiplier: options.baseFeeMultiplier,
@@ -93,6 +127,7 @@ export class SvmQuery implements QueryInterface {
93
127
  }),
94
128
  this.provider.getAccountInfo(toAddress(outputToken), { encoding: "base58" }).send(),
95
129
  ]);
130
+ const computeUnitsConsumed = toBN(_computeUnitsConsumed);
96
131
 
97
132
  // If the owner of the token account is not the token program, then we can assume that it is the 2022 token program address, in which
98
133
  // case we need to determine the extensions the token has to properly calculate rent exemption.
@@ -211,4 +246,44 @@ export class SvmQuery implements QueryInterface {
211
246
  if (!this.symbolMapping[tokenSymbol]) throw new Error(`${tokenSymbol} does not exist in mapping`);
212
247
  return this.symbolMapping[tokenSymbol].decimals;
213
248
  }
249
+
250
+ // The fill is too large; we need to simulate the transaction in a bundle.
251
+ async estimateComputeUnits(
252
+ relayData: RelayData & {
253
+ destinationChainId: number;
254
+ recipient: SvmAddress;
255
+ outputToken: SvmAddress;
256
+ exclusiveRelayer: SvmAddress;
257
+ },
258
+ relayer: SvmAddress,
259
+ repaymentChainId: number,
260
+ repaymentAddress: SvmAddress
261
+ ): Promise<number> {
262
+ // @dev There is no way to tell if the RPC supports the JITO interface without querying the rpc directly.
263
+ // Cast the rpc type to support JITO and attempt to call `simulateBundle`. Throw and error if it fails, since
264
+ // the transaction message cannot be simulated otherwise.
265
+ const provider = this.provider as Rpc<JitoInterface>;
266
+
267
+ const spokePoolAddr = toAddress(this.spokePool);
268
+ const voidSigner = SolanaVoidSigner(relayer.toBase58());
269
+
270
+ const [instructionParamsIxs, fillRelayTx] = await Promise.all([
271
+ getFillRelayViaInstructionParamsInstructions(
272
+ spokePoolAddr,
273
+ relayData,
274
+ repaymentChainId,
275
+ repaymentAddress,
276
+ voidSigner
277
+ ),
278
+ getIPFillRelayTx(this.spokePool, provider, relayData, voidSigner, repaymentChainId, repaymentAddress),
279
+ ]);
280
+ const instructionParamsTxs = await mapAsync(instructionParamsIxs, async (ix) => {
281
+ return pipe(await createDefaultTransaction(provider, voidSigner), (tx) =>
282
+ appendTransactionMessageInstruction(ix, tx)
283
+ );
284
+ });
285
+
286
+ const simulateBundleResponse = await provider.simulateBundle([...instructionParamsTxs, fillRelayTx]).send();
287
+ return simulateBundleResponse.result.unitsConsumed;
288
+ }
214
289
  }