@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.
@@ -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;AAEpD;;;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,EAC5C,cAAc,EAAE,gBAAgB,EAChC,aAAa,EAAE,aAAa,EAC5B,wBAAwB,EAAE,MAAM,GAC/B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAsDpC"}
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@across-protocol/sdk",
3
3
  "author": "UMA Team",
4
- "version": "4.2.6-alpha.3",
4
+ "version": "4.2.6",
5
5
  "license": "AGPL-3.0",
6
6
  "homepage": "https://docs.across.to/reference/sdk",
7
7
  "files": [
@@ -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
- assert(
98
- chainIsEvm(repaymentChainId) && isValidEvmAddress(fill.relayer),
99
- "validatedBundleV3Fills dictionary should only contain fills with valid repayment information"
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
- if (!isEVMSpokePoolClient(spokeClient)) {
464
- // FIXME: Handle non-EVM chains.
465
- throw new Error("Destination chain is not an EVM chain.");
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
- spokeClient.spokePool.provider,
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
- if (!isEVMSpokePoolClient(destinationClient)) {
975
- // FIXME: Handle non-EVM chains.
976
- throw new Error("Destination chain is not an EVM chain.");
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
- destinationClient.spokePool.provider,
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
- if (!isEVMSpokePoolClient(destinationClient)) {
1079
- // FIXME: Handle non-EVM chains.
1080
- throw new Error("Destination chain is not an EVM chain.");
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
- destinationClient.spokePool.provider,
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
- if (!isEVMSpokePoolClient(destinationClient)) {
1261
- // FIXME: Handle non-EVM chains.
1262
- throw new Error("Destination chain is not an EVM chain.");
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
- destinationClient.spokePool.provider,
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
- if (!isEVMSpokePoolClient(destinationClient)) {
1318
- // FIXME: Handle non-EVM chains.
1319
- throw new Error("Destination chain is not an EVM chain.");
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
- destinationClient.spokePool.provider,
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
- const fillTransaction = await destinationChainProvider.getTransaction(fill.txnRef);
95
- const destinationRelayer = fillTransaction?.from;
96
- // Repayment chain is still an EVM chain, but the msg.sender is a bytes32 address, so the fill is invalid.
97
- if (!isDefined(destinationRelayer) || !isValidEvmAddress(destinationRelayer)) {
98
- return undefined;
99
- }
100
- // If we can switch the repayment chain to the destination chain, then do so. We should only switch if the
101
- // destination chain has a valid repayment token that is equivalent to the deposited input token. This would
102
- // also be the same mapping as the repayment token on the repayment chain.
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