@coti-io/coti-wallet-plugin 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +311 -176
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +304 -169
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -876,8 +876,192 @@ var init_podSdkConfig = __esm({
|
|
|
876
876
|
}
|
|
877
877
|
});
|
|
878
878
|
|
|
879
|
-
// src/
|
|
879
|
+
// src/lib/rpcProvider.ts
|
|
880
880
|
import { ethers as ethers5 } from "ethers";
|
|
881
|
+
async function waitForTransactionResilient(chainId, txHash, options = {}) {
|
|
882
|
+
const {
|
|
883
|
+
confirmations = 1,
|
|
884
|
+
timeoutMs = 18e4,
|
|
885
|
+
pollIntervalMs = 2e3,
|
|
886
|
+
primary,
|
|
887
|
+
createProvider = createJsonRpcProvider
|
|
888
|
+
} = options;
|
|
889
|
+
if (!txHash) {
|
|
890
|
+
throw new Error("waitForTransactionResilient: missing transaction hash");
|
|
891
|
+
}
|
|
892
|
+
const deadline = Date.now() + timeoutMs;
|
|
893
|
+
let lastError;
|
|
894
|
+
if (primary) {
|
|
895
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
896
|
+
const primaryTimeout = Math.min(12e3, remaining);
|
|
897
|
+
if (primaryTimeout > 0) {
|
|
898
|
+
try {
|
|
899
|
+
const receipt = await primary.waitForTransaction(txHash, confirmations, primaryTimeout);
|
|
900
|
+
if (receipt) return receipt;
|
|
901
|
+
} catch (error) {
|
|
902
|
+
lastError = error;
|
|
903
|
+
if (isTransactionRevertError(error)) throw error;
|
|
904
|
+
if (!isTransientRpcError(error) && !isWaitTimeoutError(error)) throw error;
|
|
905
|
+
logger.warn(
|
|
906
|
+
`[rpc] primary waitForTransaction failed for ${txHash} on chain ${chainId}; polling via fallback RPCs`
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
let delay = pollIntervalMs;
|
|
912
|
+
while (Date.now() < deadline) {
|
|
913
|
+
try {
|
|
914
|
+
const receipt = await getTransactionReceiptAcrossRpcs(chainId, txHash, createProvider);
|
|
915
|
+
if (receipt) {
|
|
916
|
+
if (confirmations <= 1) return receipt;
|
|
917
|
+
const blockNumber = await withRpcFallback(chainId, (provider) => provider.getBlockNumber());
|
|
918
|
+
if (receipt.blockNumber + (confirmations - 1) <= blockNumber) {
|
|
919
|
+
return receipt;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
} catch (error) {
|
|
923
|
+
lastError = error;
|
|
924
|
+
if (!isTransientRpcError(error)) throw error;
|
|
925
|
+
logger.warn(
|
|
926
|
+
`[rpc] receipt poll failed for ${txHash} on chain ${chainId}; retrying after backoff`
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
const remaining = deadline - Date.now();
|
|
930
|
+
if (remaining <= 0) break;
|
|
931
|
+
await sleep(Math.min(delay, remaining));
|
|
932
|
+
delay = Math.min(Math.floor(delay * 1.5), 8e3);
|
|
933
|
+
}
|
|
934
|
+
throw lastError instanceof Error ? lastError : new Error(
|
|
935
|
+
`Timed out waiting for transaction ${txHash} on chain ${chainId} after ${timeoutMs}ms`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
async function getTransactionReceiptAcrossRpcs(chainId, txHash, createProvider = createJsonRpcProvider) {
|
|
939
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
940
|
+
let lastError;
|
|
941
|
+
let sawNotFound = false;
|
|
942
|
+
for (const url of urls) {
|
|
943
|
+
const provider = createProvider(url, chainId);
|
|
944
|
+
try {
|
|
945
|
+
const receipt = await provider.getTransactionReceipt(txHash);
|
|
946
|
+
if (receipt) return receipt;
|
|
947
|
+
sawNotFound = true;
|
|
948
|
+
} catch (error) {
|
|
949
|
+
lastError = error;
|
|
950
|
+
if (!isTransientRpcError(error)) throw error;
|
|
951
|
+
logger.warn(`[rpc] ${url} getTransactionReceipt failed for chain ${chainId}, trying fallback`);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
if (sawNotFound) return null;
|
|
955
|
+
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed reading receipt for ${txHash} on chain ${chainId}`);
|
|
956
|
+
}
|
|
957
|
+
var resolveRpcUrlsForChain, collectErrorText, readNestedRpcCode, readNestedHttpStatus, isTransientRpcError, createJsonRpcProvider, isWaitTimeoutError, isTransactionRevertError, sleep, createResilientJsonRpcProvider, withRpcFallback;
|
|
958
|
+
var init_rpcProvider = __esm({
|
|
959
|
+
"src/lib/rpcProvider.ts"() {
|
|
960
|
+
"use strict";
|
|
961
|
+
init_plugin();
|
|
962
|
+
init_coti();
|
|
963
|
+
init_rpcUrls();
|
|
964
|
+
init_sepolia();
|
|
965
|
+
init_logger();
|
|
966
|
+
resolveRpcUrlsForChain = (chainId) => {
|
|
967
|
+
const base = getRpcUrlsForChain(chainId);
|
|
968
|
+
const numericId = chainId == null ? void 0 : Number(chainId);
|
|
969
|
+
if (numericId == null || !Number.isFinite(numericId)) return base;
|
|
970
|
+
const plugin = getPluginConfig();
|
|
971
|
+
let override;
|
|
972
|
+
if (numericId === SEPOLIA_CHAIN_ID && plugin.sepoliaRpcUrl) {
|
|
973
|
+
override = plugin.sepoliaRpcUrl;
|
|
974
|
+
} else if (numericId === COTI_TESTNET_CHAIN_ID && plugin.cotiTestnetRpcUrl) {
|
|
975
|
+
override = plugin.cotiTestnetRpcUrl;
|
|
976
|
+
}
|
|
977
|
+
if (!override) return base;
|
|
978
|
+
return [.../* @__PURE__ */ new Set([override, ...base])];
|
|
979
|
+
};
|
|
980
|
+
collectErrorText = (error) => {
|
|
981
|
+
if (!error) return "";
|
|
982
|
+
if (typeof error === "string") return error;
|
|
983
|
+
if (error instanceof Error) return error.message;
|
|
984
|
+
try {
|
|
985
|
+
return JSON.stringify(error);
|
|
986
|
+
} catch {
|
|
987
|
+
return String(error);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
readNestedRpcCode = (error) => {
|
|
991
|
+
const e = error;
|
|
992
|
+
return e.code ?? e.error?.code ?? e.info?.error?.code;
|
|
993
|
+
};
|
|
994
|
+
readNestedHttpStatus = (error) => {
|
|
995
|
+
const e = error;
|
|
996
|
+
return e.data?.httpStatus ?? e.error?.data?.httpStatus ?? e.info?.responseStatus;
|
|
997
|
+
};
|
|
998
|
+
isTransientRpcError = (error) => {
|
|
999
|
+
const text = collectErrorText(error);
|
|
1000
|
+
const lower = text.toLowerCase();
|
|
1001
|
+
if (lower.includes("too many requests") || lower.includes("rate limit") || text.includes("-32005") || text.includes("ECONNRESET") || text.includes("ETIMEDOUT") || lower.includes("timeout") || text.includes("503") || text.includes("502") || text.includes("429")) {
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
1004
|
+
if (error && typeof error === "object") {
|
|
1005
|
+
const code = readNestedRpcCode(error);
|
|
1006
|
+
if (code === "SERVER_ERROR" || code === "TIMEOUT" || code === "NETWORK_ERROR" || code === -32005 || code === "-32005") {
|
|
1007
|
+
return true;
|
|
1008
|
+
}
|
|
1009
|
+
const httpStatus = readNestedHttpStatus(error);
|
|
1010
|
+
if (httpStatus === 429 || httpStatus === "429") {
|
|
1011
|
+
return true;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return false;
|
|
1015
|
+
};
|
|
1016
|
+
createJsonRpcProvider = (url, chainId) => new ethers5.JsonRpcProvider(url, chainId);
|
|
1017
|
+
isWaitTimeoutError = (error) => {
|
|
1018
|
+
const text = collectErrorText(error).toLowerCase();
|
|
1019
|
+
return text.includes("timeout") || text.includes("timed out") || text.includes("waitfortx");
|
|
1020
|
+
};
|
|
1021
|
+
isTransactionRevertError = (error) => {
|
|
1022
|
+
if (!error || typeof error !== "object") return false;
|
|
1023
|
+
const code = error.code;
|
|
1024
|
+
return code === "CALL_EXCEPTION" || code === "TRANSACTION_REPLACED";
|
|
1025
|
+
};
|
|
1026
|
+
sleep = (ms) => new Promise((resolve) => {
|
|
1027
|
+
setTimeout(resolve, ms);
|
|
1028
|
+
});
|
|
1029
|
+
createResilientJsonRpcProvider = async (chainId) => {
|
|
1030
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
1031
|
+
let lastError;
|
|
1032
|
+
for (const url of urls) {
|
|
1033
|
+
const provider = createJsonRpcProvider(url, chainId);
|
|
1034
|
+
try {
|
|
1035
|
+
await provider.getNetwork();
|
|
1036
|
+
return provider;
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
lastError = error;
|
|
1039
|
+
if (!isTransientRpcError(error)) throw error;
|
|
1040
|
+
logger.warn(`[rpc] ${url} unavailable for chain ${chainId}, trying fallback`);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
throw lastError instanceof Error ? lastError : new Error(`No RPC available for chain ${chainId}`);
|
|
1044
|
+
};
|
|
1045
|
+
withRpcFallback = async (chainId, fn) => {
|
|
1046
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
1047
|
+
let lastError;
|
|
1048
|
+
for (const url of urls) {
|
|
1049
|
+
const provider = createJsonRpcProvider(url, chainId);
|
|
1050
|
+
try {
|
|
1051
|
+
return await fn(provider);
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
lastError = error;
|
|
1054
|
+
if (!isTransientRpcError(error)) throw error;
|
|
1055
|
+
logger.warn(`[rpc] ${url} request failed for chain ${chainId}, trying fallback`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed for chain ${chainId}`);
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
// src/chains/portal/podPTokenBlockingDiagnostics.ts
|
|
1064
|
+
import { ethers as ethers6 } from "ethers";
|
|
881
1065
|
import { PodRequest as PodRequest2 } from "@coti-io/pod-sdk";
|
|
882
1066
|
async function diagnoseBlockingPodRequest(params) {
|
|
883
1067
|
const {
|
|
@@ -960,8 +1144,8 @@ var init_podPTokenBlockingDiagnostics = __esm({
|
|
|
960
1144
|
"callback-errored",
|
|
961
1145
|
"burn-debt"
|
|
962
1146
|
]);
|
|
963
|
-
pTokenIface = new
|
|
964
|
-
portalIface = new
|
|
1147
|
+
pTokenIface = new ethers6.Interface(POD_PTOKEN_ABI);
|
|
1148
|
+
portalIface = new ethers6.Interface(PRIVACY_PORTAL_ABI);
|
|
965
1149
|
formatBlockingPodLogSummary = (blockingRequest, action) => {
|
|
966
1150
|
if (!blockingRequest?.requestId) {
|
|
967
1151
|
return `PoD ${action} blocked: wallet has on-chain pending=true but no requestId was resolved (check eventScan / candidateRequests in the log object below).`;
|
|
@@ -1090,7 +1274,7 @@ var init_podPTokenBlockingDiagnostics = __esm({
|
|
|
1090
1274
|
}
|
|
1091
1275
|
return { logs: [], lookbackBlocks: Number(lookbackSteps[lookbackSteps.length - 1]), errors };
|
|
1092
1276
|
};
|
|
1093
|
-
paddedAddressTopic = (address) =>
|
|
1277
|
+
paddedAddressTopic = (address) => ethers6.zeroPadValue(ethers6.getAddress(address), 32);
|
|
1094
1278
|
fetchRecentPTokenEvents = async (provider, pTokenAddress, account) => {
|
|
1095
1279
|
const accountTopic = paddedAddressTopic(account);
|
|
1096
1280
|
const errors = [];
|
|
@@ -1228,7 +1412,7 @@ var fees_exports = {};
|
|
|
1228
1412
|
__export(fees_exports, {
|
|
1229
1413
|
quotePodPortalTransactionFees: () => quotePodPortalTransactionFees
|
|
1230
1414
|
});
|
|
1231
|
-
import { ethers as
|
|
1415
|
+
import { ethers as ethers7 } from "ethers";
|
|
1232
1416
|
var quotePodPortalTransactionFees;
|
|
1233
1417
|
var init_fees = __esm({
|
|
1234
1418
|
"src/chains/portal/fees.ts"() {
|
|
@@ -1238,7 +1422,7 @@ var init_fees = __esm({
|
|
|
1238
1422
|
init_podPortalFees();
|
|
1239
1423
|
quotePodPortalTransactionFees = async (params) => {
|
|
1240
1424
|
const dec = params.pubTok?.decimals ?? 18;
|
|
1241
|
-
const amountWei =
|
|
1425
|
+
const amountWei = ethers7.parseUnits(params.amount, dec);
|
|
1242
1426
|
const provider = "provider" in params.runner && params.runner.provider ? params.runner.provider : params.runner;
|
|
1243
1427
|
const gasPrice = params.gasPrice ?? await resolvePodTxGasPrice(provider);
|
|
1244
1428
|
const nativeSymbol = getChainConfig(params.chainId)?.walletNetwork.nativeCurrency.symbol ?? "ETH";
|
|
@@ -1311,7 +1495,7 @@ var init_fees = __esm({
|
|
|
1311
1495
|
});
|
|
1312
1496
|
|
|
1313
1497
|
// src/chains/portal/podPortalFees.ts
|
|
1314
|
-
import { ethers as
|
|
1498
|
+
import { ethers as ethers8 } from "ethers";
|
|
1315
1499
|
import {
|
|
1316
1500
|
DataType,
|
|
1317
1501
|
PodContract,
|
|
@@ -1352,7 +1536,7 @@ var init_podPortalFees = __esm({
|
|
|
1352
1536
|
quotePortalFeeOnly = async (runner, portalAddress, amount, direction, gasPrice) => {
|
|
1353
1537
|
const provider = resolveFeeRunnerProvider(runner);
|
|
1354
1538
|
const resolvedGasPrice = gasPrice ?? await resolvePodTxGasPrice(provider);
|
|
1355
|
-
const portal = new
|
|
1539
|
+
const portal = new ethers8.Contract(portalAddress, PRIVACY_PORTAL_ABI, runner);
|
|
1356
1540
|
if (direction === "to-private") {
|
|
1357
1541
|
const [portalFee2, usedDynamicPricing2] = await portal.estimateDepositFees(amount);
|
|
1358
1542
|
const quote2 = {
|
|
@@ -1384,8 +1568,8 @@ var init_podPortalFees = __esm({
|
|
|
1384
1568
|
});
|
|
1385
1569
|
return quote;
|
|
1386
1570
|
};
|
|
1387
|
-
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) =>
|
|
1388
|
-
formatPodFeeDisplay = (totalFee) =>
|
|
1571
|
+
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) => ethers8.formatEther(portalFee).replace(/\.?0+$/, "") || "0";
|
|
1572
|
+
formatPodFeeDisplay = (totalFee) => ethers8.formatEther(totalFee).replace(/\.?0+$/, "") || "0";
|
|
1389
1573
|
resolvePodFeeEstimationConfig = (chainId, direction, gasPrice) => {
|
|
1390
1574
|
const limits = getChainConfig(chainId)?.podFeeEstimation?.[direction === "to-private" ? "deposit" : "withdraw"];
|
|
1391
1575
|
if (!limits) {
|
|
@@ -1436,8 +1620,8 @@ var init_podPortalFees = __esm({
|
|
|
1436
1620
|
{ type: DataType.Uint256, value: "0", isCallBackFee: true },
|
|
1437
1621
|
{ type: DataType.Uint256, value: placeholderDeadline.toString(), isCallBackFee: false },
|
|
1438
1622
|
{ type: DataType.Uint8, value: "0", isCallBackFee: false },
|
|
1439
|
-
{ type: DataType.String, value:
|
|
1440
|
-
{ type: DataType.String, value:
|
|
1623
|
+
{ type: DataType.String, value: ethers8.ZeroHash, isCallBackFee: false },
|
|
1624
|
+
{ type: DataType.String, value: ethers8.ZeroHash, isCallBackFee: false }
|
|
1441
1625
|
];
|
|
1442
1626
|
}
|
|
1443
1627
|
return [
|
|
@@ -1465,8 +1649,8 @@ var init_podPortalFees = __esm({
|
|
|
1465
1649
|
const fallbackLimit = fallbackExecutionGasLimit(params.chainId, params.direction);
|
|
1466
1650
|
try {
|
|
1467
1651
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
1468
|
-
const rpcProvider = new
|
|
1469
|
-
const portal = new
|
|
1652
|
+
const rpcProvider = new ethers8.JsonRpcProvider(rpcUrl);
|
|
1653
|
+
const portal = new ethers8.Contract(params.portalAddress, PRIVACY_PORTAL_ABI, rpcProvider);
|
|
1470
1654
|
if (params.direction === "to-private") {
|
|
1471
1655
|
const method = resolvePodPortalMethod("to-private", params.isNativeDeposit);
|
|
1472
1656
|
const nativeAmount = params.isNativeDeposit ? params.amountWei : 0n;
|
|
@@ -1483,8 +1667,8 @@ var init_podPortalFees = __esm({
|
|
|
1483
1667
|
const permit = params.withdrawPermit;
|
|
1484
1668
|
const deadline = permit ? BigInt(permit.deadline) : BigInt(Math.floor(Date.now() / 1e3) + 60 * 30);
|
|
1485
1669
|
const v = permit?.v ?? 0;
|
|
1486
|
-
const r = permit?.r ??
|
|
1487
|
-
const s = permit?.s ??
|
|
1670
|
+
const r = permit?.r ?? ethers8.ZeroHash;
|
|
1671
|
+
const s = permit?.s ?? ethers8.ZeroHash;
|
|
1488
1672
|
const gasLimit = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1489
1673
|
params.wallet,
|
|
1490
1674
|
params.amountWei,
|
|
@@ -1584,11 +1768,11 @@ var init_podPortalFees = __esm({
|
|
|
1584
1768
|
});
|
|
1585
1769
|
|
|
1586
1770
|
// src/chains/portal/executePodPortalTransaction.ts
|
|
1587
|
-
import { ethers as
|
|
1771
|
+
import { ethers as ethers9 } from "ethers";
|
|
1588
1772
|
async function signPodWithdrawPermit(params) {
|
|
1589
1773
|
const { signer, pTokenAddress, portalAddress, amountWei } = params;
|
|
1590
1774
|
const wallet = await signer.getAddress();
|
|
1591
|
-
const pToken = new
|
|
1775
|
+
const pToken = new ethers9.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1592
1776
|
const signingChainId = params.chainId ?? Number((await signer.provider.getNetwork()).chainId);
|
|
1593
1777
|
const resolvedTokenSymbol = params.tokenSymbol ?? await pToken.symbol().catch(() => void 0);
|
|
1594
1778
|
await assertPodPTokenReady(pToken, wallet, "withdraw", {
|
|
@@ -1658,9 +1842,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1658
1842
|
throw new Error("PoD portal is not configured for this token");
|
|
1659
1843
|
}
|
|
1660
1844
|
const wallet = await signer.getAddress();
|
|
1661
|
-
const amountWei =
|
|
1662
|
-
const pToken = new
|
|
1663
|
-
const portalIface2 = new
|
|
1845
|
+
const amountWei = ethers9.parseUnits(txAmount, decimals);
|
|
1846
|
+
const pToken = new ethers9.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1847
|
+
const portalIface2 = new ethers9.Interface(PRIVACY_PORTAL_ABI);
|
|
1664
1848
|
const gasPrice = await resolvePodTxGasPrice(provider);
|
|
1665
1849
|
if (txDirection === "to-private") {
|
|
1666
1850
|
await assertPodPTokenReady(pToken, wallet, "deposit", {
|
|
@@ -1689,7 +1873,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1689
1873
|
});
|
|
1690
1874
|
let gasLimit2;
|
|
1691
1875
|
try {
|
|
1692
|
-
const portal = new
|
|
1876
|
+
const portal = new ethers9.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1693
1877
|
const nativeAmount = isNativeDeposit ? amountWei : 0n;
|
|
1694
1878
|
const estimated = await portal[method2].estimateGas(
|
|
1695
1879
|
wallet,
|
|
@@ -1721,7 +1905,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1721
1905
|
fee: podFee2
|
|
1722
1906
|
});
|
|
1723
1907
|
onProgress?.("transfer-start", tx2.hash);
|
|
1724
|
-
const receipt2 = await tx2.
|
|
1908
|
+
const receipt2 = await waitForTransactionResilient(chainId, tx2.hash, {
|
|
1909
|
+
primary: provider ?? signer.provider ?? void 0
|
|
1910
|
+
});
|
|
1725
1911
|
if (!receipt2 || receipt2.status !== 1) {
|
|
1726
1912
|
const failed = new Error("PoD deposit transaction failed");
|
|
1727
1913
|
failed.txHash = tx2.hash;
|
|
@@ -1778,7 +1964,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1778
1964
|
});
|
|
1779
1965
|
let gasLimit;
|
|
1780
1966
|
try {
|
|
1781
|
-
const portal = new
|
|
1967
|
+
const portal = new ethers9.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1782
1968
|
const estimated = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1783
1969
|
wallet,
|
|
1784
1970
|
amountWei,
|
|
@@ -1812,7 +1998,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1812
1998
|
fee: podFee
|
|
1813
1999
|
});
|
|
1814
2000
|
onProgress?.("transfer-start", tx.hash);
|
|
1815
|
-
const receipt = await tx.
|
|
2001
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
2002
|
+
primary: provider ?? signer.provider ?? void 0
|
|
2003
|
+
});
|
|
1816
2004
|
if (!receipt || receipt.status !== 1) {
|
|
1817
2005
|
const failed = new Error("Sepolia withdraw transaction failed");
|
|
1818
2006
|
failed.txHash = tx.hash;
|
|
@@ -1846,13 +2034,14 @@ var init_executePodPortalTransaction = __esm({
|
|
|
1846
2034
|
"use strict";
|
|
1847
2035
|
init_pod();
|
|
1848
2036
|
init_logger();
|
|
2037
|
+
init_rpcProvider();
|
|
1849
2038
|
init_podPTokenBlockingDiagnostics();
|
|
1850
2039
|
init_podPortalFees();
|
|
1851
2040
|
init_podSdkConfig();
|
|
1852
2041
|
init_podPortalFees();
|
|
1853
2042
|
init_fees();
|
|
1854
2043
|
getErrorMessage = (error) => error && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : "";
|
|
1855
|
-
pTokenErrorIface = new
|
|
2044
|
+
pTokenErrorIface = new ethers9.Interface(POD_PTOKEN_ABI);
|
|
1856
2045
|
extractRevertData = (error) => {
|
|
1857
2046
|
if (!error || typeof error !== "object") return null;
|
|
1858
2047
|
const err = error;
|
|
@@ -1908,7 +2097,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
1908
2097
|
return null;
|
|
1909
2098
|
};
|
|
1910
2099
|
splitSignature = (signature) => {
|
|
1911
|
-
const parsed =
|
|
2100
|
+
const parsed = ethers9.Signature.from(signature);
|
|
1912
2101
|
return { v: parsed.v, r: parsed.r, s: parsed.s };
|
|
1913
2102
|
};
|
|
1914
2103
|
POD_PTOKEN_FLAT_STATUS_ABI = [
|
|
@@ -2055,7 +2244,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2055
2244
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2056
2245
|
probeErrors.push(`balanceWithState: ${getErrorMessage(error) || String(error)}`);
|
|
2057
2246
|
}
|
|
2058
|
-
const flatStatusToken = new
|
|
2247
|
+
const flatStatusToken = new ethers9.Contract(
|
|
2059
2248
|
pTokenAddress,
|
|
2060
2249
|
POD_PTOKEN_FLAT_STATUS_ABI,
|
|
2061
2250
|
pToken.runner
|
|
@@ -2090,7 +2279,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2090
2279
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2091
2280
|
probeErrors.push(`balanceOfWithStatus: ${getErrorMessage(error) || String(error)}`);
|
|
2092
2281
|
}
|
|
2093
|
-
const plainToken = new
|
|
2282
|
+
const plainToken = new ethers9.Contract(
|
|
2094
2283
|
pTokenAddress,
|
|
2095
2284
|
POD_PTOKEN_PLAIN_STATUS_ABI,
|
|
2096
2285
|
pToken.runner
|
|
@@ -2297,7 +2486,7 @@ var init_ethereum = __esm({
|
|
|
2297
2486
|
});
|
|
2298
2487
|
|
|
2299
2488
|
// src/chains/portal/podTransferFees.ts
|
|
2300
|
-
import { ethers as
|
|
2489
|
+
import { ethers as ethers10 } from "ethers";
|
|
2301
2490
|
import {
|
|
2302
2491
|
DataType as DataType2,
|
|
2303
2492
|
PodContract as PodContract2,
|
|
@@ -2427,8 +2616,8 @@ var init_podTransferFees = __esm({
|
|
|
2427
2616
|
if (!overrides.gasLimit) {
|
|
2428
2617
|
try {
|
|
2429
2618
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
2430
|
-
const rpcProvider = new
|
|
2431
|
-
const pToken = new
|
|
2619
|
+
const rpcProvider = new ethers10.JsonRpcProvider(rpcUrl);
|
|
2620
|
+
const pToken = new ethers10.Contract(params.pTokenAddress, POD_PTOKEN_ABI, rpcProvider);
|
|
2432
2621
|
const estimated = await pToken.getFunction(POD_TRANSFER_METHOD).estimateGas(...vals, {
|
|
2433
2622
|
from: userAddress,
|
|
2434
2623
|
value: fee.totalFee,
|
|
@@ -2506,7 +2695,7 @@ var init_utils = __esm({
|
|
|
2506
2695
|
});
|
|
2507
2696
|
|
|
2508
2697
|
// src/hooks/privacyBridge/executePrivateTokenTransfer.ts
|
|
2509
|
-
import { ethers as
|
|
2698
|
+
import { ethers as ethers11 } from "ethers";
|
|
2510
2699
|
function normalizeAesKeyHex(aesKey) {
|
|
2511
2700
|
try {
|
|
2512
2701
|
return normalizeAesKey(aesKey);
|
|
@@ -2532,10 +2721,10 @@ function resolvePrivateTokenTransferTarget(chainId, symbol) {
|
|
|
2532
2721
|
};
|
|
2533
2722
|
}
|
|
2534
2723
|
function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2535
|
-
if (!
|
|
2724
|
+
if (!ethers11.isAddress(tokenAddress)) {
|
|
2536
2725
|
throw new Error("Invalid token contract address");
|
|
2537
2726
|
}
|
|
2538
|
-
if (!
|
|
2727
|
+
if (!ethers11.isAddress(recipient)) {
|
|
2539
2728
|
throw new Error("Invalid recipient address");
|
|
2540
2729
|
}
|
|
2541
2730
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2548,7 +2737,7 @@ function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAd
|
|
|
2548
2737
|
function parseTransferAmountWei(amount, decimals) {
|
|
2549
2738
|
let amountWei;
|
|
2550
2739
|
try {
|
|
2551
|
-
amountWei =
|
|
2740
|
+
amountWei = ethers11.parseUnits(amount, decimals);
|
|
2552
2741
|
} catch {
|
|
2553
2742
|
throw new Error("Invalid amount for token decimals");
|
|
2554
2743
|
}
|
|
@@ -2584,7 +2773,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2584
2773
|
recipient: shortHash(recipient),
|
|
2585
2774
|
amount
|
|
2586
2775
|
});
|
|
2587
|
-
const browserProvider = new
|
|
2776
|
+
const browserProvider = new ethers11.BrowserProvider(eip1193);
|
|
2777
|
+
const network = await browserProvider.getNetwork();
|
|
2778
|
+
const chainId = Number(network.chainId);
|
|
2588
2779
|
const rawTxHash = await eip1193.request({
|
|
2589
2780
|
method: "eth_sendTransaction",
|
|
2590
2781
|
params: [
|
|
@@ -2597,7 +2788,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2597
2788
|
]
|
|
2598
2789
|
});
|
|
2599
2790
|
logger.log("Waiting for private transfer tx", { txHash: shortHash(rawTxHash) });
|
|
2600
|
-
const receipt = await
|
|
2791
|
+
const receipt = await waitForTransactionResilient(chainId, rawTxHash, {
|
|
2792
|
+
primary: browserProvider
|
|
2793
|
+
});
|
|
2601
2794
|
if (!receipt || receipt.status !== 1) {
|
|
2602
2795
|
throw new Error("Private token transfer failed");
|
|
2603
2796
|
}
|
|
@@ -2635,10 +2828,10 @@ async function sendPrivateTokenTransfer(params) {
|
|
|
2635
2828
|
if (!eip1193) {
|
|
2636
2829
|
throw new Error("No wallet found");
|
|
2637
2830
|
}
|
|
2638
|
-
const browserProvider = new
|
|
2831
|
+
const browserProvider = new ethers11.BrowserProvider(eip1193);
|
|
2639
2832
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2640
2833
|
const amountWei = parseTransferAmountWei(amount, target.decimals);
|
|
2641
|
-
const transferSig =
|
|
2834
|
+
const transferSig = ethers11.id(PRIVATE_ERC20_TRANSFER_256_SIG).slice(0, 10);
|
|
2642
2835
|
let aesKey = sessionAesKey ? normalizeAesKeyHex(sessionAesKey) : null;
|
|
2643
2836
|
if (!aesKey && hasSnap && getAESKeyFromSnap) {
|
|
2644
2837
|
const snapKey = await getAESKeyFromSnap(walletAddress);
|
|
@@ -2673,6 +2866,7 @@ var init_executePrivateTokenTransfer = __esm({
|
|
|
2673
2866
|
init_aesKey();
|
|
2674
2867
|
init_ethereum();
|
|
2675
2868
|
init_logger();
|
|
2869
|
+
init_rpcProvider();
|
|
2676
2870
|
init_config();
|
|
2677
2871
|
init_chains();
|
|
2678
2872
|
init_chains();
|
|
@@ -2681,7 +2875,7 @@ var init_executePrivateTokenTransfer = __esm({
|
|
|
2681
2875
|
PRIVATE_ERC20_TRANSFER_256_SIG = "transfer(address,((uint256,uint256),bytes))";
|
|
2682
2876
|
GAS_ESTIMATE_BUFFER_PERCENT = 105n;
|
|
2683
2877
|
CONFIDENTIAL_TRANSFER_GAS_LIMIT = 2000000n;
|
|
2684
|
-
TRANSFER_INTERFACE = new
|
|
2878
|
+
TRANSFER_INTERFACE = new ethers11.Interface([
|
|
2685
2879
|
"function transfer(address to, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (uint256)"
|
|
2686
2880
|
]);
|
|
2687
2881
|
}
|
|
@@ -2695,12 +2889,12 @@ __export(executePodPrivateTokenTransfer_exports, {
|
|
|
2695
2889
|
quotePodPrivateTokenTransferFees: () => quotePodPrivateTokenTransferFees,
|
|
2696
2890
|
quotePodTransferFees: () => quotePodTransferFees
|
|
2697
2891
|
});
|
|
2698
|
-
import { ethers as
|
|
2892
|
+
import { ethers as ethers12 } from "ethers";
|
|
2699
2893
|
function validatePodTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2700
|
-
if (!
|
|
2894
|
+
if (!ethers12.isAddress(tokenAddress)) {
|
|
2701
2895
|
throw new Error("Invalid token contract address");
|
|
2702
2896
|
}
|
|
2703
|
-
if (!
|
|
2897
|
+
if (!ethers12.isAddress(recipient)) {
|
|
2704
2898
|
throw new Error("Invalid recipient address");
|
|
2705
2899
|
}
|
|
2706
2900
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2725,13 +2919,13 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2725
2919
|
if (!eip1193) {
|
|
2726
2920
|
throw new Error("No wallet found");
|
|
2727
2921
|
}
|
|
2728
|
-
const browserProvider = new
|
|
2922
|
+
const browserProvider = new ethers12.BrowserProvider(eip1193);
|
|
2729
2923
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2730
|
-
const amountWei =
|
|
2924
|
+
const amountWei = ethers12.parseUnits(amount, target.decimals);
|
|
2731
2925
|
if (amountWei <= 0n) {
|
|
2732
2926
|
throw new Error("Amount must be greater than zero");
|
|
2733
2927
|
}
|
|
2734
|
-
const pToken = new
|
|
2928
|
+
const pToken = new ethers12.Contract(target.tokenAddress, POD_PTOKEN_ABI, signer);
|
|
2735
2929
|
await assertPodPTokenReady(pToken, walletAddress, "transfer", {
|
|
2736
2930
|
chainId,
|
|
2737
2931
|
tokenSymbol: symbol,
|
|
@@ -2763,13 +2957,15 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2763
2957
|
gasPrice,
|
|
2764
2958
|
fee: podFee
|
|
2765
2959
|
});
|
|
2766
|
-
const receipt = await tx.
|
|
2960
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
2961
|
+
primary: browserProvider
|
|
2962
|
+
});
|
|
2767
2963
|
if (!receipt || receipt.status !== 1) {
|
|
2768
2964
|
const failed = new Error("PoD private token transfer failed");
|
|
2769
2965
|
failed.txHash = tx.hash;
|
|
2770
2966
|
throw failed;
|
|
2771
2967
|
}
|
|
2772
|
-
const event = findParsedEvent2(receipt, new
|
|
2968
|
+
const event = findParsedEvent2(receipt, new ethers12.Interface(POD_PTOKEN_ABI), "TransferRequestSubmitted");
|
|
2773
2969
|
const requestId = event?.args?.requestId;
|
|
2774
2970
|
return {
|
|
2775
2971
|
txHash: tx.hash,
|
|
@@ -2799,10 +2995,10 @@ async function quotePodPrivateTokenTransferFees(params) {
|
|
|
2799
2995
|
if (!eip1193) {
|
|
2800
2996
|
throw new Error("No wallet found");
|
|
2801
2997
|
}
|
|
2802
|
-
const browserProvider = new
|
|
2998
|
+
const browserProvider = new ethers12.BrowserProvider(eip1193);
|
|
2803
2999
|
const signer = await browserProvider.getSigner(params.walletAddress);
|
|
2804
|
-
const amountWei =
|
|
2805
|
-
const recipient =
|
|
3000
|
+
const amountWei = ethers12.parseUnits(params.amount, target.decimals);
|
|
3001
|
+
const recipient = ethers12.isAddress(params.recipient) && params.recipient !== ethers12.ZeroAddress ? params.recipient : params.walletAddress;
|
|
2806
3002
|
return quotePodTransferFees({
|
|
2807
3003
|
runner: signer,
|
|
2808
3004
|
chainId: params.chainId,
|
|
@@ -2819,6 +3015,7 @@ var init_executePodPrivateTokenTransfer = __esm({
|
|
|
2819
3015
|
init_chains();
|
|
2820
3016
|
init_ethereum();
|
|
2821
3017
|
init_logger();
|
|
3018
|
+
init_rpcProvider();
|
|
2822
3019
|
init_executePodPortalTransaction();
|
|
2823
3020
|
init_podPortalFees();
|
|
2824
3021
|
init_podTransferFees();
|
|
@@ -3396,7 +3593,7 @@ init_executePodPrivateTokenTransfer();
|
|
|
3396
3593
|
init_logger();
|
|
3397
3594
|
import { useState, useCallback, useEffect, useRef } from "react";
|
|
3398
3595
|
import { useAccount } from "wagmi";
|
|
3399
|
-
import { ethers as
|
|
3596
|
+
import { ethers as ethers13 } from "ethers";
|
|
3400
3597
|
var usePodTransferFees = ({
|
|
3401
3598
|
isConnected,
|
|
3402
3599
|
walletAddress,
|
|
@@ -3453,7 +3650,7 @@ var usePodTransferFees = ({
|
|
|
3453
3650
|
const quote = await quotePodPrivateTokenTransferFees({
|
|
3454
3651
|
chainId,
|
|
3455
3652
|
symbol,
|
|
3456
|
-
recipient: recipient &&
|
|
3653
|
+
recipient: recipient && ethers13.isAddress(recipient) ? recipient : walletAddress,
|
|
3457
3654
|
amount: currentAmount,
|
|
3458
3655
|
walletAddress,
|
|
3459
3656
|
provider: injected6
|
|
@@ -3502,7 +3699,7 @@ var usePodTransferFees = ({
|
|
|
3502
3699
|
init_chains();
|
|
3503
3700
|
init_rpcUrls();
|
|
3504
3701
|
init_logger();
|
|
3505
|
-
import { ethers as
|
|
3702
|
+
import { ethers as ethers14 } from "ethers";
|
|
3506
3703
|
var POD_PRICE_ORACLE_ABI = [
|
|
3507
3704
|
"function getLivePrice(address token) view returns (uint256 priceUsd)",
|
|
3508
3705
|
"function getLivePrices(address tokenA, address tokenB) view returns (uint256 priceA, uint256 priceB)"
|
|
@@ -3527,17 +3724,17 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3527
3724
|
return null;
|
|
3528
3725
|
}
|
|
3529
3726
|
const rpcUrls = provider ? [] : getRpcUrlsForChain(chainId);
|
|
3530
|
-
const providers = provider ? [provider] : rpcUrls.map((url) => new
|
|
3727
|
+
const providers = provider ? [provider] : rpcUrls.map((url) => new ethers14.JsonRpcProvider(url));
|
|
3531
3728
|
let lastError;
|
|
3532
3729
|
for (const rpcProvider of providers) {
|
|
3533
3730
|
try {
|
|
3534
|
-
const oracle = new
|
|
3731
|
+
const oracle = new ethers14.Contract(oracleAddress, POD_PRICE_ORACLE_ABI, rpcProvider);
|
|
3535
3732
|
const raw = await oracle.getLivePrice(tokenAddress);
|
|
3536
3733
|
if (raw === 0n) {
|
|
3537
3734
|
logger.warn(`PoD price oracle has no live feed for ${symbol} on chain ${chainId}`);
|
|
3538
3735
|
return null;
|
|
3539
3736
|
}
|
|
3540
|
-
return Number(
|
|
3737
|
+
return Number(ethers14.formatEther(raw));
|
|
3541
3738
|
} catch (err) {
|
|
3542
3739
|
lastError = err;
|
|
3543
3740
|
}
|
|
@@ -3551,12 +3748,12 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3551
3748
|
init_pod();
|
|
3552
3749
|
init_chains();
|
|
3553
3750
|
init_rpcUrls();
|
|
3554
|
-
import { ethers as
|
|
3751
|
+
import { ethers as ethers15 } from "ethers";
|
|
3555
3752
|
init_logger();
|
|
3556
3753
|
var ERC20_BALANCE_ABI = ["function balanceOf(address) view returns (uint256)"];
|
|
3557
3754
|
var FEE_DIVISOR = 1000000n;
|
|
3558
3755
|
var POD_NO_MAX_FEE_SENTINEL = (1n << 128n) - 1n;
|
|
3559
|
-
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" :
|
|
3756
|
+
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" : ethers15.formatEther(value);
|
|
3560
3757
|
async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
3561
3758
|
const portalAddress = config.addresses[token.bridgeAddressKey];
|
|
3562
3759
|
const privateToken = config.tokens.find(
|
|
@@ -3583,12 +3780,12 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3583
3780
|
isLoading: false
|
|
3584
3781
|
};
|
|
3585
3782
|
try {
|
|
3586
|
-
const portal = new
|
|
3783
|
+
const portal = new ethers15.Contract(portalAddress, POD_PORTAL_ADMIN_ABI, provider);
|
|
3587
3784
|
const [depCfg, wdCfg, accFees, balance] = await Promise.all([
|
|
3588
3785
|
portal.getFeeConfig(true),
|
|
3589
3786
|
portal.getFeeConfig(false),
|
|
3590
3787
|
portal.accumulatedPortalFees().catch(() => 0n),
|
|
3591
|
-
token.isNative ? provider.getBalance(portalAddress) : token.addressKey && config.addresses[token.addressKey] ? new
|
|
3788
|
+
token.isNative ? provider.getBalance(portalAddress) : token.addressKey && config.addresses[token.addressKey] ? new ethers15.Contract(config.addresses[token.addressKey], ERC20_BALANCE_ABI, provider).balanceOf(portalAddress).catch(() => 0n) : Promise.resolve(0n)
|
|
3592
3789
|
]);
|
|
3593
3790
|
return {
|
|
3594
3791
|
...base,
|
|
@@ -3598,8 +3795,8 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3598
3795
|
withdrawFixedFee: formatFee(wdCfg[0]),
|
|
3599
3796
|
withdrawPercentageBps: wdCfg[1].toString(),
|
|
3600
3797
|
withdrawMaxFee: formatFee(wdCfg[2]),
|
|
3601
|
-
accumulatedCotiFees:
|
|
3602
|
-
bridgeBalance:
|
|
3798
|
+
accumulatedCotiFees: ethers15.formatEther(accFees),
|
|
3799
|
+
bridgeBalance: ethers15.formatUnits(balance, token.decimals),
|
|
3603
3800
|
error: null
|
|
3604
3801
|
};
|
|
3605
3802
|
} catch (err) {
|
|
@@ -3627,7 +3824,7 @@ async function fetchPodBridgeData(chainId) {
|
|
|
3627
3824
|
);
|
|
3628
3825
|
let lastError;
|
|
3629
3826
|
for (const rpcUrl of getRpcUrlsForChain(chainId)) {
|
|
3630
|
-
const provider = new
|
|
3827
|
+
const provider = new ethers15.JsonRpcProvider(rpcUrl);
|
|
3631
3828
|
try {
|
|
3632
3829
|
await provider.getBlockNumber();
|
|
3633
3830
|
return await Promise.all(
|
|
@@ -3646,7 +3843,7 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3646
3843
|
if (!config) return { fee: "\u2014", explanation: "Unsupported chain" };
|
|
3647
3844
|
const token = config.tokens.find((t) => t.symbol === tokenSymbol && !t.isPrivate);
|
|
3648
3845
|
if (!token) return { fee: "\u2014", explanation: "Unknown token" };
|
|
3649
|
-
const amountWei =
|
|
3846
|
+
const amountWei = ethers15.parseUnits(amount, token.decimals);
|
|
3650
3847
|
let valueInNative;
|
|
3651
3848
|
if (token.isNative) {
|
|
3652
3849
|
valueInNative = amountWei;
|
|
@@ -3657,27 +3854,27 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3657
3854
|
fetchPodOracleTokenUsdPrice(nativeSymbol, chainId)
|
|
3658
3855
|
]);
|
|
3659
3856
|
if (!tokenUsd || !nativeUsd) {
|
|
3660
|
-
const fixed =
|
|
3661
|
-
const cap =
|
|
3857
|
+
const fixed = ethers15.parseEther(fixedFee || "0");
|
|
3858
|
+
const cap = ethers15.parseEther(maxFee || "0");
|
|
3662
3859
|
const fee2 = cap > 0n && fixed > cap ? cap : fixed;
|
|
3663
3860
|
return {
|
|
3664
|
-
fee: parseFloat(
|
|
3861
|
+
fee: parseFloat(ethers15.formatEther(fee2)).toFixed(6),
|
|
3665
3862
|
explanation: "Fixed fee applied (no live oracle price)"
|
|
3666
3863
|
};
|
|
3667
3864
|
}
|
|
3668
|
-
const tokenUsdWei =
|
|
3669
|
-
const nativeUsdWei =
|
|
3865
|
+
const tokenUsdWei = ethers15.parseEther(tokenUsd.toString());
|
|
3866
|
+
const nativeUsdWei = ethers15.parseEther(nativeUsd.toString());
|
|
3670
3867
|
const amount18 = amountWei * 10n ** BigInt(18 - token.decimals);
|
|
3671
3868
|
valueInNative = amount18 * tokenUsdWei / nativeUsdWei;
|
|
3672
3869
|
}
|
|
3673
|
-
const fixedFeeWei =
|
|
3674
|
-
const maxFeeWei =
|
|
3870
|
+
const fixedFeeWei = ethers15.parseEther(fixedFee || "0");
|
|
3871
|
+
const maxFeeWei = ethers15.parseEther(maxFee || "0");
|
|
3675
3872
|
const bps = BigInt(parseInt(percentageBps || "0", 10));
|
|
3676
3873
|
const percentageFee = valueInNative * bps / FEE_DIVISOR;
|
|
3677
3874
|
let fee = percentageFee > fixedFeeWei ? percentageFee : fixedFeeWei;
|
|
3678
3875
|
if (maxFeeWei > 0n && fee > maxFeeWei) fee = maxFeeWei;
|
|
3679
3876
|
const explanation = maxFeeWei > 0n && fee === maxFeeWei && fee !== fixedFeeWei ? "Max fee cap applied" : fee === fixedFeeWei ? "Fixed fee floor applied" : "Percentage fee applied";
|
|
3680
|
-
return { fee: parseFloat(
|
|
3877
|
+
return { fee: parseFloat(ethers15.formatEther(fee)).toFixed(6), explanation };
|
|
3681
3878
|
} catch (err) {
|
|
3682
3879
|
logger.error("simulatePodPortalFee error:", err);
|
|
3683
3880
|
return { fee: "\u2014", explanation: "Simulation failed" };
|
|
@@ -3700,7 +3897,7 @@ var LIMITS = {
|
|
|
3700
3897
|
init_plugin();
|
|
3701
3898
|
init_ethereum();
|
|
3702
3899
|
import { useState as useState2, useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
3703
|
-
import { ethers as
|
|
3900
|
+
import { ethers as ethers16 } from "ethers";
|
|
3704
3901
|
init_logger();
|
|
3705
3902
|
|
|
3706
3903
|
// src/lib/format.ts
|
|
@@ -3984,7 +4181,7 @@ var useMetamask = ({
|
|
|
3984
4181
|
});
|
|
3985
4182
|
const accounts = await eth.request({ method: "eth_requestAccounts" });
|
|
3986
4183
|
if (!accounts || accounts.length === 0) return false;
|
|
3987
|
-
const provider = new
|
|
4184
|
+
const provider = new ethers16.BrowserProvider(eth);
|
|
3988
4185
|
const network = await provider.getNetwork();
|
|
3989
4186
|
const envDefaultNetwork = getPluginConfig().defaultNetworkId;
|
|
3990
4187
|
if (accounts.length > 0) {
|
|
@@ -4001,7 +4198,7 @@ var useMetamask = ({
|
|
|
4001
4198
|
const eth = getMetaMaskProvider();
|
|
4002
4199
|
if (!eth) return;
|
|
4003
4200
|
try {
|
|
4004
|
-
const provider = new
|
|
4201
|
+
const provider = new ethers16.BrowserProvider(eth);
|
|
4005
4202
|
await checkNetwork(provider);
|
|
4006
4203
|
if (onNetworkChanged) {
|
|
4007
4204
|
await onNetworkChanged();
|
|
@@ -4238,84 +4435,8 @@ function decryptCtUint256(ciphertext, aesKey, options) {
|
|
|
4238
4435
|
}
|
|
4239
4436
|
}
|
|
4240
4437
|
|
|
4241
|
-
// src/lib/rpcProvider.ts
|
|
4242
|
-
init_plugin();
|
|
4243
|
-
init_coti();
|
|
4244
|
-
init_rpcUrls();
|
|
4245
|
-
init_sepolia();
|
|
4246
|
-
init_logger();
|
|
4247
|
-
import { ethers as ethers16 } from "ethers";
|
|
4248
|
-
var resolveRpcUrlsForChain = (chainId) => {
|
|
4249
|
-
const base = getRpcUrlsForChain(chainId);
|
|
4250
|
-
const numericId = chainId == null ? void 0 : Number(chainId);
|
|
4251
|
-
if (numericId == null || !Number.isFinite(numericId)) return base;
|
|
4252
|
-
const plugin = getPluginConfig();
|
|
4253
|
-
let override;
|
|
4254
|
-
if (numericId === SEPOLIA_CHAIN_ID && plugin.sepoliaRpcUrl) {
|
|
4255
|
-
override = plugin.sepoliaRpcUrl;
|
|
4256
|
-
} else if (numericId === COTI_TESTNET_CHAIN_ID && plugin.cotiTestnetRpcUrl) {
|
|
4257
|
-
override = plugin.cotiTestnetRpcUrl;
|
|
4258
|
-
}
|
|
4259
|
-
if (!override) return base;
|
|
4260
|
-
return [.../* @__PURE__ */ new Set([override, ...base])];
|
|
4261
|
-
};
|
|
4262
|
-
var collectErrorText = (error) => {
|
|
4263
|
-
if (!error) return "";
|
|
4264
|
-
if (typeof error === "string") return error;
|
|
4265
|
-
if (error instanceof Error) return error.message;
|
|
4266
|
-
try {
|
|
4267
|
-
return JSON.stringify(error);
|
|
4268
|
-
} catch {
|
|
4269
|
-
return String(error);
|
|
4270
|
-
}
|
|
4271
|
-
};
|
|
4272
|
-
var isTransientRpcError = (error) => {
|
|
4273
|
-
const text = collectErrorText(error);
|
|
4274
|
-
if (text.includes("Too Many Requests") || text.includes("rate limit") || text.includes("-32005") || text.includes("ECONNRESET") || text.includes("ETIMEDOUT") || text.includes("timeout") || text.includes("503") || text.includes("502")) {
|
|
4275
|
-
return true;
|
|
4276
|
-
}
|
|
4277
|
-
if (error && typeof error === "object") {
|
|
4278
|
-
const code = error.code;
|
|
4279
|
-
if (code === "SERVER_ERROR" || code === "TIMEOUT" || code === "NETWORK_ERROR") {
|
|
4280
|
-
return true;
|
|
4281
|
-
}
|
|
4282
|
-
}
|
|
4283
|
-
return false;
|
|
4284
|
-
};
|
|
4285
|
-
var createJsonRpcProvider = (url, chainId) => new ethers16.JsonRpcProvider(url, chainId);
|
|
4286
|
-
var createResilientJsonRpcProvider = async (chainId) => {
|
|
4287
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4288
|
-
let lastError;
|
|
4289
|
-
for (const url of urls) {
|
|
4290
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4291
|
-
try {
|
|
4292
|
-
await provider.getNetwork();
|
|
4293
|
-
return provider;
|
|
4294
|
-
} catch (error) {
|
|
4295
|
-
lastError = error;
|
|
4296
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4297
|
-
logger.warn(`[rpc] ${url} unavailable for chain ${chainId}, trying fallback`);
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
|
-
throw lastError instanceof Error ? lastError : new Error(`No RPC available for chain ${chainId}`);
|
|
4301
|
-
};
|
|
4302
|
-
var withRpcFallback = async (chainId, fn) => {
|
|
4303
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4304
|
-
let lastError;
|
|
4305
|
-
for (const url of urls) {
|
|
4306
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4307
|
-
try {
|
|
4308
|
-
return await fn(provider);
|
|
4309
|
-
} catch (error) {
|
|
4310
|
-
lastError = error;
|
|
4311
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4312
|
-
logger.warn(`[rpc] ${url} request failed for chain ${chainId}, trying fallback`);
|
|
4313
|
-
}
|
|
4314
|
-
}
|
|
4315
|
-
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed for chain ${chainId}`);
|
|
4316
|
-
};
|
|
4317
|
-
|
|
4318
4438
|
// src/hooks/usePrivateTokenBalance.ts
|
|
4439
|
+
init_rpcProvider();
|
|
4319
4440
|
init_plugin();
|
|
4320
4441
|
init_logger();
|
|
4321
4442
|
var PLAIN_BALANCE_ABI = [
|
|
@@ -4426,6 +4547,7 @@ var usePrivateTokenBalance = () => {
|
|
|
4426
4547
|
|
|
4427
4548
|
// src/hooks/useBalanceUpdater.ts
|
|
4428
4549
|
init_config();
|
|
4550
|
+
init_rpcProvider();
|
|
4429
4551
|
import { useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
4430
4552
|
import { ethers as ethers19 } from "ethers";
|
|
4431
4553
|
|
|
@@ -4521,6 +4643,7 @@ import { encodeKey, encodeUint, encrypt, decryptUint as decryptUint2, decodeUint
|
|
|
4521
4643
|
import { ethers as ethers18 } from "ethers";
|
|
4522
4644
|
init_logger();
|
|
4523
4645
|
init_config();
|
|
4646
|
+
init_rpcProvider();
|
|
4524
4647
|
var ROUND_TRIP_TEST_VALUE = 0x0123456789abcdefn;
|
|
4525
4648
|
var FLAT_BALANCE_ABI2 = [
|
|
4526
4649
|
"function balanceOf(address) view returns (tuple(uint256 ciphertextHigh, uint256 ciphertextLow))"
|
|
@@ -5239,6 +5362,7 @@ import { useState as useState4, useCallback as useCallback7, useEffect as useEff
|
|
|
5239
5362
|
import { useAccount as useAccount3 } from "wagmi";
|
|
5240
5363
|
import { ethers as ethers22 } from "ethers";
|
|
5241
5364
|
init_logger();
|
|
5365
|
+
init_rpcProvider();
|
|
5242
5366
|
init_encryptValue256();
|
|
5243
5367
|
init_utils();
|
|
5244
5368
|
init_ethereum();
|
|
@@ -6218,7 +6342,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6218
6342
|
}]
|
|
6219
6343
|
});
|
|
6220
6344
|
logger.log("\u{1F510} [Approve] Tx submitted, waiting for confirmation", { txHash: shortHash(rawTxHash) });
|
|
6221
|
-
await
|
|
6345
|
+
await waitForTransactionResilient(currentChainId, rawTxHash, {
|
|
6346
|
+
primary: provider
|
|
6347
|
+
});
|
|
6222
6348
|
logger.log("\u{1F510} [Approve] Tx confirmed, refreshing allowance...");
|
|
6223
6349
|
setIsApproving(false);
|
|
6224
6350
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6235,7 +6361,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6235
6361
|
title: "Approving...",
|
|
6236
6362
|
message: "Waiting for allowance confirmation..."
|
|
6237
6363
|
});
|
|
6238
|
-
await tx.
|
|
6364
|
+
await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6365
|
+
primary: provider
|
|
6366
|
+
});
|
|
6239
6367
|
await checkAllowance();
|
|
6240
6368
|
setIsApproving(false);
|
|
6241
6369
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6279,6 +6407,7 @@ import { useAccount as useAccount4 } from "wagmi";
|
|
|
6279
6407
|
import { ethers as ethers23 } from "ethers";
|
|
6280
6408
|
init_chains();
|
|
6281
6409
|
init_logger();
|
|
6410
|
+
init_rpcProvider();
|
|
6282
6411
|
init_utils();
|
|
6283
6412
|
var usePrivacyBridgeExecutor = ({
|
|
6284
6413
|
walletAddress,
|
|
@@ -6527,7 +6656,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6527
6656
|
logger.log("ERC20 deposit tx sent", { txHash: shortHash(rawDepositTxHash) });
|
|
6528
6657
|
tx = {
|
|
6529
6658
|
hash: rawDepositTxHash,
|
|
6530
|
-
wait: async () => await
|
|
6659
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawDepositTxHash, {
|
|
6660
|
+
primary: provider
|
|
6661
|
+
})
|
|
6531
6662
|
};
|
|
6532
6663
|
} else {
|
|
6533
6664
|
logger.log("\u{1F504} Executing Native COTI Deposit...");
|
|
@@ -6684,7 +6815,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6684
6815
|
logger.log("Withdraw tx sent", { txHash: shortHash(rawWithdrawTxHash) });
|
|
6685
6816
|
tx = {
|
|
6686
6817
|
hash: rawWithdrawTxHash,
|
|
6687
|
-
wait: async () => await
|
|
6818
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawWithdrawTxHash, {
|
|
6819
|
+
primary: provider
|
|
6820
|
+
})
|
|
6688
6821
|
};
|
|
6689
6822
|
} catch (e) {
|
|
6690
6823
|
setIsBridgingLoading(false);
|
|
@@ -6700,12 +6833,13 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6700
6833
|
title: "Processing Transaction",
|
|
6701
6834
|
message: "Transaction sent to network. Waiting for confirmation..."
|
|
6702
6835
|
});
|
|
6703
|
-
const receipt = await tx.
|
|
6836
|
+
const receipt = await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6837
|
+
primary: provider
|
|
6838
|
+
});
|
|
6704
6839
|
logger.log("Transaction confirmed", {
|
|
6705
6840
|
status: receipt.status,
|
|
6706
6841
|
blockNumber: receipt.blockNumber,
|
|
6707
|
-
gasUsed: receipt.gasUsed?.toString()
|
|
6708
|
-
gasLimit: receipt.gasLimit?.toString() ?? "n/a"
|
|
6842
|
+
gasUsed: receipt.gasUsed?.toString()
|
|
6709
6843
|
});
|
|
6710
6844
|
if (receipt.status !== 1) {
|
|
6711
6845
|
const gasUsed = receipt.gasUsed ? Number(receipt.gasUsed) : 0;
|
|
@@ -6720,11 +6854,12 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6720
6854
|
const replayProvider = new ethers23.JsonRpcProvider(
|
|
6721
6855
|
getRpcUrlForChain(Number(network2.chainId))
|
|
6722
6856
|
);
|
|
6857
|
+
const broadcastTx = await replayProvider.getTransaction(txHashStr);
|
|
6723
6858
|
await replayProvider.call({
|
|
6724
|
-
to: receipt.to,
|
|
6725
|
-
from: receipt.from,
|
|
6726
|
-
data:
|
|
6727
|
-
value:
|
|
6859
|
+
to: broadcastTx?.to ?? receipt.to,
|
|
6860
|
+
from: broadcastTx?.from ?? receipt.from,
|
|
6861
|
+
data: broadcastTx?.data,
|
|
6862
|
+
value: broadcastTx?.value
|
|
6728
6863
|
});
|
|
6729
6864
|
} catch (replayErr) {
|
|
6730
6865
|
const errorName = replayErr.errorName || replayErr.revert?.name;
|
|
@@ -7650,7 +7785,7 @@ async function fetchEncryptedBackupProbe(address, chainId) {
|
|
|
7650
7785
|
return null;
|
|
7651
7786
|
}
|
|
7652
7787
|
}
|
|
7653
|
-
var
|
|
7788
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7654
7789
|
function resolveAesKeyChainId(currentChainId, overrideChainId) {
|
|
7655
7790
|
const configuredChainId = getPluginConfig().aesKeyChainId;
|
|
7656
7791
|
assertAesKeyChainId(configuredChainId);
|
|
@@ -7670,7 +7805,7 @@ async function probeSnapKeyWithRetry(hasAesKeyInSnap, address, retries, confirmS
|
|
|
7670
7805
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
7671
7806
|
const result = await hasAesKeyInSnap(address);
|
|
7672
7807
|
if (result !== null) return result;
|
|
7673
|
-
if (attempt < retries) await
|
|
7808
|
+
if (attempt < retries) await sleep2(250);
|
|
7674
7809
|
}
|
|
7675
7810
|
if (confirmSnapInstalled && !await confirmSnapInstalled()) {
|
|
7676
7811
|
return false;
|
|
@@ -7963,7 +8098,7 @@ function toBigInt(value, fallback2) {
|
|
|
7963
8098
|
if (value === void 0) return fallback2;
|
|
7964
8099
|
return getBigInt(value);
|
|
7965
8100
|
}
|
|
7966
|
-
var
|
|
8101
|
+
var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7967
8102
|
function useAesKeyProvider(walletTypeInfo) {
|
|
7968
8103
|
const [isOnboarding, setIsOnboarding] = useState11(false);
|
|
7969
8104
|
const [onboardingError, setOnboardingError] = useState11(null);
|
|
@@ -8208,7 +8343,7 @@ function useAesKeyProvider(walletTypeInfo) {
|
|
|
8208
8343
|
const timeoutMs = config.onboardingGrantTimeoutMs ?? 6e4;
|
|
8209
8344
|
const startedAt = Date.now();
|
|
8210
8345
|
while (nativeBalance < requiredBalanceWei && Date.now() - startedAt < timeoutMs) {
|
|
8211
|
-
await
|
|
8346
|
+
await sleep3(pollIntervalMs);
|
|
8212
8347
|
nativeBalance = await provider.getBalance(address);
|
|
8213
8348
|
logger.log("[AesKeyProvider] Native COTI balance while waiting for grant", {
|
|
8214
8349
|
address,
|