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