@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.
- package/dist/cjs/arch/svm/SpokeUtils.d.ts +13 -5
- package/dist/cjs/arch/svm/SpokeUtils.js +74 -5
- package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/svm/utils.d.ts +4 -1
- package/dist/cjs/arch/svm/utils.js +15 -1
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +9 -5
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js +4 -3
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
- package/dist/cjs/interfaces/SpokePool.d.ts +18 -0
- package/dist/cjs/interfaces/SpokePool.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +7 -68
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/cjs/utils/AddressUtils.d.ts +2 -0
- package/dist/cjs/utils/AddressUtils.js +4 -0
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.d.ts +3 -1
- package/dist/cjs/utils/DepositUtils.js +9 -1
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/esm/arch/svm/SpokeUtils.d.ts +23 -5
- package/dist/esm/arch/svm/SpokeUtils.js +86 -5
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/utils.d.ts +7 -1
- package/dist/esm/arch/svm/utils.js +14 -0
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +10 -6
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js +5 -4
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
- package/dist/esm/interfaces/SpokePool.d.ts +18 -0
- package/dist/esm/interfaces/SpokePool.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +9 -73
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/esm/utils/AddressUtils.d.ts +2 -0
- package/dist/esm/utils/AddressUtils.js +4 -0
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.d.ts +15 -1
- package/dist/esm/utils/DepositUtils.js +19 -1
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/types/arch/svm/SpokeUtils.d.ts +23 -5
- package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
- package/dist/types/arch/svm/utils.d.ts +7 -1
- package/dist/types/arch/svm/utils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts +1 -1
- package/dist/types/clients/mocks/MockSvmCpiEventsClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockSvmSpokePoolClient.d.ts +1 -1
- package/dist/types/interfaces/SpokePool.d.ts +18 -0
- package/dist/types/interfaces/SpokePool.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +2 -1
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
- package/dist/types/utils/AddressUtils.d.ts +2 -0
- package/dist/types/utils/AddressUtils.d.ts.map +1 -1
- package/dist/types/utils/DepositUtils.d.ts +15 -1
- package/dist/types/utils/DepositUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/arch/svm/SpokeUtils.ts +97 -6
- package/src/arch/svm/utils.ts +16 -0
- package/src/clients/BundleDataClient/BundleDataClient.ts +11 -5
- package/src/clients/mocks/MockSvmCpiEventsClient.ts +5 -3
- package/src/interfaces/SpokePool.ts +23 -0
- package/src/relayFeeCalculator/chain-queries/svmQuery.ts +7 -93
- package/src/utils/AddressUtils.ts +5 -0
- 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,
|
|
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.
|
|
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
|
|
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
|
-
|
|
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:
|
|
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(
|
|
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:
|
|
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(
|
|
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)),
|
package/src/arch/svm/utils.ts
CHANGED
|
@@ -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
|
-
|
|
1609
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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 {
|
|
3
|
-
import {
|
|
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
|
-
|
|
139
|
+
signer: TransactionSigner,
|
|
162
140
|
repaymentChainId: number,
|
|
163
141
|
repaymentAddress: Address
|
|
164
142
|
) {
|
|
165
|
-
|
|
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 {
|
|
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
|
+
}
|