@across-protocol/sdk 4.3.3 → 4.3.4

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 (71) hide show
  1. package/dist/cjs/arch/svm/SpokeUtils.d.ts +13 -5
  2. package/dist/cjs/arch/svm/SpokeUtils.js +74 -5
  3. package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
  4. package/dist/cjs/arch/svm/utils.d.ts +4 -1
  5. package/dist/cjs/arch/svm/utils.js +15 -1
  6. package/dist/cjs/arch/svm/utils.js.map +1 -1
  7. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +9 -5
  8. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  9. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
  10. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js +4 -3
  11. package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
  12. package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
  13. package/dist/cjs/interfaces/SpokePool.d.ts +18 -0
  14. package/dist/cjs/interfaces/SpokePool.js.map +1 -1
  15. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
  16. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +7 -68
  17. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  18. package/dist/cjs/utils/AddressUtils.d.ts +2 -0
  19. package/dist/cjs/utils/AddressUtils.js +4 -0
  20. package/dist/cjs/utils/AddressUtils.js.map +1 -1
  21. package/dist/cjs/utils/DepositUtils.d.ts +3 -1
  22. package/dist/cjs/utils/DepositUtils.js +9 -1
  23. package/dist/cjs/utils/DepositUtils.js.map +1 -1
  24. package/dist/esm/arch/svm/SpokeUtils.d.ts +23 -5
  25. package/dist/esm/arch/svm/SpokeUtils.js +86 -5
  26. package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
  27. package/dist/esm/arch/svm/utils.d.ts +7 -1
  28. package/dist/esm/arch/svm/utils.js +14 -0
  29. package/dist/esm/arch/svm/utils.js.map +1 -1
  30. package/dist/esm/clients/BundleDataClient/BundleDataClient.js +10 -6
  31. package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  32. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
  33. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js +5 -4
  34. package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
  35. package/dist/esm/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
  36. package/dist/esm/interfaces/SpokePool.d.ts +18 -0
  37. package/dist/esm/interfaces/SpokePool.js.map +1 -1
  38. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
  39. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +9 -73
  40. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  41. package/dist/esm/utils/AddressUtils.d.ts +2 -0
  42. package/dist/esm/utils/AddressUtils.js +4 -0
  43. package/dist/esm/utils/AddressUtils.js.map +1 -1
  44. package/dist/esm/utils/DepositUtils.d.ts +15 -1
  45. package/dist/esm/utils/DepositUtils.js +19 -1
  46. package/dist/esm/utils/DepositUtils.js.map +1 -1
  47. package/dist/types/arch/svm/SpokeUtils.d.ts +23 -5
  48. package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
  49. package/dist/types/arch/svm/utils.d.ts +7 -1
  50. package/dist/types/arch/svm/utils.d.ts.map +1 -1
  51. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
  52. package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
  53. package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts.map +1 -1
  54. package/dist/types/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
  55. package/dist/types/interfaces/SpokePool.d.ts +18 -0
  56. package/dist/types/interfaces/SpokePool.d.ts.map +1 -1
  57. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
  58. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
  59. package/dist/types/utils/AddressUtils.d.ts +2 -0
  60. package/dist/types/utils/AddressUtils.d.ts.map +1 -1
  61. package/dist/types/utils/DepositUtils.d.ts +15 -1
  62. package/dist/types/utils/DepositUtils.d.ts.map +1 -1
  63. package/package.json +2 -2
  64. package/src/arch/svm/SpokeUtils.ts +97 -6
  65. package/src/arch/svm/utils.ts +16 -0
  66. package/src/clients/BundleDataClient/BundleDataClient.ts +11 -5
  67. package/src/clients/mocks/MockSvmCpiEventsClient.ts +5 -3
  68. package/src/interfaces/SpokePool.ts +23 -0
  69. package/src/relayFeeCalculator/chain-queries/svmQuery.ts +7 -93
  70. package/src/utils/AddressUtils.ts +5 -0
  71. package/src/utils/DepositUtils.ts +49 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DepositUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/DepositUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAavH,oBAAY,WAAW;IACrB,gBAAgB,IAAI;IACpB,iBAAiB,IAAA;IACjB,YAAY,IAAA;IACZ,mBAAmB,IAAA;CACpB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;;;;;;;;;GAWG;AAEH,wBAAsB,6BAA6B,CACjD,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,IAAI,GAAG,eAAe,EAC5B,KAAK,CAAC,EAAE,yBAAyB,GAChC,OAAO,CAAC,mBAAmB,CAAC,CAkF9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,GACrF,MAAM,CAkBR;AAoBD,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,EAC3F,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,GAAG,aAAa,CAAC,GAC1E;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAkBpD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,CAAC,GAAG,OAAO,CAE/F;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,OAAO,CAGnF;AAED,wBAAgB,gCAAgC,CAC9C,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,eAAe,EAAE,aAAa,GAAG,aAAa,CAAC,GAC7D,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAgB,GAAG,OAAO,CAE/D;AAED,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI9D"}
