@across-protocol/sdk 4.1.63-beta.0 → 4.1.63-beta.2
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 +3 -3
- package/dist/cjs/arch/svm/SpokeUtils.js +37 -41
- package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/svm/constants.d.ts +1 -0
- package/dist/cjs/arch/svm/constants.js +3 -1
- package/dist/cjs/arch/svm/constants.js.map +1 -1
- package/dist/cjs/arch/svm/eventsClient.d.ts +6 -1
- package/dist/cjs/arch/svm/eventsClient.js +64 -0
- package/dist/cjs/arch/svm/eventsClient.js.map +1 -1
- package/dist/cjs/arch/svm/utils.js +2 -2
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +26 -26
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.js +2 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/interfaces/SpokePool.d.ts +6 -0
- package/dist/cjs/interfaces/SpokePool.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js +5 -4
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/factory.js +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/factory.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +6 -0
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +69 -34
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/relayFeeCalculator.d.ts +2 -0
- package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js +9 -3
- package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
- package/dist/cjs/utils/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/SpokeUtils.d.ts +3 -3
- package/dist/esm/arch/svm/SpokeUtils.js +26 -30
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/constants.d.ts +1 -0
- package/dist/esm/arch/svm/constants.js +1 -0
- package/dist/esm/arch/svm/constants.js.map +1 -1
- package/dist/esm/arch/svm/eventsClient.d.ts +21 -1
- package/dist/esm/arch/svm/eventsClient.js +80 -1
- package/dist/esm/arch/svm/eventsClient.js.map +1 -1
- package/dist/esm/arch/svm/utils.js +3 -3
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +26 -26
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +1 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/interfaces/SpokePool.d.ts +6 -0
- package/dist/esm/interfaces/SpokePool.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js +6 -5
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/factory.js +3 -3
- package/dist/esm/relayFeeCalculator/chain-queries/factory.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +18 -0
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +83 -36
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/esm/relayFeeCalculator/relayFeeCalculator.d.ts +12 -1
- package/dist/esm/relayFeeCalculator/relayFeeCalculator.js +9 -4
- package/dist/esm/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/types/arch/svm/SpokeUtils.d.ts +3 -3
- package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
- package/dist/types/arch/svm/constants.d.ts +1 -0
- package/dist/types/arch/svm/constants.d.ts.map +1 -1
- package/dist/types/arch/svm/eventsClient.d.ts +21 -1
- package/dist/types/arch/svm/eventsClient.d.ts.map +1 -1
- package/dist/types/arch/svm/utils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +26 -26
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/interfaces/SpokePool.d.ts +6 -0
- package/dist/types/interfaces/SpokePool.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/factory.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +18 -0
- package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
- package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts +12 -1
- package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/arch/svm/SpokeUtils.ts +43 -43
- package/src/arch/svm/constants.ts +1 -0
- package/src/arch/svm/eventsClient.ts +114 -1
- package/src/arch/svm/utils.ts +4 -4
- package/src/constants.ts +1 -0
- package/src/interfaces/SpokePool.ts +7 -0
- package/src/relayFeeCalculator/chain-queries/baseQuery.ts +6 -6
- package/src/relayFeeCalculator/chain-queries/factory.ts +3 -3
- package/src/relayFeeCalculator/chain-queries/svmQuery.ts +59 -27
- package/src/relayFeeCalculator/relayFeeCalculator.ts +15 -3
- package/src/utils/SpokeUtils.ts +2 -2
|
@@ -1,38 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SvmAddress,
|
|
3
|
-
getTokenInfo,
|
|
4
|
-
BigNumber,
|
|
5
|
-
isDefined,
|
|
6
|
-
isUnsafeDepositId,
|
|
7
|
-
toAddressType,
|
|
8
|
-
toBN,
|
|
9
|
-
getMessageHash,
|
|
10
|
-
keccak256,
|
|
11
|
-
chainIsSvm,
|
|
12
|
-
chunk,
|
|
13
|
-
} from "../../utils";
|
|
14
1
|
import { SvmSpokeClient } from "@across-protocol/contracts";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
2
|
+
import { decodeFillStatusAccount, fetchState } from "@across-protocol/contracts/dist/src/svm/clients/SvmSpoke";
|
|
3
|
+
import { hashNonEmptyMessage } from "@across-protocol/contracts/dist/src/svm/web3-v1";
|
|
17
4
|
import {
|
|
18
|
-
TOKEN_PROGRAM_ADDRESS,
|
|
19
5
|
ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
6
|
+
TOKEN_PROGRAM_ADDRESS,
|
|
20
7
|
getApproveCheckedInstruction,
|
|
21
8
|
} from "@solana-program/token";
|
|
22
9
|
import {
|
|
23
10
|
Address,
|
|
24
|
-
some,
|
|
25
11
|
address,
|
|
26
|
-
getProgramDerivedAddress,
|
|
27
|
-
fetchEncodedAccounts,
|
|
28
12
|
fetchEncodedAccount,
|
|
13
|
+
fetchEncodedAccounts,
|
|
14
|
+
getAddressEncoder,
|
|
15
|
+
getProgramDerivedAddress,
|
|
16
|
+
getU32Encoder,
|
|
17
|
+
getU64Encoder,
|
|
18
|
+
some,
|
|
29
19
|
type TransactionSigner,
|
|
30
20
|
} from "@solana/kit";
|
|
31
21
|
import assert from "assert";
|
|
22
|
+
import { arrayify, hexZeroPad, hexlify } from "ethers/lib/utils";
|
|
32
23
|
import { Logger } from "winston";
|
|
33
|
-
import { fetchState, decodeFillStatusAccount } from "@across-protocol/contracts/dist/src/svm/clients/SvmSpoke";
|
|
34
|
-
import { SVMEventNames, SVMProvider } from "./types";
|
|
35
24
|
import { CHAIN_IDs } from "../../constants";
|
|
25
|
+
import { Deposit, FillStatus, FillWithBlock, RelayData } from "../../interfaces";
|
|
26
|
+
import {
|
|
27
|
+
BigNumber,
|
|
28
|
+
SvmAddress,
|
|
29
|
+
chainIsSvm,
|
|
30
|
+
chunk,
|
|
31
|
+
getTokenInfo,
|
|
32
|
+
isDefined,
|
|
33
|
+
isUnsafeDepositId,
|
|
34
|
+
keccak256,
|
|
35
|
+
toAddressType,
|
|
36
|
+
} from "../../utils";
|
|
37
|
+
import { SvmCpiEventsClient, getEventAuthority, getFillStatusPda, getStatePda, unwrapEventData } from "./";
|
|
38
|
+
import { SVMEventNames, SVMProvider } from "./types";
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* @param spokePool SpokePool Contract instance.
|
|
@@ -412,29 +415,26 @@ export async function getAssociatedTokenAddress(
|
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
export function getRelayDataHash(relayData: RelayData, destinationChainId: number): string {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
return littleEndian ? buffer.slice(0, byteLength).reverse() : buffer.slice(0, byteLength);
|
|
423
|
-
};
|
|
418
|
+
const addressEncoder = getAddressEncoder();
|
|
419
|
+
const uint64Encoder = getU64Encoder();
|
|
420
|
+
const uint32Encoder = getU32Encoder();
|
|
421
|
+
|
|
422
|
+
assert(relayData.message.startsWith("0x"), "Message must be a hex string");
|
|
423
|
+
|
|
424
424
|
const contentToHash = Buffer.concat([
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
425
|
+
Uint8Array.from(addressEncoder.encode(SvmAddress.from(relayData.depositor, "base16").toV2Address())),
|
|
426
|
+
Uint8Array.from(addressEncoder.encode(SvmAddress.from(relayData.recipient, "base16").toV2Address())),
|
|
427
|
+
Uint8Array.from(addressEncoder.encode(SvmAddress.from(relayData.exclusiveRelayer, "base16").toV2Address())),
|
|
428
|
+
Uint8Array.from(addressEncoder.encode(SvmAddress.from(relayData.inputToken, "base16").toV2Address())),
|
|
429
|
+
Uint8Array.from(addressEncoder.encode(SvmAddress.from(relayData.outputToken, "base16").toV2Address())),
|
|
430
|
+
Uint8Array.from(uint64Encoder.encode(BigInt(relayData.inputAmount.toString()))),
|
|
431
|
+
Uint8Array.from(uint64Encoder.encode(BigInt(relayData.outputAmount.toString()))),
|
|
432
|
+
Uint8Array.from(uint64Encoder.encode(BigInt(relayData.originChainId.toString()))),
|
|
433
|
+
arrayify(hexZeroPad(hexlify(relayData.depositId), 32)),
|
|
434
|
+
Uint8Array.from(uint32Encoder.encode(relayData.fillDeadline)),
|
|
435
|
+
Uint8Array.from(uint32Encoder.encode(relayData.exclusivityDeadline)),
|
|
436
|
+
hashNonEmptyMessage(Buffer.from(arrayify(relayData.message))),
|
|
437
|
+
Uint8Array.from(uint64Encoder.encode(BigInt(destinationChainId))),
|
|
438
438
|
]);
|
|
439
439
|
return keccak256(contentToHash);
|
|
440
440
|
}
|
|
@@ -2,9 +2,16 @@ import { Idl } from "@coral-xyz/anchor";
|
|
|
2
2
|
import { getDeployedAddress, SvmSpokeIdl } from "@across-protocol/contracts";
|
|
3
3
|
import { getSolanaChainId } from "@across-protocol/contracts/dist/src/svm/web3-v1";
|
|
4
4
|
import web3, { Address, Commitment, GetSignaturesForAddressApi, GetTransactionApi, Signature } from "@solana/kit";
|
|
5
|
-
import { bs58 } from "../../utils";
|
|
5
|
+
import { bs58, chainIsSvm, getMessageHash } from "../../utils";
|
|
6
6
|
import { EventName, EventWithData, SVMProvider } from "./types";
|
|
7
7
|
import { decodeEvent, isDevnet } from "./utils";
|
|
8
|
+
import { DepositWithTime, FillWithTime } from "../../interfaces";
|
|
9
|
+
import { unwrapEventData } from "./";
|
|
10
|
+
import assert from "assert";
|
|
11
|
+
import {
|
|
12
|
+
FundsDepositedEventObject,
|
|
13
|
+
FilledRelayEventObject,
|
|
14
|
+
} from "@across-protocol/contracts/dist/typechain/contracts/SpokePool";
|
|
8
15
|
|
|
9
16
|
// Utility type to extract the return type for the JSON encoding overload. We only care about the overload where the
|
|
10
17
|
// configuration parameter (C) has the optional property 'encoding' set to 'json'.
|
|
@@ -19,6 +26,9 @@ type GetSignaturesForAddressConfig = Parameters<GetSignaturesForAddressApi["getS
|
|
|
19
26
|
type GetSignaturesForAddressTransaction = ReturnType<GetSignaturesForAddressApi["getSignaturesForAddress"]>[number];
|
|
20
27
|
type GetSignaturesForAddressApiResponse = readonly GetSignaturesForAddressTransaction[];
|
|
21
28
|
|
|
29
|
+
export type DepositEventFromSignature = Omit<DepositWithTime, "fromLiteChain" | "toLiteChain">;
|
|
30
|
+
export type FillEventFromSignature = FillWithTime;
|
|
31
|
+
|
|
22
32
|
export class SvmCpiEventsClient {
|
|
23
33
|
private rpc: SVMProvider;
|
|
24
34
|
private programAddress: Address;
|
|
@@ -211,6 +221,109 @@ export class SvmCpiEventsClient {
|
|
|
211
221
|
return events;
|
|
212
222
|
}
|
|
213
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Finds all FundsDeposited events for a given transaction signature.
|
|
226
|
+
*
|
|
227
|
+
* @param originChainId - The chain ID where the deposit originated.
|
|
228
|
+
* @param txSignature - The transaction signature to search for events.
|
|
229
|
+
* @param commitment - Optional commitment level for the transaction query.
|
|
230
|
+
* @returns A promise that resolves to an array of deposit events for the transaction, or undefined if none found.
|
|
231
|
+
*/
|
|
232
|
+
public async getDepositEventsFromSignature(
|
|
233
|
+
originChainId: number,
|
|
234
|
+
txSignature: Signature,
|
|
235
|
+
commitment: Commitment = "confirmed"
|
|
236
|
+
): Promise<DepositEventFromSignature[] | undefined> {
|
|
237
|
+
assert(chainIsSvm(originChainId), `Origin chain ${originChainId} is not an SVM chain`);
|
|
238
|
+
|
|
239
|
+
const [events, txDetails] = await Promise.all([
|
|
240
|
+
this.readEventsFromSignature(txSignature, commitment),
|
|
241
|
+
this.rpc
|
|
242
|
+
.getTransaction(txSignature, {
|
|
243
|
+
commitment,
|
|
244
|
+
maxSupportedTransactionVersion: 0,
|
|
245
|
+
})
|
|
246
|
+
.send(),
|
|
247
|
+
]);
|
|
248
|
+
|
|
249
|
+
// Filter for FundsDeposited events only
|
|
250
|
+
const depositEvents = events?.filter((event) => event?.name === "FundsDeposited");
|
|
251
|
+
|
|
252
|
+
if (!txDetails || !depositEvents?.length) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return events.map((event) => {
|
|
257
|
+
const unwrappedEventArgs = unwrapEventData(event as Record<string, unknown>, ["depositId"]) as Record<
|
|
258
|
+
"data",
|
|
259
|
+
FundsDepositedEventObject
|
|
260
|
+
>;
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
...unwrappedEventArgs.data,
|
|
264
|
+
depositTimestamp: Number(txDetails.blockTime),
|
|
265
|
+
originChainId,
|
|
266
|
+
messageHash: getMessageHash(unwrappedEventArgs.data.message),
|
|
267
|
+
blockNumber: Number(txDetails.slot),
|
|
268
|
+
txnIndex: 0,
|
|
269
|
+
txnRef: txSignature,
|
|
270
|
+
logIndex: 0,
|
|
271
|
+
destinationChainId: unwrappedEventArgs.data.destinationChainId.toNumber(),
|
|
272
|
+
} satisfies DepositEventFromSignature;
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Finds all FilledRelay events for a given transaction signature.
|
|
278
|
+
*
|
|
279
|
+
* @param destinationChainId - The destination chain ID (must be an SVM chain).
|
|
280
|
+
* @param txSignature - The transaction signature to search for events.
|
|
281
|
+
* @returns A promise that resolves to an array of fill events for the transaction, or undefined if none found.
|
|
282
|
+
*/
|
|
283
|
+
public async getFillEventsFromSignature(
|
|
284
|
+
destinationChainId: number,
|
|
285
|
+
txSignature: Signature,
|
|
286
|
+
commitment: Commitment = "confirmed"
|
|
287
|
+
): Promise<FillEventFromSignature[] | undefined> {
|
|
288
|
+
assert(chainIsSvm(destinationChainId), `Destination chain ${destinationChainId} is not an SVM chain`);
|
|
289
|
+
|
|
290
|
+
// Find all events from the transaction signature and get transaction details
|
|
291
|
+
const [events, txDetails] = await Promise.all([
|
|
292
|
+
this.readEventsFromSignature(txSignature, commitment),
|
|
293
|
+
this.rpc
|
|
294
|
+
.getTransaction(txSignature, {
|
|
295
|
+
commitment,
|
|
296
|
+
maxSupportedTransactionVersion: 0,
|
|
297
|
+
})
|
|
298
|
+
.send(),
|
|
299
|
+
]);
|
|
300
|
+
|
|
301
|
+
// Filter for FilledRelay events only
|
|
302
|
+
const fillEvents = events?.filter((event) => event?.name === "FilledRelay");
|
|
303
|
+
|
|
304
|
+
if (!txDetails || !fillEvents?.length) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return fillEvents.map((event) => {
|
|
309
|
+
const unwrappedEventData = unwrapEventData(event as Record<string, unknown>) as Record<
|
|
310
|
+
"data",
|
|
311
|
+
FilledRelayEventObject
|
|
312
|
+
>;
|
|
313
|
+
return {
|
|
314
|
+
...unwrappedEventData.data,
|
|
315
|
+
fillTimestamp: Number(txDetails.blockTime),
|
|
316
|
+
blockNumber: Number(txDetails.slot),
|
|
317
|
+
txnRef: txSignature,
|
|
318
|
+
txnIndex: 0,
|
|
319
|
+
logIndex: 0,
|
|
320
|
+
destinationChainId,
|
|
321
|
+
repaymentChainId: unwrappedEventData.data.repaymentChainId.toNumber(),
|
|
322
|
+
originChainId: unwrappedEventData.data.originChainId.toNumber(),
|
|
323
|
+
} satisfies FillEventFromSignature;
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
214
327
|
public getProgramAddress(): Address {
|
|
215
328
|
return this.programAddress;
|
|
216
329
|
}
|
package/src/arch/svm/utils.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import { SvmSpokeClient } from "@across-protocol/contracts";
|
|
1
2
|
import { BN, BorshEventCoder, Idl } from "@coral-xyz/anchor";
|
|
2
3
|
import {
|
|
4
|
+
Address,
|
|
3
5
|
address,
|
|
6
|
+
getAddressEncoder,
|
|
4
7
|
getProgramDerivedAddress,
|
|
5
8
|
getU64Encoder,
|
|
6
|
-
getAddressEncoder,
|
|
7
|
-
Address,
|
|
8
9
|
isAddress,
|
|
9
10
|
type TransactionSigner,
|
|
10
11
|
} from "@solana/kit";
|
|
11
|
-
import { BigNumber, getRelayDataHash, isUint8Array, SvmAddress } from "../../utils";
|
|
12
|
-
import { SvmSpokeClient } from "@across-protocol/contracts";
|
|
13
12
|
import { FillType, RelayData } from "../../interfaces";
|
|
13
|
+
import { BigNumber, SvmAddress, getRelayDataHash, isUint8Array } from "../../utils";
|
|
14
14
|
import { EventName, SVMEventNames, SVMProvider } from "./types";
|
|
15
15
|
|
|
16
16
|
/**
|
package/src/constants.ts
CHANGED
|
@@ -54,6 +54,7 @@ export const DEFAULT_CACHING_TTL = 60 * 60 * 24 * 7 * 2; // 2 Weeks
|
|
|
54
54
|
export const DEFAULT_CACHING_SAFE_LAG = 60 * 60; // 1 hour
|
|
55
55
|
|
|
56
56
|
export const DEFAULT_SIMULATED_RELAYER_ADDRESS = "0x07aE8551Be970cB1cCa11Dd7a11F47Ae82e70E67";
|
|
57
|
+
export const DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM = "FmMK62wrtWVb5SVoTZftSCGw3nEDA79hDbZNTRnC1R6t";
|
|
57
58
|
export const DEFAULT_SIMULATED_RELAYER_ADDRESS_TEST = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D"; // Görli, ...
|
|
58
59
|
|
|
59
60
|
export const DEFAULT_ARWEAVE_STORAGE_ADDRESS = "Z6hjBM8FHu90lYWB8o5jR1dfX92FlV2WBaND9xgp8Lg";
|
|
@@ -37,6 +37,10 @@ export interface DepositWithBlock extends Deposit, SortableEvent {
|
|
|
37
37
|
quoteBlockNumber: number;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export interface DepositWithTime extends Deposit, SortableEvent {
|
|
41
|
+
depositTimestamp: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
export enum FillStatus {
|
|
41
45
|
Unfilled = 0,
|
|
42
46
|
RequestedSlowFill,
|
|
@@ -66,6 +70,9 @@ export interface Fill extends Omit<RelayData, "message"> {
|
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
export interface FillWithBlock extends Fill, SortableEvent {}
|
|
73
|
+
export interface FillWithTime extends Fill, SortableEvent {
|
|
74
|
+
fillTimestamp: number;
|
|
75
|
+
}
|
|
69
76
|
|
|
70
77
|
export interface EnabledDepositRoute {
|
|
71
78
|
originToken: string;
|
|
@@ -3,7 +3,7 @@ import { isL2Provider as isOptimismL2Provider } from "@eth-optimism/sdk/dist/l2-
|
|
|
3
3
|
|
|
4
4
|
import { PopulatedTransaction, providers, VoidSigner } from "ethers";
|
|
5
5
|
import { Coingecko } from "../../coingecko";
|
|
6
|
-
import { CHAIN_IDs
|
|
6
|
+
import { CHAIN_IDs } from "../../constants";
|
|
7
7
|
import { Deposit } from "../../interfaces";
|
|
8
8
|
import { SpokePool, SpokePool__factory } from "../../typechain";
|
|
9
9
|
import { populateV3Relay } from "../../arch/evm";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
fixedPointAdjustment,
|
|
18
18
|
} from "../../utils";
|
|
19
19
|
import assert from "assert";
|
|
20
|
-
import { Logger, QueryInterface } from "../relayFeeCalculator";
|
|
20
|
+
import { Logger, QueryInterface, getDefaultSimulatedRelayerAddress } from "../relayFeeCalculator";
|
|
21
21
|
import { Transport } from "viem";
|
|
22
22
|
import { getGasPriceEstimate, EvmGasPriceEstimate } from "../../gasPriceOracle";
|
|
23
23
|
type Provider = providers.Provider;
|
|
@@ -72,7 +72,7 @@ export class QueryBase implements QueryInterface {
|
|
|
72
72
|
*/
|
|
73
73
|
async getGasCosts(
|
|
74
74
|
deposit: Omit<Deposit, "messageHash">,
|
|
75
|
-
relayer =
|
|
75
|
+
relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
|
|
76
76
|
options: Partial<{
|
|
77
77
|
gasPrice: BigNumberish;
|
|
78
78
|
gasUnits: BigNumberish;
|
|
@@ -122,7 +122,7 @@ export class QueryBase implements QueryInterface {
|
|
|
122
122
|
*/
|
|
123
123
|
getUnsignedTxFromDeposit(
|
|
124
124
|
deposit: Omit<Deposit, "messageHash">,
|
|
125
|
-
relayer =
|
|
125
|
+
relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId)
|
|
126
126
|
): Promise<PopulatedTransaction> {
|
|
127
127
|
return populateV3Relay(this.spokePool, deposit, relayer);
|
|
128
128
|
}
|
|
@@ -135,7 +135,7 @@ export class QueryBase implements QueryInterface {
|
|
|
135
135
|
*/
|
|
136
136
|
async getNativeGasCost(
|
|
137
137
|
deposit: Omit<Deposit, "messageHash">,
|
|
138
|
-
relayer =
|
|
138
|
+
relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId)
|
|
139
139
|
): Promise<BigNumber> {
|
|
140
140
|
const unsignedTx = await this.getUnsignedTxFromDeposit(deposit, relayer);
|
|
141
141
|
const voidSigner = new VoidSigner(relayer, this.provider);
|
|
@@ -152,7 +152,7 @@ export class QueryBase implements QueryInterface {
|
|
|
152
152
|
*/
|
|
153
153
|
async getOpStackL1DataFee(
|
|
154
154
|
unsignedTx: PopulatedTransaction,
|
|
155
|
-
relayer =
|
|
155
|
+
relayer = getDefaultSimulatedRelayerAddress(unsignedTx.chainId),
|
|
156
156
|
options: Partial<{
|
|
157
157
|
opStackL2GasUnits: BigNumberish;
|
|
158
158
|
opStackL1DataFeeMultiplier: BigNumber;
|
|
@@ -3,11 +3,11 @@ import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "@across-protocol/constants";
|
|
|
3
3
|
import { getDeployedAddress } from "@across-protocol/contracts";
|
|
4
4
|
import { asL2Provider } from "@eth-optimism/sdk";
|
|
5
5
|
import { providers } from "ethers";
|
|
6
|
-
import {
|
|
6
|
+
import { CUSTOM_GAS_TOKENS } from "../../constants";
|
|
7
7
|
import { chainIsOPStack, isDefined, chainIsSvm, SvmAddress } from "../../utils";
|
|
8
8
|
import { QueryBase } from "./baseQuery";
|
|
9
9
|
import { SVMProvider as svmProvider } from "../../arch/svm";
|
|
10
|
-
import { DEFAULT_LOGGER, Logger } from "../relayFeeCalculator";
|
|
10
|
+
import { DEFAULT_LOGGER, getDefaultSimulatedRelayerAddress, Logger } from "../relayFeeCalculator";
|
|
11
11
|
import { CustomGasTokenQueries } from "./customGasToken";
|
|
12
12
|
import { SvmQuery } from "./svmQuery";
|
|
13
13
|
|
|
@@ -25,7 +25,7 @@ export class QueryBase__factory {
|
|
|
25
25
|
provider: providers.Provider | svmProvider,
|
|
26
26
|
symbolMapping = TOKEN_SYMBOLS_MAP,
|
|
27
27
|
spokePoolAddress = getDeployedAddress("SpokePool", chainId),
|
|
28
|
-
simulatedRelayerAddress =
|
|
28
|
+
simulatedRelayerAddress = getDefaultSimulatedRelayerAddress(chainId),
|
|
29
29
|
coingeckoProApiKey?: string,
|
|
30
30
|
logger: Logger = DEFAULT_LOGGER,
|
|
31
31
|
coingeckoBaseCurrency = "eth"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pipe } from "@solana/functional";
|
|
2
2
|
import { Coingecko } from "../../coingecko";
|
|
3
3
|
import { SymbolMappingType } from "./";
|
|
4
|
-
import { CHAIN_IDs
|
|
4
|
+
import { CHAIN_IDs } from "../../constants";
|
|
5
5
|
import { Deposit } from "../../interfaces";
|
|
6
6
|
import { getGasPriceEstimate, SvmGasPriceEstimate } from "../../gasPriceOracle";
|
|
7
7
|
import {
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
isDefined,
|
|
14
14
|
toAddressType,
|
|
15
15
|
} from "../../utils";
|
|
16
|
-
import { Logger, QueryInterface } from "../relayFeeCalculator";
|
|
16
|
+
import { getDefaultSimulatedRelayerAddress, Logger, QueryInterface } from "../relayFeeCalculator";
|
|
17
17
|
import {
|
|
18
18
|
fillRelayInstruction,
|
|
19
19
|
createApproveInstruction,
|
|
@@ -79,7 +79,7 @@ export class SvmQuery implements QueryInterface {
|
|
|
79
79
|
*/
|
|
80
80
|
async getGasCosts(
|
|
81
81
|
deposit: Omit<Deposit, "messageHash">,
|
|
82
|
-
_relayer =
|
|
82
|
+
_relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
|
|
83
83
|
options: Partial<{
|
|
84
84
|
gasPrice: BigNumberish;
|
|
85
85
|
gasUnits: BigNumberish;
|
|
@@ -87,11 +87,64 @@ export class SvmQuery implements QueryInterface {
|
|
|
87
87
|
priorityFeeMultiplier: BigNumber;
|
|
88
88
|
}> = {}
|
|
89
89
|
): Promise<TransactionCostEstimate> {
|
|
90
|
+
const relayer = _relayer ? toAddressType(_relayer).forceSvmAddress() : this.simulatedRelayerAddress;
|
|
91
|
+
|
|
92
|
+
const fillRelayTx = await this.getFillRelayTx(deposit, relayer.toBase58());
|
|
93
|
+
|
|
94
|
+
const [computeUnitsConsumed, _gasPriceEstimate] = await Promise.all([
|
|
95
|
+
toBN(await this.computeUnitEstimator(fillRelayTx)),
|
|
96
|
+
getGasPriceEstimate(this.provider, {
|
|
97
|
+
unsignedTx: fillRelayTx,
|
|
98
|
+
baseFeeMultiplier: options.baseFeeMultiplier,
|
|
99
|
+
priorityFeeMultiplier: options.priorityFeeMultiplier,
|
|
100
|
+
}),
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
// We can cast the gas price estimate to an SvmGasPriceEstimate here since the oracle should always
|
|
104
|
+
// query the Solana adapter.
|
|
105
|
+
const gasPriceEstimate = _gasPriceEstimate as SvmGasPriceEstimate;
|
|
106
|
+
const gasPrice = gasPriceEstimate.baseFee.add(
|
|
107
|
+
gasPriceEstimate.microLamportsPerComputeUnit.mul(computeUnitsConsumed).div(toBN(1_000_000)) // 1_000_000 microLamports/lamport.
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
nativeGasCost: computeUnitsConsumed,
|
|
112
|
+
tokenGasCost: gasPrice,
|
|
113
|
+
gasPrice,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @notice Return the gas cost of a simulated transaction
|
|
119
|
+
* @param fillRelayTx FillRelay transaction
|
|
120
|
+
* @param relayer SVM address of the relayer
|
|
121
|
+
* @returns Estimated gas cost in compute units
|
|
122
|
+
*/
|
|
123
|
+
async getNativeGasCost(
|
|
124
|
+
deposit: Omit<Deposit, "messageHash">,
|
|
125
|
+
_relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId)
|
|
126
|
+
): Promise<BigNumber> {
|
|
127
|
+
const fillRelayTx = await this.getFillRelayTx(deposit, _relayer);
|
|
128
|
+
const computeUnitsConsumed = toBN(await this.computeUnitEstimator(fillRelayTx));
|
|
129
|
+
return computeUnitsConsumed;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @notice Return the fillRelay transaction for a given deposit
|
|
134
|
+
* @param deposit
|
|
135
|
+
* @param relayer SVM address of the relayer
|
|
136
|
+
* @returns FillRelay transaction
|
|
137
|
+
*/
|
|
138
|
+
async getFillRelayTx(
|
|
139
|
+
deposit: Omit<Deposit, "messageHash">,
|
|
140
|
+
_relayer = getDefaultSimulatedRelayerAddress(deposit.destinationChainId)
|
|
141
|
+
) {
|
|
142
|
+
const relayer = _relayer ? toAddressType(_relayer).forceSvmAddress() : this.simulatedRelayerAddress;
|
|
90
143
|
// If the user did not have a token account created on destination, then we need to include this as a gas cost.
|
|
91
144
|
const mint = toAddressType(deposit.outputToken).forceSvmAddress();
|
|
92
145
|
const owner = toAddressType(deposit.recipient).forceSvmAddress();
|
|
93
146
|
const associatedToken = await getAssociatedTokenAddress(owner, mint);
|
|
94
|
-
const simulatedSigner = SolanaVoidSigner(
|
|
147
|
+
const simulatedSigner = SolanaVoidSigner(relayer.toBase58());
|
|
95
148
|
|
|
96
149
|
// If the recipient has an associated token account on destination, then skip generating the instruction for creating a new token account.
|
|
97
150
|
let recipientCreateTokenAccountInstructions: IInstruction[] | undefined = undefined;
|
|
@@ -134,7 +187,7 @@ export class SvmQuery implements QueryInterface {
|
|
|
134
187
|
const recentBlockhash = await this.provider.getLatestBlockhash().send();
|
|
135
188
|
const fillRelayTx = pipe(
|
|
136
189
|
createTransactionMessage({ version: 0 }),
|
|
137
|
-
(tx) => setTransactionMessageFeePayer(
|
|
190
|
+
(tx) => setTransactionMessageFeePayer(relayer.toV2Address(), tx),
|
|
138
191
|
(tx) => setTransactionMessageLifetimeUsingBlockhash(recentBlockhash.value, tx),
|
|
139
192
|
(tx) =>
|
|
140
193
|
isDefined(recipientCreateTokenAccountInstructions)
|
|
@@ -142,28 +195,7 @@ export class SvmQuery implements QueryInterface {
|
|
|
142
195
|
: tx,
|
|
143
196
|
(tx) => appendTransactionMessageInstructions([createTokenAccountsIx, approveIx, fillIx], tx)
|
|
144
197
|
);
|
|
145
|
-
|
|
146
|
-
const [computeUnitsConsumed, _gasPriceEstimate] = await Promise.all([
|
|
147
|
-
toBN(await this.computeUnitEstimator(fillRelayTx)),
|
|
148
|
-
getGasPriceEstimate(this.provider, {
|
|
149
|
-
unsignedTx: fillRelayTx,
|
|
150
|
-
baseFeeMultiplier: options.baseFeeMultiplier,
|
|
151
|
-
priorityFeeMultiplier: options.priorityFeeMultiplier,
|
|
152
|
-
}),
|
|
153
|
-
]);
|
|
154
|
-
|
|
155
|
-
// We can cast the gas price estimate to an SvmGasPriceEstimate here since the oracle should always
|
|
156
|
-
// query the Solana adapter.
|
|
157
|
-
const gasPriceEstimate = _gasPriceEstimate as SvmGasPriceEstimate;
|
|
158
|
-
const gasPrice = gasPriceEstimate.baseFee.add(
|
|
159
|
-
gasPriceEstimate.microLamportsPerComputeUnit.mul(computeUnitsConsumed).div(toBN(1_000_000)) // 1_000_000 microLamports/lamport.
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
nativeGasCost: computeUnitsConsumed,
|
|
164
|
-
tokenGasCost: gasPrice,
|
|
165
|
-
gasPrice,
|
|
166
|
-
};
|
|
198
|
+
return fillRelayTx;
|
|
167
199
|
}
|
|
168
200
|
|
|
169
201
|
/**
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_SIMULATED_RELAYER_ADDRESS,
|
|
4
|
+
DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM,
|
|
5
|
+
TOKEN_SYMBOLS_MAP,
|
|
6
|
+
} from "../constants";
|
|
3
7
|
import { Deposit } from "../interfaces";
|
|
4
8
|
import {
|
|
5
9
|
BigNumber,
|
|
@@ -18,6 +22,7 @@ import {
|
|
|
18
22
|
toBNWei,
|
|
19
23
|
isZeroAddress,
|
|
20
24
|
compareAddressesSimple,
|
|
25
|
+
chainIsSvm,
|
|
21
26
|
} from "../utils";
|
|
22
27
|
import { Transport } from "viem";
|
|
23
28
|
|
|
@@ -36,6 +41,7 @@ export interface QueryInterface {
|
|
|
36
41
|
}>
|
|
37
42
|
) => Promise<TransactionCostEstimate>;
|
|
38
43
|
getTokenPrice: (tokenSymbol: string) => Promise<number>;
|
|
44
|
+
getNativeGasCost: (deposit: Omit<Deposit, "messageHash">, relayer: string) => Promise<BigNumber>;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
export const expectedCapitalCostsKeys = ["lowerBound", "upperBound", "cutoff", "decimals"];
|
|
@@ -105,6 +111,12 @@ export const DEFAULT_LOGGER: Logger = {
|
|
|
105
111
|
error: (...args) => console.error(args),
|
|
106
112
|
};
|
|
107
113
|
|
|
114
|
+
export function getDefaultSimulatedRelayerAddress(chainId?: number) {
|
|
115
|
+
return isDefined(chainId) && chainIsSvm(chainId)
|
|
116
|
+
? DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM
|
|
117
|
+
: DEFAULT_SIMULATED_RELAYER_ADDRESS;
|
|
118
|
+
}
|
|
119
|
+
|
|
108
120
|
// Small amount to simulate filling with. Should be low enough to guarantee a successful fill.
|
|
109
121
|
const safeOutputAmount = toBN(100);
|
|
110
122
|
|
|
@@ -241,7 +253,7 @@ export class RelayFeeCalculator {
|
|
|
241
253
|
deposit: Deposit,
|
|
242
254
|
amountToRelay: BigNumberish,
|
|
243
255
|
simulateZeroFill = false,
|
|
244
|
-
relayerAddress =
|
|
256
|
+
relayerAddress = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
|
|
245
257
|
_tokenPrice?: number,
|
|
246
258
|
tokenMapping = TOKEN_SYMBOLS_MAP,
|
|
247
259
|
gasPrice?: BigNumberish,
|
|
@@ -480,7 +492,7 @@ export class RelayFeeCalculator {
|
|
|
480
492
|
deposit: Deposit,
|
|
481
493
|
amountToRelay?: BigNumberish,
|
|
482
494
|
simulateZeroFill = false,
|
|
483
|
-
relayerAddress =
|
|
495
|
+
relayerAddress = getDefaultSimulatedRelayerAddress(deposit.destinationChainId),
|
|
484
496
|
_tokenPrice?: number,
|
|
485
497
|
gasPrice?: BigNumberish,
|
|
486
498
|
gasUnits?: BigNumberish,
|
package/src/utils/SpokeUtils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { encodeAbiParameters, keccak256 } from "viem";
|
|
1
|
+
import { encodeAbiParameters, Hex, keccak256 } from "viem";
|
|
2
2
|
import { MAX_SAFE_DEPOSIT_ID, ZERO_ADDRESS, ZERO_BYTES } from "../constants";
|
|
3
3
|
import { Deposit, RelayData } from "../interfaces";
|
|
4
4
|
import { toBytes32 } from "./AddressUtils";
|
|
@@ -91,5 +91,5 @@ export function isZeroAddress(address: string): boolean {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export function getMessageHash(message: string): string {
|
|
94
|
-
return isMessageEmpty(message) ? ZERO_BYTES : keccak256(message as
|
|
94
|
+
return isMessageEmpty(message) ? ZERO_BYTES : keccak256(message as Hex);
|
|
95
95
|
}
|