@across-protocol/sdk 4.2.6-alpha.3 → 4.2.6
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/utils.d.ts +3 -0
- package/dist/cjs/arch/svm/utils.js +59 -1
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +40 -19
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +2 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +7 -3
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/esm/arch/svm/utils.d.ts +19 -0
- package/dist/esm/arch/svm/utils.js +72 -1
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +40 -24
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +2 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +7 -3
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/types/arch/svm/utils.d.ts +19 -0
- 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/BundleDataClient/utils/FillUtils.d.ts +2 -1
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/arch/svm/utils.ts +45 -0
- package/src/clients/BundleDataClient/BundleDataClient.ts +34 -24
- package/src/clients/BundleDataClient/utils/FillUtils.ts +36 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FillUtils.d.ts","sourceRoot":"","sources":["../../../../../src/clients/BundleDataClient/utils/FillUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"FillUtils.d.ts","sourceRoot":"","sources":["../../../../../src/clients/BundleDataClient/utils/FillUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;GAGG;AACH,KAAK,wBAAwB,GAAG,IAAI,GAAG;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,wBAAwB,EACnC,aAAa,EAAE,aAAa,EAC5B,wBAAwB,EAAE,MAAM,GAC/B;IACD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB,CA2BA;AACD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,wBAAwB,EAAE,SAAS,CAAC,QAAQ,GAAG,WAAW,EAC1D,cAAc,EAAE,gBAAgB,EAChC,aAAa,EAAE,aAAa,EAC5B,wBAAwB,EAAE,MAAM,GAC/B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAiEpC"}
|
package/package.json
CHANGED
package/src/arch/svm/utils.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
getAddressEncoder,
|
|
8
8
|
getProgramDerivedAddress,
|
|
9
9
|
getU64Encoder,
|
|
10
|
+
getU32Encoder,
|
|
10
11
|
isAddress,
|
|
11
12
|
type TransactionSigner,
|
|
12
13
|
} from "@solana/kit";
|
|
@@ -215,6 +216,50 @@ export async function getRoutePda(originToken: Address, seed: bigint, routeChain
|
|
|
215
216
|
return pda;
|
|
216
217
|
}
|
|
217
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Returns the PDA for the SVM Spoke's transfer liability account.
|
|
221
|
+
* @param programId the address of the spoke pool.
|
|
222
|
+
* @param originToken the address of the corresponding token.
|
|
223
|
+
*/
|
|
224
|
+
export async function getTransferLiabilityPda(programId: Address, originToken: Address): Promise<Address> {
|
|
225
|
+
const addressEncoder = getAddressEncoder();
|
|
226
|
+
const [pda] = await getProgramDerivedAddress({
|
|
227
|
+
programAddress: programId,
|
|
228
|
+
seeds: ["transfer_liability", addressEncoder.encode(originToken)],
|
|
229
|
+
});
|
|
230
|
+
return pda;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Returns the PDA for the SVM Spoke's root bundle account.
|
|
235
|
+
* @param programId the address of the spoke pool.
|
|
236
|
+
* @param statePda the spoke pool's state pda.
|
|
237
|
+
* @param rootBundleId the associated root bundle ID.
|
|
238
|
+
*/
|
|
239
|
+
export async function getRootBundlePda(programId: Address, state: Address, rootBundleId: number): Promise<Address> {
|
|
240
|
+
const intEncoder = getU32Encoder();
|
|
241
|
+
const addressEncoder = getAddressEncoder();
|
|
242
|
+
const [pda] = await getProgramDerivedAddress({
|
|
243
|
+
programAddress: programId,
|
|
244
|
+
seeds: ["root_bundle", addressEncoder.encode(state), intEncoder.encode(rootBundleId)],
|
|
245
|
+
});
|
|
246
|
+
return pda;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Returns the PDA for the SVM Spoke's instruction params account.
|
|
251
|
+
* @param programId the address of the spoke pool.
|
|
252
|
+
* @param signer the signer of the authenticated call.
|
|
253
|
+
*/
|
|
254
|
+
export async function getInstructionParamsPda(programId: Address, signer: Address): Promise<Address> {
|
|
255
|
+
const addressEncoder = getAddressEncoder();
|
|
256
|
+
const [pda] = await getProgramDerivedAddress({
|
|
257
|
+
programAddress: programId,
|
|
258
|
+
seeds: ["instruction_params", addressEncoder.encode(signer)],
|
|
259
|
+
});
|
|
260
|
+
return pda;
|
|
261
|
+
}
|
|
262
|
+
|
|
218
263
|
/**
|
|
219
264
|
* Returns the PDA for the Event Authority.
|
|
220
265
|
* @returns The PDA for the Event Authority.
|
|
@@ -94,10 +94,9 @@ function updateBundleFillsV3(
|
|
|
94
94
|
repaymentAddress: string
|
|
95
95
|
): void {
|
|
96
96
|
// We shouldn't pass any unrepayable fills into this function, so we perform an extra safety check.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
);
|
|
97
|
+
if (chainIsEvm(repaymentChainId) && !isValidEvmAddress(fill.relayer)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
101
100
|
if (!dict?.[repaymentChainId]?.[repaymentToken]) {
|
|
102
101
|
assign(dict, [repaymentChainId, repaymentToken], {
|
|
103
102
|
fills: [],
|
|
@@ -460,13 +459,15 @@ export class BundleDataClient {
|
|
|
460
459
|
assert(isDefined(matchingDeposit), "Deposit not found for fill.");
|
|
461
460
|
|
|
462
461
|
const spokeClient = this.spokePoolClients[_fill.destinationChainId];
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
462
|
+
let provider;
|
|
463
|
+
if (isEVMSpokePoolClient(spokeClient)) {
|
|
464
|
+
provider = spokeClient.spokePool.provider;
|
|
465
|
+
} else if (isSVMSpokePoolClient(spokeClient)) {
|
|
466
|
+
provider = spokeClient.svmEventsClient.getRpc();
|
|
466
467
|
}
|
|
467
468
|
const fill = await verifyFillRepayment(
|
|
468
469
|
_fill,
|
|
469
|
-
|
|
470
|
+
provider!,
|
|
470
471
|
matchingDeposit,
|
|
471
472
|
this.clients.hubPoolClient,
|
|
472
473
|
bundleEndBlockForMainnet
|
|
@@ -971,17 +972,20 @@ export class BundleDataClient {
|
|
|
971
972
|
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
972
973
|
v3RelayHashes[relayDataHash].fill = fill;
|
|
973
974
|
if (fill.blockNumber >= destinationChainBlockRange[0]) {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
975
|
+
let provider;
|
|
976
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
977
|
+
provider = destinationClient.spokePool.provider;
|
|
978
|
+
} else if (isSVMSpokePoolClient(destinationClient)) {
|
|
979
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
977
980
|
}
|
|
978
981
|
const fillToRefund = await verifyFillRepayment(
|
|
979
982
|
fill,
|
|
980
|
-
|
|
983
|
+
provider!,
|
|
981
984
|
deposits[0],
|
|
982
985
|
this.clients.hubPoolClient,
|
|
983
986
|
bundleEndBlockForMainnet
|
|
984
987
|
);
|
|
988
|
+
|
|
985
989
|
if (!isDefined(fillToRefund)) {
|
|
986
990
|
bundleUnrepayableFillsV3.push(fill);
|
|
987
991
|
// We don't return here yet because we still need to mark unexecutable slow fill leaves
|
|
@@ -1075,14 +1079,16 @@ export class BundleDataClient {
|
|
|
1075
1079
|
}
|
|
1076
1080
|
v3RelayHashes[relayDataHash].deposits = [matchedDeposit];
|
|
1077
1081
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1082
|
+
let provider;
|
|
1083
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
1084
|
+
provider = destinationClient.spokePool.provider;
|
|
1085
|
+
} else if (isSVMSpokePoolClient(destinationClient)) {
|
|
1086
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
1081
1087
|
}
|
|
1082
1088
|
|
|
1083
1089
|
const fillToRefund = await verifyFillRepayment(
|
|
1084
1090
|
fill,
|
|
1085
|
-
|
|
1091
|
+
provider!,
|
|
1086
1092
|
matchedDeposit,
|
|
1087
1093
|
this.clients.hubPoolClient,
|
|
1088
1094
|
bundleEndBlockForMainnet
|
|
@@ -1257,13 +1263,15 @@ export class BundleDataClient {
|
|
|
1257
1263
|
// include this pre fill if the fill is in an older bundle.
|
|
1258
1264
|
if (fill) {
|
|
1259
1265
|
if (fill.blockNumber < destinationChainBlockRange[0]) {
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1266
|
+
let provider;
|
|
1267
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
1268
|
+
provider = destinationClient.spokePool.provider;
|
|
1269
|
+
} else if (isSVMSpokePoolClient(destinationClient)) {
|
|
1270
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
1263
1271
|
}
|
|
1264
1272
|
const fillToRefund = await verifyFillRepayment(
|
|
1265
1273
|
fill,
|
|
1266
|
-
|
|
1274
|
+
provider!,
|
|
1267
1275
|
deposits[0],
|
|
1268
1276
|
this.clients.hubPoolClient,
|
|
1269
1277
|
bundleEndBlockForMainnet
|
|
@@ -1314,13 +1322,15 @@ export class BundleDataClient {
|
|
|
1314
1322
|
const prefill = await this.findMatchingFillEvent(deposit, destinationClient);
|
|
1315
1323
|
assert(isDefined(prefill), `findFillEvent# Cannot find prefill: ${relayDataHash}`);
|
|
1316
1324
|
assert(getRelayEventKey(prefill) === relayDataHash, "Relay hashes should match.");
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1325
|
+
let provider;
|
|
1326
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
1327
|
+
provider = destinationClient.spokePool.provider;
|
|
1328
|
+
} else if (isSVMSpokePoolClient(destinationClient)) {
|
|
1329
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
1320
1330
|
}
|
|
1321
1331
|
const verifiedFill = await verifyFillRepayment(
|
|
1322
1332
|
prefill,
|
|
1323
|
-
|
|
1333
|
+
provider!,
|
|
1324
1334
|
deposit,
|
|
1325
1335
|
this.clients.hubPoolClient,
|
|
1326
1336
|
bundleEndBlockForMainnet
|
|
@@ -4,6 +4,7 @@ import { providers } from "ethers";
|
|
|
4
4
|
import { DepositWithBlock, Fill, FillWithBlock } from "../../../interfaces";
|
|
5
5
|
import { isSlowFill, isValidEvmAddress, isDefined, chainIsEvm } from "../../../utils";
|
|
6
6
|
import { HubPoolClient } from "../../HubPoolClient";
|
|
7
|
+
import { SVMProvider } from "../../../arch/svm";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @notice FillRepaymentInformation is a fill with additional properties required to determine where it can
|
|
@@ -65,7 +66,7 @@ export function getRefundInformationFromFill(
|
|
|
65
66
|
*/
|
|
66
67
|
export async function verifyFillRepayment(
|
|
67
68
|
_fill: FillWithBlock,
|
|
68
|
-
destinationChainProvider: providers.Provider,
|
|
69
|
+
destinationChainProvider: providers.Provider | SVMProvider,
|
|
69
70
|
matchedDeposit: DepositWithBlock,
|
|
70
71
|
hubPoolClient: HubPoolClient,
|
|
71
72
|
bundleEndBlockForMainnet: number
|
|
@@ -91,32 +92,43 @@ export async function verifyFillRepayment(
|
|
|
91
92
|
if (_repaymentAddressNeedsToBeOverwritten(fill)) {
|
|
92
93
|
// TODO: Handle case where fill was sent on non-EVM chain, in which case the following call would fail
|
|
93
94
|
// or return something unexpected. We'd want to return undefined here.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
!matchedDeposit.fromLiteChain &&
|
|
105
|
-
hubPoolClient.areTokensEquivalent(fill.inputToken, fill.originChainId, fill.outputToken, fill.destinationChainId)
|
|
106
|
-
) {
|
|
107
|
-
repaymentChainId = fill.destinationChainId;
|
|
108
|
-
}
|
|
109
|
-
// If we can't switch the chain, then we need to verify that the msg.sender is a valid address on the repayment chain.
|
|
110
|
-
// Because we already checked that the `destinationRelayer` was a valid EVM address above, we only need to check
|
|
111
|
-
// that the repayment chain is an EVM chain.
|
|
112
|
-
else {
|
|
113
|
-
if (!chainIsEvm(repaymentChainId)) {
|
|
95
|
+
if (chainIsEvm(fill.destinationChainId)) {
|
|
96
|
+
assert(
|
|
97
|
+
destinationChainProvider instanceof providers.Provider,
|
|
98
|
+
`BundleDataClient#verifyFillRepayment: unexpected destination chain provider for chain ID ${fill.destinationChainId}`
|
|
99
|
+
);
|
|
100
|
+
const fillTransaction = await destinationChainProvider.getTransaction(fill.txnRef);
|
|
101
|
+
const destinationRelayer = fillTransaction?.from;
|
|
102
|
+
// Repayment chain is still an EVM chain, but the msg.sender is a bytes32 address, so the fill is invalid.
|
|
103
|
+
if (!isDefined(destinationRelayer) || !isValidEvmAddress(destinationRelayer)) {
|
|
114
104
|
return undefined;
|
|
115
105
|
}
|
|
106
|
+
// If we can switch the repayment chain to the destination chain, then do so. We should only switch if the
|
|
107
|
+
// destination chain has a valid repayment token that is equivalent to the deposited input token. This would
|
|
108
|
+
// also be the same mapping as the repayment token on the repayment chain.
|
|
109
|
+
if (
|
|
110
|
+
!matchedDeposit.fromLiteChain &&
|
|
111
|
+
hubPoolClient.areTokensEquivalent(
|
|
112
|
+
fill.inputToken,
|
|
113
|
+
fill.originChainId,
|
|
114
|
+
fill.outputToken,
|
|
115
|
+
fill.destinationChainId
|
|
116
|
+
)
|
|
117
|
+
) {
|
|
118
|
+
repaymentChainId = fill.destinationChainId;
|
|
119
|
+
}
|
|
120
|
+
// If we can't switch the chain, then we need to verify that the msg.sender is a valid address on the repayment chain.
|
|
121
|
+
// Because we already checked that the `destinationRelayer` was a valid EVM address above, we only need to check
|
|
122
|
+
// that the repayment chain is an EVM chain.
|
|
123
|
+
else {
|
|
124
|
+
if (!chainIsEvm(repaymentChainId)) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
fill.relayer = destinationRelayer;
|
|
129
|
+
} else {
|
|
130
|
+
return undefined;
|
|
116
131
|
}
|
|
117
|
-
fill.relayer = destinationRelayer;
|
|
118
|
-
|
|
119
|
-
// @todo: If chainIsSvm:
|
|
120
132
|
}
|
|
121
133
|
|
|
122
134
|
// Repayment address is now valid and repayment chain is either origin chain for lite chain or the destination
|