1
+ {"version":3,"file":"DepositUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/DepositUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EACL,yBAAyB,EACzB,OAAO,EACP,gBAAgB,EAChB,IAAI,EACJ,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AAavB,oBAAY,WAAW;IACrB,gBAAgB,IAAI;IACpB,iBAAiB,IAAA;IACjB,YAAY,IAAA;IACZ,mBAAmB,IAAA;CACpB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;;;;;;;;;GAWG;AAEH,wBAAsB,6BAA6B,CACjD,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,IAAI,GAAG,eAAe,EAC5B,KAAK,CAAC,EAAE,yBAAyB,GAChC,OAAO,CAAC,mBAAmB,CAAC,CAkF9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,GACrF,MAAM,CAkBR;AAoBD,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,EAC3F,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,GAAG,aAAa,CAAC,GAC1E;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAkBpD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,CAAC,GAAG,OAAO,CAE/F;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,OAAO,CAGnF;AAED,wBAAgB,gCAAgC,CAC9C,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,eAAe,EAAE,aAAa,GAAG,aAAa,CAAC,GAC7D,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAgB,GAAG,OAAO,CAE/D;AAED,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI9D;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,SAAS,GAAG,kBAAkB,CASxF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,aAAa,CAcpE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@across-protocol/sdk",
3
3
  "author": "UMA Team",
4
- "version": "4.3.3",
4
+ "version": "4.3.4",
5
5
  "license": "AGPL-3.0",
6
6
  "homepage": "https://docs.across.to/reference/sdk",
7
7
  "files": [
@@ -106,7 +106,7 @@
106
106
  "dependencies": {
107
107
  "@across-protocol/across-token": "^1.0.0",
108
108
  "@across-protocol/constants": "^3.1.68",
109
- "@across-protocol/contracts": "^4.0.12",
109
+ "@across-protocol/contracts": "^4.1.0",
110
110
  "@coral-xyz/anchor": "^0.30.1",
111
111
  "@eth-optimism/sdk": "^3.3.1",
112
112
  "@ethersproject/bignumber": "^5.7.0",
@@ -1,5 +1,6 @@
1
1
  import { SvmSpokeClient } from "@across-protocol/contracts";
2
2
  import { decodeFillStatusAccount, fetchState } from "@across-protocol/contracts/dist/src/svm/clients/SvmSpoke";
3
+ import { intToU8Array32 } from "@across-protocol/contracts/dist/src/svm/web3-v1/conversionUtils";
3
4
  import { hashNonEmptyMessage } from "@across-protocol/contracts/dist/src/svm/web3-v1";
4
5
  import {
5
6
  ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
@@ -18,6 +19,7 @@ import {
18
19
  getU32Encoder,
19
20
  getU64Encoder,
20
21
  pipe,
22
+ ReadonlyUint8Array,
21
23
  some,
22
24
  type TransactionSigner,
23
25
  } from "@solana/kit";
@@ -39,6 +41,7 @@ import {
39
41
  } from "../../utils";
40
42
  import {
41
43
  SvmCpiEventsClient,
44
+ bigToU8a32,
42
45
  createDefaultTransaction,
43
46
  getEventAuthority,
44
47
  getFillStatusPda,
@@ -447,7 +450,7 @@ export async function fillRelayInstruction(
447
450
  exclusiveRelayer,
448
451
  inputToken,
449
452
  outputToken,
450
- inputAmount: relayData.inputAmount.toBigInt(),
453
+ inputAmount: bigToU8a32(relayData.inputAmount.toBigInt()),
451
454
  outputAmount: relayData.outputAmount.toBigInt(),
452
455
  originChainId: BigInt(relayData.originChainId),
453
456
  fillDeadline: relayData.fillDeadline,
@@ -475,6 +478,94 @@ export function createTokenAccountsInstruction(
475
478
  });
476
479
  }
477
480
 
481
+ /**
482
+ * @notice Return the fillRelay transaction for a given deposit
483
+ * @param spokePoolAddr Address of the spoke pool we're trying to fill through
484
+ * @param solanaClient RPC client to interact with Solana chain
485
+ * @param relayData RelayData instance, supplemented with destinationChainId
486
+ * @param signer signer associated with the relayer creating a Fill. Can be VoidSigner for gas estimation
487
+ * @param repaymentChainId Chain id where relayer repayment is desired
488
+ * @param repaymentAddress Address to which repayment will go to on repaymentChainId
489
+ * @returns FillRelay transaction
490
+ */
491
+ export async function getFillRelayTx(
492
+ spokePoolAddr: SvmAddress,
493
+ solanaClient: SVMProvider,
494
+ relayData: Omit<RelayData, "recipent" | "outputToken"> & {
495
+ destinationChainId: number;
496
+ recipient: SvmAddress;
497
+ outputToken: SvmAddress;
498
+ },
499
+ signer: TransactionSigner,
500
+ repaymentChainId: number,
501
+ repaymentAddress: SdkAddress
502
+ ) {
503
+ const { depositor, recipient, inputToken, outputToken, exclusiveRelayer, destinationChainId } = relayData;
504
+
505
+ // tsc appeasement...should be unnecessary, but isn't. @todo Identify why.
506
+ assert(recipient.isSVM(), `getFillRelayTx: recipient not an SVM address (${recipient})`);
507
+ assert(
508
+ repaymentAddress.isValidOn(repaymentChainId),
509
+ `getFillRelayTx: repayment address ${repaymentAddress} not valid on chain ${repaymentChainId})`
510
+ );
511
+
512
+ const program = toAddress(spokePoolAddr);
513
+ const _relayDataHash = getRelayDataHash(relayData, destinationChainId);
514
+ const relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
515
+
516
+ const [state, delegate] = await Promise.all([
517
+ getStatePda(program),
518
+ getFillRelayDelegatePda(relayDataHash, BigInt(repaymentChainId), toAddress(repaymentAddress), program),
519
+ ]);
520
+
521
+ const mint = toAddress(outputToken);
522
+ const mintInfo = await fetchMint(solanaClient, mint);
523
+
524
+ const [recipientAta, relayerAta, fillStatus, eventAuthority] = await Promise.all([
525
+ getAssociatedTokenAddress(recipient, outputToken, mintInfo.programAddress),
526
+ getAssociatedTokenAddress(SvmAddress.from(signer.address), outputToken, mintInfo.programAddress),
527
+ getFillStatusPda(program, relayData, destinationChainId),
528
+ getEventAuthority(program),
529
+ ]);
530
+
531
+ const svmRelayData: SvmSpokeClient.FillRelayInput["relayData"] = {
532
+ depositor: toAddress(depositor),
533
+ recipient: toAddress(recipient),
534
+ exclusiveRelayer: toAddress(exclusiveRelayer),
535
+ inputToken: toAddress(inputToken),
536
+ outputToken: mint,
537
+ inputAmount: bigToU8a32(relayData.inputAmount.toBigInt()),
538
+ outputAmount: relayData.outputAmount.toBigInt(),
539
+ originChainId: relayData.originChainId,
540
+ depositId: new Uint8Array(intToU8Array32(relayData.depositId.toNumber())),
541
+ fillDeadline: relayData.fillDeadline,
542
+ exclusivityDeadline: relayData.exclusivityDeadline,
543
+ message: new Uint8Array(Buffer.from(relayData.message, "hex")),
544
+ };
545
+
546
+ const fillInput: SvmSpokeClient.FillRelayInput = {
547
+ signer: signer,
548
+ state,
549
+ delegate,
550
+ mint,
551
+ relayerTokenAccount: relayerAta,
552
+ recipientTokenAccount: recipientAta,
553
+ fillStatus,
554
+ tokenProgram: mintInfo.programAddress,
555
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
556
+ systemProgram: SYSTEM_PROGRAM_ADDRESS,
557
+ eventAuthority,
558
+ program,
559
+ relayHash: relayDataHash,
560
+ relayData: svmRelayData,
561
+ repaymentChainId: BigInt(repaymentChainId),
562
+ repaymentAddress: toAddress(repaymentAddress),
563
+ };
564
+ // Pass createRecipientAtaIfNeeded =true to the createFillInstruction function to create the recipient token account
565
+ // if it doesn't exist.
566
+ return createFillInstruction(signer, solanaClient, fillInput, mintInfo.data.decimals, true);
567
+ }
568
+
478
569
  /**
479
570
  * Creates a fill instruction.
480
571
  * @param signer - The signer of the transaction.
@@ -643,7 +734,7 @@ export function getRelayDataHash(relayData: RelayData, destinationChainId: numbe
643
734
  encodeAddress(relayData.exclusiveRelayer),
644
735
  encodeAddress(relayData.inputToken),
645
736
  encodeAddress(relayData.outputToken),
646
- Uint8Array.from(uint64Encoder.encode(BigInt(relayData.inputAmount.toString()))),
737
+ arrayify(hexZeroPad(hexlify(relayData.inputAmount), 32)),
647
738
  Uint8Array.from(uint64Encoder.encode(BigInt(relayData.outputAmount.toString()))),
648
739
  Uint8Array.from(uint64Encoder.encode(BigInt(relayData.originChainId.toString()))),
649
740
  arrayify(hexZeroPad(hexlify(relayData.depositId), 32)),
@@ -751,7 +842,7 @@ export async function getDepositDelegatePda(
751
842
  inputToken: Address<string>;
752
843
  outputToken: Address<string>;
753
844
  inputAmount: bigint;
754
- outputAmount: bigint;
845
+ outputAmount: ReadonlyUint8Array;
755
846
  destinationChainId: bigint;
756
847
  exclusiveRelayer: Address<string>;
757
848
  quoteTimestamp: bigint;
@@ -771,7 +862,7 @@ export async function getDepositDelegatePda(
771
862
  Uint8Array.from(addrEnc.encode(depositData.inputToken)),
772
863
  Uint8Array.from(addrEnc.encode(depositData.outputToken)),
773
864
  Uint8Array.from(u64.encode(depositData.inputAmount)),
774
- Uint8Array.from(u64.encode(depositData.outputAmount)),
865
+ Uint8Array.from(depositData.outputAmount),
775
866
  Uint8Array.from(u64.encode(depositData.destinationChainId)),
776
867
  Uint8Array.from(addrEnc.encode(depositData.exclusiveRelayer)),
777
868
  Uint8Array.from(u32.encode(depositData.quoteTimestamp)),
@@ -801,7 +892,7 @@ export async function getDepositNowDelegatePda(
801
892
  inputToken: Address<string>;
802
893
  outputToken: Address<string>;
803
894
  inputAmount: bigint;
804
- outputAmount: bigint;
895
+ outputAmount: ReadonlyUint8Array;
805
896
  destinationChainId: bigint;
806
897
  exclusiveRelayer: Address<string>;
807
898
  fillDeadlineOffset: bigint;
@@ -820,7 +911,7 @@ export async function getDepositNowDelegatePda(
820
911
  Uint8Array.from(addrEnc.encode(depositData.inputToken)),
821
912
  Uint8Array.from(addrEnc.encode(depositData.outputToken)),
822
913
  Uint8Array.from(u64.encode(depositData.inputAmount)),
823
- Uint8Array.from(u64.encode(depositData.outputAmount)),
914
+ Uint8Array.from(depositData.outputAmount),
824
915
  Uint8Array.from(u64.encode(depositData.destinationChainId)),
825
916
  Uint8Array.from(addrEnc.encode(depositData.exclusiveRelayer)),
826
917
  Uint8Array.from(u32.encode(depositData.fillDeadlineOffset)),
@@ -311,3 +311,19 @@ export const createDefaultTransaction = async (rpcClient: SVMProvider, signer: T
311
311
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
312
312
  );
313
313
  };
314
+
315
+ /**
316
+ * Convert a bigint (0 ≤ n < 2^256) to a 32-byte Uint8Array (big-endian).
317
+ */
318
+ export function bigintToU8a32(n: bigint): Uint8Array {
319
+ if (n < BigInt(0) || n > ethers.constants.MaxUint256.toBigInt()) {
320
+ throw new RangeError("Value must fit in 256 bits");
321
+ }
322
+ const hexPadded = ethers.utils.hexZeroPad("0x" + n.toString(16), 32);
323
+ return ethers.utils.arrayify(hexPadded);
324
+ }
325
+
326
+ export const bigToU8a32 = (bn: bigint | BigNumber) =>
327
+ bigintToU8a32(typeof bn === "bigint" ? bn : BigInt(bn.toString()));
328
+
329
+ export const numberToU8a32 = (n: number) => bigintToU8a32(BigInt(n));
@@ -44,6 +44,8 @@ import {
44
44
  Address,
45
45
  getNetworkName,
46
46
  toBytes32,
47
+ convertRelayDataParamsToBytes32,
48
+ convertFillParamsToBytes32,
47
49
  } from "../../utils";
48
50
  import winston from "winston";
49
51
  import {
@@ -923,7 +925,7 @@ export class BundleDataClient {
923
925
  this.logger.debug({
924
926
  at: "BundleDataClient#loadData",
925
927
  message: "Duplicate deposit detected",
926
- deposit,
928
+ deposit: convertRelayDataParamsToBytes32(deposit),
927
929
  });
928
930
  throw new Error("Duplicate deposit detected");
929
931
  }
@@ -1052,7 +1054,7 @@ export class BundleDataClient {
1052
1054
  this.logger.debug({
1053
1055
  at: "BundleDataClient#loadData",
1054
1056
  message: "Duplicate fill detected",
1055
- fill,
1057
+ fill: convertFillParamsToBytes32(fill),
1056
1058
  });
1057
1059
  throw new Error("Duplicate fill detected");
1058
1060
  }
@@ -1604,9 +1606,13 @@ export class BundleDataClient {
1604
1606
  at: "BundleDataClient#loadData",
1605
1607
  message: "Finished loading V3 spoke pool data and found some invalid fills in range",
1606
1608
  blockRangesForChains,
1607
- invalidFillsWithPartialMatchedDeposits,
1608
- preFillsForNextBundle,
1609
- unknownReasonInvalidFills,
1609
+ invalidFillsWithPartialMatchedDeposits: invalidFillsWithPartialMatchedDeposits.map((invalidFill) =>
1610
+ convertFillParamsToBytes32(invalidFill)
1611
+ ),
1612
+ preFillsForNextBundle: preFillsForNextBundle.map((preFill) => convertFillParamsToBytes32(preFill)),
1613
+ unknownReasonInvalidFills: unknownReasonInvalidFills.map((invalidFill) =>
1614
+ convertFillParamsToBytes32(invalidFill)
1615
+ ),
1610
1616
  });
1611
1617
  }
1612
1618
 
@@ -17,6 +17,7 @@ import {
17
17
  SVMEventNames,
18
18
  SVMProvider,
19
19
  getRandomSvmAddress,
20
+ bigToU8a32,
20
21
  } from "../../arch/svm";
21
22
  import { bnZero, bnOne, bs58, getCurrentTime, randomAddress, EvmAddress, SvmAddress } from "../../utils";
22
23
  import { FillType } from "../../interfaces";
@@ -82,7 +83,7 @@ export class MockSvmCpiEventsClient extends SvmCpiEventsClient {
82
83
  const inputToken = deposit.inputToken ?? getRandomSvmAddress();
83
84
  const outputToken = deposit.outputToken ?? SvmAddress.from(randomBytes(32), "base16").toBase58();
84
85
  inputAmount ??= BigInt(random(1, 1000, false));
85
- outputAmount ??= (inputAmount * BigInt(95)) / BigInt(100);
86
+ outputAmount ??= bigToU8a32((inputAmount * BigInt(95)) / BigInt(100));
86
87
  const message = deposit.message ?? new Uint8Array(32);
87
88
  const quoteTimestamp = deposit.quoteTimestamp ?? getCurrentTime();
88
89
 
@@ -114,8 +115,9 @@ export class MockSvmCpiEventsClient extends SvmCpiEventsClient {
114
115
  const { slot } = fill;
115
116
  let { depositId, inputAmount, outputAmount, fillDeadline } = fill;
116
117
  depositId ??= arrayify(hexZeroPad(hexlify(random(1, 100_000, false)), 32));
117
- inputAmount ??= BigInt(random(1, 1000, false));
118
- outputAmount ??= (inputAmount * BigInt(95)) / BigInt(100);
118
+ const inputAmountBigInt = BigInt(random(1, 1000, false));
119
+ inputAmount ??= bigToU8a32(inputAmountBigInt);
120
+ outputAmount ??= (inputAmountBigInt * BigInt(95)) / BigInt(100);
119
121
  fillDeadline ??= getCurrentTime() + 60;
120
122
 
121
123
  const depositor = fill.depositor ?? EvmAddress.from(randomAddress()).toBase58();
@@ -18,6 +18,15 @@ export interface RelayData {
18
18
  exclusivityDeadline: number;
19
19
  }
20
20
 
21
+ export interface ConvertedRelayData
22
+ extends Omit<RelayData, "depositor" | "recipient" | "inputToken" | "outputToken" | "exclusiveRelayer"> {
23
+ depositor: string;
24
+ recipient: string;
25
+ inputToken: string;
26
+ outputToken: string;
27
+ exclusiveRelayer: string;
28
+ }
29
+
21
30
  export interface SpeedUpCommon {
22
31
  updatedRecipient: Address;
23
32
  updatedOutputAmount: BigNumber;
@@ -69,6 +78,20 @@ export interface Fill extends Omit<RelayData, "message"> {
69
78
  relayExecutionInfo: RelayExecutionEventInfo;
70
79
  }
71
80
 
81
+ export interface ConvertedFill
82
+ extends Omit<
83
+ Fill,
84
+ "depositor" | "recipient" | "inputToken" | "outputToken" | "exclusiveRelayer" | "relayer" | "relayExecutionInfo"
85
+ > {
86
+ depositor: string;
87
+ recipient: string;
88
+ inputToken: string;
89
+ outputToken: string;
90
+ exclusiveRelayer: string;
91
+ relayer: string;
92
+ relayExecutionInfo: Omit<RelayExecutionEventInfo, "updatedRecipient"> & { updatedRecipient: string };
93
+ }
94
+
72
95
  export interface FillWithBlock extends Fill, SortableEvent {}
73
96
  export interface FillWithTime extends Fill, SortableEvent {
74
97
  fillTimestamp: number;
@@ -1,33 +1,11 @@
1
1
  import assert from "assert";
2
- import { SvmSpokeClient } from "@across-protocol/contracts";
3
- import { intToU8Array32 } from "@across-protocol/contracts/dist/src/svm/web3-v1/conversionUtils";
4
- import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
5
- import { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, fetchMint } from "@solana-program/token";
6
- import { getComputeUnitEstimateForTransactionMessageFactory } from "@solana/kit";
7
- import {
8
- SVMProvider,
9
- SolanaVoidSigner,
10
- createFillInstruction,
11
- getAssociatedTokenAddress,
12
- getEventAuthority,
13
- getFillRelayDelegatePda,
14
- getFillStatusPda,
15
- getStatePda,
16
- toAddress,
17
- } from "../../arch/svm";
2
+ import { getComputeUnitEstimateForTransactionMessageFactory, TransactionSigner } from "@solana/kit";
3
+ import { SVMProvider, SolanaVoidSigner, getFillRelayTx } from "../../arch/svm";
18
4
  import { Coingecko } from "../../coingecko";
19
5
  import { CHAIN_IDs } from "../../constants";
20
6
  import { getGasPriceEstimate } from "../../gasPriceOracle";
21
7
  import { RelayData } from "../../interfaces";
22
- import {
23
- Address,
24
- BigNumber,
25
- BigNumberish,
26
- SvmAddress,
27
- TransactionCostEstimate,
28
- getRelayDataHash,
29
- toBN,
30
- } from "../../utils";
8
+ import { Address, BigNumber, BigNumberish, SvmAddress, TransactionCostEstimate, toBN } from "../../utils";
31
9
  import { Logger, QueryInterface, getDefaultRelayer } from "../relayFeeCalculator";
32
10
  import { SymbolMappingType } from "./";
33
11
 
@@ -93,7 +71,7 @@ export class SvmQuery implements QueryInterface {
93
71
  const [repaymentChainId, repaymentAddress] = [destinationChainId, relayer]; // These are not important for gas cost simulation.
94
72
  const fillRelayTx = await this.getFillRelayTx(
95
73
  { ...relayData, recipient, outputToken, exclusiveRelayer },
96
- relayer,
74
+ SolanaVoidSigner(relayer.toBase58()),
97
75
  repaymentChainId,
98
76
  repaymentAddress
99
77
  );
@@ -139,7 +117,7 @@ export class SvmQuery implements QueryInterface {
139
117
  const [repaymentChainId, repaymentAddress] = [destinationChainId, relayer]; // These are not important for gas cost simulation.
140
118
  const fillRelayTx = await this.getFillRelayTx(
141
119
  { ...deposit, recipient, outputToken, exclusiveRelayer },
142
- relayer,
120
+ SolanaVoidSigner(relayer.toBase58()),
143
121
  repaymentChainId,
144
122
  repaymentAddress
145
123
  );
@@ -158,75 +136,11 @@ export class SvmQuery implements QueryInterface {
158
136
  recipient: SvmAddress;
159
137
  outputToken: SvmAddress;
160
138
  },
161
- relayer: SvmAddress,
139
+ signer: TransactionSigner,
162
140
  repaymentChainId: number,
163
141
  repaymentAddress: Address
164
142
  ) {
165
- const { depositor, recipient, inputToken, outputToken, exclusiveRelayer, destinationChainId } = relayData;
166
-
167
- // tsc appeasement...should be unnecessary, but isn't. @todo Identify why.
168
- assert(recipient.isSVM(), `getFillRelayTx: recipient not an SVM address (${recipient})`);
169
- assert(
170
- repaymentAddress.isValidOn(repaymentChainId),
171
- `getFillRelayTx: repayment address ${repaymentAddress} not valid on chain ${repaymentChainId})`
172
- );
173
-
174
- const program = toAddress(this.spokePool);
175
- const _relayDataHash = getRelayDataHash(relayData, destinationChainId);
176
- const relayDataHash = new Uint8Array(Buffer.from(_relayDataHash.slice(2), "hex"));
177
-
178
- const [state, delegate] = await Promise.all([
179
- getStatePda(program),
180
- getFillRelayDelegatePda(relayDataHash, BigInt(repaymentChainId), toAddress(repaymentAddress), program),
181
- ]);
182
-
183
- const mint = toAddress(outputToken);
184
- const mintInfo = await fetchMint(this.provider, mint);
185
-
186
- const [recipientAta, relayerAta, fillStatus, eventAuthority] = await Promise.all([
187
- getAssociatedTokenAddress(recipient, outputToken, mintInfo.programAddress),
188
- getAssociatedTokenAddress(SvmAddress.from(relayer.toBase58()), outputToken, mintInfo.programAddress),
189
- getFillStatusPda(program, relayData, destinationChainId),
190
- getEventAuthority(program),
191
- ]);
192
-
193
- const svmRelayData: SvmSpokeClient.FillRelayInput["relayData"] = {
194
- depositor: toAddress(depositor),
195
- recipient: toAddress(recipient),
196
- exclusiveRelayer: toAddress(exclusiveRelayer),
197
- inputToken: toAddress(inputToken),
198
- outputToken: mint,
199
- inputAmount: relayData.inputAmount.toBigInt(),
200
- outputAmount: relayData.outputAmount.toBigInt(),
201
- originChainId: relayData.originChainId,
202
- depositId: new Uint8Array(intToU8Array32(relayData.depositId.toNumber())),
203
- fillDeadline: relayData.fillDeadline,
204
- exclusivityDeadline: relayData.exclusivityDeadline,
205
- message: new Uint8Array(Buffer.from(relayData.message, "hex")),
206
- };
207
-
208
- const simulatedSigner = SolanaVoidSigner(relayer.toBase58());
209
- const fillInput: SvmSpokeClient.FillRelayInput = {
210
- signer: simulatedSigner,
211
- state,
212
- delegate,
213
- mint,
214
- relayerTokenAccount: relayerAta,
215
- recipientTokenAccount: recipientAta,
216
- fillStatus,
217
- tokenProgram: mintInfo.programAddress,
218
- associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
219
- systemProgram: SYSTEM_PROGRAM_ADDRESS,
220
- eventAuthority,
221
- program,
222
- relayHash: relayDataHash,
223
- relayData: svmRelayData,
224
- repaymentChainId: BigInt(repaymentChainId),
225
- repaymentAddress: toAddress(repaymentAddress),
226
- };
227
- // Pass createRecipientAtaIfNeeded =true to the createFillInstruction function to create the recipient token account
228
- // if it doesn't exist.
229
- return createFillInstruction(simulatedSigner, this.provider, fillInput, mintInfo.data.decimals, true);
143
+ return await getFillRelayTx(this.spokePool, this.provider, relayData, signer, repaymentChainId, repaymentAddress);
230
144
  }
231
145
 
232
146
  /**
@@ -90,6 +90,7 @@ export function toAddressType(address: string, chainId: number): Address {
90
90
  // The Address class can contain any address type. It is up to the subclasses to determine how to format the address's internal representation,
91
91
  // which for this class, is a bytes32 hex string.
92
92
  export abstract class Address {
93
+ readonly __address_type_brand = true;
93
94
  readonly rawAddress: Uint8Array;
94
95
 
95
96
  // Keep all address types in cache so that we may lazily evaluate them when necessary.
@@ -109,6 +110,10 @@ export abstract class Address {
109
110
  this.rawAddress = utils.zeroPad(_rawAddress, 32);
110
111
  }
111
112
 
113
+ static isAddress(obj: unknown): obj is Address {
114
+ return "__address_type_brand" in (obj as { __address_type_brand: boolean });
115
+ }
116
+
112
117
  // Converts the address into a bytes32 string. Note that the output bytes will be lowercase so that it matches ethers event data. This function will never
113
118
  // throw since address length validation was done at construction time.
114
119
  toBytes32(): string {
@@ -1,7 +1,16 @@
1
1
  import assert from "assert";
2
2
  import { SpokePoolClient } from "../clients";
3
3
  import { DEFAULT_CACHING_TTL, EMPTY_MESSAGE, UNDEFINED_MESSAGE_HASH, ZERO_BYTES } from "../constants";
4
- import { CachingMechanismInterface, Deposit, DepositWithBlock, Fill, RelayData, SlowFillRequest } from "../interfaces";
4
+ import {
5
+ CachingMechanismInterface,
6
+ Deposit,
7
+ DepositWithBlock,
8
+ Fill,
9
+ RelayData,
10
+ SlowFillRequest,
11
+ ConvertedRelayData,
12
+ ConvertedFill,
13
+ } from "../interfaces";
5
14
  import { getMessageHash, isUnsafeDepositId } from "./SpokeUtils";
6
15
  import { getNetworkName } from "./NetworkUtils";
7
16
  import { bnZero } from "./BigNumberUtils";
@@ -251,3 +260,42 @@ export function resolveDepositMessage(deposit: Deposit): string {
251
260
  assert(isDefined(message)); // Appease tsc about the updatedMessage being possibly undefined.
252
261
  return message;
253
262
  }
263
+
264
+ /**
265
+ * Converts a RelayData object with `Address` types as address fields to a `RelayData`-like object with
266
+ * strings as address fields.
267
+ * @param relayData RelayData type.
268
+ * @returns a RelayData-like type which has strings as fields.
269
+ */
270
+ export function convertRelayDataParamsToBytes32(relayData: RelayData): ConvertedRelayData {
271
+ return {
272
+ ...relayData,
273
+ depositor: relayData.depositor.toBytes32(),
274
+ recipient: relayData.recipient.toBytes32(),
275
+ inputToken: relayData.inputToken.toBytes32(),
276
+ outputToken: relayData.outputToken.toBytes32(),
277
+ exclusiveRelayer: relayData.exclusiveRelayer.toBytes32(),
278
+ };
279
+ }
280
+
281
+ /**
282
+ * Converts a Fill object with `Address` types as address fields to a `RelayData`-like object with
283
+ * strings as address fields.
284
+ * @param relayData RelayData type.
285
+ * @returns a RelayData-like type which has strings as fields.
286
+ */
287
+ export function convertFillParamsToBytes32(fill: Fill): ConvertedFill {
288
+ return {
289
+ ...fill,
290
+ depositor: fill.depositor.toBytes32(),
291
+ recipient: fill.recipient.toBytes32(),
292
+ inputToken: fill.inputToken.toBytes32(),
293
+ outputToken: fill.outputToken.toBytes32(),
294
+ exclusiveRelayer: fill.exclusiveRelayer.toBytes32(),
295
+ relayer: fill.relayer.toBytes32(),
296
+ relayExecutionInfo: {
297
+ ...fill.relayExecutionInfo,
298
+ updatedRecipient: fill.relayExecutionInfo.updatedRecipient.toBytes32(),
299
+ },
300
+ };
301
+ }