@continuumdao/ctm-mpc-defi 0.2.0 → 0.2.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/README.md +20 -78
- package/dist/agent/catalog.cjs +563 -5
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +166 -20
- package/dist/agent/catalog.js +551 -7
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/aave-v4/SKILL.md +43 -0
- package/dist/agent/skills/curve-dao/SKILL.md +13 -0
- package/dist/agent/skills/ethena/SKILL.md +10 -0
- package/dist/agent/skills/euler-v2/SKILL.md +10 -0
- package/dist/agent/skills/lido/SKILL.md +22 -0
- package/dist/agent/skills/maple-syrup/SKILL.md +10 -0
- package/dist/agent/skills/sky/SKILL.md +10 -0
- package/dist/agent/skills/uniswap-v4/SKILL.md +22 -0
- package/dist/chains/evm/index.cjs +79 -224
- package/dist/chains/evm/index.cjs.map +1 -1
- package/dist/chains/evm/index.d.ts +26 -26
- package/dist/chains/evm/index.js +69 -209
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/near/index.d.ts +1 -1
- package/dist/chains/solana/index.d.ts +1 -1
- package/dist/core/index.cjs +68 -106
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +21 -36
- package/dist/core/index.js +57 -96
- package/dist/core/index.js.map +1 -1
- package/dist/{envelope-CcE5Cz_q.d.ts → envelope-CpBUh9eP.d.ts} +1 -1
- package/dist/index.cjs +356 -1855
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -11
- package/dist/index.js +332 -1826
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +1152 -669
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +418 -3
- package/dist/protocols/evm/aave-v4/index.js +1126 -670
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +257 -131
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +69 -5
- package/dist/protocols/evm/curve-dao/index.js +242 -124
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +394 -402
- package/dist/protocols/evm/ethena/index.cjs.map +1 -1
- package/dist/protocols/evm/ethena/index.d.ts +47 -3
- package/dist/protocols/evm/ethena/index.js +390 -404
- package/dist/protocols/evm/ethena/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +2810 -1191
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +465 -3
- package/dist/protocols/evm/euler-v2/index.js +2761 -1192
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.cjs +351 -236
- package/dist/protocols/evm/lido/index.cjs.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +34 -4
- package/dist/protocols/evm/lido/index.js +348 -238
- package/dist/protocols/evm/lido/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs +390 -395
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.d.ts +23 -3
- package/dist/protocols/evm/maple/index.js +390 -397
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/sky/index.cjs +454 -232
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.d.ts +57 -3
- package/dist/protocols/evm/sky/index.js +444 -231
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.cjs +423 -658
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +3 -4
- package/dist/protocols/evm/uniswap-v4/index.js +422 -657
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/dist/{registry-oMKlO_5z.d.ts → registry-Bv5o37_w.d.ts} +1 -1
- package/dist/{types-Ce2qNHai.d.cts → types-BfjWdw1j.d.ts} +3 -1
- package/dist/{types-5u863Fd9.d.ts → types-DUeNJLr9.d.ts} +1 -1
- package/package.json +7 -6
- package/dist/agent/catalog.d.cts +0 -939
- package/dist/chains/evm/index.d.cts +0 -64
- package/dist/chains/near/index.d.cts +0 -37
- package/dist/chains/solana/index.d.cts +0 -40
- package/dist/core/index.d.cts +0 -43
- package/dist/envelope-DYDPnrHZ.d.cts +0 -35
- package/dist/index.d.cts +0 -16
- package/dist/keygen-CfNp8yKJ.d.cts +0 -9
- package/dist/keygen-DsINazx8.d.ts +0 -9
- package/dist/nodeRead-BnmSaMGO.d.cts +0 -8
- package/dist/nodeRead-BnmSaMGO.d.ts +0 -8
- package/dist/protocols/evm/aave-v4/index.d.cts +0 -500
- package/dist/protocols/evm/curve-dao/index.d.cts +0 -147
- package/dist/protocols/evm/ethena/index.d.cts +0 -161
- package/dist/protocols/evm/euler-v2/index.d.cts +0 -317
- package/dist/protocols/evm/lido/index.d.cts +0 -120
- package/dist/protocols/evm/maple/index.d.cts +0 -109
- package/dist/protocols/evm/sky/index.d.cts +0 -218
- package/dist/protocols/evm/uniswap-v4/index.d.cts +0 -324
- package/dist/registry-BwZoE668.d.cts +0 -8
- package/dist/txParams-BC7ogvdR.d.cts +0 -19
- package/dist/txParams-BC7ogvdR.d.ts +0 -19
- package/dist/types-B8idm_gu.d.cts +0 -34
- package/dist/types-Ce2qNHai.d.ts +0 -57
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var viem = require('viem');
|
|
4
|
+
var continuumNodeSdk = require('@continuumdao/continuum-node-sdk');
|
|
4
5
|
|
|
5
6
|
// src/core/registry.ts
|
|
6
7
|
var modules = [];
|
|
@@ -12,18 +13,26 @@ function registerProtocolModule(mod) {
|
|
|
12
13
|
modules.push(mod);
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const r = await fetch(AAVE_V4_GRAPHQL_URL, {
|
|
16
|
+
async function postJsonViaOptionalProxy(args) {
|
|
17
|
+
const r = await fetch(args.directUrl, {
|
|
18
18
|
method: "POST",
|
|
19
19
|
headers: { "content-type": "application/json" },
|
|
20
|
-
body: JSON.stringify(
|
|
20
|
+
body: JSON.stringify(args.body)
|
|
21
21
|
});
|
|
22
22
|
if (!r.ok) {
|
|
23
23
|
const t = await r.text().catch(() => "");
|
|
24
|
-
throw new Error(t ? `
|
|
24
|
+
throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
return await r.json();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/protocols/evm/aave-v4/api.ts
|
|
30
|
+
var AAVE_V4_GRAPHQL_URL = "https://api.v4.aave.com/graphql";
|
|
31
|
+
async function aaveV4Gql(query, variables) {
|
|
32
|
+
const body = { query, variables: variables ?? {} };
|
|
33
|
+
const j = await postJsonViaOptionalProxy({
|
|
34
|
+
directUrl: AAVE_V4_GRAPHQL_URL,
|
|
35
|
+
body});
|
|
27
36
|
if (j.errors?.length) {
|
|
28
37
|
const msg = j.errors.map((e) => e.message ?? "Unknown").join("; ");
|
|
29
38
|
throw new Error(msg);
|
|
@@ -562,20 +571,6 @@ function buildAaveV4BorrowTableRowsFromHub(borrowable, hubReserves, debtByUnderl
|
|
|
562
571
|
};
|
|
563
572
|
});
|
|
564
573
|
}
|
|
565
|
-
|
|
566
|
-
// src/chains/evm/rpcUrl.ts
|
|
567
|
-
function isValidRpcUrl(url) {
|
|
568
|
-
const t = url.trim();
|
|
569
|
-
if (!t) return false;
|
|
570
|
-
try {
|
|
571
|
-
const u = new URL(t);
|
|
572
|
-
return u.protocol === "http:" || u.protocol === "https:";
|
|
573
|
-
} catch {
|
|
574
|
-
return false;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// src/protocols/evm/aave-v4/spokeOnChain.ts
|
|
579
574
|
var spokeStaticAbi = [
|
|
580
575
|
{
|
|
581
576
|
name: "getReserveCount",
|
|
@@ -627,7 +622,7 @@ var spokeStaticAbi = [
|
|
|
627
622
|
];
|
|
628
623
|
async function fetchAaveV4SpokeReserveIdForUnderlying(args) {
|
|
629
624
|
const url = (args.rpcUrl ?? "").trim();
|
|
630
|
-
if (!isValidRpcUrl(url)) return null;
|
|
625
|
+
if (!continuumNodeSdk.isValidRpcUrl(url)) return null;
|
|
631
626
|
if (!Number.isFinite(args.chainId) || args.chainId < 0) return null;
|
|
632
627
|
const spoke = viem.getAddress(args.spoke);
|
|
633
628
|
const want = viem.getAddress(args.underlying).toLowerCase();
|
|
@@ -684,87 +679,234 @@ async function fetchAaveV4SpokeReserveStatusForUnderlying(args) {
|
|
|
684
679
|
};
|
|
685
680
|
}
|
|
686
681
|
|
|
687
|
-
// src/core/
|
|
688
|
-
function
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
682
|
+
// src/core/purpose.ts
|
|
683
|
+
function mergePurposeText(purposeText, purposeSuffix) {
|
|
684
|
+
const t = purposeText.trim();
|
|
685
|
+
const suffix = (purposeSuffix ?? "").trim();
|
|
686
|
+
if (!suffix) return t;
|
|
687
|
+
return t ? `${t}
|
|
688
|
+
|
|
689
|
+
${suffix}` : suffix;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// src/core/envelope.ts
|
|
693
|
+
function finalizeMultisign(input) {
|
|
694
|
+
const { keyGen, destinationChainID, legs } = input;
|
|
695
|
+
if (legs.length === 0) {
|
|
696
|
+
throw new Error("finalizeMultisign requires at least one leg");
|
|
693
697
|
}
|
|
694
|
-
|
|
698
|
+
const ph = (keyGen.pubkeyhex ?? "").trim();
|
|
699
|
+
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
700
|
+
const keyList = keyGen.keylist ?? [];
|
|
701
|
+
const clientId = continuumNodeSdk.getClientIdFromKeyGenResult(keyGen);
|
|
702
|
+
const first = legs[0];
|
|
703
|
+
const messageHashes = legs.map((l) => l.msgHash);
|
|
704
|
+
const messageRawBatch = legs.map((l) => l.msgRaw);
|
|
705
|
+
const batchMeta = legs.map((l) => ({
|
|
706
|
+
destinationAddress: l.destinationAddress,
|
|
707
|
+
signatureText: l.signatureText,
|
|
708
|
+
...l.audit
|
|
709
|
+
}));
|
|
710
|
+
const proposalTxParams = legs.map((l) => l.proposalTxParams).filter((p) => p != null && typeof p === "object");
|
|
711
|
+
const extraPayload = {
|
|
712
|
+
batchMeta,
|
|
713
|
+
...input.extraJSON ?? {}
|
|
714
|
+
};
|
|
715
|
+
const extraJSON = JSON.stringify(extraPayload);
|
|
716
|
+
const bodyForSign = {
|
|
717
|
+
keyList,
|
|
718
|
+
pubKey: ph,
|
|
719
|
+
msgHash: messageHashes[0],
|
|
720
|
+
msgRaw: first.msgRaw,
|
|
721
|
+
destinationChainID,
|
|
722
|
+
destinationAddress: input.destinationAddress ?? first.destinationAddress,
|
|
723
|
+
extraJSON,
|
|
724
|
+
signatureText: first.signatureText,
|
|
725
|
+
purpose: mergePurposeText(input.purposeText, input.purposeSuffix),
|
|
726
|
+
...first.feeSnapshot
|
|
727
|
+
};
|
|
728
|
+
if (legs.length > 1) {
|
|
729
|
+
bodyForSign.messageHashes = messageHashes;
|
|
730
|
+
bodyForSign.messageRawBatch = messageRawBatch;
|
|
731
|
+
}
|
|
732
|
+
if (proposalTxParams.length > 0) {
|
|
733
|
+
bodyForSign.proposalTxParams = proposalTxParams;
|
|
734
|
+
}
|
|
735
|
+
const valueWei = first.valueWei;
|
|
736
|
+
if (valueWei != null && valueWei > 0n) {
|
|
737
|
+
bodyForSign.value = valueWei.toString();
|
|
738
|
+
}
|
|
739
|
+
if (clientId) bodyForSign.clientId = clientId;
|
|
740
|
+
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
741
|
+
}
|
|
742
|
+
function routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimit) {
|
|
743
|
+
if (chainGasLimit != null && Number.isFinite(chainGasLimit) && chainGasLimit > 0) {
|
|
744
|
+
return continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit);
|
|
745
|
+
}
|
|
746
|
+
return (estimatedGas * 12n + 9n) / 10n;
|
|
695
747
|
}
|
|
696
748
|
|
|
697
|
-
// src/chains/evm/
|
|
698
|
-
function
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
749
|
+
// src/chains/evm/buildBatch.ts
|
|
750
|
+
async function buildEvmMultisignBatch(args) {
|
|
751
|
+
const { context, steps } = args;
|
|
752
|
+
const {
|
|
753
|
+
chainId,
|
|
754
|
+
rpcUrl,
|
|
755
|
+
executorAddress,
|
|
756
|
+
chainDetail,
|
|
757
|
+
useCustomGas,
|
|
758
|
+
customGasChainDetails,
|
|
759
|
+
keyGen,
|
|
760
|
+
purposeText
|
|
761
|
+
} = context;
|
|
762
|
+
if (steps.length === 0) throw new Error("buildEvmMultisignBatch requires at least one step");
|
|
763
|
+
const ch = viem.defineChain({
|
|
764
|
+
id: chainId,
|
|
765
|
+
name: "Destination",
|
|
713
766
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
714
|
-
rpcUrls: { default: { http: [
|
|
715
|
-
});
|
|
716
|
-
const publicClient = viem.createPublicClient({
|
|
717
|
-
chain,
|
|
718
|
-
transport: viem.http(url)
|
|
767
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
719
768
|
});
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
769
|
+
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(rpcUrl) });
|
|
770
|
+
const feeParams = await continuumNodeSdk.fetchChainFeeParams(rpcUrl, chainId);
|
|
771
|
+
const legacy = Boolean(chainDetail?.legacy) || !feeParams.isEip1559;
|
|
772
|
+
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
773
|
+
const gasLimitConfig = useCustomGas && chainDetail?.gasLimit != null ? Number(chainDetail.gasLimit) : void 0;
|
|
774
|
+
const chainGasLimitRouter = chainDetail?.gasLimit != null && Number.isFinite(Number(chainDetail.gasLimit)) && Number(chainDetail.gasLimit) > 0 ? Number(chainDetail.gasLimit) : void 0;
|
|
775
|
+
const gasFeeMultiplier = useCustomGas && chainDetail?.gasMultiplier != null ? Number(chainDetail.gasMultiplier) : void 0;
|
|
776
|
+
const executor = viem.getAddress(executorAddress);
|
|
777
|
+
const baseNonce = await publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
778
|
+
const legs = [];
|
|
779
|
+
for (let i = 0; i < steps.length; i++) {
|
|
780
|
+
const step = steps[i];
|
|
781
|
+
const currentNonce = baseNonce + i;
|
|
782
|
+
let estimatedGas;
|
|
783
|
+
if (args.estimateGasForStep) {
|
|
784
|
+
estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient, executor });
|
|
785
|
+
} else {
|
|
786
|
+
try {
|
|
787
|
+
estimatedGas = await publicClient.estimateGas({
|
|
788
|
+
to: step.to,
|
|
789
|
+
data: step.data,
|
|
790
|
+
value: step.value,
|
|
791
|
+
account: executor
|
|
792
|
+
});
|
|
793
|
+
} catch {
|
|
794
|
+
estimatedGas = step.fallbackGas ?? 100000n;
|
|
795
|
+
}
|
|
730
796
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
}
|
|
797
|
+
let gasLimitI;
|
|
798
|
+
if (args.resolveGasLimit) {
|
|
799
|
+
gasLimitI = await args.resolveGasLimit({ step, index: i, estimatedGas, publicClient });
|
|
800
|
+
} else if (step.routerSwap) {
|
|
801
|
+
gasLimitI = routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimitRouter);
|
|
802
|
+
} else {
|
|
803
|
+
gasLimitI = useCustomGas ? continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
737
804
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
805
|
+
let proposalTxParams;
|
|
806
|
+
let feeSnapshot;
|
|
807
|
+
let serialized;
|
|
808
|
+
if (legacy) {
|
|
809
|
+
let gasPriceWei = await publicClient.getGasPrice();
|
|
810
|
+
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
811
|
+
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
812
|
+
}
|
|
813
|
+
if (useCustomGas && chainDetail?.gasPrice != null && chainDetail.gasPrice > 0) {
|
|
814
|
+
const configured = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(Number(chainDetail.gasPrice)));
|
|
815
|
+
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
816
|
+
}
|
|
817
|
+
serialized = viem.serializeTransaction({
|
|
818
|
+
type: "legacy",
|
|
819
|
+
to: step.to,
|
|
820
|
+
data: step.data,
|
|
821
|
+
value: step.value,
|
|
822
|
+
gas: gasLimitI,
|
|
823
|
+
gasPrice: gasPriceWei,
|
|
824
|
+
nonce: currentNonce,
|
|
825
|
+
chainId
|
|
826
|
+
});
|
|
827
|
+
proposalTxParams = {
|
|
828
|
+
nonce: currentNonce,
|
|
829
|
+
gasLimit: gasLimitI.toString(),
|
|
830
|
+
txType: "legacy",
|
|
831
|
+
gasPrice: gasPriceWei.toString()
|
|
832
|
+
};
|
|
833
|
+
feeSnapshot = continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams);
|
|
834
|
+
} else {
|
|
835
|
+
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
836
|
+
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
837
|
+
const configuredBase = useCustomGas && chainDetail?.baseFee != null ? Number(chainDetail.baseFee) : 0;
|
|
838
|
+
const configuredPriority = useCustomGas && chainDetail?.priorityFee != null ? Number(chainDetail.priorityFee) : 0;
|
|
839
|
+
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
840
|
+
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
841
|
+
const baseFeeMultiplierPct = useCustomGas && chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(chainDetail.baseFeeMultiplier)) : 100;
|
|
842
|
+
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
843
|
+
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
844
|
+
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(continuumNodeSdk.gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
|
|
845
|
+
let maxFeePerGas = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(maxFeePerGasGwei));
|
|
846
|
+
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
847
|
+
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
848
|
+
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
849
|
+
}
|
|
850
|
+
({ maxFeePerGas, maxPriorityFeePerGas } = continuumNodeSdk.alignEip1559FeesWithLatestBase(
|
|
851
|
+
maxFeePerGas,
|
|
852
|
+
maxPriorityFeePerGas,
|
|
853
|
+
latestBaseFeeWei
|
|
854
|
+
));
|
|
855
|
+
serialized = viem.serializeTransaction({
|
|
856
|
+
type: "eip1559",
|
|
857
|
+
to: step.to,
|
|
858
|
+
data: step.data,
|
|
859
|
+
value: step.value,
|
|
860
|
+
gas: gasLimitI,
|
|
861
|
+
maxFeePerGas,
|
|
862
|
+
maxPriorityFeePerGas,
|
|
863
|
+
nonce: currentNonce,
|
|
864
|
+
chainId
|
|
865
|
+
});
|
|
866
|
+
proposalTxParams = {
|
|
867
|
+
nonce: currentNonce,
|
|
868
|
+
gasLimit: gasLimitI.toString(),
|
|
869
|
+
txType: "eip1559",
|
|
870
|
+
maxFeePerGas: maxFeePerGas.toString(),
|
|
871
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
872
|
+
};
|
|
873
|
+
feeSnapshot = i === 0 ? continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams) : {};
|
|
874
|
+
}
|
|
875
|
+
const h = viem.keccak256(serialized);
|
|
876
|
+
const msgHash = h.startsWith("0x") ? h.slice(2) : h;
|
|
877
|
+
const batchMetaExtra = args.buildBatchMeta({ step, index: i, gasLimit: gasLimitI });
|
|
878
|
+
legs.push({
|
|
879
|
+
msgHash,
|
|
880
|
+
msgRaw: i === 0 && args.firstMsgRawNo0x != null ? args.firstMsgRawNo0x : serialized,
|
|
881
|
+
destinationAddress: step.to,
|
|
882
|
+
signatureText: typeof batchMetaExtra.signatureText === "string" ? batchMetaExtra.signatureText : JSON.stringify(batchMetaExtra.signatureText ?? {}),
|
|
883
|
+
audit: batchMetaExtra,
|
|
884
|
+
feeSnapshot: i === 0 ? feeSnapshot : {},
|
|
885
|
+
proposalTxParams,
|
|
886
|
+
valueWei: i === 0 ? step.value : void 0
|
|
887
|
+
});
|
|
888
|
+
if (i === 0 && args.firstMsgRawNo0x != null) {
|
|
889
|
+
legs[0].msgRaw = args.firstMsgRawNo0x;
|
|
752
890
|
}
|
|
753
891
|
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
let maxF = maxFeePerGas;
|
|
758
|
-
if (baseWei > 0n && maxF < baseWei + maxP) {
|
|
759
|
-
maxF = baseWei + maxP + viem.parseGwei("0.001");
|
|
892
|
+
const extraJSON = {};
|
|
893
|
+
if (useCustomGas && customGasChainDetails && Object.keys(customGasChainDetails).length > 0) {
|
|
894
|
+
extraJSON.customGasChainDetails = customGasChainDetails;
|
|
760
895
|
}
|
|
761
|
-
|
|
762
|
-
|
|
896
|
+
const result = finalizeMultisign({
|
|
897
|
+
keyGen,
|
|
898
|
+
purposeText,
|
|
899
|
+
purposeSuffix: args.purposeSuffix,
|
|
900
|
+
destinationChainID: String(chainId),
|
|
901
|
+
destinationAddress: args.destinationAddress ?? steps[0].to,
|
|
902
|
+
legs,
|
|
903
|
+
extraJSON: Object.keys(extraJSON).length > 0 ? extraJSON : void 0
|
|
904
|
+
});
|
|
905
|
+
const pv = args.payableValueWei;
|
|
906
|
+
if (pv != null && pv > 0n) {
|
|
907
|
+
result.bodyForSign.value = pv.toString();
|
|
763
908
|
}
|
|
764
|
-
return
|
|
765
|
-
}
|
|
766
|
-
function alignEip1559FeesWithLatestBase(maxFeePerGas, maxPriorityFeePerGas, latestBlockBaseFeeWei) {
|
|
767
|
-
return finalizeEip1559Fees(maxFeePerGas, maxPriorityFeePerGas, null, latestBlockBaseFeeWei);
|
|
909
|
+
return result;
|
|
768
910
|
}
|
|
769
911
|
|
|
770
912
|
// src/protocols/evm/aave-v4/multisign.ts
|
|
@@ -781,16 +923,6 @@ var AAVE_V4_SPOKE_REPAY_DEFAULT_GAS_UNITS = 1000000n;
|
|
|
781
923
|
var AAVE_SPOKE_REPAY_ESTIMATE_FALLBACK = AAVE_V4_SPOKE_REPAY_DEFAULT_GAS_UNITS;
|
|
782
924
|
var AAVE_MERKL_CLAIM_ESTIMATE_FALLBACK = 500000n;
|
|
783
925
|
var EULER_REUL_UNLOCK_ESTIMATE_FALLBACK = 500000n;
|
|
784
|
-
function gweiToDecimalString(n) {
|
|
785
|
-
if (!Number.isFinite(n)) return "0";
|
|
786
|
-
if (n === 0) return "0";
|
|
787
|
-
const s = String(n);
|
|
788
|
-
if (s.indexOf("e") !== -1 || s.indexOf("E") !== -1) return n.toFixed(9).replace(/\.?0+$/, "") || "0";
|
|
789
|
-
return s;
|
|
790
|
-
}
|
|
791
|
-
function txToViemStep(tx) {
|
|
792
|
-
return { to: viem.getAddress(tx.to), data: tx.data, value: tx.value };
|
|
793
|
-
}
|
|
794
926
|
var wethDepositAbi = viem.parseAbi(["function deposit() payable"]);
|
|
795
927
|
var erc20AllowanceAbi = viem.parseAbi([
|
|
796
928
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
@@ -805,10 +937,6 @@ var spokeSetUsingAsCollateralAbi = viem.parseAbi([
|
|
|
805
937
|
"function setUsingAsCollateral(uint256 reserveId, bool usingAsCollateral, address onBehalfOf)"
|
|
806
938
|
]);
|
|
807
939
|
async function buildEvmMultisignBodyAaveV4DepositBatch(args) {
|
|
808
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
809
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
810
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
811
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
812
940
|
const asset = viem.getAddress(args.asset);
|
|
813
941
|
const spoke = viem.getAddress(args.spoke);
|
|
814
942
|
const weth = viem.getAddress(args.nativeWrapped);
|
|
@@ -906,172 +1034,102 @@ async function buildEvmMultisignBodyAaveV4DepositBatch(args) {
|
|
|
906
1034
|
});
|
|
907
1035
|
steps.push({ kind: "set_collateral", to: spoke, data: setCollateralData, value: 0n });
|
|
908
1036
|
}
|
|
909
|
-
const feeParams = await fetchChainFeeParams(args.rpcUrl, args.chainId);
|
|
910
|
-
const legacy = Boolean(args.chainDetail?.legacy) || !feeParams.isEip1559;
|
|
911
|
-
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
912
|
-
const useCustomGas = args.useCustomGas;
|
|
913
|
-
const gasLimitConfig = useCustomGas && args.chainDetail?.gasLimit != null ? Number(args.chainDetail.gasLimit) : void 0;
|
|
914
|
-
const gasFeeMultiplier = useCustomGas && args.chainDetail?.gasMultiplier != null ? Number(args.chainDetail.gasMultiplier) : void 0;
|
|
915
|
-
const baseNonce = await publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
916
|
-
const messageHashes = [];
|
|
917
|
-
const messageRawBatch = [];
|
|
918
|
-
const proposalTxParamsBatch = [];
|
|
919
|
-
const batchMeta = [];
|
|
920
|
-
let firstTxFeePayload = {};
|
|
921
|
-
let firstDataNo0x = "";
|
|
922
1037
|
const marketLabel = String(args.market);
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
})
|
|
935
|
-
} catch {
|
|
936
|
-
if (s.kind === "weth_deposit") estimatedGas = AAVE_WETH_DEPOSIT_FALLBACK;
|
|
937
|
-
else if (s.kind === "approve") estimatedGas = AAVE_ERC20_APPROVE_FALLBACK;
|
|
938
|
-
else if (s.kind === "set_collateral") estimatedGas = AAVE_SPOKE_SET_USING_AS_COLLATERAL_FALLBACK;
|
|
939
|
-
else estimatedGas = AAVE_SPOKE_SUPPLY_ESTIMATE_FALLBACK;
|
|
1038
|
+
const evmSteps = steps.map((s) => ({
|
|
1039
|
+
to: s.to,
|
|
1040
|
+
data: s.data,
|
|
1041
|
+
value: s.value,
|
|
1042
|
+
fallbackGas: s.kind === "weth_deposit" ? AAVE_WETH_DEPOSIT_FALLBACK : s.kind === "approve" ? AAVE_ERC20_APPROVE_FALLBACK : s.kind === "set_collateral" ? AAVE_SPOKE_SET_USING_AS_COLLATERAL_FALLBACK : AAVE_SPOKE_SUPPLY_ESTIMATE_FALLBACK
|
|
1043
|
+
}));
|
|
1044
|
+
const n = steps.length;
|
|
1045
|
+
const hasWrap = args.isNativeIn;
|
|
1046
|
+
const withCollateral = args.enableAsCollateralAfterSupply === true;
|
|
1047
|
+
const purposeSuffix = (() => {
|
|
1048
|
+
if (hasWrap) {
|
|
1049
|
+
return withCollateral ? `Aave v4: ${n}-tx batch \u2014 wrap native to WETH (if needed), approve spoke for the exact amount, supply, then setUsingAsCollateral.` : `Aave v4: ${n}-tx batch \u2014 wrap native to WETH (if needed), approve spoke for the exact amount, then supply.`;
|
|
940
1050
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1051
|
+
if (n === 1) {
|
|
1052
|
+
return "Aave v4: 1-tx \u2014 supply (allowance already sufficient).";
|
|
1053
|
+
}
|
|
1054
|
+
if (withCollateral && n === 2) {
|
|
1055
|
+
return "Aave v4: 2-tx batch \u2014 supply (allowance already sufficient), then setUsingAsCollateral.";
|
|
1056
|
+
}
|
|
1057
|
+
if (withCollateral) {
|
|
1058
|
+
return `Aave v4: ${n}-tx batch \u2014 approve spoke for the exact amount, supply, then setUsingAsCollateral.`;
|
|
1059
|
+
}
|
|
1060
|
+
return `Aave v4: ${n}-tx batch \u2014 approve spoke for the exact amount, then supply.`;
|
|
1061
|
+
})();
|
|
1062
|
+
const firstDataNo0x = evmSteps[0].data.startsWith("0x") ? evmSteps[0].data.slice(2) : evmSteps[0].data;
|
|
1063
|
+
return buildEvmMultisignBatch({
|
|
1064
|
+
context: {
|
|
1065
|
+
chainCategory: "evm",
|
|
1066
|
+
keyGen: args.keyGen,
|
|
1067
|
+
purposeText: args.purposeText,
|
|
1068
|
+
chainId: args.chainId,
|
|
1069
|
+
rpcUrl: args.rpcUrl,
|
|
1070
|
+
executorAddress: executor,
|
|
1071
|
+
chainDetail: args.chainDetail,
|
|
1072
|
+
useCustomGas: args.useCustomGas,
|
|
1073
|
+
customGasChainDetails: args.customGasChainDetails
|
|
1074
|
+
},
|
|
1075
|
+
steps: evmSteps,
|
|
1076
|
+
purposeSuffix,
|
|
1077
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
1078
|
+
destinationAddress: steps[0].to,
|
|
1079
|
+
buildBatchMeta: ({ index, gasLimit }) => {
|
|
1080
|
+
const s = steps[index];
|
|
1081
|
+
if (s.kind === "weth_deposit") {
|
|
1082
|
+
return {
|
|
1083
|
+
signatureText: JSON.stringify({
|
|
1084
|
+
kind: "AaveV4",
|
|
1085
|
+
name: "WETH.deposit",
|
|
1086
|
+
function: "deposit()",
|
|
1087
|
+
valueWei: amountWei.toString(),
|
|
1088
|
+
market: marketLabel,
|
|
1089
|
+
note: "Wrap native to WETH, then supply to Aave v4 (same batch)."
|
|
1090
|
+
}),
|
|
1091
|
+
evm: { type: "aave_v4_weth_deposit", version: 1, chainId: String(args.chainId) },
|
|
1092
|
+
aaveV4: { step: "weth_deposit", market: marketLabel, amountHuman: args.amountHuman, hubAsset: asset }
|
|
1093
|
+
};
|
|
973
1094
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1095
|
+
if (s.kind === "approve") {
|
|
1096
|
+
return {
|
|
1097
|
+
signatureText: JSON.stringify({
|
|
1098
|
+
kind: "AaveV4",
|
|
1099
|
+
name: "ERC20.approve",
|
|
1100
|
+
to: "Aave v4 spoke",
|
|
1101
|
+
function: "approve(address spender, uint256 amount)",
|
|
1102
|
+
spoke,
|
|
1103
|
+
amountHuman: args.amountHuman,
|
|
1104
|
+
note: "Allowance for this supply amount only (not unlimited)."
|
|
1105
|
+
}),
|
|
1106
|
+
evm: { type: "aave_v4_erc20_approve", version: 1, chainId: String(args.chainId) },
|
|
1107
|
+
aaveV4: { market: marketLabel, amountHuman: args.amountHuman, spoke }
|
|
1108
|
+
};
|
|
989
1109
|
}
|
|
990
|
-
(
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
nonce: currentNonce,
|
|
1011
|
-
gasLimit: gasLimitI.toString(),
|
|
1012
|
-
txType: "eip1559",
|
|
1013
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
1014
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1015
|
-
});
|
|
1016
|
-
if (i === 0) {
|
|
1017
|
-
firstTxFeePayload = {
|
|
1018
|
-
txNonce: currentNonce,
|
|
1019
|
-
txGasLimit: gasLimitI.toString(),
|
|
1020
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
1021
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1110
|
+
if (s.kind === "set_collateral") {
|
|
1111
|
+
return {
|
|
1112
|
+
signatureText: JSON.stringify({
|
|
1113
|
+
kind: "AaveV4",
|
|
1114
|
+
name: "Spoke.setUsingAsCollateral",
|
|
1115
|
+
function: "setUsingAsCollateral(uint256 reserveId, bool usingAsCollateral, address onBehalfOf)",
|
|
1116
|
+
reserveId: reserveId.toString(),
|
|
1117
|
+
usingAsCollateral: true,
|
|
1118
|
+
onBehalfOf: onBehalf,
|
|
1119
|
+
market: marketLabel,
|
|
1120
|
+
note: "Enables this supplied reserve as collateral for borrowing (after supply in the same batch)."
|
|
1121
|
+
}),
|
|
1122
|
+
evm: { type: "aave_v4_spoke_set_using_as_collateral", version: 1, chainId: String(args.chainId) },
|
|
1123
|
+
aaveV4: {
|
|
1124
|
+
market: marketLabel,
|
|
1125
|
+
asset,
|
|
1126
|
+
spoke,
|
|
1127
|
+
reserveId: reserveId.toString(),
|
|
1128
|
+
gasBuildSetCollateral: { baseGasUnits: gasLimit.toString() }
|
|
1129
|
+
}
|
|
1022
1130
|
};
|
|
1023
|
-
firstDataNo0x = v.data.startsWith("0x") ? v.data.slice(2) : v.data;
|
|
1024
1131
|
}
|
|
1025
|
-
|
|
1026
|
-
if (s.kind === "weth_deposit") {
|
|
1027
|
-
batchMeta.push({
|
|
1028
|
-
destinationAddress: weth,
|
|
1029
|
-
signatureText: JSON.stringify({
|
|
1030
|
-
kind: "AaveV4",
|
|
1031
|
-
name: "WETH.deposit",
|
|
1032
|
-
function: "deposit()",
|
|
1033
|
-
valueWei: amountWei.toString(),
|
|
1034
|
-
market: marketLabel,
|
|
1035
|
-
note: "Wrap native to WETH, then supply to Aave v4 (same batch)."
|
|
1036
|
-
}),
|
|
1037
|
-
evm: { type: "aave_v4_weth_deposit", version: 1, chainId: String(args.chainId) },
|
|
1038
|
-
aaveV4: { step: "weth_deposit", market: marketLabel, amountHuman: args.amountHuman, hubAsset: asset }
|
|
1039
|
-
});
|
|
1040
|
-
} else if (s.kind === "approve") {
|
|
1041
|
-
const tokenForApprove = s.to;
|
|
1042
|
-
batchMeta.push({
|
|
1043
|
-
destinationAddress: tokenForApprove,
|
|
1044
|
-
signatureText: JSON.stringify({
|
|
1045
|
-
kind: "AaveV4",
|
|
1046
|
-
name: "ERC20.approve",
|
|
1047
|
-
to: "Aave v4 spoke",
|
|
1048
|
-
function: "approve(address spender, uint256 amount)",
|
|
1049
|
-
spoke,
|
|
1050
|
-
amountHuman: args.amountHuman,
|
|
1051
|
-
note: "Allowance for this supply amount only (not unlimited)."
|
|
1052
|
-
}),
|
|
1053
|
-
evm: { type: "aave_v4_erc20_approve", version: 1, chainId: String(args.chainId) },
|
|
1054
|
-
aaveV4: { market: marketLabel, amountHuman: args.amountHuman, spoke }
|
|
1055
|
-
});
|
|
1056
|
-
} else if (s.kind === "set_collateral") {
|
|
1057
|
-
batchMeta.push({
|
|
1058
|
-
destinationAddress: spoke,
|
|
1059
|
-
signatureText: JSON.stringify({
|
|
1060
|
-
kind: "AaveV4",
|
|
1061
|
-
name: "Spoke.setUsingAsCollateral",
|
|
1062
|
-
function: "setUsingAsCollateral(uint256 reserveId, bool usingAsCollateral, address onBehalfOf)",
|
|
1063
|
-
reserveId: reserveId.toString(),
|
|
1064
|
-
usingAsCollateral: true,
|
|
1065
|
-
onBehalfOf: onBehalf,
|
|
1066
|
-
market: marketLabel,
|
|
1067
|
-
note: "Enables this supplied reserve as collateral for borrowing (after supply in the same batch)."
|
|
1068
|
-
}),
|
|
1069
|
-
evm: { type: "aave_v4_spoke_set_using_as_collateral", version: 1, chainId: String(args.chainId) },
|
|
1070
|
-
aaveV4: { market: marketLabel, asset, spoke, reserveId: reserveId.toString(), gasBuildSetCollateral: { baseGasUnits: gasLimitI.toString() } }
|
|
1071
|
-
});
|
|
1072
|
-
} else {
|
|
1073
|
-
batchMeta.push({
|
|
1074
|
-
destinationAddress: spoke,
|
|
1132
|
+
return {
|
|
1075
1133
|
signatureText: JSON.stringify({
|
|
1076
1134
|
kind: "AaveV4",
|
|
1077
1135
|
name: "Spoke.supply",
|
|
@@ -1089,67 +1147,13 @@ async function buildEvmMultisignBodyAaveV4DepositBatch(args) {
|
|
|
1089
1147
|
asset,
|
|
1090
1148
|
spoke,
|
|
1091
1149
|
reserveId: reserveId.toString(),
|
|
1092
|
-
gasBuildSupply: { baseGasUnits:
|
|
1150
|
+
gasBuildSupply: { baseGasUnits: gasLimit.toString() }
|
|
1093
1151
|
}
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
const extraPayload = { batchMeta };
|
|
1098
|
-
if (useCustomGas && args.customGasChainDetails && Object.keys(args.customGasChainDetails).length > 0) {
|
|
1099
|
-
extraPayload.customGasChainDetails = args.customGasChainDetails;
|
|
1100
|
-
}
|
|
1101
|
-
const extraJSON = JSON.stringify(extraPayload);
|
|
1102
|
-
const firstSigText = batchMeta[0].signatureText;
|
|
1103
|
-
const n = steps.length;
|
|
1104
|
-
const hasWrap = args.isNativeIn;
|
|
1105
|
-
const withCollateral = args.enableAsCollateralAfterSupply === true;
|
|
1106
|
-
const purposeSuffix = (() => {
|
|
1107
|
-
if (hasWrap) {
|
|
1108
|
-
return withCollateral ? `Aave v4: ${n}-tx batch \u2014 wrap native to WETH (if needed), approve spoke for the exact amount, supply, then setUsingAsCollateral.` : `Aave v4: ${n}-tx batch \u2014 wrap native to WETH (if needed), approve spoke for the exact amount, then supply.`;
|
|
1109
|
-
}
|
|
1110
|
-
if (n === 1) {
|
|
1111
|
-
return "Aave v4: 1-tx \u2014 supply (allowance already sufficient).";
|
|
1152
|
+
};
|
|
1112
1153
|
}
|
|
1113
|
-
|
|
1114
|
-
return "Aave v4: 2-tx batch \u2014 supply (allowance already sufficient), then setUsingAsCollateral.";
|
|
1115
|
-
}
|
|
1116
|
-
if (withCollateral) {
|
|
1117
|
-
return `Aave v4: ${n}-tx batch \u2014 approve spoke for the exact amount, supply, then setUsingAsCollateral.`;
|
|
1118
|
-
}
|
|
1119
|
-
return `Aave v4: ${n}-tx batch \u2014 approve spoke for the exact amount, then supply.`;
|
|
1120
|
-
})();
|
|
1121
|
-
const firstValue = steps[0].value;
|
|
1122
|
-
const bodyForSign = {
|
|
1123
|
-
keyList,
|
|
1124
|
-
pubKey: ph,
|
|
1125
|
-
msgHash: messageHashes[0],
|
|
1126
|
-
msgRaw: firstDataNo0x,
|
|
1127
|
-
messageHashes,
|
|
1128
|
-
messageRawBatch,
|
|
1129
|
-
destinationChainID: String(args.chainId),
|
|
1130
|
-
destinationAddress: steps[0].to,
|
|
1131
|
-
extraJSON,
|
|
1132
|
-
signatureText: firstSigText,
|
|
1133
|
-
purpose: (() => {
|
|
1134
|
-
const t = args.purposeText.trim();
|
|
1135
|
-
return (t ? `${t}
|
|
1136
|
-
|
|
1137
|
-
` : "") + purposeSuffix;
|
|
1138
|
-
})(),
|
|
1139
|
-
...firstTxFeePayload,
|
|
1140
|
-
proposalTxParams: proposalTxParamsBatch
|
|
1141
|
-
};
|
|
1142
|
-
if (firstValue > 0n) {
|
|
1143
|
-
bodyForSign.value = firstValue.toString();
|
|
1144
|
-
}
|
|
1145
|
-
if (clientId) bodyForSign.clientId = clientId;
|
|
1146
|
-
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
1154
|
+
});
|
|
1147
1155
|
}
|
|
1148
1156
|
async function buildEvmMultisignBodyAaveV4SpokeWithdraw(args) {
|
|
1149
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1150
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1151
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1152
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1153
1157
|
const asset = viem.getAddress(args.underlying);
|
|
1154
1158
|
const spoke = viem.getAddress(args.spoke);
|
|
1155
1159
|
const onBehalf = viem.getAddress(args.onBehalfOf);
|
|
@@ -1190,9 +1194,7 @@ async function buildEvmMultisignBodyAaveV4SpokeWithdraw(args) {
|
|
|
1190
1194
|
});
|
|
1191
1195
|
const tx = { to: spoke, data, value: 0n };
|
|
1192
1196
|
return buildEvmMultisignBodyAaveV4OneStep({
|
|
1193
|
-
|
|
1194
|
-
keyList,
|
|
1195
|
-
clientId: clientId ?? void 0,
|
|
1197
|
+
keyGen: args.keyGen,
|
|
1196
1198
|
chainId: args.chainId,
|
|
1197
1199
|
rpcUrl: args.rpcUrl,
|
|
1198
1200
|
chainDetail: args.chainDetail,
|
|
@@ -1228,10 +1230,6 @@ async function buildEvmMultisignBodyAaveV4SpokeWithdraw(args) {
|
|
|
1228
1230
|
});
|
|
1229
1231
|
}
|
|
1230
1232
|
async function buildEvmMultisignBodyAaveV4SpokeBorrow(args) {
|
|
1231
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1232
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1233
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1234
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1235
1233
|
const asset = viem.getAddress(args.underlying);
|
|
1236
1234
|
const spoke = viem.getAddress(args.spoke);
|
|
1237
1235
|
const onBehalf = viem.getAddress(args.onBehalfOf);
|
|
@@ -1272,9 +1270,7 @@ async function buildEvmMultisignBodyAaveV4SpokeBorrow(args) {
|
|
|
1272
1270
|
});
|
|
1273
1271
|
const tx = { to: spoke, data, value: 0n };
|
|
1274
1272
|
return buildEvmMultisignBodyAaveV4OneStep({
|
|
1275
|
-
|
|
1276
|
-
keyList,
|
|
1277
|
-
clientId: clientId ?? void 0,
|
|
1273
|
+
keyGen: args.keyGen,
|
|
1278
1274
|
chainId: args.chainId,
|
|
1279
1275
|
rpcUrl: args.rpcUrl,
|
|
1280
1276
|
chainDetail: args.chainDetail,
|
|
@@ -1310,10 +1306,6 @@ async function buildEvmMultisignBodyAaveV4SpokeBorrow(args) {
|
|
|
1310
1306
|
});
|
|
1311
1307
|
}
|
|
1312
1308
|
async function buildEvmMultisignBodyAaveV4SpokeRepay(args) {
|
|
1313
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1314
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1315
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1316
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1317
1309
|
const asset = viem.getAddress(args.underlying);
|
|
1318
1310
|
const spoke = viem.getAddress(args.spoke);
|
|
1319
1311
|
const onBehalf = viem.getAddress(args.onBehalfOf);
|
|
@@ -1376,140 +1368,50 @@ async function buildEvmMultisignBodyAaveV4SpokeRepay(args) {
|
|
|
1376
1368
|
args: [reserveId, amountWei, onBehalf]
|
|
1377
1369
|
});
|
|
1378
1370
|
steps.push({ kind: "repay", to: spoke, data: repayData, value: 0n });
|
|
1379
|
-
const feeParams = await fetchChainFeeParams(args.rpcUrl, args.chainId);
|
|
1380
|
-
const legacy = Boolean(args.chainDetail?.legacy) || !feeParams.isEip1559;
|
|
1381
|
-
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
1382
|
-
const useCustom = args.useCustomGas;
|
|
1383
|
-
const gasLimitConfig = useCustom && args.chainDetail?.gasLimit != null ? Number(args.chainDetail.gasLimit) : void 0;
|
|
1384
|
-
const gasFeeMultiplier = useCustom && args.chainDetail?.gasMultiplier != null ? Number(args.chainDetail.gasMultiplier) : void 0;
|
|
1385
|
-
const baseNonce = await publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
1386
|
-
const messageHashes = [];
|
|
1387
|
-
const messageRawBatch = [];
|
|
1388
|
-
const proposalTxParamsBatch = [];
|
|
1389
|
-
const batchMeta = [];
|
|
1390
|
-
let firstTxFeePayload = {};
|
|
1391
|
-
let firstDataNo0x = "";
|
|
1392
1371
|
const marketLabel = String(args.market);
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
const
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
nonce: currentNonce,
|
|
1434
|
-
gasLimit: gasLimitI.toString(),
|
|
1435
|
-
txType: "legacy",
|
|
1436
|
-
gasPrice: gasPriceWei.toString()
|
|
1437
|
-
});
|
|
1438
|
-
if (i === 0) {
|
|
1439
|
-
firstTxFeePayload = { txNonce: currentNonce, txGasLimit: gasLimitI.toString(), txGasPrice: gasPriceWei.toString() };
|
|
1440
|
-
firstDataNo0x = v.data.startsWith("0x") ? v.data.slice(2) : v.data;
|
|
1441
|
-
}
|
|
1442
|
-
} else {
|
|
1443
|
-
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
1444
|
-
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
1445
|
-
const configuredBase = useCustom && args.chainDetail?.baseFee != null ? Number(args.chainDetail.baseFee) : 0;
|
|
1446
|
-
const configuredPriority = useCustom && args.chainDetail?.priorityFee != null ? Number(args.chainDetail.priorityFee) : 0;
|
|
1447
|
-
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
1448
|
-
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
1449
|
-
const baseFeeMultiplierPct = useCustom && args.chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(args.chainDetail.baseFeeMultiplier)) : 100;
|
|
1450
|
-
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
1451
|
-
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
1452
|
-
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
|
|
1453
|
-
let maxFeePerGas = viem.parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
1454
|
-
if (useCustom && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
1455
|
-
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1456
|
-
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1457
|
-
}
|
|
1458
|
-
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
1459
|
-
maxFeePerGas,
|
|
1460
|
-
maxPriorityFeePerGas,
|
|
1461
|
-
latestBaseFeeWei
|
|
1462
|
-
));
|
|
1463
|
-
const ser = viem.serializeTransaction({
|
|
1464
|
-
type: "eip1559",
|
|
1465
|
-
to: v.to,
|
|
1466
|
-
data: v.data,
|
|
1467
|
-
value: v.value,
|
|
1468
|
-
gas: gasLimitI,
|
|
1469
|
-
maxFeePerGas,
|
|
1470
|
-
maxPriorityFeePerGas,
|
|
1471
|
-
nonce: currentNonce,
|
|
1472
|
-
chainId: args.chainId
|
|
1473
|
-
});
|
|
1474
|
-
const h = viem.keccak256(ser);
|
|
1475
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
1476
|
-
messageRawBatch.push(ser);
|
|
1477
|
-
proposalTxParamsBatch.push({
|
|
1478
|
-
nonce: currentNonce,
|
|
1479
|
-
gasLimit: gasLimitI.toString(),
|
|
1480
|
-
txType: "eip1559",
|
|
1481
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
1482
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1483
|
-
});
|
|
1484
|
-
if (i === 0) {
|
|
1485
|
-
firstTxFeePayload = {
|
|
1486
|
-
txNonce: currentNonce,
|
|
1487
|
-
txGasLimit: gasLimitI.toString(),
|
|
1488
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
1489
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1372
|
+
const evmSteps = steps.map((s) => ({
|
|
1373
|
+
to: s.to,
|
|
1374
|
+
data: s.data,
|
|
1375
|
+
value: s.value,
|
|
1376
|
+
fallbackGas: s.kind === "approve" ? AAVE_ERC20_APPROVE_FALLBACK : AAVE_SPOKE_REPAY_ESTIMATE_FALLBACK
|
|
1377
|
+
}));
|
|
1378
|
+
const n = steps.length;
|
|
1379
|
+
const purposeSuffix = `Aave v4: ${n}-tx batch \u2014 approve spoke if needed, then repay ${(args.amountHuman || "").trim() || "\u2026"} of debt.`;
|
|
1380
|
+
const firstDataNo0x = evmSteps[0].data.startsWith("0x") ? evmSteps[0].data.slice(2) : evmSteps[0].data;
|
|
1381
|
+
return buildEvmMultisignBatch({
|
|
1382
|
+
context: {
|
|
1383
|
+
chainCategory: "evm",
|
|
1384
|
+
keyGen: args.keyGen,
|
|
1385
|
+
purposeText: args.purposeText,
|
|
1386
|
+
chainId: args.chainId,
|
|
1387
|
+
rpcUrl: args.rpcUrl,
|
|
1388
|
+
executorAddress: executor,
|
|
1389
|
+
chainDetail: args.chainDetail,
|
|
1390
|
+
useCustomGas: args.useCustomGas,
|
|
1391
|
+
customGasChainDetails: args.customGasChainDetails
|
|
1392
|
+
},
|
|
1393
|
+
steps: evmSteps,
|
|
1394
|
+
purposeSuffix,
|
|
1395
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
1396
|
+
destinationAddress: steps[0].to,
|
|
1397
|
+
buildBatchMeta: ({ index, gasLimit }) => {
|
|
1398
|
+
const s = steps[index];
|
|
1399
|
+
if (s.kind === "approve") {
|
|
1400
|
+
return {
|
|
1401
|
+
signatureText: JSON.stringify({
|
|
1402
|
+
kind: "AaveV4",
|
|
1403
|
+
name: "ERC20.approve (repay)",
|
|
1404
|
+
to: "Aave v4 spoke",
|
|
1405
|
+
function: "approve(address spender, uint256 amount)",
|
|
1406
|
+
spoke,
|
|
1407
|
+
amountHuman: args.amountHuman,
|
|
1408
|
+
note: "Allowance to repay this amount (or reset+approve to exact amount)."
|
|
1409
|
+
}),
|
|
1410
|
+
evm: { type: "aave_v4_erc20_approve", version: 1, chainId: String(args.chainId) },
|
|
1411
|
+
aaveV4: { market: marketLabel, amountHuman: args.amountHuman, spoke, step: "repay_prepare" }
|
|
1490
1412
|
};
|
|
1491
|
-
firstDataNo0x = v.data.startsWith("0x") ? v.data.slice(2) : v.data;
|
|
1492
1413
|
}
|
|
1493
|
-
|
|
1494
|
-
if (s.kind === "approve") {
|
|
1495
|
-
const tokenForApprove = s.to;
|
|
1496
|
-
batchMeta.push({
|
|
1497
|
-
destinationAddress: tokenForApprove,
|
|
1498
|
-
signatureText: JSON.stringify({
|
|
1499
|
-
kind: "AaveV4",
|
|
1500
|
-
name: "ERC20.approve (repay)",
|
|
1501
|
-
to: "Aave v4 spoke",
|
|
1502
|
-
function: "approve(address spender, uint256 amount)",
|
|
1503
|
-
spoke,
|
|
1504
|
-
amountHuman: args.amountHuman,
|
|
1505
|
-
note: "Allowance to repay this amount (or reset+approve to exact amount)."
|
|
1506
|
-
}),
|
|
1507
|
-
evm: { type: "aave_v4_erc20_approve", version: 1, chainId: String(args.chainId) },
|
|
1508
|
-
aaveV4: { market: marketLabel, amountHuman: args.amountHuman, spoke, step: "repay_prepare" }
|
|
1509
|
-
});
|
|
1510
|
-
} else {
|
|
1511
|
-
batchMeta.push({
|
|
1512
|
-
destinationAddress: spoke,
|
|
1414
|
+
return {
|
|
1513
1415
|
signatureText: JSON.stringify({
|
|
1514
1416
|
kind: "AaveV4",
|
|
1515
1417
|
name: "Spoke.repay",
|
|
@@ -1527,57 +1429,17 @@ async function buildEvmMultisignBodyAaveV4SpokeRepay(args) {
|
|
|
1527
1429
|
asset,
|
|
1528
1430
|
spoke,
|
|
1529
1431
|
reserveId: reserveId.toString(),
|
|
1530
|
-
gasBuildRepay: { baseGasUnits:
|
|
1432
|
+
gasBuildRepay: { baseGasUnits: gasLimit.toString() }
|
|
1531
1433
|
}
|
|
1532
|
-
}
|
|
1434
|
+
};
|
|
1533
1435
|
}
|
|
1534
|
-
}
|
|
1535
|
-
const extraPayload = { batchMeta };
|
|
1536
|
-
if (useCustom && args.customGasChainDetails && Object.keys(args.customGasChainDetails).length > 0) {
|
|
1537
|
-
extraPayload.customGasChainDetails = args.customGasChainDetails;
|
|
1538
|
-
}
|
|
1539
|
-
const extraJSON = JSON.stringify(extraPayload);
|
|
1540
|
-
const firstSigText = batchMeta[0].signatureText;
|
|
1541
|
-
const n = steps.length;
|
|
1542
|
-
const purposeSuffix = `Aave v4: ${n}-tx batch \u2014 approve spoke if needed, then repay ${(args.amountHuman || "").trim() || "\u2026"} of debt.`;
|
|
1543
|
-
const firstValue = steps[0].value;
|
|
1544
|
-
const bodyForSign = {
|
|
1545
|
-
keyList,
|
|
1546
|
-
pubKey: ph,
|
|
1547
|
-
msgHash: messageHashes[0],
|
|
1548
|
-
msgRaw: firstDataNo0x,
|
|
1549
|
-
messageHashes,
|
|
1550
|
-
messageRawBatch,
|
|
1551
|
-
destinationChainID: String(args.chainId),
|
|
1552
|
-
destinationAddress: steps[0].to,
|
|
1553
|
-
extraJSON,
|
|
1554
|
-
signatureText: firstSigText,
|
|
1555
|
-
purpose: (() => {
|
|
1556
|
-
const t = args.purposeText.trim();
|
|
1557
|
-
return (t ? `${t}
|
|
1558
|
-
|
|
1559
|
-
` : "") + purposeSuffix;
|
|
1560
|
-
})(),
|
|
1561
|
-
...firstTxFeePayload,
|
|
1562
|
-
proposalTxParams: proposalTxParamsBatch
|
|
1563
|
-
};
|
|
1564
|
-
if (firstValue > 0n) {
|
|
1565
|
-
bodyForSign.value = firstValue.toString();
|
|
1566
|
-
}
|
|
1567
|
-
if (clientId) bodyForSign.clientId = clientId;
|
|
1568
|
-
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
1436
|
+
});
|
|
1569
1437
|
}
|
|
1570
1438
|
async function buildEvmMultisignBodyAaveV4MerklClaimRewards(args) {
|
|
1571
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1572
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1573
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1574
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1575
1439
|
const to = viem.getAddress(args.to);
|
|
1576
1440
|
const executor = viem.getAddress(args.executorAddress);
|
|
1577
1441
|
return buildEvmMultisignBodyAaveV4OneStep({
|
|
1578
|
-
|
|
1579
|
-
keyList,
|
|
1580
|
-
clientId: clientId ?? void 0,
|
|
1442
|
+
keyGen: args.keyGen,
|
|
1581
1443
|
chainId: args.chainId,
|
|
1582
1444
|
rpcUrl: args.rpcUrl,
|
|
1583
1445
|
chainDetail: args.chainDetail,
|
|
@@ -1604,16 +1466,10 @@ async function buildEvmMultisignBodyAaveV4MerklClaimRewards(args) {
|
|
|
1604
1466
|
});
|
|
1605
1467
|
}
|
|
1606
1468
|
async function buildEvmMultisignBodyEulerV2MerklDistributorClaim(args) {
|
|
1607
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1608
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1609
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1610
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1611
1469
|
const to = viem.getAddress(args.to);
|
|
1612
1470
|
const executor = viem.getAddress(args.executorAddress);
|
|
1613
1471
|
return buildEvmMultisignBodyAaveV4OneStep({
|
|
1614
|
-
|
|
1615
|
-
keyList,
|
|
1616
|
-
clientId: clientId ?? void 0,
|
|
1472
|
+
keyGen: args.keyGen,
|
|
1617
1473
|
chainId: args.chainId,
|
|
1618
1474
|
rpcUrl: args.rpcUrl,
|
|
1619
1475
|
chainDetail: args.chainDetail,
|
|
@@ -1640,17 +1496,11 @@ async function buildEvmMultisignBodyEulerV2MerklDistributorClaim(args) {
|
|
|
1640
1496
|
});
|
|
1641
1497
|
}
|
|
1642
1498
|
async function buildEvmMultisignBodyEulerV2ReulUnlock(args) {
|
|
1643
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
1644
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
1645
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
1646
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
1647
1499
|
const to = viem.getAddress(args.to);
|
|
1648
1500
|
const executor = viem.getAddress(args.executorAddress);
|
|
1649
1501
|
const lossLabel = args.allowRemainderLoss ? "early unlock (remainder to receiver)" : "vested only";
|
|
1650
1502
|
return buildEvmMultisignBodyAaveV4OneStep({
|
|
1651
|
-
|
|
1652
|
-
keyList,
|
|
1653
|
-
clientId: clientId ?? void 0,
|
|
1503
|
+
keyGen: args.keyGen,
|
|
1654
1504
|
chainId: args.chainId,
|
|
1655
1505
|
rpcUrl: args.rpcUrl,
|
|
1656
1506
|
chainDetail: args.chainDetail,
|
|
@@ -1683,151 +1533,32 @@ async function buildEvmMultisignBodyEulerV2ReulUnlock(args) {
|
|
|
1683
1533
|
});
|
|
1684
1534
|
}
|
|
1685
1535
|
async function buildEvmMultisignBodyAaveV4OneStep(args) {
|
|
1686
|
-
const
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1536
|
+
const firstDataNo0x = args.v.data.startsWith("0x") ? args.v.data.slice(2) : args.v.data;
|
|
1537
|
+
return buildEvmMultisignBatch({
|
|
1538
|
+
context: {
|
|
1539
|
+
chainCategory: "evm",
|
|
1540
|
+
keyGen: args.keyGen,
|
|
1541
|
+
purposeText: args.purposeText,
|
|
1542
|
+
chainId: args.chainId,
|
|
1543
|
+
rpcUrl: args.rpcUrl,
|
|
1544
|
+
executorAddress: args.executorAddress,
|
|
1545
|
+
chainDetail: args.chainDetail,
|
|
1546
|
+
useCustomGas: args.useCustomGas,
|
|
1547
|
+
customGasChainDetails: args.customGasChainDetails
|
|
1548
|
+
},
|
|
1549
|
+
steps: [
|
|
1550
|
+
{
|
|
1551
|
+
to: args.v.to,
|
|
1552
|
+
data: args.v.data,
|
|
1553
|
+
value: args.v.value,
|
|
1554
|
+
fallbackGas: args.estimateGasFallback
|
|
1555
|
+
}
|
|
1556
|
+
],
|
|
1557
|
+
purposeSuffix: args.purposeSuffix,
|
|
1558
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
1559
|
+
destinationAddress: args.v.to,
|
|
1560
|
+
buildBatchMeta: ({ gasLimit }) => args.buildBatchMeta({ gasLimit })
|
|
1691
1561
|
});
|
|
1692
|
-
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(args.rpcUrl) });
|
|
1693
|
-
const v = args.v;
|
|
1694
|
-
const feeParams = await fetchChainFeeParams(args.rpcUrl, args.chainId);
|
|
1695
|
-
const legacy = Boolean(args.chainDetail?.legacy) || !feeParams.isEip1559;
|
|
1696
|
-
const latestBaseFeeWeiOneStep = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
1697
|
-
const useCustomGas = args.useCustomGas;
|
|
1698
|
-
const gasLimitConfig = useCustomGas && args.chainDetail?.gasLimit != null ? Number(args.chainDetail.gasLimit) : void 0;
|
|
1699
|
-
const gasFeeMultiplier = useCustomGas && args.chainDetail?.gasMultiplier != null ? Number(args.chainDetail.gasMultiplier) : void 0;
|
|
1700
|
-
const baseNonce = await publicClient.getTransactionCount({ address: args.executorAddress, blockTag: "pending" });
|
|
1701
|
-
const currentNonce = baseNonce;
|
|
1702
|
-
let estimatedGas;
|
|
1703
|
-
try {
|
|
1704
|
-
estimatedGas = await publicClient.estimateGas({
|
|
1705
|
-
to: v.to,
|
|
1706
|
-
data: v.data,
|
|
1707
|
-
value: v.value,
|
|
1708
|
-
account: args.executorAddress
|
|
1709
|
-
});
|
|
1710
|
-
} catch {
|
|
1711
|
-
estimatedGas = args.estimateGasFallback;
|
|
1712
|
-
}
|
|
1713
|
-
const gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
1714
|
-
const batchMeta0 = args.buildBatchMeta({ gasLimit: gasLimitI });
|
|
1715
|
-
let firstTxFeePayload = {};
|
|
1716
|
-
let firstDataNo0x = "";
|
|
1717
|
-
const messageHashes = [];
|
|
1718
|
-
const messageRawBatch = [];
|
|
1719
|
-
const proposalTxParamsBatch = [];
|
|
1720
|
-
if (legacy) {
|
|
1721
|
-
let gasPriceWei = await publicClient.getGasPrice();
|
|
1722
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
1723
|
-
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1724
|
-
}
|
|
1725
|
-
if (useCustomGas && args.chainDetail?.gasPrice != null && args.chainDetail.gasPrice > 0) {
|
|
1726
|
-
const configured = viem.parseGwei(gweiToDecimalString(Number(args.chainDetail.gasPrice)));
|
|
1727
|
-
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
1728
|
-
}
|
|
1729
|
-
const ser = viem.serializeTransaction({
|
|
1730
|
-
type: "legacy",
|
|
1731
|
-
to: v.to,
|
|
1732
|
-
data: v.data,
|
|
1733
|
-
value: v.value,
|
|
1734
|
-
gas: gasLimitI,
|
|
1735
|
-
gasPrice: gasPriceWei,
|
|
1736
|
-
nonce: currentNonce,
|
|
1737
|
-
chainId: args.chainId
|
|
1738
|
-
});
|
|
1739
|
-
const h = viem.keccak256(ser);
|
|
1740
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
1741
|
-
messageRawBatch.push(ser);
|
|
1742
|
-
proposalTxParamsBatch.push({
|
|
1743
|
-
nonce: currentNonce,
|
|
1744
|
-
gasLimit: gasLimitI.toString(),
|
|
1745
|
-
txType: "legacy",
|
|
1746
|
-
gasPrice: gasPriceWei.toString()
|
|
1747
|
-
});
|
|
1748
|
-
firstTxFeePayload = { txNonce: currentNonce, txGasLimit: gasLimitI.toString(), txGasPrice: gasPriceWei.toString() };
|
|
1749
|
-
firstDataNo0x = v.data.startsWith("0x") ? v.data.slice(2) : v.data;
|
|
1750
|
-
} else {
|
|
1751
|
-
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
1752
|
-
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
1753
|
-
const configuredBase = useCustomGas && args.chainDetail?.baseFee != null ? Number(args.chainDetail.baseFee) : 0;
|
|
1754
|
-
const configuredPriority = useCustomGas && args.chainDetail?.priorityFee != null ? Number(args.chainDetail.priorityFee) : 0;
|
|
1755
|
-
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
1756
|
-
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
1757
|
-
const baseFeeMultiplierPct = useCustomGas && args.chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(args.chainDetail.baseFeeMultiplier)) : 100;
|
|
1758
|
-
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
1759
|
-
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
1760
|
-
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
|
|
1761
|
-
let maxFeePerGas = viem.parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
1762
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
1763
|
-
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1764
|
-
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
1765
|
-
}
|
|
1766
|
-
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
1767
|
-
maxFeePerGas,
|
|
1768
|
-
maxPriorityFeePerGas,
|
|
1769
|
-
latestBaseFeeWeiOneStep
|
|
1770
|
-
));
|
|
1771
|
-
const ser = viem.serializeTransaction({
|
|
1772
|
-
type: "eip1559",
|
|
1773
|
-
to: v.to,
|
|
1774
|
-
data: v.data,
|
|
1775
|
-
value: v.value,
|
|
1776
|
-
gas: gasLimitI,
|
|
1777
|
-
maxFeePerGas,
|
|
1778
|
-
maxPriorityFeePerGas,
|
|
1779
|
-
nonce: currentNonce,
|
|
1780
|
-
chainId: args.chainId
|
|
1781
|
-
});
|
|
1782
|
-
const h = viem.keccak256(ser);
|
|
1783
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
1784
|
-
messageRawBatch.push(ser);
|
|
1785
|
-
proposalTxParamsBatch.push({
|
|
1786
|
-
nonce: currentNonce,
|
|
1787
|
-
gasLimit: gasLimitI.toString(),
|
|
1788
|
-
txType: "eip1559",
|
|
1789
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
1790
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1791
|
-
});
|
|
1792
|
-
firstTxFeePayload = {
|
|
1793
|
-
txNonce: currentNonce,
|
|
1794
|
-
txGasLimit: gasLimitI.toString(),
|
|
1795
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
1796
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
1797
|
-
};
|
|
1798
|
-
firstDataNo0x = v.data.startsWith("0x") ? v.data.slice(2) : v.data;
|
|
1799
|
-
}
|
|
1800
|
-
const extraPayload = { batchMeta: [batchMeta0] };
|
|
1801
|
-
if (useCustomGas && args.customGasChainDetails && Object.keys(args.customGasChainDetails).length > 0) {
|
|
1802
|
-
extraPayload.customGasChainDetails = args.customGasChainDetails;
|
|
1803
|
-
}
|
|
1804
|
-
const extraJSON = JSON.stringify(extraPayload);
|
|
1805
|
-
const firstSigText = batchMeta0.signatureText;
|
|
1806
|
-
const bodyForSign = {
|
|
1807
|
-
keyList: args.keyList,
|
|
1808
|
-
pubKey: args.ph,
|
|
1809
|
-
msgHash: messageHashes[0],
|
|
1810
|
-
msgRaw: firstDataNo0x,
|
|
1811
|
-
messageHashes,
|
|
1812
|
-
messageRawBatch,
|
|
1813
|
-
destinationChainID: String(args.chainId),
|
|
1814
|
-
destinationAddress: v.to,
|
|
1815
|
-
extraJSON,
|
|
1816
|
-
signatureText: firstSigText,
|
|
1817
|
-
purpose: (() => {
|
|
1818
|
-
const t = args.purposeText.trim();
|
|
1819
|
-
return (t ? `${t}
|
|
1820
|
-
|
|
1821
|
-
` : "") + args.purposeSuffix;
|
|
1822
|
-
})(),
|
|
1823
|
-
...firstTxFeePayload,
|
|
1824
|
-
proposalTxParams: proposalTxParamsBatch
|
|
1825
|
-
};
|
|
1826
|
-
if (v.value > 0n) {
|
|
1827
|
-
bodyForSign.value = v.value.toString();
|
|
1828
|
-
}
|
|
1829
|
-
if (args.clientId) bodyForSign.clientId = args.clientId;
|
|
1830
|
-
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
1831
1562
|
}
|
|
1832
1563
|
var MIN_AAVE_V4_DEPOSIT_GAS_EXEC = 400000n;
|
|
1833
1564
|
var AAVE_V4_EVM_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -1919,6 +1650,731 @@ function resolveAaveV4DepositGasUnitsFromSignRequest(detail, batchIndex) {
|
|
|
1919
1650
|
}
|
|
1920
1651
|
return null;
|
|
1921
1652
|
}
|
|
1653
|
+
var POSITIONS_LIST = `
|
|
1654
|
+
query AaveUserPositions($r: UserPositionsRequest!, $currency: Currency! = USD, $w: TimeWindow! = LAST_DAY) {
|
|
1655
|
+
userPositions(request: $r) {
|
|
1656
|
+
id
|
|
1657
|
+
user
|
|
1658
|
+
createdAt
|
|
1659
|
+
spoke {
|
|
1660
|
+
id
|
|
1661
|
+
name
|
|
1662
|
+
address
|
|
1663
|
+
chain {
|
|
1664
|
+
chainId
|
|
1665
|
+
name
|
|
1666
|
+
}
|
|
1667
|
+
liquidationConfig {
|
|
1668
|
+
targetHealthFactor
|
|
1669
|
+
healthFactorForMaxBonus
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
totalSupplied(currency: $currency) {
|
|
1673
|
+
current { value name symbol }
|
|
1674
|
+
}
|
|
1675
|
+
totalDebt(currency: $currency) {
|
|
1676
|
+
current { value name symbol }
|
|
1677
|
+
}
|
|
1678
|
+
netBalance(currency: $currency) {
|
|
1679
|
+
current { value name symbol }
|
|
1680
|
+
}
|
|
1681
|
+
healthFactor {
|
|
1682
|
+
current
|
|
1683
|
+
change(window: $w) {
|
|
1684
|
+
normalized
|
|
1685
|
+
value
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
netApy {
|
|
1689
|
+
normalized
|
|
1690
|
+
value
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
`;
|
|
1695
|
+
var POSITION_DETAIL = `
|
|
1696
|
+
query AaveUserPosition(
|
|
1697
|
+
$r: UserPositionRequest!
|
|
1698
|
+
$currency: Currency! = USD
|
|
1699
|
+
$w: TimeWindow! = LAST_DAY
|
|
1700
|
+
) {
|
|
1701
|
+
userPosition(request: $r) {
|
|
1702
|
+
id
|
|
1703
|
+
user
|
|
1704
|
+
createdAt
|
|
1705
|
+
spoke {
|
|
1706
|
+
id
|
|
1707
|
+
name
|
|
1708
|
+
address
|
|
1709
|
+
chain {
|
|
1710
|
+
chainId
|
|
1711
|
+
name
|
|
1712
|
+
}
|
|
1713
|
+
liquidationConfig {
|
|
1714
|
+
targetHealthFactor
|
|
1715
|
+
healthFactorForMaxBonus
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
totalSupplied(currency: $currency) {
|
|
1719
|
+
current { value name symbol }
|
|
1720
|
+
change { normalized value }
|
|
1721
|
+
}
|
|
1722
|
+
totalCollateral(currency: $currency) {
|
|
1723
|
+
current { value name symbol }
|
|
1724
|
+
change { normalized value }
|
|
1725
|
+
}
|
|
1726
|
+
totalDebt(currency: $currency) {
|
|
1727
|
+
current { value name symbol }
|
|
1728
|
+
change { normalized value }
|
|
1729
|
+
}
|
|
1730
|
+
netBalance(currency: $currency) {
|
|
1731
|
+
current { value name symbol }
|
|
1732
|
+
change { normalized value }
|
|
1733
|
+
}
|
|
1734
|
+
netCollateral(currency: $currency) {
|
|
1735
|
+
current { value name symbol }
|
|
1736
|
+
change { normalized value }
|
|
1737
|
+
}
|
|
1738
|
+
netApy {
|
|
1739
|
+
normalized
|
|
1740
|
+
value
|
|
1741
|
+
}
|
|
1742
|
+
netSupplyApy {
|
|
1743
|
+
current {
|
|
1744
|
+
normalized
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
netBorrowApy {
|
|
1748
|
+
current {
|
|
1749
|
+
normalized
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
netAccruedInterest(currency: $currency) {
|
|
1753
|
+
value
|
|
1754
|
+
name
|
|
1755
|
+
symbol
|
|
1756
|
+
}
|
|
1757
|
+
healthFactor {
|
|
1758
|
+
current
|
|
1759
|
+
change(window: $w) {
|
|
1760
|
+
normalized
|
|
1761
|
+
value
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
maxBorrowingPower(currency: $currency) {
|
|
1765
|
+
value
|
|
1766
|
+
name
|
|
1767
|
+
symbol
|
|
1768
|
+
}
|
|
1769
|
+
remainingBorrowingPower(currency: $currency) {
|
|
1770
|
+
value
|
|
1771
|
+
name
|
|
1772
|
+
symbol
|
|
1773
|
+
}
|
|
1774
|
+
averageCollateralFactor {
|
|
1775
|
+
normalized
|
|
1776
|
+
}
|
|
1777
|
+
liquidationPrice(currency: $currency) {
|
|
1778
|
+
value
|
|
1779
|
+
name
|
|
1780
|
+
symbol
|
|
1781
|
+
}
|
|
1782
|
+
canUpdateDynamicConfig
|
|
1783
|
+
netBalancePercentChange(window: $w) {
|
|
1784
|
+
normalized
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
`;
|
|
1789
|
+
var USER_SUPPLIES = `
|
|
1790
|
+
query AaveUserSupplies($r: UserSuppliesRequest!) {
|
|
1791
|
+
userSupplies(request: $r) {
|
|
1792
|
+
id
|
|
1793
|
+
isCollateral
|
|
1794
|
+
principal {
|
|
1795
|
+
amount {
|
|
1796
|
+
value
|
|
1797
|
+
}
|
|
1798
|
+
token {
|
|
1799
|
+
address
|
|
1800
|
+
info {
|
|
1801
|
+
symbol
|
|
1802
|
+
name
|
|
1803
|
+
icon
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
balance {
|
|
1808
|
+
amount {
|
|
1809
|
+
value
|
|
1810
|
+
}
|
|
1811
|
+
token {
|
|
1812
|
+
address
|
|
1813
|
+
info {
|
|
1814
|
+
symbol
|
|
1815
|
+
name
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
withdrawable {
|
|
1820
|
+
amount {
|
|
1821
|
+
value
|
|
1822
|
+
}
|
|
1823
|
+
token {
|
|
1824
|
+
address
|
|
1825
|
+
info {
|
|
1826
|
+
symbol
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
interest {
|
|
1831
|
+
amount {
|
|
1832
|
+
value
|
|
1833
|
+
}
|
|
1834
|
+
token {
|
|
1835
|
+
address
|
|
1836
|
+
info {
|
|
1837
|
+
symbol
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
reserve {
|
|
1842
|
+
id
|
|
1843
|
+
onChainId
|
|
1844
|
+
summary {
|
|
1845
|
+
supplyApy {
|
|
1846
|
+
normalized
|
|
1847
|
+
value
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
asset {
|
|
1851
|
+
underlying {
|
|
1852
|
+
address
|
|
1853
|
+
info {
|
|
1854
|
+
symbol
|
|
1855
|
+
name
|
|
1856
|
+
icon
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
`;
|
|
1864
|
+
var DEFAULT_CURRENCY = "USD";
|
|
1865
|
+
var DEFAULT_TIME_WINDOW = "LAST_DAY";
|
|
1866
|
+
function formatAaveV4ExchangeLabel(ex) {
|
|
1867
|
+
if (ex == null) return "\u2014";
|
|
1868
|
+
const sym = (ex.symbol ?? "").trim();
|
|
1869
|
+
const name = (ex.name ?? "").trim();
|
|
1870
|
+
if (sym === "$" && name) return name;
|
|
1871
|
+
if (name && sym && name.toUpperCase() !== sym) return name;
|
|
1872
|
+
return sym || name || "\u2014";
|
|
1873
|
+
}
|
|
1874
|
+
function formatAaveV4PositionPercent(normalized, value) {
|
|
1875
|
+
const n = (normalized ?? "").trim();
|
|
1876
|
+
const v = (value ?? "").trim();
|
|
1877
|
+
if (n === "0" && (v === "0" || v === "")) return "0%";
|
|
1878
|
+
const out = formatAaveV4PercentDisplay(normalized, value);
|
|
1879
|
+
return out;
|
|
1880
|
+
}
|
|
1881
|
+
function formatAaveV4PositionHealthFactor(raw) {
|
|
1882
|
+
if (raw == null || String(raw).trim() === "") return "\u221E";
|
|
1883
|
+
return formatAaveV4HealthFactorInner(raw);
|
|
1884
|
+
}
|
|
1885
|
+
function formatAaveV4HealthFactorInner(raw) {
|
|
1886
|
+
const n = Number(raw);
|
|
1887
|
+
if (!Number.isFinite(n)) return String(raw);
|
|
1888
|
+
if (n >= 1e12) return "\u221E";
|
|
1889
|
+
return n >= 10 ? n.toFixed(1) : n.toFixed(2);
|
|
1890
|
+
}
|
|
1891
|
+
function buildUserPositionsRequest(user, filter) {
|
|
1892
|
+
return {
|
|
1893
|
+
user,
|
|
1894
|
+
filter,
|
|
1895
|
+
orderBy: { balance: "DESC" }
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
async function fetchAaveV4UserPositionsForChain(args) {
|
|
1899
|
+
const u = (args.user ?? "").trim();
|
|
1900
|
+
if (!u || !viem.isAddress(u)) return [];
|
|
1901
|
+
const user = viem.getAddress(u);
|
|
1902
|
+
const d = await aaveV4Gql(POSITIONS_LIST, {
|
|
1903
|
+
r: buildUserPositionsRequest(user, { chainIds: [args.chainId] }),
|
|
1904
|
+
currency: DEFAULT_CURRENCY,
|
|
1905
|
+
w: DEFAULT_TIME_WINDOW
|
|
1906
|
+
});
|
|
1907
|
+
return d.userPositions ?? [];
|
|
1908
|
+
}
|
|
1909
|
+
async function fetchAaveV4UserPositionsByAssetOnChain(args) {
|
|
1910
|
+
const u = (args.user ?? "").trim();
|
|
1911
|
+
if (!u || !viem.isAddress(u)) {
|
|
1912
|
+
return { forAsset: [], other: [], filterUnderlying: null };
|
|
1913
|
+
}
|
|
1914
|
+
const user = viem.getAddress(u);
|
|
1915
|
+
const c = args.chainId;
|
|
1916
|
+
const f = args.filterUnderlying;
|
|
1917
|
+
if (f == null) {
|
|
1918
|
+
const all2 = await fetchAaveV4UserPositionsForChain({ user: u, chainId: c });
|
|
1919
|
+
return { forAsset: all2, other: [], filterUnderlying: null };
|
|
1920
|
+
}
|
|
1921
|
+
const token = viem.getAddress(f);
|
|
1922
|
+
const [allRes, withTokenRes] = await Promise.all([
|
|
1923
|
+
aaveV4Gql(POSITIONS_LIST, {
|
|
1924
|
+
r: buildUserPositionsRequest(user, { chainIds: [c] }),
|
|
1925
|
+
currency: DEFAULT_CURRENCY,
|
|
1926
|
+
w: DEFAULT_TIME_WINDOW
|
|
1927
|
+
}),
|
|
1928
|
+
aaveV4Gql(POSITIONS_LIST, {
|
|
1929
|
+
r: buildUserPositionsRequest(user, { tokens: [{ address: token, chainId: c }] }),
|
|
1930
|
+
currency: DEFAULT_CURRENCY,
|
|
1931
|
+
w: DEFAULT_TIME_WINDOW
|
|
1932
|
+
})
|
|
1933
|
+
]);
|
|
1934
|
+
const all = allRes.userPositions ?? [];
|
|
1935
|
+
const forAsset = withTokenRes.userPositions ?? [];
|
|
1936
|
+
const want = new Set(forAsset.map((p) => p.id));
|
|
1937
|
+
const other = all.filter((p) => !want.has(p.id));
|
|
1938
|
+
return { forAsset, other, filterUnderlying: token };
|
|
1939
|
+
}
|
|
1940
|
+
async function fetchAaveV4UserPositionById(positionId) {
|
|
1941
|
+
const id = (positionId ?? "").trim();
|
|
1942
|
+
if (!id) return null;
|
|
1943
|
+
const d = await aaveV4Gql(POSITION_DETAIL, {
|
|
1944
|
+
r: { id },
|
|
1945
|
+
currency: DEFAULT_CURRENCY,
|
|
1946
|
+
w: DEFAULT_TIME_WINDOW
|
|
1947
|
+
});
|
|
1948
|
+
return d.userPosition ?? null;
|
|
1949
|
+
}
|
|
1950
|
+
async function fetchAaveV4UserSuppliesForPosition(userPositionId) {
|
|
1951
|
+
const pid = (userPositionId ?? "").trim();
|
|
1952
|
+
if (!pid) return [];
|
|
1953
|
+
const d = await aaveV4Gql(USER_SUPPLIES, {
|
|
1954
|
+
r: {
|
|
1955
|
+
query: { userPositionId: pid },
|
|
1956
|
+
orderBy: { amount: "DESC" },
|
|
1957
|
+
includeZeroBalances: false
|
|
1958
|
+
}
|
|
1959
|
+
});
|
|
1960
|
+
return d.userSupplies ?? [];
|
|
1961
|
+
}
|
|
1962
|
+
async function aaveV4UserHasAvailableBorrowCollateralForContextOnSpoke(args) {
|
|
1963
|
+
let wantSpoke;
|
|
1964
|
+
try {
|
|
1965
|
+
wantSpoke = viem.getAddress(args.spokeAddress).toLowerCase();
|
|
1966
|
+
} catch {
|
|
1967
|
+
return false;
|
|
1968
|
+
}
|
|
1969
|
+
const u0 = viem.getAddress(args.contextUnderlying).toLowerCase();
|
|
1970
|
+
const positions = await fetchAaveV4UserPositionsForChain({ user: args.user, chainId: args.chainId });
|
|
1971
|
+
const pos = positions.find((p) => {
|
|
1972
|
+
const a = (p.spoke?.address ?? "").trim();
|
|
1973
|
+
if (!a) return false;
|
|
1974
|
+
try {
|
|
1975
|
+
return viem.getAddress(a).toLowerCase() === wantSpoke;
|
|
1976
|
+
} catch {
|
|
1977
|
+
return false;
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
if (!pos) return false;
|
|
1981
|
+
const supplies = await fetchAaveV4UserSuppliesForPosition(pos.id);
|
|
1982
|
+
const row = supplies.find((s) => {
|
|
1983
|
+
const a = (s.reserve?.asset?.underlying?.address ?? "").trim();
|
|
1984
|
+
if (!a) return false;
|
|
1985
|
+
try {
|
|
1986
|
+
return viem.getAddress(a).toLowerCase() === u0;
|
|
1987
|
+
} catch {
|
|
1988
|
+
return false;
|
|
1989
|
+
}
|
|
1990
|
+
});
|
|
1991
|
+
if (!row) return false;
|
|
1992
|
+
const bal = parseFloat((row.balance?.amount?.value ?? "").trim());
|
|
1993
|
+
if (!Number.isFinite(bal) || bal <= 0) return false;
|
|
1994
|
+
return row.isCollateral === true;
|
|
1995
|
+
}
|
|
1996
|
+
function formatAaveV4DecimalString(raw, maxFractionDigits = 6) {
|
|
1997
|
+
const s = (raw ?? "").trim();
|
|
1998
|
+
if (!s) return "\u2014";
|
|
1999
|
+
const n = Number(s);
|
|
2000
|
+
if (!Number.isFinite(n)) return s;
|
|
2001
|
+
if (Math.abs(n) >= 1e9) return n.toExponential(2);
|
|
2002
|
+
return n.toLocaleString(void 0, { maximumFractionDigits: maxFractionDigits });
|
|
2003
|
+
}
|
|
2004
|
+
function formatAaveV4RiskNotionalString(raw) {
|
|
2005
|
+
const s = (raw ?? "").trim();
|
|
2006
|
+
if (!s) return "\u2014";
|
|
2007
|
+
const n = Number(s);
|
|
2008
|
+
if (!Number.isFinite(n)) return s;
|
|
2009
|
+
if (n === 0) return "0";
|
|
2010
|
+
if (Math.abs(n) >= 1e9) return n.toExponential(2);
|
|
2011
|
+
if (n > 0 && n < 0.5) {
|
|
2012
|
+
return n.toLocaleString(void 0, { maximumSignificantDigits: 4, maximumFractionDigits: 8 });
|
|
2013
|
+
}
|
|
2014
|
+
return n.toLocaleString(void 0, { maximumFractionDigits: 6 });
|
|
2015
|
+
}
|
|
2016
|
+
function formatAaveV4HealthFactor(raw) {
|
|
2017
|
+
if (raw == null || String(raw).trim() === "") return "\u2014";
|
|
2018
|
+
return formatAaveV4HealthFactorInner(String(raw).trim());
|
|
2019
|
+
}
|
|
2020
|
+
var HF_EPS = 1e-9;
|
|
2021
|
+
function aaveV4WithdrawHealthGate(args) {
|
|
2022
|
+
const { hasBorrowDebt, liquidationConfig: liq } = args;
|
|
2023
|
+
const r0 = args.resultingHealthFactor;
|
|
2024
|
+
if (!hasBorrowDebt) {
|
|
2025
|
+
return { outcome: "allow" };
|
|
2026
|
+
}
|
|
2027
|
+
if (r0 == null || !Number.isFinite(r0)) {
|
|
2028
|
+
return { outcome: "block", reason: "Could not determine health factor after withdrawal." };
|
|
2029
|
+
}
|
|
2030
|
+
const r = r0;
|
|
2031
|
+
const t = liq == null ? NaN : Number(liq.targetHealthFactor);
|
|
2032
|
+
const m = liq == null ? NaN : Number(liq.healthFactorForMaxBonus);
|
|
2033
|
+
if (r <= 1 + HF_EPS) {
|
|
2034
|
+
return {
|
|
2035
|
+
outcome: "block",
|
|
2036
|
+
reason: "This withdrawal would leave health factor at or below 1.0 (liquidation range)."
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
if (Number.isFinite(m) && m > 1 + HF_EPS && r <= m + HF_EPS) {
|
|
2040
|
+
return {
|
|
2041
|
+
outcome: "block",
|
|
2042
|
+
reason: `This withdrawal would put health factor at or below the spoke\u2019s max-liquidation-bonus threshold (${m}).`
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
if (Number.isFinite(t) && r < t - HF_EPS) {
|
|
2046
|
+
return {
|
|
2047
|
+
outcome: "confirm",
|
|
2048
|
+
reason: `The resulting health factor would be below this market\u2019s target (${t.toFixed(4)}).`,
|
|
2049
|
+
targetHealthFactor: t,
|
|
2050
|
+
healthFactorForMaxBonus: Number.isFinite(m) ? m : 0
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
return { outcome: "allow" };
|
|
2054
|
+
}
|
|
2055
|
+
function aaveV4BorrowHealthGate(args) {
|
|
2056
|
+
return aaveV4WithdrawHealthGate({
|
|
2057
|
+
resultingHealthFactor: args.resultingHealthFactor,
|
|
2058
|
+
hasBorrowDebt: true,
|
|
2059
|
+
liquidationConfig: args.liquidationConfig
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
function aaveV4RepayHealthGate(args) {
|
|
2063
|
+
if (!args.strict) {
|
|
2064
|
+
return { outcome: "allow" };
|
|
2065
|
+
}
|
|
2066
|
+
return aaveV4WithdrawHealthGate({
|
|
2067
|
+
resultingHealthFactor: args.resultingHealthFactor,
|
|
2068
|
+
hasBorrowDebt: true,
|
|
2069
|
+
liquidationConfig: args.liquidationConfig
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
// src/protocols/evm/aave-v4/positionActionsApi.ts
|
|
2074
|
+
var PREVIEW_WITHDRAW = `
|
|
2075
|
+
query AaveV4PreviewWithdraw($req: PreviewRequest!) {
|
|
2076
|
+
preview(request: $req) {
|
|
2077
|
+
__typename
|
|
2078
|
+
... on PreviewUserPosition {
|
|
2079
|
+
id
|
|
2080
|
+
healthFactor {
|
|
2081
|
+
__typename
|
|
2082
|
+
... on HealthFactorVariation {
|
|
2083
|
+
current
|
|
2084
|
+
after
|
|
2085
|
+
}
|
|
2086
|
+
... on HealthFactorError {
|
|
2087
|
+
reason
|
|
2088
|
+
current
|
|
2089
|
+
after
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
`;
|
|
2096
|
+
var USER_CLAIMABLE = `
|
|
2097
|
+
query AaveV4UserClaimableRewards($req: UserClaimableRewardsRequest!) {
|
|
2098
|
+
userClaimableRewards(request: $req) {
|
|
2099
|
+
__typename
|
|
2100
|
+
... on UserMerklClaimableReward {
|
|
2101
|
+
id
|
|
2102
|
+
claimable {
|
|
2103
|
+
amount { value }
|
|
2104
|
+
exchange { value name symbol }
|
|
2105
|
+
token {
|
|
2106
|
+
address
|
|
2107
|
+
info { symbol name }
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
`;
|
|
2114
|
+
var CLAIM_REWARDS = `
|
|
2115
|
+
query AaveV4ClaimRewards($req: ClaimRewardsRequest!) {
|
|
2116
|
+
claimRewards(request: $req) {
|
|
2117
|
+
to
|
|
2118
|
+
from
|
|
2119
|
+
data
|
|
2120
|
+
value
|
|
2121
|
+
chainId
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
`;
|
|
2125
|
+
function parseBigDecimalHf(s) {
|
|
2126
|
+
if (s == null || !String(s).trim()) return null;
|
|
2127
|
+
const n = Number(String(s).trim());
|
|
2128
|
+
return Number.isFinite(n) ? n : null;
|
|
2129
|
+
}
|
|
2130
|
+
async function previewAaveV4WithdrawResultingHf(args) {
|
|
2131
|
+
const req = {
|
|
2132
|
+
action: {
|
|
2133
|
+
withdraw: {
|
|
2134
|
+
sender: args.user,
|
|
2135
|
+
reserve: args.reserveId,
|
|
2136
|
+
amount: { erc20: { exact: args.amountExactHuman } }
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
const d = await aaveV4Gql(PREVIEW_WITHDRAW, { req });
|
|
2141
|
+
const p = d.preview;
|
|
2142
|
+
if (p?.__typename !== "PreviewUserPosition") {
|
|
2143
|
+
return { resultingHf: null, error: "Withdraw preview is not available for this request." };
|
|
2144
|
+
}
|
|
2145
|
+
const hf = p.healthFactor;
|
|
2146
|
+
if (hf?.__typename === "HealthFactorError") {
|
|
2147
|
+
return { resultingHf: null, error: hf.reason ?? "Invalid withdrawal for this position." };
|
|
2148
|
+
}
|
|
2149
|
+
if (hf?.__typename === "HealthFactorVariation") {
|
|
2150
|
+
return { resultingHf: parseBigDecimalHf(hf.after), error: null };
|
|
2151
|
+
}
|
|
2152
|
+
return { resultingHf: null, error: "Could not read health factor from preview." };
|
|
2153
|
+
}
|
|
2154
|
+
async function previewAaveV4BorrowResultingHf(args) {
|
|
2155
|
+
const req = {
|
|
2156
|
+
action: {
|
|
2157
|
+
borrow: {
|
|
2158
|
+
sender: args.user,
|
|
2159
|
+
reserve: args.reserveGraphqlId,
|
|
2160
|
+
amount: { erc20: { value: args.amountExactHuman } }
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
const d = await aaveV4Gql(PREVIEW_WITHDRAW, { req });
|
|
2165
|
+
const p = d.preview;
|
|
2166
|
+
if (p?.__typename !== "PreviewUserPosition") {
|
|
2167
|
+
return { resultingHf: null, error: "Borrow preview is not available for this request." };
|
|
2168
|
+
}
|
|
2169
|
+
const hf = p.healthFactor;
|
|
2170
|
+
if (hf?.__typename === "HealthFactorError") {
|
|
2171
|
+
return { resultingHf: null, error: hf.reason ?? "Invalid borrow for this position." };
|
|
2172
|
+
}
|
|
2173
|
+
if (hf?.__typename === "HealthFactorVariation") {
|
|
2174
|
+
return { resultingHf: parseBigDecimalHf(hf.after), error: null };
|
|
2175
|
+
}
|
|
2176
|
+
return { resultingHf: null, error: "Could not read health factor from borrow preview." };
|
|
2177
|
+
}
|
|
2178
|
+
var PREVIEW_REPAY = `
|
|
2179
|
+
query AaveV4PreviewRepay($req: PreviewRequest!) {
|
|
2180
|
+
preview(request: $req) {
|
|
2181
|
+
__typename
|
|
2182
|
+
... on PreviewUserPosition {
|
|
2183
|
+
id
|
|
2184
|
+
healthFactor {
|
|
2185
|
+
__typename
|
|
2186
|
+
... on HealthFactorVariation {
|
|
2187
|
+
current
|
|
2188
|
+
after
|
|
2189
|
+
}
|
|
2190
|
+
... on HealthFactorError {
|
|
2191
|
+
reason
|
|
2192
|
+
current
|
|
2193
|
+
after
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
`;
|
|
2200
|
+
async function previewAaveV4RepayResultingHf(args) {
|
|
2201
|
+
const req = {
|
|
2202
|
+
action: {
|
|
2203
|
+
repay: {
|
|
2204
|
+
sender: args.user,
|
|
2205
|
+
reserve: args.reserveGraphqlId,
|
|
2206
|
+
amount: { erc20: { value: { exact: args.amountExactHuman } } }
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2210
|
+
const d = await aaveV4Gql(PREVIEW_REPAY, { req });
|
|
2211
|
+
const p = d.preview;
|
|
2212
|
+
if (p?.__typename !== "PreviewUserPosition") {
|
|
2213
|
+
return { resultingHf: null, error: "Repay preview is not available for this request." };
|
|
2214
|
+
}
|
|
2215
|
+
const hf = p.healthFactor;
|
|
2216
|
+
if (hf?.__typename === "HealthFactorError") {
|
|
2217
|
+
return { resultingHf: null, error: hf.reason ?? "Invalid repay for this position." };
|
|
2218
|
+
}
|
|
2219
|
+
if (hf?.__typename === "HealthFactorVariation") {
|
|
2220
|
+
return { resultingHf: parseBigDecimalHf(hf.after), error: null };
|
|
2221
|
+
}
|
|
2222
|
+
return { resultingHf: null, error: "Could not read health factor from repay preview." };
|
|
2223
|
+
}
|
|
2224
|
+
async function fetchAaveV4MerklClaimableRewardsForChain(args) {
|
|
2225
|
+
const d = await aaveV4Gql(USER_CLAIMABLE, { req: { user: args.user, chainId: args.chainId } });
|
|
2226
|
+
const out = [];
|
|
2227
|
+
for (const r of d.userClaimableRewards ?? []) {
|
|
2228
|
+
if (r.__typename !== "UserMerklClaimableReward" || !("claimable" in r)) continue;
|
|
2229
|
+
const id = (r.id ?? "").trim();
|
|
2230
|
+
if (!id) continue;
|
|
2231
|
+
const c = r.claimable;
|
|
2232
|
+
const sym = (c?.token?.info?.symbol ?? "").trim() || "\u2014";
|
|
2233
|
+
const name = (c?.token?.info?.name ?? "").trim() || sym;
|
|
2234
|
+
const addr = (c?.token?.address ?? "").trim();
|
|
2235
|
+
const amt = (c?.amount?.value ?? "").trim();
|
|
2236
|
+
const exV = (c?.exchange?.value ?? "").trim();
|
|
2237
|
+
const exName = (c?.exchange?.name ?? "").trim();
|
|
2238
|
+
const exSym = (c?.exchange?.symbol ?? "").trim();
|
|
2239
|
+
const exchangeLabel = exName && exSym && exName.toUpperCase() !== exSym.toUpperCase() ? exName : exSym || exName || "\u2014";
|
|
2240
|
+
let exchangeValue = null;
|
|
2241
|
+
if (exV) {
|
|
2242
|
+
const n = parseFloat(exV);
|
|
2243
|
+
exchangeValue = Number.isFinite(n) ? exV : null;
|
|
2244
|
+
}
|
|
2245
|
+
out.push({
|
|
2246
|
+
id,
|
|
2247
|
+
tokenSymbol: sym,
|
|
2248
|
+
tokenName: name,
|
|
2249
|
+
tokenAddress: addr,
|
|
2250
|
+
amountValue: amt,
|
|
2251
|
+
exchangeValue,
|
|
2252
|
+
exchangeLabel
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
return out;
|
|
2256
|
+
}
|
|
2257
|
+
async function fetchAaveV4MerklClaimRewardIdsForChain(args) {
|
|
2258
|
+
const rows = await fetchAaveV4MerklClaimableRewardsForChain(args);
|
|
2259
|
+
return rows.map((r) => r.id);
|
|
2260
|
+
}
|
|
2261
|
+
async function fetchAaveV4ClaimRewardsCalldata(args) {
|
|
2262
|
+
if (args.rewardIds.length === 0) return null;
|
|
2263
|
+
const d = await aaveV4Gql(CLAIM_REWARDS, { req: { user: args.user, chainId: args.chainId, ids: args.rewardIds } });
|
|
2264
|
+
const c = d.claimRewards;
|
|
2265
|
+
if (!c) return null;
|
|
2266
|
+
return {
|
|
2267
|
+
to: c.to,
|
|
2268
|
+
from: c.from,
|
|
2269
|
+
data: c.data,
|
|
2270
|
+
value: c.value,
|
|
2271
|
+
chainId: c.chainId
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
// src/protocols/evm/aave-v4/loadSupportedChainIds.ts
|
|
2276
|
+
var cached = null;
|
|
2277
|
+
var inflight = null;
|
|
2278
|
+
function loadAaveV4SupportedChainIds() {
|
|
2279
|
+
if (cached) return Promise.resolve(cached);
|
|
2280
|
+
if (inflight) return inflight;
|
|
2281
|
+
inflight = (async () => {
|
|
2282
|
+
try {
|
|
2283
|
+
const s = await loadAaveV4SupportedChainIdsFromV4Api();
|
|
2284
|
+
cached = s;
|
|
2285
|
+
return s;
|
|
2286
|
+
} finally {
|
|
2287
|
+
inflight = null;
|
|
2288
|
+
}
|
|
2289
|
+
})();
|
|
2290
|
+
return inflight;
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
// src/chains/evm/chainIdParse.ts
|
|
2294
|
+
function parseEvmChainIdToNumber(chainId) {
|
|
2295
|
+
if (chainId == null) return Number.NaN;
|
|
2296
|
+
if (typeof chainId === "bigint") {
|
|
2297
|
+
const n = Number(chainId);
|
|
2298
|
+
return Number.isSafeInteger(n) && n >= 0 ? n : Number.NaN;
|
|
2299
|
+
}
|
|
2300
|
+
if (typeof chainId === "number") {
|
|
2301
|
+
return Number.isInteger(chainId) && chainId >= 0 ? chainId : Number.NaN;
|
|
2302
|
+
}
|
|
2303
|
+
const t = String(chainId).trim();
|
|
2304
|
+
if (!t) return Number.NaN;
|
|
2305
|
+
const low = t.toLowerCase();
|
|
2306
|
+
if (low.startsWith("eip155:")) {
|
|
2307
|
+
const rest = t.slice("eip155:".length).trim();
|
|
2308
|
+
const n = Number.parseInt(rest, 10);
|
|
2309
|
+
return Number.isNaN(n) || n < 0 ? Number.NaN : n;
|
|
2310
|
+
}
|
|
2311
|
+
if (low.startsWith("0x")) {
|
|
2312
|
+
return Number.parseInt(t, 16);
|
|
2313
|
+
}
|
|
2314
|
+
return Number.parseInt(t, 10);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
// src/protocols/evm/aave-v4/reserveDisplay.ts
|
|
2318
|
+
function formatAavePercentDisplay(p) {
|
|
2319
|
+
if (!p) return "\u2014";
|
|
2320
|
+
const t = (p.formatted ?? "").trim();
|
|
2321
|
+
if (t) return t.includes("%") ? t : `${t}%`;
|
|
2322
|
+
const v = (p.value ?? "").trim();
|
|
2323
|
+
if (!v) return "\u2014";
|
|
2324
|
+
const n = Number(v) * 100;
|
|
2325
|
+
if (!Number.isFinite(n)) return "\u2014";
|
|
2326
|
+
if (n >= 0.01) return `${n.toFixed(2)}%`;
|
|
2327
|
+
if (n > 0) return `${n.toFixed(4)}%`;
|
|
2328
|
+
return "0%";
|
|
2329
|
+
}
|
|
2330
|
+
function aaveAvailableLiquidityDisplay(supplyInfo, borrowInfo) {
|
|
2331
|
+
const sTotal = supplyInfo?.total;
|
|
2332
|
+
const bAmt = borrowInfo?.total?.amount;
|
|
2333
|
+
if (!sTotal?.raw || sTotal.decimals == null) return "\u2014";
|
|
2334
|
+
if (!bAmt?.raw || bAmt.decimals == null) return "\u2014";
|
|
2335
|
+
try {
|
|
2336
|
+
if (sTotal.decimals !== bAmt.decimals) return "\u2014";
|
|
2337
|
+
const a = BigInt(sTotal.raw) - BigInt(bAmt.raw);
|
|
2338
|
+
if (a < 0n) return "0";
|
|
2339
|
+
return viem.formatUnits(a, sTotal.decimals);
|
|
2340
|
+
} catch {
|
|
2341
|
+
return "\u2014";
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
function aaveUnderlyingAddressForContext(args) {
|
|
2345
|
+
const raw = (args.contextContract ?? "").trim();
|
|
2346
|
+
try {
|
|
2347
|
+
const a = viem.getAddress(raw);
|
|
2348
|
+
if (a.toLowerCase() === viem.zeroAddress.toLowerCase() && args.chainNativeWrapped) {
|
|
2349
|
+
return viem.getAddress(args.chainNativeWrapped.trim());
|
|
2350
|
+
}
|
|
2351
|
+
return a;
|
|
2352
|
+
} catch {
|
|
2353
|
+
return viem.getAddress(viem.zeroAddress);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
function isValidAaveChainId(assetsChainId) {
|
|
2357
|
+
if (assetsChainId == null) return false;
|
|
2358
|
+
const n = parseEvmChainIdToNumber(assetsChainId);
|
|
2359
|
+
return !Number.isNaN(n) && n >= 0;
|
|
2360
|
+
}
|
|
2361
|
+
function aaveReadSupplyMetrics(reserve, symbolForDisplay) {
|
|
2362
|
+
if (!reserve || typeof reserve !== "object") {
|
|
2363
|
+
return { depositedAmount: "\u2014", apy: "\u2014", totalDeposits: "\u2014", availableLiquidity: "\u2014" };
|
|
2364
|
+
}
|
|
2365
|
+
const r = reserve;
|
|
2366
|
+
const apy = formatAavePercentDisplay(r.supplyInfo?.apy);
|
|
2367
|
+
const tot = r.supplyInfo?.total?.value ?? "\u2014";
|
|
2368
|
+
const liq = aaveAvailableLiquidityDisplay(r.supplyInfo, r.borrowInfo);
|
|
2369
|
+
const dep = r.userState?.balance?.amount?.value ?? "\u2014";
|
|
2370
|
+
const sym = (symbolForDisplay ?? "").trim();
|
|
2371
|
+
return {
|
|
2372
|
+
depositedAmount: dep === "\u2014" ? "\u2014" : sym ? `${dep} ${sym}` : dep,
|
|
2373
|
+
apy,
|
|
2374
|
+
totalDeposits: tot === "\u2014" ? "\u2014" : sym ? `${tot} ${sym}` : tot,
|
|
2375
|
+
availableLiquidity: liq === "\u2014" ? "\u2014" : sym ? `${liq} ${sym}` : liq
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
1922
2378
|
|
|
1923
2379
|
// src/protocols/evm/aave-v4/index.ts
|
|
1924
2380
|
var AAVE_V4_PROTOCOL_ID = "aave-v4";
|
|
@@ -1947,10 +2403,17 @@ exports.AAVE_V4_SPOKE_REPAY_DEFAULT_GAS_UNITS = AAVE_V4_SPOKE_REPAY_DEFAULT_GAS_
|
|
|
1947
2403
|
exports.AAVE_V4_SPOKE_SUPPLY_DEFAULT_GAS_UNITS = AAVE_V4_SPOKE_SUPPLY_DEFAULT_GAS_UNITS;
|
|
1948
2404
|
exports.AAVE_V4_SPOKE_WITHDRAW_DEFAULT_GAS_UNITS = AAVE_V4_SPOKE_WITHDRAW_DEFAULT_GAS_UNITS;
|
|
1949
2405
|
exports.MIN_AAVE_V4_DEPOSIT_GAS_EXEC = MIN_AAVE_V4_DEPOSIT_GAS_EXEC;
|
|
2406
|
+
exports.aaveAvailableLiquidityDisplay = aaveAvailableLiquidityDisplay;
|
|
2407
|
+
exports.aaveReadSupplyMetrics = aaveReadSupplyMetrics;
|
|
2408
|
+
exports.aaveUnderlyingAddressForContext = aaveUnderlyingAddressForContext;
|
|
2409
|
+
exports.aaveV4BorrowHealthGate = aaveV4BorrowHealthGate;
|
|
1950
2410
|
exports.aaveV4Gql = aaveV4Gql;
|
|
1951
2411
|
exports.aaveV4KeyForNodeAssetRow = aaveV4KeyForNodeAssetRow;
|
|
1952
2412
|
exports.aaveV4ProtocolModule = aaveV4ProtocolModule;
|
|
2413
|
+
exports.aaveV4RepayHealthGate = aaveV4RepayHealthGate;
|
|
1953
2414
|
exports.aaveV4UiMarketIdForHubName = aaveV4UiMarketIdForHubName;
|
|
2415
|
+
exports.aaveV4UserHasAvailableBorrowCollateralForContextOnSpoke = aaveV4UserHasAvailableBorrowCollateralForContextOnSpoke;
|
|
2416
|
+
exports.aaveV4WithdrawHealthGate = aaveV4WithdrawHealthGate;
|
|
1954
2417
|
exports.aggregateV4SupplyDisplay = aggregateV4SupplyDisplay;
|
|
1955
2418
|
exports.borrowableAssetsFromHubReserves = borrowableAssetsFromHubReserves;
|
|
1956
2419
|
exports.buildAaveV4BorrowTableRowsFromHub = buildAaveV4BorrowTableRowsFromHub;
|
|
@@ -1963,24 +2426,44 @@ exports.buildEvmMultisignBodyEulerV2MerklDistributorClaim = buildEvmMultisignBod
|
|
|
1963
2426
|
exports.buildEvmMultisignBodyEulerV2ReulUnlock = buildEvmMultisignBodyEulerV2ReulUnlock;
|
|
1964
2427
|
exports.ensureAaveV4ChainTokenCache = ensureAaveV4ChainTokenCache;
|
|
1965
2428
|
exports.fetchAaveV4Chains = fetchAaveV4Chains;
|
|
2429
|
+
exports.fetchAaveV4ClaimRewardsCalldata = fetchAaveV4ClaimRewardsCalldata;
|
|
1966
2430
|
exports.fetchAaveV4HubReserves = fetchAaveV4HubReserves;
|
|
1967
2431
|
exports.fetchAaveV4HubsForChain = fetchAaveV4HubsForChain;
|
|
2432
|
+
exports.fetchAaveV4MerklClaimRewardIdsForChain = fetchAaveV4MerklClaimRewardIdsForChain;
|
|
2433
|
+
exports.fetchAaveV4MerklClaimableRewardsForChain = fetchAaveV4MerklClaimableRewardsForChain;
|
|
1968
2434
|
exports.fetchAaveV4NativeWrappedToken = fetchAaveV4NativeWrappedToken;
|
|
1969
2435
|
exports.fetchAaveV4ReservesForUnderlying = fetchAaveV4ReservesForUnderlying;
|
|
1970
2436
|
exports.fetchAaveV4SpokeReserveIdForUnderlying = fetchAaveV4SpokeReserveIdForUnderlying;
|
|
1971
2437
|
exports.fetchAaveV4SpokeReserveStatusForUnderlying = fetchAaveV4SpokeReserveStatusForUnderlying;
|
|
1972
2438
|
exports.fetchAaveV4SupportedUnderlyingAddressSet = fetchAaveV4SupportedUnderlyingAddressSet;
|
|
1973
2439
|
exports.fetchAaveV4UserBorrowsDebtByUnderlyingForHub = fetchAaveV4UserBorrowsDebtByUnderlyingForHub;
|
|
2440
|
+
exports.fetchAaveV4UserPositionById = fetchAaveV4UserPositionById;
|
|
2441
|
+
exports.fetchAaveV4UserPositionsByAssetOnChain = fetchAaveV4UserPositionsByAssetOnChain;
|
|
2442
|
+
exports.fetchAaveV4UserPositionsForChain = fetchAaveV4UserPositionsForChain;
|
|
2443
|
+
exports.fetchAaveV4UserSuppliesForPosition = fetchAaveV4UserSuppliesForPosition;
|
|
1974
2444
|
exports.findAaveV4HubReserveForChainUnderlying = findAaveV4HubReserveForChainUnderlying;
|
|
1975
2445
|
exports.findHubReserveForUnderlying = findHubReserveForUnderlying;
|
|
2446
|
+
exports.formatAavePercentDisplay = formatAavePercentDisplay;
|
|
1976
2447
|
exports.formatAaveV4AmountHumanFromApiString = formatAaveV4AmountHumanFromApiString;
|
|
2448
|
+
exports.formatAaveV4DecimalString = formatAaveV4DecimalString;
|
|
2449
|
+
exports.formatAaveV4ExchangeLabel = formatAaveV4ExchangeLabel;
|
|
2450
|
+
exports.formatAaveV4HealthFactor = formatAaveV4HealthFactor;
|
|
1977
2451
|
exports.formatAaveV4PercentDisplay = formatAaveV4PercentDisplay;
|
|
2452
|
+
exports.formatAaveV4PositionHealthFactor = formatAaveV4PositionHealthFactor;
|
|
2453
|
+
exports.formatAaveV4PositionPercent = formatAaveV4PositionPercent;
|
|
1978
2454
|
exports.formatAaveV4ReserveLiquidityFromSummary = formatAaveV4ReserveLiquidityFromSummary;
|
|
1979
2455
|
exports.formatAaveV4RiskDisplay = formatAaveV4RiskDisplay;
|
|
2456
|
+
exports.formatAaveV4RiskNotionalString = formatAaveV4RiskNotionalString;
|
|
1980
2457
|
exports.formatAaveV4TokenAmount = formatAaveV4TokenAmount;
|
|
1981
2458
|
exports.isAaveV4DepositEvmSignRequest = isAaveV4DepositEvmSignRequest;
|
|
2459
|
+
exports.isValidAaveChainId = isValidAaveChainId;
|
|
2460
|
+
exports.loadAaveV4SupportedChainIds = loadAaveV4SupportedChainIds;
|
|
1982
2461
|
exports.loadAaveV4SupportedChainIdsFromV4Api = loadAaveV4SupportedChainIdsFromV4Api;
|
|
2462
|
+
exports.parseBigDecimalHf = parseBigDecimalHf;
|
|
1983
2463
|
exports.pickAaveV4ReserveRowForSpoke = pickAaveV4ReserveRowForSpoke;
|
|
2464
|
+
exports.previewAaveV4BorrowResultingHf = previewAaveV4BorrowResultingHf;
|
|
2465
|
+
exports.previewAaveV4RepayResultingHf = previewAaveV4RepayResultingHf;
|
|
2466
|
+
exports.previewAaveV4WithdrawResultingHf = previewAaveV4WithdrawResultingHf;
|
|
1984
2467
|
exports.resolveAaveV4DepositGasUnitsFromSignRequest = resolveAaveV4DepositGasUnitsFromSignRequest;
|
|
1985
2468
|
exports.resolveAaveV4HubForUiMarket = resolveAaveV4HubForUiMarket;
|
|
1986
2469
|
//# sourceMappingURL=index.cjs.map
|