@across-protocol/sdk 4.3.20 → 4.3.23
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 +4 -2
- package/dist/cjs/arch/svm/SpokeUtils.js +68 -26
- 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 +31 -8
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/caching/Arweave/ArweaveClient.d.ts +4 -1
- package/dist/cjs/caching/Arweave/ArweaveClient.js +66 -17
- package/dist/cjs/caching/Arweave/ArweaveClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +24 -24
- package/dist/cjs/gasPriceOracle/adapters/ethereum.js +1 -5
- package/dist/cjs/gasPriceOracle/adapters/ethereum.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/solana.js +1 -5
- package/dist/cjs/gasPriceOracle/adapters/solana.js.map +1 -1
- package/dist/cjs/providers/utils.js +2 -0
- package/dist/cjs/providers/utils.js.map +1 -1
- package/dist/cjs/utils/BigNumberUtils.d.ts +2 -0
- package/dist/cjs/utils/BigNumberUtils.js +5 -1
- package/dist/cjs/utils/BigNumberUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.d.ts +2 -0
- package/dist/cjs/utils/DepositUtils.js +9 -1
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/cjs/utils/TokenUtils.d.ts +1 -1
- package/dist/cjs/utils/TokenUtils.js +1 -1
- package/dist/cjs/utils/TokenUtils.js.map +1 -1
- package/dist/esm/arch/svm/SpokeUtils.d.ts +4 -2
- package/dist/esm/arch/svm/SpokeUtils.js +70 -29
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/utils.d.ts +15 -1
- package/dist/esm/arch/svm/utils.js +40 -9
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/caching/Arweave/ArweaveClient.d.ts +4 -1
- package/dist/esm/caching/Arweave/ArweaveClient.js +72 -20
- package/dist/esm/caching/Arweave/ArweaveClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +24 -24
- package/dist/esm/gasPriceOracle/adapters/ethereum.js +2 -6
- package/dist/esm/gasPriceOracle/adapters/ethereum.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/solana.js +2 -6
- package/dist/esm/gasPriceOracle/adapters/solana.js.map +1 -1
- package/dist/esm/providers/utils.js +4 -1
- package/dist/esm/providers/utils.js.map +1 -1
- package/dist/esm/utils/BigNumberUtils.d.ts +5 -0
- package/dist/esm/utils/BigNumberUtils.js +5 -0
- package/dist/esm/utils/BigNumberUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.d.ts +16 -2
- package/dist/esm/utils/DepositUtils.js +20 -2
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/esm/utils/TokenUtils.d.ts +3 -23
- package/dist/esm/utils/TokenUtils.js +1 -1
- package/dist/esm/utils/TokenUtils.js.map +1 -1
- package/dist/types/arch/svm/SpokeUtils.d.ts +4 -2
- package/dist/types/arch/svm/SpokeUtils.d.ts.map +1 -1
- package/dist/types/arch/svm/utils.d.ts +15 -1
- package/dist/types/arch/svm/utils.d.ts.map +1 -1
- package/dist/types/caching/Arweave/ArweaveClient.d.ts +4 -1
- package/dist/types/caching/Arweave/ArweaveClient.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +24 -24
- package/dist/types/gasPriceOracle/adapters/ethereum.d.ts.map +1 -1
- package/dist/types/gasPriceOracle/adapters/solana.d.ts.map +1 -1
- package/dist/types/providers/utils.d.ts.map +1 -1
- package/dist/types/utils/BigNumberUtils.d.ts +5 -0
- package/dist/types/utils/BigNumberUtils.d.ts.map +1 -1
- package/dist/types/utils/DepositUtils.d.ts +16 -2
- package/dist/types/utils/DepositUtils.d.ts.map +1 -1
- package/dist/types/utils/TokenUtils.d.ts +3 -23
- package/dist/types/utils/TokenUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/arch/svm/SpokeUtils.ts +75 -14
- package/src/arch/svm/utils.ts +43 -8
- package/src/caching/Arweave/ArweaveClient.ts +47 -12
- package/src/gasPriceOracle/adapters/ethereum.ts +2 -6
- package/src/gasPriceOracle/adapters/solana.ts +2 -7
- package/src/providers/utils.ts +3 -0
- package/src/utils/BigNumberUtils.ts +6 -0
- package/src/utils/DepositUtils.ts +41 -2
- package/src/utils/TokenUtils.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/TokenUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAY,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAGpE,KAAK,gBAAgB,GAAG,SAAS,CAAC,QAAQ,GAAG,MAAM,CAAC;AAEpD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAI9G;AAED,eAAO,MAAM,mBAAmB,mBACd,MAAM;;aAMvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAa/E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,WAC5B,MAAM,WACL,MAAM
|
|
1
|
+
{"version":3,"file":"TokenUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/TokenUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { MessageTransmitterClient, SvmSpokeClient, TokenMessengerMinterClient } from "@across-protocol/contracts";
|
|
2
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";
|
|
3
|
+
import { decodeMessageHeader, hashNonEmptyMessage } from "@across-protocol/contracts/dist/src/svm/web3-v1";
|
|
4
4
|
import { intToU8Array32 } from "@across-protocol/contracts/dist/src/svm/web3-v1/conversionUtils";
|
|
5
5
|
import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
|
|
6
6
|
import {
|
|
7
7
|
ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
8
|
+
Mint,
|
|
8
9
|
TOKEN_PROGRAM_ADDRESS,
|
|
9
10
|
fetchMint,
|
|
10
11
|
getApproveCheckedInstruction,
|
|
11
12
|
getCreateAssociatedTokenIdempotentInstruction,
|
|
12
13
|
} from "@solana-program/token";
|
|
13
14
|
import {
|
|
15
|
+
Account,
|
|
14
16
|
AccountRole,
|
|
15
17
|
Address,
|
|
18
|
+
FetchAccountConfig,
|
|
16
19
|
IAccountMeta,
|
|
17
20
|
KeyPairSigner,
|
|
18
21
|
ReadonlyUint8Array,
|
|
@@ -61,11 +64,17 @@ import {
|
|
|
61
64
|
simulateAndDecode,
|
|
62
65
|
toAddress,
|
|
63
66
|
unwrapEventData,
|
|
67
|
+
getRootBundlePda,
|
|
64
68
|
} from "./";
|
|
65
69
|
import { SvmCpiEventsClient } from "./eventsClient";
|
|
66
70
|
import { SVM_NO_BLOCK_AT_SLOT, isSolanaError } from "./provider";
|
|
67
71
|
import { AttestedCCTPMessage, SVMEventNames, SVMProvider } from "./types";
|
|
68
|
-
import {
|
|
72
|
+
import {
|
|
73
|
+
getEmergencyDeleteRootBundleRootBundleId,
|
|
74
|
+
getNearestSlotTime,
|
|
75
|
+
isEmergencyDeleteRootBundleMessageBody,
|
|
76
|
+
isRelayRootBundleMessageBody,
|
|
77
|
+
} from "./utils";
|
|
69
78
|
|
|
70
79
|
/**
|
|
71
80
|
* @note: Average Solana slot duration is about 400-500ms. We can be conservative
|
|
@@ -555,7 +564,7 @@ export async function getFillRelayTx(
|
|
|
555
564
|
]);
|
|
556
565
|
|
|
557
566
|
const mint = toAddress(outputToken);
|
|
558
|
-
const mintInfo = await
|
|
567
|
+
const mintInfo = await getMintInfo(solanaClient, mint);
|
|
559
568
|
|
|
560
569
|
const [recipientAta, relayerAta, fillStatus, eventAuthority] = await Promise.all([
|
|
561
570
|
getAssociatedTokenAddress(recipient, outputToken, mintInfo.programAddress),
|
|
@@ -618,7 +627,7 @@ export const createFillInstruction = async (
|
|
|
618
627
|
tokenDecimals: number,
|
|
619
628
|
createRecipientAtaIfNeeded: boolean = true
|
|
620
629
|
) => {
|
|
621
|
-
const mintInfo = await
|
|
630
|
+
const mintInfo = await getMintInfo(solanaClient, fillInput.mint);
|
|
622
631
|
const approveIx = getApproveCheckedInstruction(
|
|
623
632
|
{
|
|
624
633
|
source: fillInput.relayerTokenAccount,
|
|
@@ -679,7 +688,7 @@ export const createDepositInstruction = async (
|
|
|
679
688
|
systemProgram: depositInput.systemProgram,
|
|
680
689
|
tokenProgram: depositInput.tokenProgram,
|
|
681
690
|
});
|
|
682
|
-
const mintInfo = await
|
|
691
|
+
const mintInfo = await getMintInfo(solanaClient, depositInput.mint);
|
|
683
692
|
const approveIx = getApproveCheckedInstruction(
|
|
684
693
|
{
|
|
685
694
|
source: depositInput.depositorTokenAccount,
|
|
@@ -1112,15 +1121,59 @@ export const hasCCTPV1MessageBeenProcessed = async (
|
|
|
1112
1121
|
* Returns the account metas for a tokenless message.
|
|
1113
1122
|
* @returns The account metas for a tokenless message.
|
|
1114
1123
|
*/
|
|
1115
|
-
export async function getAccountMetasForTokenlessMessage(
|
|
1116
|
-
|
|
1117
|
-
|
|
1124
|
+
export async function getAccountMetasForTokenlessMessage(
|
|
1125
|
+
solanaClient: SVMProvider,
|
|
1126
|
+
signer: KeyPairSigner,
|
|
1127
|
+
messageBytes: string
|
|
1128
|
+
): Promise<IAccountMeta<string>[]> {
|
|
1129
|
+
const messageHeader = decodeMessageHeader(Buffer.from(messageBytes, "hex"));
|
|
1130
|
+
const programAddress = SvmSpokeClient.SVM_SPOKE_PROGRAM_ADDRESS;
|
|
1131
|
+
const statePda = await getStatePda(programAddress);
|
|
1132
|
+
const selfAuthority = await getSelfAuthority();
|
|
1133
|
+
const eventAuthority = await getEventAuthority(programAddress);
|
|
1134
|
+
|
|
1135
|
+
const base: IAccountMeta<string>[] = [
|
|
1118
1136
|
{ address: statePda, role: AccountRole.READONLY },
|
|
1119
|
-
{ address:
|
|
1120
|
-
{ address:
|
|
1137
|
+
{ address: selfAuthority, role: AccountRole.READONLY },
|
|
1138
|
+
{ address: programAddress, role: AccountRole.READONLY },
|
|
1139
|
+
];
|
|
1140
|
+
|
|
1141
|
+
if (isRelayRootBundleMessageBody(messageHeader.messageBody)) {
|
|
1142
|
+
const {
|
|
1143
|
+
data: { rootBundleId },
|
|
1144
|
+
} = await SvmSpokeClient.fetchState(solanaClient, statePda);
|
|
1145
|
+
const rootBundle = await getRootBundlePda(programAddress, rootBundleId);
|
|
1146
|
+
|
|
1147
|
+
return [
|
|
1148
|
+
...base,
|
|
1149
|
+
{ address: signer.address, role: AccountRole.WRITABLE },
|
|
1150
|
+
{ address: statePda, role: AccountRole.WRITABLE },
|
|
1151
|
+
{ address: rootBundle, role: AccountRole.WRITABLE },
|
|
1152
|
+
{ address: SYSTEM_PROGRAM_ADDRESS, role: AccountRole.READONLY },
|
|
1153
|
+
{ address: eventAuthority, role: AccountRole.READONLY },
|
|
1154
|
+
{ address: programAddress, role: AccountRole.READONLY },
|
|
1155
|
+
];
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
if (isEmergencyDeleteRootBundleMessageBody(messageHeader.messageBody)) {
|
|
1159
|
+
const rootBundleId = getEmergencyDeleteRootBundleRootBundleId(messageHeader.messageBody);
|
|
1160
|
+
const rootBundle = await getRootBundlePda(programAddress, rootBundleId);
|
|
1161
|
+
|
|
1162
|
+
return [
|
|
1163
|
+
...base,
|
|
1164
|
+
{ address: signer.address, role: AccountRole.READONLY },
|
|
1165
|
+
{ address: statePda, role: AccountRole.READONLY },
|
|
1166
|
+
{ address: rootBundle, role: AccountRole.WRITABLE },
|
|
1167
|
+
{ address: eventAuthority, role: AccountRole.READONLY },
|
|
1168
|
+
{ address: programAddress, role: AccountRole.READONLY },
|
|
1169
|
+
];
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
return [
|
|
1173
|
+
...base,
|
|
1121
1174
|
{ address: statePda, role: AccountRole.WRITABLE },
|
|
1122
|
-
{ address:
|
|
1123
|
-
{ address:
|
|
1175
|
+
{ address: eventAuthority, role: AccountRole.READONLY },
|
|
1176
|
+
{ address: programAddress, role: AccountRole.READONLY },
|
|
1124
1177
|
];
|
|
1125
1178
|
}
|
|
1126
1179
|
|
|
@@ -1246,7 +1299,7 @@ export async function getCCTPV1ReceiveMessageTx(
|
|
|
1246
1299
|
hubChainId,
|
|
1247
1300
|
TokenMessengerMinterClient.TOKEN_MESSENGER_MINTER_PROGRAM_ADDRESS
|
|
1248
1301
|
)
|
|
1249
|
-
: await getAccountMetasForTokenlessMessage();
|
|
1302
|
+
: await getAccountMetasForTokenlessMessage(solanaClient, signer, message.messageBytes);
|
|
1250
1303
|
|
|
1251
1304
|
const messageBytes = message.messageBytes.startsWith("0x")
|
|
1252
1305
|
? Buffer.from(message.messageBytes.slice(2), "hex")
|
|
@@ -1260,7 +1313,7 @@ export async function getCCTPV1ReceiveMessageTx(
|
|
|
1260
1313
|
messageTransmitter: messageTransmitterPda,
|
|
1261
1314
|
eventAuthority: eventAuthorityPda,
|
|
1262
1315
|
usedNonces,
|
|
1263
|
-
receiver:
|
|
1316
|
+
receiver: cctpMessageReceiver,
|
|
1264
1317
|
systemProgram: SYSTEM_PROGRAM_ADDRESS,
|
|
1265
1318
|
message: messageBytes,
|
|
1266
1319
|
attestation: Buffer.from(message.attestation.slice(2), "hex"),
|
|
@@ -1315,3 +1368,11 @@ export function finalizeCCTPV1Messages(
|
|
|
1315
1368
|
return signature;
|
|
1316
1369
|
});
|
|
1317
1370
|
}
|
|
1371
|
+
|
|
1372
|
+
export async function getMintInfo(
|
|
1373
|
+
solanaClient: SVMProvider,
|
|
1374
|
+
mint: Address<string>,
|
|
1375
|
+
config?: FetchAccountConfig
|
|
1376
|
+
): Promise<Account<Mint, string>> {
|
|
1377
|
+
return await fetchMint(solanaClient, mint, config);
|
|
1378
|
+
}
|
package/src/arch/svm/utils.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { MessageTransmitterClient, SvmSpokeClient } from "@across-protocol/contracts";
|
|
1
|
+
import { MessageTransmitterClient, SpokePool__factory, SvmSpokeClient } from "@across-protocol/contracts";
|
|
3
2
|
import { BN, BorshEventCoder, Idl } from "@coral-xyz/anchor";
|
|
4
3
|
import {
|
|
5
4
|
Address,
|
|
6
|
-
type Commitment,
|
|
7
5
|
IInstruction,
|
|
8
6
|
KeyPairSigner,
|
|
9
7
|
address,
|
|
@@ -19,14 +17,16 @@ import {
|
|
|
19
17
|
setTransactionMessageFeePayerSigner,
|
|
20
18
|
setTransactionMessageLifetimeUsingBlockhash,
|
|
21
19
|
signTransactionMessageWithSigners,
|
|
20
|
+
type Commitment,
|
|
22
21
|
type TransactionSigner,
|
|
23
22
|
} from "@solana/kit";
|
|
23
|
+
import assert from "assert";
|
|
24
24
|
import bs58 from "bs58";
|
|
25
25
|
import { ethers } from "ethers";
|
|
26
26
|
import { FillType, RelayData } from "../../interfaces";
|
|
27
|
-
import { BigNumber, Address as SdkAddress, getRelayDataHash, isDefined, isUint8Array } from "../../utils";
|
|
28
|
-
import { AttestedCCTPMessage, EventName, SVMEventNames, SVMProvider } from "./types";
|
|
27
|
+
import { BigNumber, Address as SdkAddress, biMin, getRelayDataHash, isDefined, isUint8Array } from "../../utils";
|
|
29
28
|
import { getTimestampForSlot } from "./SpokeUtils";
|
|
29
|
+
import { AttestedCCTPMessage, EventName, SVMEventNames, SVMProvider } from "./types";
|
|
30
30
|
|
|
31
31
|
export { isSolanaError } from "@solana/kit";
|
|
32
32
|
|
|
@@ -90,11 +90,11 @@ export async function getLatestFinalizedSlotWithBlock(
|
|
|
90
90
|
maxSlot: bigint,
|
|
91
91
|
maxLookback = 1000
|
|
92
92
|
): Promise<number> {
|
|
93
|
-
const { slot: finalizedSlot } = await getNearestSlotTime(provider, { commitment: "finalized" });
|
|
94
|
-
const endSlot = Math.min(Number(maxSlot), Number(finalizedSlot));
|
|
95
93
|
const opts = { maxSupportedTransactionVersion: 0, transactionDetails: "none", rewards: false } as const;
|
|
94
|
+
const { slot: finalizedSlot } = await getNearestSlotTime(provider, { commitment: "finalized" });
|
|
95
|
+
const endSlot = biMin(maxSlot, finalizedSlot);
|
|
96
96
|
|
|
97
|
-
let slot =
|
|
97
|
+
let slot = endSlot;
|
|
98
98
|
do {
|
|
99
99
|
const block = await provider.getBlock(slot, opts).send();
|
|
100
100
|
if (isDefined(block) && [block.blockHeight, block.blockTime].every(isDefined)) {
|
|
@@ -472,6 +472,41 @@ export function isDepositForBurnEvent(event: AttestedCCTPMessage): boolean {
|
|
|
472
472
|
return event.type === "transfer";
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
/**
|
|
476
|
+
* True if `body` encodes a `relayRootBundle(bytes32,bytes32)` call.
|
|
477
|
+
*/
|
|
478
|
+
export const isRelayRootBundleMessageBody = (body: Buffer): boolean => {
|
|
479
|
+
if (body.length < 4) return false;
|
|
480
|
+
|
|
481
|
+
const spokePoolInterface = new ethers.utils.Interface(SpokePool__factory.abi);
|
|
482
|
+
const relayRootBundleSelector = spokePoolInterface.getSighash("relayRootBundle");
|
|
483
|
+
|
|
484
|
+
return body.slice(0, 4).equals(Buffer.from(relayRootBundleSelector.slice(2), "hex"));
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* True if `body` encodes a `emergencyDeleteRootBundle(uint32)` call.
|
|
489
|
+
*/
|
|
490
|
+
export const isEmergencyDeleteRootBundleMessageBody = (body: Buffer): boolean => {
|
|
491
|
+
if (body.length < 4) return false;
|
|
492
|
+
|
|
493
|
+
const spokePoolInterface = new ethers.utils.Interface(SpokePool__factory.abi);
|
|
494
|
+
const emergencyDeleteRootBundleSelector = spokePoolInterface.getSighash("emergencyDeleteRootBundle");
|
|
495
|
+
|
|
496
|
+
return body.slice(0, 4).equals(Buffer.from(emergencyDeleteRootBundleSelector.slice(2), "hex"));
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Decodes the root bundle ID from an emergency delete root bundle message body.
|
|
501
|
+
* @param body The message body.
|
|
502
|
+
* @returns The root bundle ID.
|
|
503
|
+
*/
|
|
504
|
+
export const getEmergencyDeleteRootBundleRootBundleId = (body: Buffer): number => {
|
|
505
|
+
const spokePoolInterface = new ethers.utils.Interface(SpokePool__factory.abi);
|
|
506
|
+
const result = spokePoolInterface.decodeFunctionData("emergencyDeleteRootBundle", body);
|
|
507
|
+
return result.rootBundleId.toNumber();
|
|
508
|
+
};
|
|
509
|
+
|
|
475
510
|
/**
|
|
476
511
|
* Convert a bigint (0 ≤ n < 2^256) to a 32-byte Uint8Array (big-endian).
|
|
477
512
|
* @param n The bigint to convert.
|
|
@@ -4,7 +4,7 @@ import axios from "axios";
|
|
|
4
4
|
import { Struct, create } from "superstruct";
|
|
5
5
|
import winston from "winston";
|
|
6
6
|
import { ARWEAVE_TAG_APP_NAME, ARWEAVE_TAG_APP_VERSION, DEFAULT_ARWEAVE_STORAGE_ADDRESS } from "../../constants";
|
|
7
|
-
import { BigNumber, isDefined, jsonReplacerWithBigNumbers, toBN } from "../../utils";
|
|
7
|
+
import { BigNumber, delay, isDefined, jsonReplacerWithBigNumbers, toBN } from "../../utils";
|
|
8
8
|
|
|
9
9
|
export class ArweaveClient {
|
|
10
10
|
private client: Arweave;
|
|
@@ -15,7 +15,9 @@ export class ArweaveClient {
|
|
|
15
15
|
private logger: winston.Logger,
|
|
16
16
|
gatewayURL = "arweave.net",
|
|
17
17
|
protocol = "https",
|
|
18
|
-
port = 443
|
|
18
|
+
port = 443,
|
|
19
|
+
private readonly retries = 2,
|
|
20
|
+
private readonly retryDelaySeconds = 1
|
|
19
21
|
) {
|
|
20
22
|
this.gatewayUrl = `${protocol}://${gatewayURL}:${port}`;
|
|
21
23
|
this.client = new Arweave({
|
|
@@ -30,6 +32,12 @@ export class ArweaveClient {
|
|
|
30
32
|
message: "Arweave client initialized",
|
|
31
33
|
gateway: this.gatewayUrl,
|
|
32
34
|
});
|
|
35
|
+
if (this.retries < 0) {
|
|
36
|
+
throw new Error(`retries cannot be < 0 and must be an integer. Currently set to ${this.retries}`);
|
|
37
|
+
}
|
|
38
|
+
if (this.retryDelaySeconds < 0) {
|
|
39
|
+
throw new Error(`delay cannot be < 0. Currently set to ${this.retryDelaySeconds}`);
|
|
40
|
+
}
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
/**
|
|
@@ -225,21 +233,48 @@ export class ArweaveClient {
|
|
|
225
233
|
return this.client.wallets.jwkToAddress(this.arweaveJWT);
|
|
226
234
|
}
|
|
227
235
|
|
|
236
|
+
private async _retryRequest<T>(request: () => Promise<T>, retryCount: number): Promise<T> {
|
|
237
|
+
try {
|
|
238
|
+
return request();
|
|
239
|
+
} catch (e) {
|
|
240
|
+
if (retryCount < this.retries) {
|
|
241
|
+
// Implement a slightly aggressive exponential backoff to account for fierce parallelism.
|
|
242
|
+
const baseDelay = this.retryDelaySeconds * Math.pow(2, retryCount); // ms; attempt = [0, 1, 2, ...]
|
|
243
|
+
const delayS = baseDelay + baseDelay * Math.random();
|
|
244
|
+
this.logger.debug({
|
|
245
|
+
at: "ArweaveClient:getBalance",
|
|
246
|
+
message: `Arweave request failed, retrying after waiting ${delayS} seconds: ${e}`,
|
|
247
|
+
retryCount,
|
|
248
|
+
});
|
|
249
|
+
await delay(delayS);
|
|
250
|
+
return this._retryRequest(request, retryCount + 1);
|
|
251
|
+
} else {
|
|
252
|
+
throw e;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
228
257
|
/**
|
|
229
258
|
* The balance of the signer
|
|
230
259
|
* @returns The balance of the signer in winston units
|
|
231
260
|
*/
|
|
232
261
|
async getBalance(): Promise<BigNumber> {
|
|
233
262
|
const address = await this.getAddress();
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
263
|
+
const request = async () => {
|
|
264
|
+
const balanceInFloat = await this.client.wallets.getBalance(address);
|
|
265
|
+
// @dev The reason we add in the BN.from into this retry loop is because the client.getBalance call
|
|
266
|
+
// does not correctly throw an error if the request fails, instead it will return the error string as the
|
|
267
|
+
// balanceInFloat.
|
|
268
|
+
// Sometimes the balance is returned in scientific notation, so we need to
|
|
269
|
+
// convert it to a BigNumber
|
|
270
|
+
if (balanceInFloat.includes("e")) {
|
|
271
|
+
const [balance, exponent] = balanceInFloat.split("e");
|
|
272
|
+
const resultingBN = BigNumber.from(balance).mul(toBN(10).pow(exponent.replace("+", "")));
|
|
273
|
+
return BigNumber.from(resultingBN.toString());
|
|
274
|
+
} else {
|
|
275
|
+
return BigNumber.from(balanceInFloat);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
return await this._retryRequest(request, 0);
|
|
244
279
|
}
|
|
245
280
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
2
|
import { providers } from "ethers";
|
|
3
|
-
import { BigNumber, bnZero, fixedPointAdjustment, getNetworkName
|
|
3
|
+
import { BigNumber, bnZero, fixedPointAdjustment, getNetworkName } from "../../utils";
|
|
4
4
|
import { EvmGasPriceEstimate } from "../types";
|
|
5
5
|
import { gasPriceError } from "../util";
|
|
6
6
|
import { GasPriceEstimateOptions } from "../oracle";
|
|
@@ -37,11 +37,7 @@ export async function eip1559Raw(
|
|
|
37
37
|
const maxPriorityFeePerGas = BigNumber.from(_maxPriorityFeePerGas);
|
|
38
38
|
assert(BigNumber.isBigNumber(baseFeePerGas), `No baseFeePerGas received on ${getNetworkName(chainId)}`);
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
const flooredPriorityFeePerGas = parseUnits(process.env[`MIN_PRIORITY_FEE_PER_GAS_${chainId}`] || "0", 9);
|
|
42
|
-
if (scaledPriorityFee.lt(flooredPriorityFeePerGas)) {
|
|
43
|
-
scaledPriorityFee = BigNumber.from(flooredPriorityFeePerGas);
|
|
44
|
-
}
|
|
40
|
+
const scaledPriorityFee = maxPriorityFeePerGas.mul(priorityFeeMultiplier).div(fixedPointAdjustment);
|
|
45
41
|
const scaledBaseFee = baseFeePerGas.mul(baseFeeMultiplier).div(fixedPointAdjustment);
|
|
46
42
|
return {
|
|
47
43
|
maxFeePerGas: scaledPriorityFee.add(scaledBaseFee),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SVMProvider } from "../../arch/svm";
|
|
2
|
-
import { toBN, dedupArray
|
|
2
|
+
import { toBN, dedupArray } from "../../utils";
|
|
3
3
|
import { SvmGasPriceEstimate } from "../types";
|
|
4
4
|
import { GasPriceEstimateOptions } from "../oracle";
|
|
5
5
|
import { CompilableTransactionMessage, TransactionMessageBytesBase64, compileTransaction } from "@solana/kit";
|
|
@@ -32,14 +32,9 @@ export async function messageFee(provider: SVMProvider, opts: GasPriceEstimateOp
|
|
|
32
32
|
.filter((fee) => fee > 0);
|
|
33
33
|
const totalPrioritizationFees = nonzeroPrioritizationFees.reduce((acc, fee) => acc + fee, BigInt(0));
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
const flooredPriorityFeePerGas = parseUnits(process.env[`MIN_PRIORITY_FEE_PER_GAS_${opts.chainId}`] || "0", 6);
|
|
37
|
-
let microLamportsPerComputeUnit = toBN(
|
|
35
|
+
const microLamportsPerComputeUnit = toBN(
|
|
38
36
|
totalPrioritizationFees / BigInt(Math.max(nonzeroPrioritizationFees.length, 1))
|
|
39
37
|
);
|
|
40
|
-
if (microLamportsPerComputeUnit.lt(flooredPriorityFeePerGas)) {
|
|
41
|
-
microLamportsPerComputeUnit = flooredPriorityFeePerGas;
|
|
42
|
-
}
|
|
43
38
|
return {
|
|
44
39
|
baseFee: toBN(baseFeeResponse!.value!),
|
|
45
40
|
microLamportsPerComputeUnit,
|
package/src/providers/utils.ts
CHANGED
|
@@ -96,14 +96,17 @@ const IGNORED_FIELDS = {
|
|
|
96
96
|
// 2023-08-31 Added blockHash because of upstream zkSync provider disagreements. Consider removing later.
|
|
97
97
|
// 2024-05-07 Added l1BatchNumber and logType due to Alchemy. Consider removing later.
|
|
98
98
|
// 2024-07-11 Added blockTimestamp after zkSync rolled out a new node release.
|
|
99
|
+
// 2025-07-24 Added additional fields returned by Chainstack on (at least) Polygon.
|
|
99
100
|
eth_getBlockByNumber: [
|
|
100
101
|
"miner", // polygon (sometimes)
|
|
101
102
|
"l1BatchNumber", // zkSync
|
|
102
103
|
"l1BatchTimestamp", // zkSync
|
|
104
|
+
"requestsHash", // Chainstack (Polygon)
|
|
103
105
|
"size", // Alchemy/Arbitrum (temporary)
|
|
104
106
|
"totalDifficulty", // Quicknode/Alchemy (sometimes)
|
|
105
107
|
"logsBloom", // zkSync (third-party providers return 0x0..0)
|
|
106
108
|
"transactions", // Polygon yParity field in transactions[]
|
|
109
|
+
"withdrawals", // Chainstack (Polygon)
|
|
107
110
|
],
|
|
108
111
|
eth_getLogs: ["blockTimestamp", "transactionLogIndex", "l1BatchNumber", "logType"],
|
|
109
112
|
};
|
|
@@ -19,6 +19,12 @@ export const bnOne = BigNumber.from("1");
|
|
|
19
19
|
export const bnUint32Max = BigNumber.from("0xffffffff");
|
|
20
20
|
export const bnUint256Max = BigNumber.from("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* BigInt min/max helpers.
|
|
24
|
+
*/
|
|
25
|
+
export const biMin = (a: bigint, b: bigint) => (a > b ? b : a);
|
|
26
|
+
export const biMax = (a: bigint, b: bigint) => (a > b ? a : b);
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* Converts a stringified number into a BigNumber with 18 decimal places.
|
|
24
30
|
* @param num The number to parse.
|
|
@@ -265,7 +265,7 @@ export function resolveDepositMessage(deposit: Deposit): string {
|
|
|
265
265
|
* Converts a RelayData object with `Address` types as address fields to a `RelayData`-like object with
|
|
266
266
|
* strings as address fields.
|
|
267
267
|
* @param relayData RelayData type.
|
|
268
|
-
* @returns a RelayData-like type which has strings as fields.
|
|
268
|
+
* @returns a RelayData-like type which has hex 32 byte strings as fields.
|
|
269
269
|
*/
|
|
270
270
|
export function convertRelayDataParamsToBytes32(relayData: RelayData): ConvertedRelayData {
|
|
271
271
|
return {
|
|
@@ -282,7 +282,7 @@ export function convertRelayDataParamsToBytes32(relayData: RelayData): Converted
|
|
|
282
282
|
* Converts a Fill object with `Address` types as address fields to a `RelayData`-like object with
|
|
283
283
|
* strings as address fields.
|
|
284
284
|
* @param relayData RelayData type.
|
|
285
|
-
* @returns a RelayData-like type which has strings as fields.
|
|
285
|
+
* @returns a RelayData-like type which has hex 32 byte strings as fields.
|
|
286
286
|
*/
|
|
287
287
|
export function convertFillParamsToBytes32(fill: Fill): ConvertedFill {
|
|
288
288
|
return {
|
|
@@ -299,3 +299,42 @@ export function convertFillParamsToBytes32(fill: Fill): ConvertedFill {
|
|
|
299
299
|
},
|
|
300
300
|
};
|
|
301
301
|
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Converts a RelayData object with `Address` types as address fields to a `RelayData`-like object with
|
|
305
|
+
* strings as address fields.
|
|
306
|
+
* @param relayData RelayData type.
|
|
307
|
+
* @returns a RelayData-like type which has native address representation strings as fields.
|
|
308
|
+
*/
|
|
309
|
+
export function convertRelayDataParamsToNative(relayData: RelayData): ConvertedRelayData {
|
|
310
|
+
return {
|
|
311
|
+
...relayData,
|
|
312
|
+
depositor: relayData.depositor.toNative(),
|
|
313
|
+
recipient: relayData.recipient.toNative(),
|
|
314
|
+
inputToken: relayData.inputToken.toNative(),
|
|
315
|
+
outputToken: relayData.outputToken.toNative(),
|
|
316
|
+
exclusiveRelayer: relayData.exclusiveRelayer.toNative(),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Converts a Fill object with `Address` types as address fields to a `RelayData`-like object with
|
|
322
|
+
* strings as address fields.
|
|
323
|
+
* @param relayData RelayData type.
|
|
324
|
+
* @returns a RelayData-like type which has native address representation strings as fields.
|
|
325
|
+
*/
|
|
326
|
+
export function convertFillParamsToNative(fill: Fill): ConvertedFill {
|
|
327
|
+
return {
|
|
328
|
+
...fill,
|
|
329
|
+
depositor: fill.depositor.toNative(),
|
|
330
|
+
recipient: fill.recipient.toNative(),
|
|
331
|
+
inputToken: fill.inputToken.toNative(),
|
|
332
|
+
outputToken: fill.outputToken.toNative(),
|
|
333
|
+
exclusiveRelayer: fill.exclusiveRelayer.toNative(),
|
|
334
|
+
relayer: fill.relayer.toNative(),
|
|
335
|
+
relayExecutionInfo: {
|
|
336
|
+
...fill.relayExecutionInfo,
|
|
337
|
+
updatedRecipient: fill.relayExecutionInfo.updatedRecipient.toNative(),
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
}
|
package/src/utils/TokenUtils.ts
CHANGED
|
@@ -58,12 +58,12 @@ export function resolveSymbolOnChain(chainId: number, symbol: string): TokenInfo
|
|
|
58
58
|
*/
|
|
59
59
|
export const resolveContractFromSymbol = (
|
|
60
60
|
symbol: string,
|
|
61
|
-
chainId:
|
|
61
|
+
chainId: number,
|
|
62
62
|
tokenMapping = TOKEN_SYMBOLS_MAP
|
|
63
63
|
): string | undefined => {
|
|
64
64
|
return Object.values(tokenMapping).find((details) => {
|
|
65
65
|
return details.symbol.toLowerCase() === symbol.toLowerCase();
|
|
66
|
-
})?.addresses[
|
|
66
|
+
})?.addresses[chainId];
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
export function getCoingeckoTokenIdByAddress(address: string, chainId: number): string {
|