@coti-io/coti-wallet-plugin 0.2.4 → 0.2.6
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.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +314 -198
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -191
- 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,
|
|
@@ -1339,20 +1523,14 @@ var init_podPortalFees = __esm({
|
|
|
1339
1523
|
return BigInt(gasPriceHex);
|
|
1340
1524
|
};
|
|
1341
1525
|
resolvePodTxGasPrice = async (provider) => {
|
|
1342
|
-
|
|
1343
|
-
try {
|
|
1344
|
-
const feeData = await provider.getFeeData();
|
|
1345
|
-
base = feeData.gasPrice ?? await getPodGasPrice(provider);
|
|
1346
|
-
} catch {
|
|
1347
|
-
base = await getPodGasPrice(provider);
|
|
1348
|
-
}
|
|
1526
|
+
const base = await getPodGasPrice(provider);
|
|
1349
1527
|
return base * POD_GAS_PRICE_BUFFER_BPS / 1000n;
|
|
1350
1528
|
};
|
|
1351
1529
|
getSepoliaGasPrice = resolvePodTxGasPrice;
|
|
1352
1530
|
quotePortalFeeOnly = async (runner, portalAddress, amount, direction, gasPrice) => {
|
|
1353
1531
|
const provider = resolveFeeRunnerProvider(runner);
|
|
1354
1532
|
const resolvedGasPrice = gasPrice ?? await resolvePodTxGasPrice(provider);
|
|
1355
|
-
const portal = new
|
|
1533
|
+
const portal = new ethers8.Contract(portalAddress, PRIVACY_PORTAL_ABI, runner);
|
|
1356
1534
|
if (direction === "to-private") {
|
|
1357
1535
|
const [portalFee2, usedDynamicPricing2] = await portal.estimateDepositFees(amount);
|
|
1358
1536
|
const quote2 = {
|
|
@@ -1384,8 +1562,8 @@ var init_podPortalFees = __esm({
|
|
|
1384
1562
|
});
|
|
1385
1563
|
return quote;
|
|
1386
1564
|
};
|
|
1387
|
-
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) =>
|
|
1388
|
-
formatPodFeeDisplay = (totalFee) =>
|
|
1565
|
+
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) => ethers8.formatEther(portalFee).replace(/\.?0+$/, "") || "0";
|
|
1566
|
+
formatPodFeeDisplay = (totalFee) => ethers8.formatEther(totalFee).replace(/\.?0+$/, "") || "0";
|
|
1389
1567
|
resolvePodFeeEstimationConfig = (chainId, direction, gasPrice) => {
|
|
1390
1568
|
const limits = getChainConfig(chainId)?.podFeeEstimation?.[direction === "to-private" ? "deposit" : "withdraw"];
|
|
1391
1569
|
if (!limits) {
|
|
@@ -1436,8 +1614,8 @@ var init_podPortalFees = __esm({
|
|
|
1436
1614
|
{ type: DataType.Uint256, value: "0", isCallBackFee: true },
|
|
1437
1615
|
{ type: DataType.Uint256, value: placeholderDeadline.toString(), isCallBackFee: false },
|
|
1438
1616
|
{ type: DataType.Uint8, value: "0", isCallBackFee: false },
|
|
1439
|
-
{ type: DataType.String, value:
|
|
1440
|
-
{ type: DataType.String, value:
|
|
1617
|
+
{ type: DataType.String, value: ethers8.ZeroHash, isCallBackFee: false },
|
|
1618
|
+
{ type: DataType.String, value: ethers8.ZeroHash, isCallBackFee: false }
|
|
1441
1619
|
];
|
|
1442
1620
|
}
|
|
1443
1621
|
return [
|
|
@@ -1465,8 +1643,8 @@ var init_podPortalFees = __esm({
|
|
|
1465
1643
|
const fallbackLimit = fallbackExecutionGasLimit(params.chainId, params.direction);
|
|
1466
1644
|
try {
|
|
1467
1645
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
1468
|
-
const rpcProvider = new
|
|
1469
|
-
const portal = new
|
|
1646
|
+
const rpcProvider = new ethers8.JsonRpcProvider(rpcUrl);
|
|
1647
|
+
const portal = new ethers8.Contract(params.portalAddress, PRIVACY_PORTAL_ABI, rpcProvider);
|
|
1470
1648
|
if (params.direction === "to-private") {
|
|
1471
1649
|
const method = resolvePodPortalMethod("to-private", params.isNativeDeposit);
|
|
1472
1650
|
const nativeAmount = params.isNativeDeposit ? params.amountWei : 0n;
|
|
@@ -1483,8 +1661,8 @@ var init_podPortalFees = __esm({
|
|
|
1483
1661
|
const permit = params.withdrawPermit;
|
|
1484
1662
|
const deadline = permit ? BigInt(permit.deadline) : BigInt(Math.floor(Date.now() / 1e3) + 60 * 30);
|
|
1485
1663
|
const v = permit?.v ?? 0;
|
|
1486
|
-
const r = permit?.r ??
|
|
1487
|
-
const s = permit?.s ??
|
|
1664
|
+
const r = permit?.r ?? ethers8.ZeroHash;
|
|
1665
|
+
const s = permit?.s ?? ethers8.ZeroHash;
|
|
1488
1666
|
const gasLimit = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1489
1667
|
params.wallet,
|
|
1490
1668
|
params.amountWei,
|
|
@@ -1531,8 +1709,8 @@ var init_podPortalFees = __esm({
|
|
|
1531
1709
|
let supportsEip1559 = false;
|
|
1532
1710
|
if (provider) {
|
|
1533
1711
|
try {
|
|
1534
|
-
const
|
|
1535
|
-
supportsEip1559 =
|
|
1712
|
+
const block = await provider.getBlock("latest");
|
|
1713
|
+
supportsEip1559 = block?.baseFeePerGas != null;
|
|
1536
1714
|
} catch {
|
|
1537
1715
|
supportsEip1559 = false;
|
|
1538
1716
|
}
|
|
@@ -1584,11 +1762,11 @@ var init_podPortalFees = __esm({
|
|
|
1584
1762
|
});
|
|
1585
1763
|
|
|
1586
1764
|
// src/chains/portal/executePodPortalTransaction.ts
|
|
1587
|
-
import { ethers as
|
|
1765
|
+
import { ethers as ethers9 } from "ethers";
|
|
1588
1766
|
async function signPodWithdrawPermit(params) {
|
|
1589
1767
|
const { signer, pTokenAddress, portalAddress, amountWei } = params;
|
|
1590
1768
|
const wallet = await signer.getAddress();
|
|
1591
|
-
const pToken = new
|
|
1769
|
+
const pToken = new ethers9.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1592
1770
|
const signingChainId = params.chainId ?? Number((await signer.provider.getNetwork()).chainId);
|
|
1593
1771
|
const resolvedTokenSymbol = params.tokenSymbol ?? await pToken.symbol().catch(() => void 0);
|
|
1594
1772
|
await assertPodPTokenReady(pToken, wallet, "withdraw", {
|
|
@@ -1658,9 +1836,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1658
1836
|
throw new Error("PoD portal is not configured for this token");
|
|
1659
1837
|
}
|
|
1660
1838
|
const wallet = await signer.getAddress();
|
|
1661
|
-
const amountWei =
|
|
1662
|
-
const pToken = new
|
|
1663
|
-
const portalIface2 = new
|
|
1839
|
+
const amountWei = ethers9.parseUnits(txAmount, decimals);
|
|
1840
|
+
const pToken = new ethers9.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1841
|
+
const portalIface2 = new ethers9.Interface(PRIVACY_PORTAL_ABI);
|
|
1664
1842
|
const gasPrice = await resolvePodTxGasPrice(provider);
|
|
1665
1843
|
if (txDirection === "to-private") {
|
|
1666
1844
|
await assertPodPTokenReady(pToken, wallet, "deposit", {
|
|
@@ -1689,7 +1867,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1689
1867
|
});
|
|
1690
1868
|
let gasLimit2;
|
|
1691
1869
|
try {
|
|
1692
|
-
const portal = new
|
|
1870
|
+
const portal = new ethers9.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1693
1871
|
const nativeAmount = isNativeDeposit ? amountWei : 0n;
|
|
1694
1872
|
const estimated = await portal[method2].estimateGas(
|
|
1695
1873
|
wallet,
|
|
@@ -1721,7 +1899,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1721
1899
|
fee: podFee2
|
|
1722
1900
|
});
|
|
1723
1901
|
onProgress?.("transfer-start", tx2.hash);
|
|
1724
|
-
const receipt2 = await tx2.
|
|
1902
|
+
const receipt2 = await waitForTransactionResilient(chainId, tx2.hash, {
|
|
1903
|
+
primary: provider ?? signer.provider ?? void 0
|
|
1904
|
+
});
|
|
1725
1905
|
if (!receipt2 || receipt2.status !== 1) {
|
|
1726
1906
|
const failed = new Error("PoD deposit transaction failed");
|
|
1727
1907
|
failed.txHash = tx2.hash;
|
|
@@ -1778,7 +1958,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1778
1958
|
});
|
|
1779
1959
|
let gasLimit;
|
|
1780
1960
|
try {
|
|
1781
|
-
const portal = new
|
|
1961
|
+
const portal = new ethers9.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1782
1962
|
const estimated = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1783
1963
|
wallet,
|
|
1784
1964
|
amountWei,
|
|
@@ -1812,7 +1992,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1812
1992
|
fee: podFee
|
|
1813
1993
|
});
|
|
1814
1994
|
onProgress?.("transfer-start", tx.hash);
|
|
1815
|
-
const receipt = await tx.
|
|
1995
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
1996
|
+
primary: provider ?? signer.provider ?? void 0
|
|
1997
|
+
});
|
|
1816
1998
|
if (!receipt || receipt.status !== 1) {
|
|
1817
1999
|
const failed = new Error("Sepolia withdraw transaction failed");
|
|
1818
2000
|
failed.txHash = tx.hash;
|
|
@@ -1846,13 +2028,14 @@ var init_executePodPortalTransaction = __esm({
|
|
|
1846
2028
|
"use strict";
|
|
1847
2029
|
init_pod();
|
|
1848
2030
|
init_logger();
|
|
2031
|
+
init_rpcProvider();
|
|
1849
2032
|
init_podPTokenBlockingDiagnostics();
|
|
1850
2033
|
init_podPortalFees();
|
|
1851
2034
|
init_podSdkConfig();
|
|
1852
2035
|
init_podPortalFees();
|
|
1853
2036
|
init_fees();
|
|
1854
2037
|
getErrorMessage = (error) => error && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : "";
|
|
1855
|
-
pTokenErrorIface = new
|
|
2038
|
+
pTokenErrorIface = new ethers9.Interface(POD_PTOKEN_ABI);
|
|
1856
2039
|
extractRevertData = (error) => {
|
|
1857
2040
|
if (!error || typeof error !== "object") return null;
|
|
1858
2041
|
const err = error;
|
|
@@ -1908,7 +2091,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
1908
2091
|
return null;
|
|
1909
2092
|
};
|
|
1910
2093
|
splitSignature = (signature) => {
|
|
1911
|
-
const parsed =
|
|
2094
|
+
const parsed = ethers9.Signature.from(signature);
|
|
1912
2095
|
return { v: parsed.v, r: parsed.r, s: parsed.s };
|
|
1913
2096
|
};
|
|
1914
2097
|
POD_PTOKEN_FLAT_STATUS_ABI = [
|
|
@@ -2055,7 +2238,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2055
2238
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2056
2239
|
probeErrors.push(`balanceWithState: ${getErrorMessage(error) || String(error)}`);
|
|
2057
2240
|
}
|
|
2058
|
-
const flatStatusToken = new
|
|
2241
|
+
const flatStatusToken = new ethers9.Contract(
|
|
2059
2242
|
pTokenAddress,
|
|
2060
2243
|
POD_PTOKEN_FLAT_STATUS_ABI,
|
|
2061
2244
|
pToken.runner
|
|
@@ -2090,7 +2273,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2090
2273
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2091
2274
|
probeErrors.push(`balanceOfWithStatus: ${getErrorMessage(error) || String(error)}`);
|
|
2092
2275
|
}
|
|
2093
|
-
const plainToken = new
|
|
2276
|
+
const plainToken = new ethers9.Contract(
|
|
2094
2277
|
pTokenAddress,
|
|
2095
2278
|
POD_PTOKEN_PLAIN_STATUS_ABI,
|
|
2096
2279
|
pToken.runner
|
|
@@ -2297,7 +2480,7 @@ var init_ethereum = __esm({
|
|
|
2297
2480
|
});
|
|
2298
2481
|
|
|
2299
2482
|
// src/chains/portal/podTransferFees.ts
|
|
2300
|
-
import { ethers as
|
|
2483
|
+
import { ethers as ethers10 } from "ethers";
|
|
2301
2484
|
import {
|
|
2302
2485
|
DataType as DataType2,
|
|
2303
2486
|
PodContract as PodContract2,
|
|
@@ -2427,8 +2610,8 @@ var init_podTransferFees = __esm({
|
|
|
2427
2610
|
if (!overrides.gasLimit) {
|
|
2428
2611
|
try {
|
|
2429
2612
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
2430
|
-
const rpcProvider = new
|
|
2431
|
-
const pToken = new
|
|
2613
|
+
const rpcProvider = new ethers10.JsonRpcProvider(rpcUrl);
|
|
2614
|
+
const pToken = new ethers10.Contract(params.pTokenAddress, POD_PTOKEN_ABI, rpcProvider);
|
|
2432
2615
|
const estimated = await pToken.getFunction(POD_TRANSFER_METHOD).estimateGas(...vals, {
|
|
2433
2616
|
from: userAddress,
|
|
2434
2617
|
value: fee.totalFee,
|
|
@@ -2506,7 +2689,7 @@ var init_utils = __esm({
|
|
|
2506
2689
|
});
|
|
2507
2690
|
|
|
2508
2691
|
// src/hooks/privacyBridge/executePrivateTokenTransfer.ts
|
|
2509
|
-
import { ethers as
|
|
2692
|
+
import { ethers as ethers11 } from "ethers";
|
|
2510
2693
|
function normalizeAesKeyHex(aesKey) {
|
|
2511
2694
|
try {
|
|
2512
2695
|
return normalizeAesKey(aesKey);
|
|
@@ -2532,10 +2715,10 @@ function resolvePrivateTokenTransferTarget(chainId, symbol) {
|
|
|
2532
2715
|
};
|
|
2533
2716
|
}
|
|
2534
2717
|
function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2535
|
-
if (!
|
|
2718
|
+
if (!ethers11.isAddress(tokenAddress)) {
|
|
2536
2719
|
throw new Error("Invalid token contract address");
|
|
2537
2720
|
}
|
|
2538
|
-
if (!
|
|
2721
|
+
if (!ethers11.isAddress(recipient)) {
|
|
2539
2722
|
throw new Error("Invalid recipient address");
|
|
2540
2723
|
}
|
|
2541
2724
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2548,7 +2731,7 @@ function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAd
|
|
|
2548
2731
|
function parseTransferAmountWei(amount, decimals) {
|
|
2549
2732
|
let amountWei;
|
|
2550
2733
|
try {
|
|
2551
|
-
amountWei =
|
|
2734
|
+
amountWei = ethers11.parseUnits(amount, decimals);
|
|
2552
2735
|
} catch {
|
|
2553
2736
|
throw new Error("Invalid amount for token decimals");
|
|
2554
2737
|
}
|
|
@@ -2584,7 +2767,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2584
2767
|
recipient: shortHash(recipient),
|
|
2585
2768
|
amount
|
|
2586
2769
|
});
|
|
2587
|
-
const browserProvider = new
|
|
2770
|
+
const browserProvider = new ethers11.BrowserProvider(eip1193);
|
|
2771
|
+
const network = await browserProvider.getNetwork();
|
|
2772
|
+
const chainId = Number(network.chainId);
|
|
2588
2773
|
const rawTxHash = await eip1193.request({
|
|
2589
2774
|
method: "eth_sendTransaction",
|
|
2590
2775
|
params: [
|
|
@@ -2597,7 +2782,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2597
2782
|
]
|
|
2598
2783
|
});
|
|
2599
2784
|
logger.log("Waiting for private transfer tx", { txHash: shortHash(rawTxHash) });
|
|
2600
|
-
const receipt = await
|
|
2785
|
+
const receipt = await waitForTransactionResilient(chainId, rawTxHash, {
|
|
2786
|
+
primary: browserProvider
|
|
2787
|
+
});
|
|
2601
2788
|
if (!receipt || receipt.status !== 1) {
|
|
2602
2789
|
throw new Error("Private token transfer failed");
|
|
2603
2790
|
}
|
|
@@ -2635,10 +2822,10 @@ async function sendPrivateTokenTransfer(params) {
|
|
|
2635
2822
|
if (!eip1193) {
|
|
2636
2823
|
throw new Error("No wallet found");
|
|
2637
2824
|
}
|
|
2638
|
-
const browserProvider = new
|
|
2825
|
+
const browserProvider = new ethers11.BrowserProvider(eip1193);
|
|
2639
2826
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2640
2827
|
const amountWei = parseTransferAmountWei(amount, target.decimals);
|
|
2641
|
-
const transferSig =
|
|
2828
|
+
const transferSig = ethers11.id(PRIVATE_ERC20_TRANSFER_256_SIG).slice(0, 10);
|
|
2642
2829
|
let aesKey = sessionAesKey ? normalizeAesKeyHex(sessionAesKey) : null;
|
|
2643
2830
|
if (!aesKey && hasSnap && getAESKeyFromSnap) {
|
|
2644
2831
|
const snapKey = await getAESKeyFromSnap(walletAddress);
|
|
@@ -2673,6 +2860,7 @@ var init_executePrivateTokenTransfer = __esm({
|
|
|
2673
2860
|
init_aesKey();
|
|
2674
2861
|
init_ethereum();
|
|
2675
2862
|
init_logger();
|
|
2863
|
+
init_rpcProvider();
|
|
2676
2864
|
init_config();
|
|
2677
2865
|
init_chains();
|
|
2678
2866
|
init_chains();
|
|
@@ -2681,7 +2869,7 @@ var init_executePrivateTokenTransfer = __esm({
|
|
|
2681
2869
|
PRIVATE_ERC20_TRANSFER_256_SIG = "transfer(address,((uint256,uint256),bytes))";
|
|
2682
2870
|
GAS_ESTIMATE_BUFFER_PERCENT = 105n;
|
|
2683
2871
|
CONFIDENTIAL_TRANSFER_GAS_LIMIT = 2000000n;
|
|
2684
|
-
TRANSFER_INTERFACE = new
|
|
2872
|
+
TRANSFER_INTERFACE = new ethers11.Interface([
|
|
2685
2873
|
"function transfer(address to, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (uint256)"
|
|
2686
2874
|
]);
|
|
2687
2875
|
}
|
|
@@ -2695,12 +2883,12 @@ __export(executePodPrivateTokenTransfer_exports, {
|
|
|
2695
2883
|
quotePodPrivateTokenTransferFees: () => quotePodPrivateTokenTransferFees,
|
|
2696
2884
|
quotePodTransferFees: () => quotePodTransferFees
|
|
2697
2885
|
});
|
|
2698
|
-
import { ethers as
|
|
2886
|
+
import { ethers as ethers12 } from "ethers";
|
|
2699
2887
|
function validatePodTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2700
|
-
if (!
|
|
2888
|
+
if (!ethers12.isAddress(tokenAddress)) {
|
|
2701
2889
|
throw new Error("Invalid token contract address");
|
|
2702
2890
|
}
|
|
2703
|
-
if (!
|
|
2891
|
+
if (!ethers12.isAddress(recipient)) {
|
|
2704
2892
|
throw new Error("Invalid recipient address");
|
|
2705
2893
|
}
|
|
2706
2894
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2725,13 +2913,13 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2725
2913
|
if (!eip1193) {
|
|
2726
2914
|
throw new Error("No wallet found");
|
|
2727
2915
|
}
|
|
2728
|
-
const browserProvider = new
|
|
2916
|
+
const browserProvider = new ethers12.BrowserProvider(eip1193);
|
|
2729
2917
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2730
|
-
const amountWei =
|
|
2918
|
+
const amountWei = ethers12.parseUnits(amount, target.decimals);
|
|
2731
2919
|
if (amountWei <= 0n) {
|
|
2732
2920
|
throw new Error("Amount must be greater than zero");
|
|
2733
2921
|
}
|
|
2734
|
-
const pToken = new
|
|
2922
|
+
const pToken = new ethers12.Contract(target.tokenAddress, POD_PTOKEN_ABI, signer);
|
|
2735
2923
|
await assertPodPTokenReady(pToken, walletAddress, "transfer", {
|
|
2736
2924
|
chainId,
|
|
2737
2925
|
tokenSymbol: symbol,
|
|
@@ -2763,13 +2951,15 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2763
2951
|
gasPrice,
|
|
2764
2952
|
fee: podFee
|
|
2765
2953
|
});
|
|
2766
|
-
const receipt = await tx.
|
|
2954
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
2955
|
+
primary: browserProvider
|
|
2956
|
+
});
|
|
2767
2957
|
if (!receipt || receipt.status !== 1) {
|
|
2768
2958
|
const failed = new Error("PoD private token transfer failed");
|
|
2769
2959
|
failed.txHash = tx.hash;
|
|
2770
2960
|
throw failed;
|
|
2771
2961
|
}
|
|
2772
|
-
const event = findParsedEvent2(receipt, new
|
|
2962
|
+
const event = findParsedEvent2(receipt, new ethers12.Interface(POD_PTOKEN_ABI), "TransferRequestSubmitted");
|
|
2773
2963
|
const requestId = event?.args?.requestId;
|
|
2774
2964
|
return {
|
|
2775
2965
|
txHash: tx.hash,
|
|
@@ -2799,10 +2989,10 @@ async function quotePodPrivateTokenTransferFees(params) {
|
|
|
2799
2989
|
if (!eip1193) {
|
|
2800
2990
|
throw new Error("No wallet found");
|
|
2801
2991
|
}
|
|
2802
|
-
const browserProvider = new
|
|
2992
|
+
const browserProvider = new ethers12.BrowserProvider(eip1193);
|
|
2803
2993
|
const signer = await browserProvider.getSigner(params.walletAddress);
|
|
2804
|
-
const amountWei =
|
|
2805
|
-
const recipient =
|
|
2994
|
+
const amountWei = ethers12.parseUnits(params.amount, target.decimals);
|
|
2995
|
+
const recipient = ethers12.isAddress(params.recipient) && params.recipient !== ethers12.ZeroAddress ? params.recipient : params.walletAddress;
|
|
2806
2996
|
return quotePodTransferFees({
|
|
2807
2997
|
runner: signer,
|
|
2808
2998
|
chainId: params.chainId,
|
|
@@ -2819,6 +3009,7 @@ var init_executePodPrivateTokenTransfer = __esm({
|
|
|
2819
3009
|
init_chains();
|
|
2820
3010
|
init_ethereum();
|
|
2821
3011
|
init_logger();
|
|
3012
|
+
init_rpcProvider();
|
|
2822
3013
|
init_executePodPortalTransaction();
|
|
2823
3014
|
init_podPortalFees();
|
|
2824
3015
|
init_podTransferFees();
|
|
@@ -3396,7 +3587,7 @@ init_executePodPrivateTokenTransfer();
|
|
|
3396
3587
|
init_logger();
|
|
3397
3588
|
import { useState, useCallback, useEffect, useRef } from "react";
|
|
3398
3589
|
import { useAccount } from "wagmi";
|
|
3399
|
-
import { ethers as
|
|
3590
|
+
import { ethers as ethers13 } from "ethers";
|
|
3400
3591
|
var usePodTransferFees = ({
|
|
3401
3592
|
isConnected,
|
|
3402
3593
|
walletAddress,
|
|
@@ -3453,7 +3644,7 @@ var usePodTransferFees = ({
|
|
|
3453
3644
|
const quote = await quotePodPrivateTokenTransferFees({
|
|
3454
3645
|
chainId,
|
|
3455
3646
|
symbol,
|
|
3456
|
-
recipient: recipient &&
|
|
3647
|
+
recipient: recipient && ethers13.isAddress(recipient) ? recipient : walletAddress,
|
|
3457
3648
|
amount: currentAmount,
|
|
3458
3649
|
walletAddress,
|
|
3459
3650
|
provider: injected6
|
|
@@ -3502,7 +3693,7 @@ var usePodTransferFees = ({
|
|
|
3502
3693
|
init_chains();
|
|
3503
3694
|
init_rpcUrls();
|
|
3504
3695
|
init_logger();
|
|
3505
|
-
import { ethers as
|
|
3696
|
+
import { ethers as ethers14 } from "ethers";
|
|
3506
3697
|
var POD_PRICE_ORACLE_ABI = [
|
|
3507
3698
|
"function getLivePrice(address token) view returns (uint256 priceUsd)",
|
|
3508
3699
|
"function getLivePrices(address tokenA, address tokenB) view returns (uint256 priceA, uint256 priceB)"
|
|
@@ -3527,17 +3718,17 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3527
3718
|
return null;
|
|
3528
3719
|
}
|
|
3529
3720
|
const rpcUrls = provider ? [] : getRpcUrlsForChain(chainId);
|
|
3530
|
-
const providers = provider ? [provider] : rpcUrls.map((url) => new
|
|
3721
|
+
const providers = provider ? [provider] : rpcUrls.map((url) => new ethers14.JsonRpcProvider(url));
|
|
3531
3722
|
let lastError;
|
|
3532
3723
|
for (const rpcProvider of providers) {
|
|
3533
3724
|
try {
|
|
3534
|
-
const oracle = new
|
|
3725
|
+
const oracle = new ethers14.Contract(oracleAddress, POD_PRICE_ORACLE_ABI, rpcProvider);
|
|
3535
3726
|
const raw = await oracle.getLivePrice(tokenAddress);
|
|
3536
3727
|
if (raw === 0n) {
|
|
3537
3728
|
logger.warn(`PoD price oracle has no live feed for ${symbol} on chain ${chainId}`);
|
|
3538
3729
|
return null;
|
|
3539
3730
|
}
|
|
3540
|
-
return Number(
|
|
3731
|
+
return Number(ethers14.formatEther(raw));
|
|
3541
3732
|
} catch (err) {
|
|
3542
3733
|
lastError = err;
|
|
3543
3734
|
}
|
|
@@ -3551,12 +3742,12 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3551
3742
|
init_pod();
|
|
3552
3743
|
init_chains();
|
|
3553
3744
|
init_rpcUrls();
|
|
3554
|
-
import { ethers as
|
|
3745
|
+
import { ethers as ethers15 } from "ethers";
|
|
3555
3746
|
init_logger();
|
|
3556
3747
|
var ERC20_BALANCE_ABI = ["function balanceOf(address) view returns (uint256)"];
|
|
3557
3748
|
var FEE_DIVISOR = 1000000n;
|
|
3558
3749
|
var POD_NO_MAX_FEE_SENTINEL = (1n << 128n) - 1n;
|
|
3559
|
-
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" :
|
|
3750
|
+
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" : ethers15.formatEther(value);
|
|
3560
3751
|
async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
3561
3752
|
const portalAddress = config.addresses[token.bridgeAddressKey];
|
|
3562
3753
|
const privateToken = config.tokens.find(
|
|
@@ -3583,12 +3774,12 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3583
3774
|
isLoading: false
|
|
3584
3775
|
};
|
|
3585
3776
|
try {
|
|
3586
|
-
const portal = new
|
|
3777
|
+
const portal = new ethers15.Contract(portalAddress, POD_PORTAL_ADMIN_ABI, provider);
|
|
3587
3778
|
const [depCfg, wdCfg, accFees, balance] = await Promise.all([
|
|
3588
3779
|
portal.getFeeConfig(true),
|
|
3589
3780
|
portal.getFeeConfig(false),
|
|
3590
3781
|
portal.accumulatedPortalFees().catch(() => 0n),
|
|
3591
|
-
token.isNative ? provider.getBalance(portalAddress) : token.addressKey && config.addresses[token.addressKey] ? new
|
|
3782
|
+
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
3783
|
]);
|
|
3593
3784
|
return {
|
|
3594
3785
|
...base,
|
|
@@ -3598,8 +3789,8 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3598
3789
|
withdrawFixedFee: formatFee(wdCfg[0]),
|
|
3599
3790
|
withdrawPercentageBps: wdCfg[1].toString(),
|
|
3600
3791
|
withdrawMaxFee: formatFee(wdCfg[2]),
|
|
3601
|
-
accumulatedCotiFees:
|
|
3602
|
-
bridgeBalance:
|
|
3792
|
+
accumulatedCotiFees: ethers15.formatEther(accFees),
|
|
3793
|
+
bridgeBalance: ethers15.formatUnits(balance, token.decimals),
|
|
3603
3794
|
error: null
|
|
3604
3795
|
};
|
|
3605
3796
|
} catch (err) {
|
|
@@ -3627,7 +3818,7 @@ async function fetchPodBridgeData(chainId) {
|
|
|
3627
3818
|
);
|
|
3628
3819
|
let lastError;
|
|
3629
3820
|
for (const rpcUrl of getRpcUrlsForChain(chainId)) {
|
|
3630
|
-
const provider = new
|
|
3821
|
+
const provider = new ethers15.JsonRpcProvider(rpcUrl);
|
|
3631
3822
|
try {
|
|
3632
3823
|
await provider.getBlockNumber();
|
|
3633
3824
|
return await Promise.all(
|
|
@@ -3646,7 +3837,7 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3646
3837
|
if (!config) return { fee: "\u2014", explanation: "Unsupported chain" };
|
|
3647
3838
|
const token = config.tokens.find((t) => t.symbol === tokenSymbol && !t.isPrivate);
|
|
3648
3839
|
if (!token) return { fee: "\u2014", explanation: "Unknown token" };
|
|
3649
|
-
const amountWei =
|
|
3840
|
+
const amountWei = ethers15.parseUnits(amount, token.decimals);
|
|
3650
3841
|
let valueInNative;
|
|
3651
3842
|
if (token.isNative) {
|
|
3652
3843
|
valueInNative = amountWei;
|
|
@@ -3657,27 +3848,27 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3657
3848
|
fetchPodOracleTokenUsdPrice(nativeSymbol, chainId)
|
|
3658
3849
|
]);
|
|
3659
3850
|
if (!tokenUsd || !nativeUsd) {
|
|
3660
|
-
const fixed =
|
|
3661
|
-
const cap =
|
|
3851
|
+
const fixed = ethers15.parseEther(fixedFee || "0");
|
|
3852
|
+
const cap = ethers15.parseEther(maxFee || "0");
|
|
3662
3853
|
const fee2 = cap > 0n && fixed > cap ? cap : fixed;
|
|
3663
3854
|
return {
|
|
3664
|
-
fee: parseFloat(
|
|
3855
|
+
fee: parseFloat(ethers15.formatEther(fee2)).toFixed(6),
|
|
3665
3856
|
explanation: "Fixed fee applied (no live oracle price)"
|
|
3666
3857
|
};
|
|
3667
3858
|
}
|
|
3668
|
-
const tokenUsdWei =
|
|
3669
|
-
const nativeUsdWei =
|
|
3859
|
+
const tokenUsdWei = ethers15.parseEther(tokenUsd.toString());
|
|
3860
|
+
const nativeUsdWei = ethers15.parseEther(nativeUsd.toString());
|
|
3670
3861
|
const amount18 = amountWei * 10n ** BigInt(18 - token.decimals);
|
|
3671
3862
|
valueInNative = amount18 * tokenUsdWei / nativeUsdWei;
|
|
3672
3863
|
}
|
|
3673
|
-
const fixedFeeWei =
|
|
3674
|
-
const maxFeeWei =
|
|
3864
|
+
const fixedFeeWei = ethers15.parseEther(fixedFee || "0");
|
|
3865
|
+
const maxFeeWei = ethers15.parseEther(maxFee || "0");
|
|
3675
3866
|
const bps = BigInt(parseInt(percentageBps || "0", 10));
|
|
3676
3867
|
const percentageFee = valueInNative * bps / FEE_DIVISOR;
|
|
3677
3868
|
let fee = percentageFee > fixedFeeWei ? percentageFee : fixedFeeWei;
|
|
3678
3869
|
if (maxFeeWei > 0n && fee > maxFeeWei) fee = maxFeeWei;
|
|
3679
3870
|
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(
|
|
3871
|
+
return { fee: parseFloat(ethers15.formatEther(fee)).toFixed(6), explanation };
|
|
3681
3872
|
} catch (err) {
|
|
3682
3873
|
logger.error("simulatePodPortalFee error:", err);
|
|
3683
3874
|
return { fee: "\u2014", explanation: "Simulation failed" };
|
|
@@ -3700,7 +3891,7 @@ var LIMITS = {
|
|
|
3700
3891
|
init_plugin();
|
|
3701
3892
|
init_ethereum();
|
|
3702
3893
|
import { useState as useState2, useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
3703
|
-
import { ethers as
|
|
3894
|
+
import { ethers as ethers16 } from "ethers";
|
|
3704
3895
|
init_logger();
|
|
3705
3896
|
|
|
3706
3897
|
// src/lib/format.ts
|
|
@@ -3984,7 +4175,7 @@ var useMetamask = ({
|
|
|
3984
4175
|
});
|
|
3985
4176
|
const accounts = await eth.request({ method: "eth_requestAccounts" });
|
|
3986
4177
|
if (!accounts || accounts.length === 0) return false;
|
|
3987
|
-
const provider = new
|
|
4178
|
+
const provider = new ethers16.BrowserProvider(eth);
|
|
3988
4179
|
const network = await provider.getNetwork();
|
|
3989
4180
|
const envDefaultNetwork = getPluginConfig().defaultNetworkId;
|
|
3990
4181
|
if (accounts.length > 0) {
|
|
@@ -4001,7 +4192,7 @@ var useMetamask = ({
|
|
|
4001
4192
|
const eth = getMetaMaskProvider();
|
|
4002
4193
|
if (!eth) return;
|
|
4003
4194
|
try {
|
|
4004
|
-
const provider = new
|
|
4195
|
+
const provider = new ethers16.BrowserProvider(eth);
|
|
4005
4196
|
await checkNetwork(provider);
|
|
4006
4197
|
if (onNetworkChanged) {
|
|
4007
4198
|
await onNetworkChanged();
|
|
@@ -4238,97 +4429,8 @@ function decryptCtUint256(ciphertext, aesKey, options) {
|
|
|
4238
4429
|
}
|
|
4239
4430
|
}
|
|
4240
4431
|
|
|
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 readNestedRpcCode = (error) => {
|
|
4273
|
-
const e = error;
|
|
4274
|
-
return e.code ?? e.error?.code ?? e.info?.error?.code;
|
|
4275
|
-
};
|
|
4276
|
-
var readNestedHttpStatus = (error) => {
|
|
4277
|
-
const e = error;
|
|
4278
|
-
return e.data?.httpStatus ?? e.error?.data?.httpStatus ?? e.info?.responseStatus;
|
|
4279
|
-
};
|
|
4280
|
-
var isTransientRpcError = (error) => {
|
|
4281
|
-
const text = collectErrorText(error);
|
|
4282
|
-
const lower = text.toLowerCase();
|
|
4283
|
-
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")) {
|
|
4284
|
-
return true;
|
|
4285
|
-
}
|
|
4286
|
-
if (error && typeof error === "object") {
|
|
4287
|
-
const code = readNestedRpcCode(error);
|
|
4288
|
-
if (code === "SERVER_ERROR" || code === "TIMEOUT" || code === "NETWORK_ERROR" || code === -32005 || code === "-32005") {
|
|
4289
|
-
return true;
|
|
4290
|
-
}
|
|
4291
|
-
const httpStatus = readNestedHttpStatus(error);
|
|
4292
|
-
if (httpStatus === 429 || httpStatus === "429") {
|
|
4293
|
-
return true;
|
|
4294
|
-
}
|
|
4295
|
-
}
|
|
4296
|
-
return false;
|
|
4297
|
-
};
|
|
4298
|
-
var createJsonRpcProvider = (url, chainId) => new ethers16.JsonRpcProvider(url, chainId);
|
|
4299
|
-
var createResilientJsonRpcProvider = async (chainId) => {
|
|
4300
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4301
|
-
let lastError;
|
|
4302
|
-
for (const url of urls) {
|
|
4303
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4304
|
-
try {
|
|
4305
|
-
await provider.getNetwork();
|
|
4306
|
-
return provider;
|
|
4307
|
-
} catch (error) {
|
|
4308
|
-
lastError = error;
|
|
4309
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4310
|
-
logger.warn(`[rpc] ${url} unavailable for chain ${chainId}, trying fallback`);
|
|
4311
|
-
}
|
|
4312
|
-
}
|
|
4313
|
-
throw lastError instanceof Error ? lastError : new Error(`No RPC available for chain ${chainId}`);
|
|
4314
|
-
};
|
|
4315
|
-
var withRpcFallback = async (chainId, fn) => {
|
|
4316
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4317
|
-
let lastError;
|
|
4318
|
-
for (const url of urls) {
|
|
4319
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4320
|
-
try {
|
|
4321
|
-
return await fn(provider);
|
|
4322
|
-
} catch (error) {
|
|
4323
|
-
lastError = error;
|
|
4324
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4325
|
-
logger.warn(`[rpc] ${url} request failed for chain ${chainId}, trying fallback`);
|
|
4326
|
-
}
|
|
4327
|
-
}
|
|
4328
|
-
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed for chain ${chainId}`);
|
|
4329
|
-
};
|
|
4330
|
-
|
|
4331
4432
|
// src/hooks/usePrivateTokenBalance.ts
|
|
4433
|
+
init_rpcProvider();
|
|
4332
4434
|
init_plugin();
|
|
4333
4435
|
init_logger();
|
|
4334
4436
|
var PLAIN_BALANCE_ABI = [
|
|
@@ -4439,6 +4541,7 @@ var usePrivateTokenBalance = () => {
|
|
|
4439
4541
|
|
|
4440
4542
|
// src/hooks/useBalanceUpdater.ts
|
|
4441
4543
|
init_config();
|
|
4544
|
+
init_rpcProvider();
|
|
4442
4545
|
import { useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
4443
4546
|
import { ethers as ethers19 } from "ethers";
|
|
4444
4547
|
|
|
@@ -4534,6 +4637,7 @@ import { encodeKey, encodeUint, encrypt, decryptUint as decryptUint2, decodeUint
|
|
|
4534
4637
|
import { ethers as ethers18 } from "ethers";
|
|
4535
4638
|
init_logger();
|
|
4536
4639
|
init_config();
|
|
4640
|
+
init_rpcProvider();
|
|
4537
4641
|
var ROUND_TRIP_TEST_VALUE = 0x0123456789abcdefn;
|
|
4538
4642
|
var FLAT_BALANCE_ABI2 = [
|
|
4539
4643
|
"function balanceOf(address) view returns (tuple(uint256 ciphertextHigh, uint256 ciphertextLow))"
|
|
@@ -5252,6 +5356,7 @@ import { useState as useState4, useCallback as useCallback7, useEffect as useEff
|
|
|
5252
5356
|
import { useAccount as useAccount3 } from "wagmi";
|
|
5253
5357
|
import { ethers as ethers22 } from "ethers";
|
|
5254
5358
|
init_logger();
|
|
5359
|
+
init_rpcProvider();
|
|
5255
5360
|
init_encryptValue256();
|
|
5256
5361
|
init_utils();
|
|
5257
5362
|
init_ethereum();
|
|
@@ -6231,7 +6336,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6231
6336
|
}]
|
|
6232
6337
|
});
|
|
6233
6338
|
logger.log("\u{1F510} [Approve] Tx submitted, waiting for confirmation", { txHash: shortHash(rawTxHash) });
|
|
6234
|
-
await
|
|
6339
|
+
await waitForTransactionResilient(currentChainId, rawTxHash, {
|
|
6340
|
+
primary: provider
|
|
6341
|
+
});
|
|
6235
6342
|
logger.log("\u{1F510} [Approve] Tx confirmed, refreshing allowance...");
|
|
6236
6343
|
setIsApproving(false);
|
|
6237
6344
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6248,7 +6355,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6248
6355
|
title: "Approving...",
|
|
6249
6356
|
message: "Waiting for allowance confirmation..."
|
|
6250
6357
|
});
|
|
6251
|
-
await tx.
|
|
6358
|
+
await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6359
|
+
primary: provider
|
|
6360
|
+
});
|
|
6252
6361
|
await checkAllowance();
|
|
6253
6362
|
setIsApproving(false);
|
|
6254
6363
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6292,6 +6401,7 @@ import { useAccount as useAccount4 } from "wagmi";
|
|
|
6292
6401
|
import { ethers as ethers23 } from "ethers";
|
|
6293
6402
|
init_chains();
|
|
6294
6403
|
init_logger();
|
|
6404
|
+
init_rpcProvider();
|
|
6295
6405
|
init_utils();
|
|
6296
6406
|
var usePrivacyBridgeExecutor = ({
|
|
6297
6407
|
walletAddress,
|
|
@@ -6540,7 +6650,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6540
6650
|
logger.log("ERC20 deposit tx sent", { txHash: shortHash(rawDepositTxHash) });
|
|
6541
6651
|
tx = {
|
|
6542
6652
|
hash: rawDepositTxHash,
|
|
6543
|
-
wait: async () => await
|
|
6653
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawDepositTxHash, {
|
|
6654
|
+
primary: provider
|
|
6655
|
+
})
|
|
6544
6656
|
};
|
|
6545
6657
|
} else {
|
|
6546
6658
|
logger.log("\u{1F504} Executing Native COTI Deposit...");
|
|
@@ -6697,7 +6809,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6697
6809
|
logger.log("Withdraw tx sent", { txHash: shortHash(rawWithdrawTxHash) });
|
|
6698
6810
|
tx = {
|
|
6699
6811
|
hash: rawWithdrawTxHash,
|
|
6700
|
-
wait: async () => await
|
|
6812
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawWithdrawTxHash, {
|
|
6813
|
+
primary: provider
|
|
6814
|
+
})
|
|
6701
6815
|
};
|
|
6702
6816
|
} catch (e) {
|
|
6703
6817
|
setIsBridgingLoading(false);
|
|
@@ -6713,12 +6827,13 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6713
6827
|
title: "Processing Transaction",
|
|
6714
6828
|
message: "Transaction sent to network. Waiting for confirmation..."
|
|
6715
6829
|
});
|
|
6716
|
-
const receipt = await tx.
|
|
6830
|
+
const receipt = await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6831
|
+
primary: provider
|
|
6832
|
+
});
|
|
6717
6833
|
logger.log("Transaction confirmed", {
|
|
6718
6834
|
status: receipt.status,
|
|
6719
6835
|
blockNumber: receipt.blockNumber,
|
|
6720
|
-
gasUsed: receipt.gasUsed?.toString()
|
|
6721
|
-
gasLimit: receipt.gasLimit?.toString() ?? "n/a"
|
|
6836
|
+
gasUsed: receipt.gasUsed?.toString()
|
|
6722
6837
|
});
|
|
6723
6838
|
if (receipt.status !== 1) {
|
|
6724
6839
|
const gasUsed = receipt.gasUsed ? Number(receipt.gasUsed) : 0;
|
|
@@ -6733,11 +6848,12 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6733
6848
|
const replayProvider = new ethers23.JsonRpcProvider(
|
|
6734
6849
|
getRpcUrlForChain(Number(network2.chainId))
|
|
6735
6850
|
);
|
|
6851
|
+
const broadcastTx = await replayProvider.getTransaction(txHashStr);
|
|
6736
6852
|
await replayProvider.call({
|
|
6737
|
-
to: receipt.to,
|
|
6738
|
-
from: receipt.from,
|
|
6739
|
-
data:
|
|
6740
|
-
value:
|
|
6853
|
+
to: broadcastTx?.to ?? receipt.to,
|
|
6854
|
+
from: broadcastTx?.from ?? receipt.from,
|
|
6855
|
+
data: broadcastTx?.data,
|
|
6856
|
+
value: broadcastTx?.value
|
|
6741
6857
|
});
|
|
6742
6858
|
} catch (replayErr) {
|
|
6743
6859
|
const errorName = replayErr.errorName || replayErr.revert?.name;
|
|
@@ -7663,7 +7779,7 @@ async function fetchEncryptedBackupProbe(address, chainId) {
|
|
|
7663
7779
|
return null;
|
|
7664
7780
|
}
|
|
7665
7781
|
}
|
|
7666
|
-
var
|
|
7782
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7667
7783
|
function resolveAesKeyChainId(currentChainId, overrideChainId) {
|
|
7668
7784
|
const configuredChainId = getPluginConfig().aesKeyChainId;
|
|
7669
7785
|
assertAesKeyChainId(configuredChainId);
|
|
@@ -7683,7 +7799,7 @@ async function probeSnapKeyWithRetry(hasAesKeyInSnap, address, retries, confirmS
|
|
|
7683
7799
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
7684
7800
|
const result = await hasAesKeyInSnap(address);
|
|
7685
7801
|
if (result !== null) return result;
|
|
7686
|
-
if (attempt < retries) await
|
|
7802
|
+
if (attempt < retries) await sleep2(250);
|
|
7687
7803
|
}
|
|
7688
7804
|
if (confirmSnapInstalled && !await confirmSnapInstalled()) {
|
|
7689
7805
|
return false;
|
|
@@ -7976,7 +8092,7 @@ function toBigInt(value, fallback2) {
|
|
|
7976
8092
|
if (value === void 0) return fallback2;
|
|
7977
8093
|
return getBigInt(value);
|
|
7978
8094
|
}
|
|
7979
|
-
var
|
|
8095
|
+
var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7980
8096
|
function useAesKeyProvider(walletTypeInfo) {
|
|
7981
8097
|
const [isOnboarding, setIsOnboarding] = useState11(false);
|
|
7982
8098
|
const [onboardingError, setOnboardingError] = useState11(null);
|
|
@@ -8221,7 +8337,7 @@ function useAesKeyProvider(walletTypeInfo) {
|
|
|
8221
8337
|
const timeoutMs = config.onboardingGrantTimeoutMs ?? 6e4;
|
|
8222
8338
|
const startedAt = Date.now();
|
|
8223
8339
|
while (nativeBalance < requiredBalanceWei && Date.now() - startedAt < timeoutMs) {
|
|
8224
|
-
await
|
|
8340
|
+
await sleep3(pollIntervalMs);
|
|
8225
8341
|
nativeBalance = await provider.getBalance(address);
|
|
8226
8342
|
logger.log("[AesKeyProvider] Native COTI balance while waiting for grant", {
|
|
8227
8343
|
address,
|