@coti-io/coti-wallet-plugin 0.2.4 → 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 -189
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +304 -182
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -898,6 +898,190 @@ var init_podSdkConfig = __esm({
|
|
|
898
898
|
}
|
|
899
899
|
});
|
|
900
900
|
|
|
901
|
+
// src/lib/rpcProvider.ts
|
|
902
|
+
async function waitForTransactionResilient(chainId, txHash, options = {}) {
|
|
903
|
+
const {
|
|
904
|
+
confirmations = 1,
|
|
905
|
+
timeoutMs = 18e4,
|
|
906
|
+
pollIntervalMs = 2e3,
|
|
907
|
+
primary,
|
|
908
|
+
createProvider = createJsonRpcProvider
|
|
909
|
+
} = options;
|
|
910
|
+
if (!txHash) {
|
|
911
|
+
throw new Error("waitForTransactionResilient: missing transaction hash");
|
|
912
|
+
}
|
|
913
|
+
const deadline = Date.now() + timeoutMs;
|
|
914
|
+
let lastError;
|
|
915
|
+
if (primary) {
|
|
916
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
917
|
+
const primaryTimeout = Math.min(12e3, remaining);
|
|
918
|
+
if (primaryTimeout > 0) {
|
|
919
|
+
try {
|
|
920
|
+
const receipt = await primary.waitForTransaction(txHash, confirmations, primaryTimeout);
|
|
921
|
+
if (receipt) return receipt;
|
|
922
|
+
} catch (error) {
|
|
923
|
+
lastError = error;
|
|
924
|
+
if (isTransactionRevertError(error)) throw error;
|
|
925
|
+
if (!isTransientRpcError(error) && !isWaitTimeoutError(error)) throw error;
|
|
926
|
+
logger.warn(
|
|
927
|
+
`[rpc] primary waitForTransaction failed for ${txHash} on chain ${chainId}; polling via fallback RPCs`
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
let delay = pollIntervalMs;
|
|
933
|
+
while (Date.now() < deadline) {
|
|
934
|
+
try {
|
|
935
|
+
const receipt = await getTransactionReceiptAcrossRpcs(chainId, txHash, createProvider);
|
|
936
|
+
if (receipt) {
|
|
937
|
+
if (confirmations <= 1) return receipt;
|
|
938
|
+
const blockNumber = await withRpcFallback(chainId, (provider) => provider.getBlockNumber());
|
|
939
|
+
if (receipt.blockNumber + (confirmations - 1) <= blockNumber) {
|
|
940
|
+
return receipt;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
} catch (error) {
|
|
944
|
+
lastError = error;
|
|
945
|
+
if (!isTransientRpcError(error)) throw error;
|
|
946
|
+
logger.warn(
|
|
947
|
+
`[rpc] receipt poll failed for ${txHash} on chain ${chainId}; retrying after backoff`
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
const remaining = deadline - Date.now();
|
|
951
|
+
if (remaining <= 0) break;
|
|
952
|
+
await sleep(Math.min(delay, remaining));
|
|
953
|
+
delay = Math.min(Math.floor(delay * 1.5), 8e3);
|
|
954
|
+
}
|
|
955
|
+
throw lastError instanceof Error ? lastError : new Error(
|
|
956
|
+
`Timed out waiting for transaction ${txHash} on chain ${chainId} after ${timeoutMs}ms`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
async function getTransactionReceiptAcrossRpcs(chainId, txHash, createProvider = createJsonRpcProvider) {
|
|
960
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
961
|
+
let lastError;
|
|
962
|
+
let sawNotFound = false;
|
|
963
|
+
for (const url of urls) {
|
|
964
|
+
const provider = createProvider(url, chainId);
|
|
965
|
+
try {
|
|
966
|
+
const receipt = await provider.getTransactionReceipt(txHash);
|
|
967
|
+
if (receipt) return receipt;
|
|
968
|
+
sawNotFound = true;
|
|
969
|
+
} catch (error) {
|
|
970
|
+
lastError = error;
|
|
971
|
+
if (!isTransientRpcError(error)) throw error;
|
|
972
|
+
logger.warn(`[rpc] ${url} getTransactionReceipt failed for chain ${chainId}, trying fallback`);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
if (sawNotFound) return null;
|
|
976
|
+
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed reading receipt for ${txHash} on chain ${chainId}`);
|
|
977
|
+
}
|
|
978
|
+
var import_ethers5, resolveRpcUrlsForChain, collectErrorText, readNestedRpcCode, readNestedHttpStatus, isTransientRpcError, createJsonRpcProvider, isWaitTimeoutError, isTransactionRevertError, sleep, createResilientJsonRpcProvider, withRpcFallback;
|
|
979
|
+
var init_rpcProvider = __esm({
|
|
980
|
+
"src/lib/rpcProvider.ts"() {
|
|
981
|
+
"use strict";
|
|
982
|
+
import_ethers5 = require("ethers");
|
|
983
|
+
init_plugin();
|
|
984
|
+
init_coti();
|
|
985
|
+
init_rpcUrls();
|
|
986
|
+
init_sepolia();
|
|
987
|
+
init_logger();
|
|
988
|
+
resolveRpcUrlsForChain = (chainId) => {
|
|
989
|
+
const base = getRpcUrlsForChain(chainId);
|
|
990
|
+
const numericId = chainId == null ? void 0 : Number(chainId);
|
|
991
|
+
if (numericId == null || !Number.isFinite(numericId)) return base;
|
|
992
|
+
const plugin = getPluginConfig();
|
|
993
|
+
let override;
|
|
994
|
+
if (numericId === SEPOLIA_CHAIN_ID && plugin.sepoliaRpcUrl) {
|
|
995
|
+
override = plugin.sepoliaRpcUrl;
|
|
996
|
+
} else if (numericId === COTI_TESTNET_CHAIN_ID && plugin.cotiTestnetRpcUrl) {
|
|
997
|
+
override = plugin.cotiTestnetRpcUrl;
|
|
998
|
+
}
|
|
999
|
+
if (!override) return base;
|
|
1000
|
+
return [.../* @__PURE__ */ new Set([override, ...base])];
|
|
1001
|
+
};
|
|
1002
|
+
collectErrorText = (error) => {
|
|
1003
|
+
if (!error) return "";
|
|
1004
|
+
if (typeof error === "string") return error;
|
|
1005
|
+
if (error instanceof Error) return error.message;
|
|
1006
|
+
try {
|
|
1007
|
+
return JSON.stringify(error);
|
|
1008
|
+
} catch {
|
|
1009
|
+
return String(error);
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
readNestedRpcCode = (error) => {
|
|
1013
|
+
const e = error;
|
|
1014
|
+
return e.code ?? e.error?.code ?? e.info?.error?.code;
|
|
1015
|
+
};
|
|
1016
|
+
readNestedHttpStatus = (error) => {
|
|
1017
|
+
const e = error;
|
|
1018
|
+
return e.data?.httpStatus ?? e.error?.data?.httpStatus ?? e.info?.responseStatus;
|
|
1019
|
+
};
|
|
1020
|
+
isTransientRpcError = (error) => {
|
|
1021
|
+
const text = collectErrorText(error);
|
|
1022
|
+
const lower = text.toLowerCase();
|
|
1023
|
+
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")) {
|
|
1024
|
+
return true;
|
|
1025
|
+
}
|
|
1026
|
+
if (error && typeof error === "object") {
|
|
1027
|
+
const code = readNestedRpcCode(error);
|
|
1028
|
+
if (code === "SERVER_ERROR" || code === "TIMEOUT" || code === "NETWORK_ERROR" || code === -32005 || code === "-32005") {
|
|
1029
|
+
return true;
|
|
1030
|
+
}
|
|
1031
|
+
const httpStatus = readNestedHttpStatus(error);
|
|
1032
|
+
if (httpStatus === 429 || httpStatus === "429") {
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return false;
|
|
1037
|
+
};
|
|
1038
|
+
createJsonRpcProvider = (url, chainId) => new import_ethers5.ethers.JsonRpcProvider(url, chainId);
|
|
1039
|
+
isWaitTimeoutError = (error) => {
|
|
1040
|
+
const text = collectErrorText(error).toLowerCase();
|
|
1041
|
+
return text.includes("timeout") || text.includes("timed out") || text.includes("waitfortx");
|
|
1042
|
+
};
|
|
1043
|
+
isTransactionRevertError = (error) => {
|
|
1044
|
+
if (!error || typeof error !== "object") return false;
|
|
1045
|
+
const code = error.code;
|
|
1046
|
+
return code === "CALL_EXCEPTION" || code === "TRANSACTION_REPLACED";
|
|
1047
|
+
};
|
|
1048
|
+
sleep = (ms) => new Promise((resolve) => {
|
|
1049
|
+
setTimeout(resolve, ms);
|
|
1050
|
+
});
|
|
1051
|
+
createResilientJsonRpcProvider = async (chainId) => {
|
|
1052
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
1053
|
+
let lastError;
|
|
1054
|
+
for (const url of urls) {
|
|
1055
|
+
const provider = createJsonRpcProvider(url, chainId);
|
|
1056
|
+
try {
|
|
1057
|
+
await provider.getNetwork();
|
|
1058
|
+
return provider;
|
|
1059
|
+
} catch (error) {
|
|
1060
|
+
lastError = error;
|
|
1061
|
+
if (!isTransientRpcError(error)) throw error;
|
|
1062
|
+
logger.warn(`[rpc] ${url} unavailable for chain ${chainId}, trying fallback`);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
throw lastError instanceof Error ? lastError : new Error(`No RPC available for chain ${chainId}`);
|
|
1066
|
+
};
|
|
1067
|
+
withRpcFallback = async (chainId, fn) => {
|
|
1068
|
+
const urls = resolveRpcUrlsForChain(chainId);
|
|
1069
|
+
let lastError;
|
|
1070
|
+
for (const url of urls) {
|
|
1071
|
+
const provider = createJsonRpcProvider(url, chainId);
|
|
1072
|
+
try {
|
|
1073
|
+
return await fn(provider);
|
|
1074
|
+
} catch (error) {
|
|
1075
|
+
lastError = error;
|
|
1076
|
+
if (!isTransientRpcError(error)) throw error;
|
|
1077
|
+
logger.warn(`[rpc] ${url} request failed for chain ${chainId}, trying fallback`);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed for chain ${chainId}`);
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
|
|
901
1085
|
// src/chains/portal/podPTokenBlockingDiagnostics.ts
|
|
902
1086
|
async function diagnoseBlockingPodRequest(params) {
|
|
903
1087
|
const {
|
|
@@ -967,11 +1151,11 @@ async function diagnoseBlockingPodRequest(params) {
|
|
|
967
1151
|
eventScan
|
|
968
1152
|
};
|
|
969
1153
|
}
|
|
970
|
-
var
|
|
1154
|
+
var import_ethers6, import_pod_sdk2, TERMINAL_POD_REQUEST_STATUSES, pTokenIface, portalIface, formatBlockingPodLogSummary, chainIdToExplorerSlug2, withExplorerUrl, tokenMatchesContext, summarizeInFlightLocalPodRequests, summarizeLocalCandidates, isPodRequestStillInFlight, enrichWithPodTracking, POD_EVENT_LOOKBACK_STEPS, fetchLogsWithLookback, paddedAddressTopic, fetchRecentPTokenEvents, fetchRecentPortalEvents, dedupeCandidates, pickBlockingRequest;
|
|
971
1155
|
var init_podPTokenBlockingDiagnostics = __esm({
|
|
972
1156
|
"src/chains/portal/podPTokenBlockingDiagnostics.ts"() {
|
|
973
1157
|
"use strict";
|
|
974
|
-
|
|
1158
|
+
import_ethers6 = require("ethers");
|
|
975
1159
|
import_pod_sdk2 = require("@coti-io/pod-sdk");
|
|
976
1160
|
init_pod();
|
|
977
1161
|
init_podPortalRequestsStorage();
|
|
@@ -982,8 +1166,8 @@ var init_podPTokenBlockingDiagnostics = __esm({
|
|
|
982
1166
|
"callback-errored",
|
|
983
1167
|
"burn-debt"
|
|
984
1168
|
]);
|
|
985
|
-
pTokenIface = new
|
|
986
|
-
portalIface = new
|
|
1169
|
+
pTokenIface = new import_ethers6.ethers.Interface(POD_PTOKEN_ABI);
|
|
1170
|
+
portalIface = new import_ethers6.ethers.Interface(PRIVACY_PORTAL_ABI);
|
|
987
1171
|
formatBlockingPodLogSummary = (blockingRequest, action) => {
|
|
988
1172
|
if (!blockingRequest?.requestId) {
|
|
989
1173
|
return `PoD ${action} blocked: wallet has on-chain pending=true but no requestId was resolved (check eventScan / candidateRequests in the log object below).`;
|
|
@@ -1112,7 +1296,7 @@ var init_podPTokenBlockingDiagnostics = __esm({
|
|
|
1112
1296
|
}
|
|
1113
1297
|
return { logs: [], lookbackBlocks: Number(lookbackSteps[lookbackSteps.length - 1]), errors };
|
|
1114
1298
|
};
|
|
1115
|
-
paddedAddressTopic = (address) =>
|
|
1299
|
+
paddedAddressTopic = (address) => import_ethers6.ethers.zeroPadValue(import_ethers6.ethers.getAddress(address), 32);
|
|
1116
1300
|
fetchRecentPTokenEvents = async (provider, pTokenAddress, account) => {
|
|
1117
1301
|
const accountTopic = paddedAddressTopic(account);
|
|
1118
1302
|
const errors = [];
|
|
@@ -1250,17 +1434,17 @@ var fees_exports = {};
|
|
|
1250
1434
|
__export(fees_exports, {
|
|
1251
1435
|
quotePodPortalTransactionFees: () => quotePodPortalTransactionFees
|
|
1252
1436
|
});
|
|
1253
|
-
var
|
|
1437
|
+
var import_ethers7, quotePodPortalTransactionFees;
|
|
1254
1438
|
var init_fees = __esm({
|
|
1255
1439
|
"src/chains/portal/fees.ts"() {
|
|
1256
1440
|
"use strict";
|
|
1257
|
-
|
|
1441
|
+
import_ethers7 = require("ethers");
|
|
1258
1442
|
init_chains();
|
|
1259
1443
|
init_logger();
|
|
1260
1444
|
init_podPortalFees();
|
|
1261
1445
|
quotePodPortalTransactionFees = async (params) => {
|
|
1262
1446
|
const dec = params.pubTok?.decimals ?? 18;
|
|
1263
|
-
const amountWei =
|
|
1447
|
+
const amountWei = import_ethers7.ethers.parseUnits(params.amount, dec);
|
|
1264
1448
|
const provider = "provider" in params.runner && params.runner.provider ? params.runner.provider : params.runner;
|
|
1265
1449
|
const gasPrice = params.gasPrice ?? await resolvePodTxGasPrice(provider);
|
|
1266
1450
|
const nativeSymbol = getChainConfig(params.chainId)?.walletNetwork.nativeCurrency.symbol ?? "ETH";
|
|
@@ -1333,11 +1517,11 @@ var init_fees = __esm({
|
|
|
1333
1517
|
});
|
|
1334
1518
|
|
|
1335
1519
|
// src/chains/portal/podPortalFees.ts
|
|
1336
|
-
var
|
|
1520
|
+
var import_ethers8, import_pod_sdk3, resolveFeeRunnerProvider, POD_GAS_PRICE_BUFFER_BPS, getPodGasPrice, resolvePodTxGasPrice, getSepoliaGasPrice, quotePortalFeeOnly, formatPortalFeeDisplay, formatPodFeeDisplay, resolvePodFeeEstimationConfig, resolvePodPortalMethod, buildPodMethodArgs, createPodContract, fallbackExecutionGasLimit, estimatePodExecutionGasWei, estimatePodFee, estimatePodPortalFees, buildPodPortalTxGasOverrides, sendPodPortalMethod;
|
|
1337
1521
|
var init_podPortalFees = __esm({
|
|
1338
1522
|
"src/chains/portal/podPortalFees.ts"() {
|
|
1339
1523
|
"use strict";
|
|
1340
|
-
|
|
1524
|
+
import_ethers8 = require("ethers");
|
|
1341
1525
|
import_pod_sdk3 = require("@coti-io/pod-sdk");
|
|
1342
1526
|
init_pod();
|
|
1343
1527
|
init_chains();
|
|
@@ -1370,7 +1554,7 @@ var init_podPortalFees = __esm({
|
|
|
1370
1554
|
quotePortalFeeOnly = async (runner, portalAddress, amount, direction, gasPrice) => {
|
|
1371
1555
|
const provider = resolveFeeRunnerProvider(runner);
|
|
1372
1556
|
const resolvedGasPrice = gasPrice ?? await resolvePodTxGasPrice(provider);
|
|
1373
|
-
const portal = new
|
|
1557
|
+
const portal = new import_ethers8.ethers.Contract(portalAddress, PRIVACY_PORTAL_ABI, runner);
|
|
1374
1558
|
if (direction === "to-private") {
|
|
1375
1559
|
const [portalFee2, usedDynamicPricing2] = await portal.estimateDepositFees(amount);
|
|
1376
1560
|
const quote2 = {
|
|
@@ -1402,8 +1586,8 @@ var init_podPortalFees = __esm({
|
|
|
1402
1586
|
});
|
|
1403
1587
|
return quote;
|
|
1404
1588
|
};
|
|
1405
|
-
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) =>
|
|
1406
|
-
formatPodFeeDisplay = (totalFee) =>
|
|
1589
|
+
formatPortalFeeDisplay = (portalFee, _usedDynamicPricing) => import_ethers8.ethers.formatEther(portalFee).replace(/\.?0+$/, "") || "0";
|
|
1590
|
+
formatPodFeeDisplay = (totalFee) => import_ethers8.ethers.formatEther(totalFee).replace(/\.?0+$/, "") || "0";
|
|
1407
1591
|
resolvePodFeeEstimationConfig = (chainId, direction, gasPrice) => {
|
|
1408
1592
|
const limits = getChainConfig(chainId)?.podFeeEstimation?.[direction === "to-private" ? "deposit" : "withdraw"];
|
|
1409
1593
|
if (!limits) {
|
|
@@ -1454,8 +1638,8 @@ var init_podPortalFees = __esm({
|
|
|
1454
1638
|
{ type: import_pod_sdk3.DataType.Uint256, value: "0", isCallBackFee: true },
|
|
1455
1639
|
{ type: import_pod_sdk3.DataType.Uint256, value: placeholderDeadline.toString(), isCallBackFee: false },
|
|
1456
1640
|
{ type: import_pod_sdk3.DataType.Uint8, value: "0", isCallBackFee: false },
|
|
1457
|
-
{ type: import_pod_sdk3.DataType.String, value:
|
|
1458
|
-
{ type: import_pod_sdk3.DataType.String, value:
|
|
1641
|
+
{ type: import_pod_sdk3.DataType.String, value: import_ethers8.ethers.ZeroHash, isCallBackFee: false },
|
|
1642
|
+
{ type: import_pod_sdk3.DataType.String, value: import_ethers8.ethers.ZeroHash, isCallBackFee: false }
|
|
1459
1643
|
];
|
|
1460
1644
|
}
|
|
1461
1645
|
return [
|
|
@@ -1483,8 +1667,8 @@ var init_podPortalFees = __esm({
|
|
|
1483
1667
|
const fallbackLimit = fallbackExecutionGasLimit(params.chainId, params.direction);
|
|
1484
1668
|
try {
|
|
1485
1669
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
1486
|
-
const rpcProvider = new
|
|
1487
|
-
const portal = new
|
|
1670
|
+
const rpcProvider = new import_ethers8.ethers.JsonRpcProvider(rpcUrl);
|
|
1671
|
+
const portal = new import_ethers8.ethers.Contract(params.portalAddress, PRIVACY_PORTAL_ABI, rpcProvider);
|
|
1488
1672
|
if (params.direction === "to-private") {
|
|
1489
1673
|
const method = resolvePodPortalMethod("to-private", params.isNativeDeposit);
|
|
1490
1674
|
const nativeAmount = params.isNativeDeposit ? params.amountWei : 0n;
|
|
@@ -1501,8 +1685,8 @@ var init_podPortalFees = __esm({
|
|
|
1501
1685
|
const permit = params.withdrawPermit;
|
|
1502
1686
|
const deadline = permit ? BigInt(permit.deadline) : BigInt(Math.floor(Date.now() / 1e3) + 60 * 30);
|
|
1503
1687
|
const v = permit?.v ?? 0;
|
|
1504
|
-
const r = permit?.r ??
|
|
1505
|
-
const s = permit?.s ??
|
|
1688
|
+
const r = permit?.r ?? import_ethers8.ethers.ZeroHash;
|
|
1689
|
+
const s = permit?.s ?? import_ethers8.ethers.ZeroHash;
|
|
1506
1690
|
const gasLimit = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1507
1691
|
params.wallet,
|
|
1508
1692
|
params.amountWei,
|
|
@@ -1605,7 +1789,7 @@ var init_podPortalFees = __esm({
|
|
|
1605
1789
|
async function signPodWithdrawPermit(params) {
|
|
1606
1790
|
const { signer, pTokenAddress, portalAddress, amountWei } = params;
|
|
1607
1791
|
const wallet = await signer.getAddress();
|
|
1608
|
-
const pToken = new
|
|
1792
|
+
const pToken = new import_ethers9.ethers.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1609
1793
|
const signingChainId = params.chainId ?? Number((await signer.provider.getNetwork()).chainId);
|
|
1610
1794
|
const resolvedTokenSymbol = params.tokenSymbol ?? await pToken.symbol().catch(() => void 0);
|
|
1611
1795
|
await assertPodPTokenReady(pToken, wallet, "withdraw", {
|
|
@@ -1675,9 +1859,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1675
1859
|
throw new Error("PoD portal is not configured for this token");
|
|
1676
1860
|
}
|
|
1677
1861
|
const wallet = await signer.getAddress();
|
|
1678
|
-
const amountWei =
|
|
1679
|
-
const pToken = new
|
|
1680
|
-
const portalIface2 = new
|
|
1862
|
+
const amountWei = import_ethers9.ethers.parseUnits(txAmount, decimals);
|
|
1863
|
+
const pToken = new import_ethers9.ethers.Contract(pTokenAddress, POD_PTOKEN_ABI, signer);
|
|
1864
|
+
const portalIface2 = new import_ethers9.ethers.Interface(PRIVACY_PORTAL_ABI);
|
|
1681
1865
|
const gasPrice = await resolvePodTxGasPrice(provider);
|
|
1682
1866
|
if (txDirection === "to-private") {
|
|
1683
1867
|
await assertPodPTokenReady(pToken, wallet, "deposit", {
|
|
@@ -1706,7 +1890,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1706
1890
|
});
|
|
1707
1891
|
let gasLimit2;
|
|
1708
1892
|
try {
|
|
1709
|
-
const portal = new
|
|
1893
|
+
const portal = new import_ethers9.ethers.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1710
1894
|
const nativeAmount = isNativeDeposit ? amountWei : 0n;
|
|
1711
1895
|
const estimated = await portal[method2].estimateGas(
|
|
1712
1896
|
wallet,
|
|
@@ -1738,7 +1922,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1738
1922
|
fee: podFee2
|
|
1739
1923
|
});
|
|
1740
1924
|
onProgress?.("transfer-start", tx2.hash);
|
|
1741
|
-
const receipt2 = await tx2.
|
|
1925
|
+
const receipt2 = await waitForTransactionResilient(chainId, tx2.hash, {
|
|
1926
|
+
primary: provider ?? signer.provider ?? void 0
|
|
1927
|
+
});
|
|
1742
1928
|
if (!receipt2 || receipt2.status !== 1) {
|
|
1743
1929
|
const failed = new Error("PoD deposit transaction failed");
|
|
1744
1930
|
failed.txHash = tx2.hash;
|
|
@@ -1795,7 +1981,7 @@ async function executePodPortalTransaction(params) {
|
|
|
1795
1981
|
});
|
|
1796
1982
|
let gasLimit;
|
|
1797
1983
|
try {
|
|
1798
|
-
const portal = new
|
|
1984
|
+
const portal = new import_ethers9.ethers.Contract(portalAddress, PRIVACY_PORTAL_ABI, signer);
|
|
1799
1985
|
const estimated = await portal.requestWithdrawWithPermit.estimateGas(
|
|
1800
1986
|
wallet,
|
|
1801
1987
|
amountWei,
|
|
@@ -1829,7 +2015,9 @@ async function executePodPortalTransaction(params) {
|
|
|
1829
2015
|
fee: podFee
|
|
1830
2016
|
});
|
|
1831
2017
|
onProgress?.("transfer-start", tx.hash);
|
|
1832
|
-
const receipt = await tx.
|
|
2018
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
2019
|
+
primary: provider ?? signer.provider ?? void 0
|
|
2020
|
+
});
|
|
1833
2021
|
if (!receipt || receipt.status !== 1) {
|
|
1834
2022
|
const failed = new Error("Sepolia withdraw transaction failed");
|
|
1835
2023
|
failed.txHash = tx.hash;
|
|
@@ -1857,20 +2045,21 @@ async function executePodPortalTransaction(params) {
|
|
|
1857
2045
|
}
|
|
1858
2046
|
};
|
|
1859
2047
|
}
|
|
1860
|
-
var
|
|
2048
|
+
var import_ethers9, getErrorMessage, pTokenErrorIface, extractRevertData, parseTransferAlreadyPendingRevert, pendingProbeFromRevert, findParsedEvent, splitSignature, POD_PTOKEN_FLAT_STATUS_ABI, POD_PTOKEN_PLAIN_STATUS_ABI, serializePodBalanceStatusResponse, readContractResultField, buildBalanceWithStateRaw, buildBalanceOfWithStatusRaw, formatBalanceStatusRawForLog, logBalanceStatusRawResponse, getContractProvider, logPodPTokenReadinessProbe, logPodPTokenReadinessBlocked, resolveBlockingRequestId, readPodPTokenPendingState, assertPodPTokenReady;
|
|
1861
2049
|
var init_executePodPortalTransaction = __esm({
|
|
1862
2050
|
"src/chains/portal/executePodPortalTransaction.ts"() {
|
|
1863
2051
|
"use strict";
|
|
1864
|
-
|
|
2052
|
+
import_ethers9 = require("ethers");
|
|
1865
2053
|
init_pod();
|
|
1866
2054
|
init_logger();
|
|
2055
|
+
init_rpcProvider();
|
|
1867
2056
|
init_podPTokenBlockingDiagnostics();
|
|
1868
2057
|
init_podPortalFees();
|
|
1869
2058
|
init_podSdkConfig();
|
|
1870
2059
|
init_podPortalFees();
|
|
1871
2060
|
init_fees();
|
|
1872
2061
|
getErrorMessage = (error) => error && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : "";
|
|
1873
|
-
pTokenErrorIface = new
|
|
2062
|
+
pTokenErrorIface = new import_ethers9.ethers.Interface(POD_PTOKEN_ABI);
|
|
1874
2063
|
extractRevertData = (error) => {
|
|
1875
2064
|
if (!error || typeof error !== "object") return null;
|
|
1876
2065
|
const err = error;
|
|
@@ -1926,7 +2115,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
1926
2115
|
return null;
|
|
1927
2116
|
};
|
|
1928
2117
|
splitSignature = (signature) => {
|
|
1929
|
-
const parsed =
|
|
2118
|
+
const parsed = import_ethers9.ethers.Signature.from(signature);
|
|
1930
2119
|
return { v: parsed.v, r: parsed.r, s: parsed.s };
|
|
1931
2120
|
};
|
|
1932
2121
|
POD_PTOKEN_FLAT_STATUS_ABI = [
|
|
@@ -2073,7 +2262,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2073
2262
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2074
2263
|
probeErrors.push(`balanceWithState: ${getErrorMessage(error) || String(error)}`);
|
|
2075
2264
|
}
|
|
2076
|
-
const flatStatusToken = new
|
|
2265
|
+
const flatStatusToken = new import_ethers9.ethers.Contract(
|
|
2077
2266
|
pTokenAddress,
|
|
2078
2267
|
POD_PTOKEN_FLAT_STATUS_ABI,
|
|
2079
2268
|
pToken.runner
|
|
@@ -2108,7 +2297,7 @@ var init_executePodPortalTransaction = __esm({
|
|
|
2108
2297
|
if (pendingFromRevert) return pendingFromRevert;
|
|
2109
2298
|
probeErrors.push(`balanceOfWithStatus: ${getErrorMessage(error) || String(error)}`);
|
|
2110
2299
|
}
|
|
2111
|
-
const plainToken = new
|
|
2300
|
+
const plainToken = new import_ethers9.ethers.Contract(
|
|
2112
2301
|
pTokenAddress,
|
|
2113
2302
|
POD_PTOKEN_PLAIN_STATUS_ABI,
|
|
2114
2303
|
pToken.runner
|
|
@@ -2315,11 +2504,11 @@ var init_ethereum = __esm({
|
|
|
2315
2504
|
});
|
|
2316
2505
|
|
|
2317
2506
|
// src/chains/portal/podTransferFees.ts
|
|
2318
|
-
var
|
|
2507
|
+
var import_ethers10, import_pod_sdk4, POD_TRANSFER_METHOD, POD_TRANSFER_FORWARD_DATA_SIZE, POD_TRANSFER_L1_EXECUTION_GAS_FALLBACK, createPodPTokenContract, buildPodTransferMethodArgs, resolvePodTransferFeeEstimationConfig, estimatePodTransferFee, fallbackTransferGasLimit, estimatePodTransferExecutionGasWei, resolveNativeFeeSymbol, quotePodTransferFees, sendPodTransferMethod;
|
|
2319
2508
|
var init_podTransferFees = __esm({
|
|
2320
2509
|
"src/chains/portal/podTransferFees.ts"() {
|
|
2321
2510
|
"use strict";
|
|
2322
|
-
|
|
2511
|
+
import_ethers10 = require("ethers");
|
|
2323
2512
|
import_pod_sdk4 = require("@coti-io/pod-sdk");
|
|
2324
2513
|
init_pod();
|
|
2325
2514
|
init_chains();
|
|
@@ -2441,8 +2630,8 @@ var init_podTransferFees = __esm({
|
|
|
2441
2630
|
if (!overrides.gasLimit) {
|
|
2442
2631
|
try {
|
|
2443
2632
|
const rpcUrl = getRpcUrlForChain(params.chainId);
|
|
2444
|
-
const rpcProvider = new
|
|
2445
|
-
const pToken = new
|
|
2633
|
+
const rpcProvider = new import_ethers10.ethers.JsonRpcProvider(rpcUrl);
|
|
2634
|
+
const pToken = new import_ethers10.ethers.Contract(params.pTokenAddress, POD_PTOKEN_ABI, rpcProvider);
|
|
2446
2635
|
const estimated = await pToken.getFunction(POD_TRANSFER_METHOD).estimateGas(...vals, {
|
|
2447
2636
|
from: userAddress,
|
|
2448
2637
|
value: fee.totalFee,
|
|
@@ -2546,10 +2735,10 @@ function resolvePrivateTokenTransferTarget(chainId, symbol) {
|
|
|
2546
2735
|
};
|
|
2547
2736
|
}
|
|
2548
2737
|
function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2549
|
-
if (!
|
|
2738
|
+
if (!import_ethers11.ethers.isAddress(tokenAddress)) {
|
|
2550
2739
|
throw new Error("Invalid token contract address");
|
|
2551
2740
|
}
|
|
2552
|
-
if (!
|
|
2741
|
+
if (!import_ethers11.ethers.isAddress(recipient)) {
|
|
2553
2742
|
throw new Error("Invalid recipient address");
|
|
2554
2743
|
}
|
|
2555
2744
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2562,7 +2751,7 @@ function validatePrivateTransferInputs(tokenAddress, recipient, amount, walletAd
|
|
|
2562
2751
|
function parseTransferAmountWei(amount, decimals) {
|
|
2563
2752
|
let amountWei;
|
|
2564
2753
|
try {
|
|
2565
|
-
amountWei =
|
|
2754
|
+
amountWei = import_ethers11.ethers.parseUnits(amount, decimals);
|
|
2566
2755
|
} catch {
|
|
2567
2756
|
throw new Error("Invalid amount for token decimals");
|
|
2568
2757
|
}
|
|
@@ -2598,7 +2787,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2598
2787
|
recipient: shortHash(recipient),
|
|
2599
2788
|
amount
|
|
2600
2789
|
});
|
|
2601
|
-
const browserProvider = new
|
|
2790
|
+
const browserProvider = new import_ethers11.ethers.BrowserProvider(eip1193);
|
|
2791
|
+
const network = await browserProvider.getNetwork();
|
|
2792
|
+
const chainId = Number(network.chainId);
|
|
2602
2793
|
const rawTxHash = await eip1193.request({
|
|
2603
2794
|
method: "eth_sendTransaction",
|
|
2604
2795
|
params: [
|
|
@@ -2611,7 +2802,9 @@ async function submitPrivateTokenTransferTx(params) {
|
|
|
2611
2802
|
]
|
|
2612
2803
|
});
|
|
2613
2804
|
logger.log("Waiting for private transfer tx", { txHash: shortHash(rawTxHash) });
|
|
2614
|
-
const receipt = await
|
|
2805
|
+
const receipt = await waitForTransactionResilient(chainId, rawTxHash, {
|
|
2806
|
+
primary: browserProvider
|
|
2807
|
+
});
|
|
2615
2808
|
if (!receipt || receipt.status !== 1) {
|
|
2616
2809
|
throw new Error("Private token transfer failed");
|
|
2617
2810
|
}
|
|
@@ -2649,10 +2842,10 @@ async function sendPrivateTokenTransfer(params) {
|
|
|
2649
2842
|
if (!eip1193) {
|
|
2650
2843
|
throw new Error("No wallet found");
|
|
2651
2844
|
}
|
|
2652
|
-
const browserProvider = new
|
|
2845
|
+
const browserProvider = new import_ethers11.ethers.BrowserProvider(eip1193);
|
|
2653
2846
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2654
2847
|
const amountWei = parseTransferAmountWei(amount, target.decimals);
|
|
2655
|
-
const transferSig =
|
|
2848
|
+
const transferSig = import_ethers11.ethers.id(PRIVATE_ERC20_TRANSFER_256_SIG).slice(0, 10);
|
|
2656
2849
|
let aesKey = sessionAesKey ? normalizeAesKeyHex(sessionAesKey) : null;
|
|
2657
2850
|
if (!aesKey && hasSnap && getAESKeyFromSnap) {
|
|
2658
2851
|
const snapKey = await getAESKeyFromSnap(walletAddress);
|
|
@@ -2680,14 +2873,15 @@ async function sendPrivateTokenTransfer(params) {
|
|
|
2680
2873
|
provider: eip1193
|
|
2681
2874
|
});
|
|
2682
2875
|
}
|
|
2683
|
-
var
|
|
2876
|
+
var import_ethers11, PRIVATE_ERC20_TRANSFER_256_SIG, GAS_ESTIMATE_BUFFER_PERCENT, CONFIDENTIAL_TRANSFER_GAS_LIMIT, TRANSFER_INTERFACE;
|
|
2684
2877
|
var init_executePrivateTokenTransfer = __esm({
|
|
2685
2878
|
"src/hooks/privacyBridge/executePrivateTokenTransfer.ts"() {
|
|
2686
2879
|
"use strict";
|
|
2687
|
-
|
|
2880
|
+
import_ethers11 = require("ethers");
|
|
2688
2881
|
init_aesKey();
|
|
2689
2882
|
init_ethereum();
|
|
2690
2883
|
init_logger();
|
|
2884
|
+
init_rpcProvider();
|
|
2691
2885
|
init_config();
|
|
2692
2886
|
init_chains();
|
|
2693
2887
|
init_chains();
|
|
@@ -2696,7 +2890,7 @@ var init_executePrivateTokenTransfer = __esm({
|
|
|
2696
2890
|
PRIVATE_ERC20_TRANSFER_256_SIG = "transfer(address,((uint256,uint256),bytes))";
|
|
2697
2891
|
GAS_ESTIMATE_BUFFER_PERCENT = 105n;
|
|
2698
2892
|
CONFIDENTIAL_TRANSFER_GAS_LIMIT = 2000000n;
|
|
2699
|
-
TRANSFER_INTERFACE = new
|
|
2893
|
+
TRANSFER_INTERFACE = new import_ethers11.ethers.Interface([
|
|
2700
2894
|
"function transfer(address to, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (uint256)"
|
|
2701
2895
|
]);
|
|
2702
2896
|
}
|
|
@@ -2711,10 +2905,10 @@ __export(executePodPrivateTokenTransfer_exports, {
|
|
|
2711
2905
|
quotePodTransferFees: () => quotePodTransferFees
|
|
2712
2906
|
});
|
|
2713
2907
|
function validatePodTransferInputs(tokenAddress, recipient, amount, walletAddress) {
|
|
2714
|
-
if (!
|
|
2908
|
+
if (!import_ethers12.ethers.isAddress(tokenAddress)) {
|
|
2715
2909
|
throw new Error("Invalid token contract address");
|
|
2716
2910
|
}
|
|
2717
|
-
if (!
|
|
2911
|
+
if (!import_ethers12.ethers.isAddress(recipient)) {
|
|
2718
2912
|
throw new Error("Invalid recipient address");
|
|
2719
2913
|
}
|
|
2720
2914
|
if (recipient.toLowerCase() === walletAddress.toLowerCase()) {
|
|
@@ -2739,13 +2933,13 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2739
2933
|
if (!eip1193) {
|
|
2740
2934
|
throw new Error("No wallet found");
|
|
2741
2935
|
}
|
|
2742
|
-
const browserProvider = new
|
|
2936
|
+
const browserProvider = new import_ethers12.ethers.BrowserProvider(eip1193);
|
|
2743
2937
|
const signer = await browserProvider.getSigner(walletAddress);
|
|
2744
|
-
const amountWei =
|
|
2938
|
+
const amountWei = import_ethers12.ethers.parseUnits(amount, target.decimals);
|
|
2745
2939
|
if (amountWei <= 0n) {
|
|
2746
2940
|
throw new Error("Amount must be greater than zero");
|
|
2747
2941
|
}
|
|
2748
|
-
const pToken = new
|
|
2942
|
+
const pToken = new import_ethers12.ethers.Contract(target.tokenAddress, POD_PTOKEN_ABI, signer);
|
|
2749
2943
|
await assertPodPTokenReady(pToken, walletAddress, "transfer", {
|
|
2750
2944
|
chainId,
|
|
2751
2945
|
tokenSymbol: symbol,
|
|
@@ -2777,13 +2971,15 @@ async function executePodPrivateTokenTransfer(params) {
|
|
|
2777
2971
|
gasPrice,
|
|
2778
2972
|
fee: podFee
|
|
2779
2973
|
});
|
|
2780
|
-
const receipt = await tx.
|
|
2974
|
+
const receipt = await waitForTransactionResilient(chainId, tx.hash, {
|
|
2975
|
+
primary: browserProvider
|
|
2976
|
+
});
|
|
2781
2977
|
if (!receipt || receipt.status !== 1) {
|
|
2782
2978
|
const failed = new Error("PoD private token transfer failed");
|
|
2783
2979
|
failed.txHash = tx.hash;
|
|
2784
2980
|
throw failed;
|
|
2785
2981
|
}
|
|
2786
|
-
const event = findParsedEvent2(receipt, new
|
|
2982
|
+
const event = findParsedEvent2(receipt, new import_ethers12.ethers.Interface(POD_PTOKEN_ABI), "TransferRequestSubmitted");
|
|
2787
2983
|
const requestId = event?.args?.requestId;
|
|
2788
2984
|
return {
|
|
2789
2985
|
txHash: tx.hash,
|
|
@@ -2813,10 +3009,10 @@ async function quotePodPrivateTokenTransferFees(params) {
|
|
|
2813
3009
|
if (!eip1193) {
|
|
2814
3010
|
throw new Error("No wallet found");
|
|
2815
3011
|
}
|
|
2816
|
-
const browserProvider = new
|
|
3012
|
+
const browserProvider = new import_ethers12.ethers.BrowserProvider(eip1193);
|
|
2817
3013
|
const signer = await browserProvider.getSigner(params.walletAddress);
|
|
2818
|
-
const amountWei =
|
|
2819
|
-
const recipient =
|
|
3014
|
+
const amountWei = import_ethers12.ethers.parseUnits(params.amount, target.decimals);
|
|
3015
|
+
const recipient = import_ethers12.ethers.isAddress(params.recipient) && params.recipient !== import_ethers12.ethers.ZeroAddress ? params.recipient : params.walletAddress;
|
|
2820
3016
|
return quotePodTransferFees({
|
|
2821
3017
|
runner: signer,
|
|
2822
3018
|
chainId: params.chainId,
|
|
@@ -2825,15 +3021,16 @@ async function quotePodPrivateTokenTransferFees(params) {
|
|
|
2825
3021
|
amountWei
|
|
2826
3022
|
});
|
|
2827
3023
|
}
|
|
2828
|
-
var
|
|
3024
|
+
var import_ethers12, findParsedEvent2;
|
|
2829
3025
|
var init_executePodPrivateTokenTransfer = __esm({
|
|
2830
3026
|
"src/chains/portal/executePodPrivateTokenTransfer.ts"() {
|
|
2831
3027
|
"use strict";
|
|
2832
|
-
|
|
3028
|
+
import_ethers12 = require("ethers");
|
|
2833
3029
|
init_pod();
|
|
2834
3030
|
init_chains();
|
|
2835
3031
|
init_ethereum();
|
|
2836
3032
|
init_logger();
|
|
3033
|
+
init_rpcProvider();
|
|
2837
3034
|
init_executePodPortalTransaction();
|
|
2838
3035
|
init_podPortalFees();
|
|
2839
3036
|
init_podTransferFees();
|
|
@@ -3554,7 +3751,7 @@ init_executePodPrivateTokenTransfer();
|
|
|
3554
3751
|
// src/hooks/privacyBridge/usePodTransferFees.ts
|
|
3555
3752
|
var import_react = require("react");
|
|
3556
3753
|
var import_wagmi = require("wagmi");
|
|
3557
|
-
var
|
|
3754
|
+
var import_ethers13 = require("ethers");
|
|
3558
3755
|
init_chains();
|
|
3559
3756
|
init_executePodPrivateTokenTransfer();
|
|
3560
3757
|
init_logger();
|
|
@@ -3614,7 +3811,7 @@ var usePodTransferFees = ({
|
|
|
3614
3811
|
const quote = await quotePodPrivateTokenTransferFees({
|
|
3615
3812
|
chainId,
|
|
3616
3813
|
symbol,
|
|
3617
|
-
recipient: recipient &&
|
|
3814
|
+
recipient: recipient && import_ethers13.ethers.isAddress(recipient) ? recipient : walletAddress,
|
|
3618
3815
|
amount: currentAmount,
|
|
3619
3816
|
walletAddress,
|
|
3620
3817
|
provider: injected6
|
|
@@ -3660,7 +3857,7 @@ var usePodTransferFees = ({
|
|
|
3660
3857
|
};
|
|
3661
3858
|
|
|
3662
3859
|
// src/chains/podPriceOracle.ts
|
|
3663
|
-
var
|
|
3860
|
+
var import_ethers14 = require("ethers");
|
|
3664
3861
|
init_chains();
|
|
3665
3862
|
init_rpcUrls();
|
|
3666
3863
|
init_logger();
|
|
@@ -3688,17 +3885,17 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3688
3885
|
return null;
|
|
3689
3886
|
}
|
|
3690
3887
|
const rpcUrls = provider ? [] : getRpcUrlsForChain(chainId);
|
|
3691
|
-
const providers = provider ? [provider] : rpcUrls.map((url) => new
|
|
3888
|
+
const providers = provider ? [provider] : rpcUrls.map((url) => new import_ethers14.ethers.JsonRpcProvider(url));
|
|
3692
3889
|
let lastError;
|
|
3693
3890
|
for (const rpcProvider of providers) {
|
|
3694
3891
|
try {
|
|
3695
|
-
const oracle = new
|
|
3892
|
+
const oracle = new import_ethers14.ethers.Contract(oracleAddress, POD_PRICE_ORACLE_ABI, rpcProvider);
|
|
3696
3893
|
const raw = await oracle.getLivePrice(tokenAddress);
|
|
3697
3894
|
if (raw === 0n) {
|
|
3698
3895
|
logger.warn(`PoD price oracle has no live feed for ${symbol} on chain ${chainId}`);
|
|
3699
3896
|
return null;
|
|
3700
3897
|
}
|
|
3701
|
-
return Number(
|
|
3898
|
+
return Number(import_ethers14.ethers.formatEther(raw));
|
|
3702
3899
|
} catch (err) {
|
|
3703
3900
|
lastError = err;
|
|
3704
3901
|
}
|
|
@@ -3709,7 +3906,7 @@ async function fetchPodOracleTokenUsdPrice(symbol, chainId, provider) {
|
|
|
3709
3906
|
}
|
|
3710
3907
|
|
|
3711
3908
|
// src/chains/portal/podPortalAdminData.ts
|
|
3712
|
-
var
|
|
3909
|
+
var import_ethers15 = require("ethers");
|
|
3713
3910
|
init_pod();
|
|
3714
3911
|
init_chains();
|
|
3715
3912
|
init_rpcUrls();
|
|
@@ -3717,7 +3914,7 @@ init_logger();
|
|
|
3717
3914
|
var ERC20_BALANCE_ABI = ["function balanceOf(address) view returns (uint256)"];
|
|
3718
3915
|
var FEE_DIVISOR = 1000000n;
|
|
3719
3916
|
var POD_NO_MAX_FEE_SENTINEL = (1n << 128n) - 1n;
|
|
3720
|
-
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" :
|
|
3917
|
+
var formatFee = (value) => value >= POD_NO_MAX_FEE_SENTINEL ? "0" : import_ethers15.ethers.formatEther(value);
|
|
3721
3918
|
async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
3722
3919
|
const portalAddress = config.addresses[token.bridgeAddressKey];
|
|
3723
3920
|
const privateToken = config.tokens.find(
|
|
@@ -3744,12 +3941,12 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3744
3941
|
isLoading: false
|
|
3745
3942
|
};
|
|
3746
3943
|
try {
|
|
3747
|
-
const portal = new
|
|
3944
|
+
const portal = new import_ethers15.ethers.Contract(portalAddress, POD_PORTAL_ADMIN_ABI, provider);
|
|
3748
3945
|
const [depCfg, wdCfg, accFees, balance] = await Promise.all([
|
|
3749
3946
|
portal.getFeeConfig(true),
|
|
3750
3947
|
portal.getFeeConfig(false),
|
|
3751
3948
|
portal.accumulatedPortalFees().catch(() => 0n),
|
|
3752
|
-
token.isNative ? provider.getBalance(portalAddress) : token.addressKey && config.addresses[token.addressKey] ? new
|
|
3949
|
+
token.isNative ? provider.getBalance(portalAddress) : token.addressKey && config.addresses[token.addressKey] ? new import_ethers15.ethers.Contract(config.addresses[token.addressKey], ERC20_BALANCE_ABI, provider).balanceOf(portalAddress).catch(() => 0n) : Promise.resolve(0n)
|
|
3753
3950
|
]);
|
|
3754
3951
|
return {
|
|
3755
3952
|
...base,
|
|
@@ -3759,8 +3956,8 @@ async function fetchPortalRow(token, config, provider, nativeSymbol) {
|
|
|
3759
3956
|
withdrawFixedFee: formatFee(wdCfg[0]),
|
|
3760
3957
|
withdrawPercentageBps: wdCfg[1].toString(),
|
|
3761
3958
|
withdrawMaxFee: formatFee(wdCfg[2]),
|
|
3762
|
-
accumulatedCotiFees:
|
|
3763
|
-
bridgeBalance:
|
|
3959
|
+
accumulatedCotiFees: import_ethers15.ethers.formatEther(accFees),
|
|
3960
|
+
bridgeBalance: import_ethers15.ethers.formatUnits(balance, token.decimals),
|
|
3764
3961
|
error: null
|
|
3765
3962
|
};
|
|
3766
3963
|
} catch (err) {
|
|
@@ -3788,7 +3985,7 @@ async function fetchPodBridgeData(chainId) {
|
|
|
3788
3985
|
);
|
|
3789
3986
|
let lastError;
|
|
3790
3987
|
for (const rpcUrl of getRpcUrlsForChain(chainId)) {
|
|
3791
|
-
const provider = new
|
|
3988
|
+
const provider = new import_ethers15.ethers.JsonRpcProvider(rpcUrl);
|
|
3792
3989
|
try {
|
|
3793
3990
|
await provider.getBlockNumber();
|
|
3794
3991
|
return await Promise.all(
|
|
@@ -3807,7 +4004,7 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3807
4004
|
if (!config) return { fee: "\u2014", explanation: "Unsupported chain" };
|
|
3808
4005
|
const token = config.tokens.find((t) => t.symbol === tokenSymbol && !t.isPrivate);
|
|
3809
4006
|
if (!token) return { fee: "\u2014", explanation: "Unknown token" };
|
|
3810
|
-
const amountWei =
|
|
4007
|
+
const amountWei = import_ethers15.ethers.parseUnits(amount, token.decimals);
|
|
3811
4008
|
let valueInNative;
|
|
3812
4009
|
if (token.isNative) {
|
|
3813
4010
|
valueInNative = amountWei;
|
|
@@ -3818,27 +4015,27 @@ async function simulatePodPortalFee(chainId, tokenSymbol, amount, fixedFee, perc
|
|
|
3818
4015
|
fetchPodOracleTokenUsdPrice(nativeSymbol, chainId)
|
|
3819
4016
|
]);
|
|
3820
4017
|
if (!tokenUsd || !nativeUsd) {
|
|
3821
|
-
const fixed =
|
|
3822
|
-
const cap =
|
|
4018
|
+
const fixed = import_ethers15.ethers.parseEther(fixedFee || "0");
|
|
4019
|
+
const cap = import_ethers15.ethers.parseEther(maxFee || "0");
|
|
3823
4020
|
const fee2 = cap > 0n && fixed > cap ? cap : fixed;
|
|
3824
4021
|
return {
|
|
3825
|
-
fee: parseFloat(
|
|
4022
|
+
fee: parseFloat(import_ethers15.ethers.formatEther(fee2)).toFixed(6),
|
|
3826
4023
|
explanation: "Fixed fee applied (no live oracle price)"
|
|
3827
4024
|
};
|
|
3828
4025
|
}
|
|
3829
|
-
const tokenUsdWei =
|
|
3830
|
-
const nativeUsdWei =
|
|
4026
|
+
const tokenUsdWei = import_ethers15.ethers.parseEther(tokenUsd.toString());
|
|
4027
|
+
const nativeUsdWei = import_ethers15.ethers.parseEther(nativeUsd.toString());
|
|
3831
4028
|
const amount18 = amountWei * 10n ** BigInt(18 - token.decimals);
|
|
3832
4029
|
valueInNative = amount18 * tokenUsdWei / nativeUsdWei;
|
|
3833
4030
|
}
|
|
3834
|
-
const fixedFeeWei =
|
|
3835
|
-
const maxFeeWei =
|
|
4031
|
+
const fixedFeeWei = import_ethers15.ethers.parseEther(fixedFee || "0");
|
|
4032
|
+
const maxFeeWei = import_ethers15.ethers.parseEther(maxFee || "0");
|
|
3836
4033
|
const bps = BigInt(parseInt(percentageBps || "0", 10));
|
|
3837
4034
|
const percentageFee = valueInNative * bps / FEE_DIVISOR;
|
|
3838
4035
|
let fee = percentageFee > fixedFeeWei ? percentageFee : fixedFeeWei;
|
|
3839
4036
|
if (maxFeeWei > 0n && fee > maxFeeWei) fee = maxFeeWei;
|
|
3840
4037
|
const explanation = maxFeeWei > 0n && fee === maxFeeWei && fee !== fixedFeeWei ? "Max fee cap applied" : fee === fixedFeeWei ? "Fixed fee floor applied" : "Percentage fee applied";
|
|
3841
|
-
return { fee: parseFloat(
|
|
4038
|
+
return { fee: parseFloat(import_ethers15.ethers.formatEther(fee)).toFixed(6), explanation };
|
|
3842
4039
|
} catch (err) {
|
|
3843
4040
|
logger.error("simulatePodPortalFee error:", err);
|
|
3844
4041
|
return { fee: "\u2014", explanation: "Simulation failed" };
|
|
@@ -3859,7 +4056,7 @@ var LIMITS = {
|
|
|
3859
4056
|
|
|
3860
4057
|
// src/hooks/useMetamask.ts
|
|
3861
4058
|
var import_react2 = require("react");
|
|
3862
|
-
var
|
|
4059
|
+
var import_ethers16 = require("ethers");
|
|
3863
4060
|
init_plugin();
|
|
3864
4061
|
init_ethereum();
|
|
3865
4062
|
init_logger();
|
|
@@ -4145,7 +4342,7 @@ var useMetamask = ({
|
|
|
4145
4342
|
});
|
|
4146
4343
|
const accounts = await eth.request({ method: "eth_requestAccounts" });
|
|
4147
4344
|
if (!accounts || accounts.length === 0) return false;
|
|
4148
|
-
const provider = new
|
|
4345
|
+
const provider = new import_ethers16.ethers.BrowserProvider(eth);
|
|
4149
4346
|
const network = await provider.getNetwork();
|
|
4150
4347
|
const envDefaultNetwork = getPluginConfig().defaultNetworkId;
|
|
4151
4348
|
if (accounts.length > 0) {
|
|
@@ -4162,7 +4359,7 @@ var useMetamask = ({
|
|
|
4162
4359
|
const eth = getMetaMaskProvider();
|
|
4163
4360
|
if (!eth) return;
|
|
4164
4361
|
try {
|
|
4165
|
-
const provider = new
|
|
4362
|
+
const provider = new import_ethers16.ethers.BrowserProvider(eth);
|
|
4166
4363
|
await checkNetwork(provider);
|
|
4167
4364
|
if (onNetworkChanged) {
|
|
4168
4365
|
await onNetworkChanged();
|
|
@@ -4396,97 +4593,8 @@ function decryptCtUint256(ciphertext, aesKey, options) {
|
|
|
4396
4593
|
}
|
|
4397
4594
|
}
|
|
4398
4595
|
|
|
4399
|
-
// src/lib/rpcProvider.ts
|
|
4400
|
-
var import_ethers16 = require("ethers");
|
|
4401
|
-
init_plugin();
|
|
4402
|
-
init_coti();
|
|
4403
|
-
init_rpcUrls();
|
|
4404
|
-
init_sepolia();
|
|
4405
|
-
init_logger();
|
|
4406
|
-
var resolveRpcUrlsForChain = (chainId) => {
|
|
4407
|
-
const base = getRpcUrlsForChain(chainId);
|
|
4408
|
-
const numericId = chainId == null ? void 0 : Number(chainId);
|
|
4409
|
-
if (numericId == null || !Number.isFinite(numericId)) return base;
|
|
4410
|
-
const plugin = getPluginConfig();
|
|
4411
|
-
let override;
|
|
4412
|
-
if (numericId === SEPOLIA_CHAIN_ID && plugin.sepoliaRpcUrl) {
|
|
4413
|
-
override = plugin.sepoliaRpcUrl;
|
|
4414
|
-
} else if (numericId === COTI_TESTNET_CHAIN_ID && plugin.cotiTestnetRpcUrl) {
|
|
4415
|
-
override = plugin.cotiTestnetRpcUrl;
|
|
4416
|
-
}
|
|
4417
|
-
if (!override) return base;
|
|
4418
|
-
return [.../* @__PURE__ */ new Set([override, ...base])];
|
|
4419
|
-
};
|
|
4420
|
-
var collectErrorText = (error) => {
|
|
4421
|
-
if (!error) return "";
|
|
4422
|
-
if (typeof error === "string") return error;
|
|
4423
|
-
if (error instanceof Error) return error.message;
|
|
4424
|
-
try {
|
|
4425
|
-
return JSON.stringify(error);
|
|
4426
|
-
} catch {
|
|
4427
|
-
return String(error);
|
|
4428
|
-
}
|
|
4429
|
-
};
|
|
4430
|
-
var readNestedRpcCode = (error) => {
|
|
4431
|
-
const e = error;
|
|
4432
|
-
return e.code ?? e.error?.code ?? e.info?.error?.code;
|
|
4433
|
-
};
|
|
4434
|
-
var readNestedHttpStatus = (error) => {
|
|
4435
|
-
const e = error;
|
|
4436
|
-
return e.data?.httpStatus ?? e.error?.data?.httpStatus ?? e.info?.responseStatus;
|
|
4437
|
-
};
|
|
4438
|
-
var isTransientRpcError = (error) => {
|
|
4439
|
-
const text = collectErrorText(error);
|
|
4440
|
-
const lower = text.toLowerCase();
|
|
4441
|
-
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")) {
|
|
4442
|
-
return true;
|
|
4443
|
-
}
|
|
4444
|
-
if (error && typeof error === "object") {
|
|
4445
|
-
const code = readNestedRpcCode(error);
|
|
4446
|
-
if (code === "SERVER_ERROR" || code === "TIMEOUT" || code === "NETWORK_ERROR" || code === -32005 || code === "-32005") {
|
|
4447
|
-
return true;
|
|
4448
|
-
}
|
|
4449
|
-
const httpStatus = readNestedHttpStatus(error);
|
|
4450
|
-
if (httpStatus === 429 || httpStatus === "429") {
|
|
4451
|
-
return true;
|
|
4452
|
-
}
|
|
4453
|
-
}
|
|
4454
|
-
return false;
|
|
4455
|
-
};
|
|
4456
|
-
var createJsonRpcProvider = (url, chainId) => new import_ethers16.ethers.JsonRpcProvider(url, chainId);
|
|
4457
|
-
var createResilientJsonRpcProvider = async (chainId) => {
|
|
4458
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4459
|
-
let lastError;
|
|
4460
|
-
for (const url of urls) {
|
|
4461
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4462
|
-
try {
|
|
4463
|
-
await provider.getNetwork();
|
|
4464
|
-
return provider;
|
|
4465
|
-
} catch (error) {
|
|
4466
|
-
lastError = error;
|
|
4467
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4468
|
-
logger.warn(`[rpc] ${url} unavailable for chain ${chainId}, trying fallback`);
|
|
4469
|
-
}
|
|
4470
|
-
}
|
|
4471
|
-
throw lastError instanceof Error ? lastError : new Error(`No RPC available for chain ${chainId}`);
|
|
4472
|
-
};
|
|
4473
|
-
var withRpcFallback = async (chainId, fn) => {
|
|
4474
|
-
const urls = resolveRpcUrlsForChain(chainId);
|
|
4475
|
-
let lastError;
|
|
4476
|
-
for (const url of urls) {
|
|
4477
|
-
const provider = createJsonRpcProvider(url, chainId);
|
|
4478
|
-
try {
|
|
4479
|
-
return await fn(provider);
|
|
4480
|
-
} catch (error) {
|
|
4481
|
-
lastError = error;
|
|
4482
|
-
if (!isTransientRpcError(error)) throw error;
|
|
4483
|
-
logger.warn(`[rpc] ${url} request failed for chain ${chainId}, trying fallback`);
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
throw lastError instanceof Error ? lastError : new Error(`All RPC endpoints failed for chain ${chainId}`);
|
|
4487
|
-
};
|
|
4488
|
-
|
|
4489
4596
|
// src/hooks/usePrivateTokenBalance.ts
|
|
4597
|
+
init_rpcProvider();
|
|
4490
4598
|
init_plugin();
|
|
4491
4599
|
init_logger();
|
|
4492
4600
|
var PLAIN_BALANCE_ABI = [
|
|
@@ -4599,6 +4707,7 @@ var usePrivateTokenBalance = () => {
|
|
|
4599
4707
|
var import_react4 = require("react");
|
|
4600
4708
|
var import_ethers19 = require("ethers");
|
|
4601
4709
|
init_config();
|
|
4710
|
+
init_rpcProvider();
|
|
4602
4711
|
|
|
4603
4712
|
// src/lib/utils.ts
|
|
4604
4713
|
var TOKEN_BALANCE_DISPLAY_DECIMALS = {
|
|
@@ -4692,6 +4801,7 @@ var import_ethers18 = require("ethers");
|
|
|
4692
4801
|
init_aesKey();
|
|
4693
4802
|
init_logger();
|
|
4694
4803
|
init_config();
|
|
4804
|
+
init_rpcProvider();
|
|
4695
4805
|
var ROUND_TRIP_TEST_VALUE = 0x0123456789abcdefn;
|
|
4696
4806
|
var FLAT_BALANCE_ABI2 = [
|
|
4697
4807
|
"function balanceOf(address) view returns (tuple(uint256 ciphertextHigh, uint256 ciphertextLow))"
|
|
@@ -5410,6 +5520,7 @@ init_config();
|
|
|
5410
5520
|
init_executePodPortalTransaction();
|
|
5411
5521
|
init_chains();
|
|
5412
5522
|
init_logger();
|
|
5523
|
+
init_rpcProvider();
|
|
5413
5524
|
init_encryptValue256();
|
|
5414
5525
|
init_utils();
|
|
5415
5526
|
init_ethereum();
|
|
@@ -6389,7 +6500,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6389
6500
|
}]
|
|
6390
6501
|
});
|
|
6391
6502
|
logger.log("\u{1F510} [Approve] Tx submitted, waiting for confirmation", { txHash: shortHash(rawTxHash) });
|
|
6392
|
-
await
|
|
6503
|
+
await waitForTransactionResilient(currentChainId, rawTxHash, {
|
|
6504
|
+
primary: provider
|
|
6505
|
+
});
|
|
6393
6506
|
logger.log("\u{1F510} [Approve] Tx confirmed, refreshing allowance...");
|
|
6394
6507
|
setIsApproving(false);
|
|
6395
6508
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6406,7 +6519,9 @@ var usePrivacyBridgeAllowance = ({
|
|
|
6406
6519
|
title: "Approving...",
|
|
6407
6520
|
message: "Waiting for allowance confirmation..."
|
|
6408
6521
|
});
|
|
6409
|
-
await tx.
|
|
6522
|
+
await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6523
|
+
primary: provider
|
|
6524
|
+
});
|
|
6410
6525
|
await checkAllowance();
|
|
6411
6526
|
setIsApproving(false);
|
|
6412
6527
|
setToastState((prev) => ({ ...prev, visible: false }));
|
|
@@ -6450,6 +6565,7 @@ init_config();
|
|
|
6450
6565
|
init_executePodPortalTransaction();
|
|
6451
6566
|
init_chains();
|
|
6452
6567
|
init_logger();
|
|
6568
|
+
init_rpcProvider();
|
|
6453
6569
|
init_utils();
|
|
6454
6570
|
var usePrivacyBridgeExecutor = ({
|
|
6455
6571
|
walletAddress,
|
|
@@ -6698,7 +6814,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6698
6814
|
logger.log("ERC20 deposit tx sent", { txHash: shortHash(rawDepositTxHash) });
|
|
6699
6815
|
tx = {
|
|
6700
6816
|
hash: rawDepositTxHash,
|
|
6701
|
-
wait: async () => await
|
|
6817
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawDepositTxHash, {
|
|
6818
|
+
primary: provider
|
|
6819
|
+
})
|
|
6702
6820
|
};
|
|
6703
6821
|
} else {
|
|
6704
6822
|
logger.log("\u{1F504} Executing Native COTI Deposit...");
|
|
@@ -6855,7 +6973,9 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6855
6973
|
logger.log("Withdraw tx sent", { txHash: shortHash(rawWithdrawTxHash) });
|
|
6856
6974
|
tx = {
|
|
6857
6975
|
hash: rawWithdrawTxHash,
|
|
6858
|
-
wait: async () => await
|
|
6976
|
+
wait: async () => await waitForTransactionResilient(currentChainId, rawWithdrawTxHash, {
|
|
6977
|
+
primary: provider
|
|
6978
|
+
})
|
|
6859
6979
|
};
|
|
6860
6980
|
} catch (e) {
|
|
6861
6981
|
setIsBridgingLoading(false);
|
|
@@ -6871,12 +6991,13 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6871
6991
|
title: "Processing Transaction",
|
|
6872
6992
|
message: "Transaction sent to network. Waiting for confirmation..."
|
|
6873
6993
|
});
|
|
6874
|
-
const receipt = await tx.
|
|
6994
|
+
const receipt = await waitForTransactionResilient(currentChainId, tx.hash, {
|
|
6995
|
+
primary: provider
|
|
6996
|
+
});
|
|
6875
6997
|
logger.log("Transaction confirmed", {
|
|
6876
6998
|
status: receipt.status,
|
|
6877
6999
|
blockNumber: receipt.blockNumber,
|
|
6878
|
-
gasUsed: receipt.gasUsed?.toString()
|
|
6879
|
-
gasLimit: receipt.gasLimit?.toString() ?? "n/a"
|
|
7000
|
+
gasUsed: receipt.gasUsed?.toString()
|
|
6880
7001
|
});
|
|
6881
7002
|
if (receipt.status !== 1) {
|
|
6882
7003
|
const gasUsed = receipt.gasUsed ? Number(receipt.gasUsed) : 0;
|
|
@@ -6891,11 +7012,12 @@ var usePrivacyBridgeExecutor = ({
|
|
|
6891
7012
|
const replayProvider = new import_ethers23.ethers.JsonRpcProvider(
|
|
6892
7013
|
getRpcUrlForChain(Number(network2.chainId))
|
|
6893
7014
|
);
|
|
7015
|
+
const broadcastTx = await replayProvider.getTransaction(txHashStr);
|
|
6894
7016
|
await replayProvider.call({
|
|
6895
|
-
to: receipt.to,
|
|
6896
|
-
from: receipt.from,
|
|
6897
|
-
data:
|
|
6898
|
-
value:
|
|
7017
|
+
to: broadcastTx?.to ?? receipt.to,
|
|
7018
|
+
from: broadcastTx?.from ?? receipt.from,
|
|
7019
|
+
data: broadcastTx?.data,
|
|
7020
|
+
value: broadcastTx?.value
|
|
6899
7021
|
});
|
|
6900
7022
|
} catch (replayErr) {
|
|
6901
7023
|
const errorName = replayErr.errorName || replayErr.revert?.name;
|
|
@@ -7821,7 +7943,7 @@ async function fetchEncryptedBackupProbe(address, chainId) {
|
|
|
7821
7943
|
return null;
|
|
7822
7944
|
}
|
|
7823
7945
|
}
|
|
7824
|
-
var
|
|
7946
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7825
7947
|
function resolveAesKeyChainId(currentChainId, overrideChainId) {
|
|
7826
7948
|
const configuredChainId = getPluginConfig().aesKeyChainId;
|
|
7827
7949
|
assertAesKeyChainId(configuredChainId);
|
|
@@ -7841,7 +7963,7 @@ async function probeSnapKeyWithRetry(hasAesKeyInSnap, address, retries, confirmS
|
|
|
7841
7963
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
7842
7964
|
const result = await hasAesKeyInSnap(address);
|
|
7843
7965
|
if (result !== null) return result;
|
|
7844
|
-
if (attempt < retries) await
|
|
7966
|
+
if (attempt < retries) await sleep2(250);
|
|
7845
7967
|
}
|
|
7846
7968
|
if (confirmSnapInstalled && !await confirmSnapInstalled()) {
|
|
7847
7969
|
return false;
|
|
@@ -8134,7 +8256,7 @@ function toBigInt(value, fallback2) {
|
|
|
8134
8256
|
if (value === void 0) return fallback2;
|
|
8135
8257
|
return (0, import_ethers26.getBigInt)(value);
|
|
8136
8258
|
}
|
|
8137
|
-
var
|
|
8259
|
+
var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8138
8260
|
function useAesKeyProvider(walletTypeInfo) {
|
|
8139
8261
|
const [isOnboarding, setIsOnboarding] = (0, import_react17.useState)(false);
|
|
8140
8262
|
const [onboardingError, setOnboardingError] = (0, import_react17.useState)(null);
|
|
@@ -8379,7 +8501,7 @@ function useAesKeyProvider(walletTypeInfo) {
|
|
|
8379
8501
|
const timeoutMs = config.onboardingGrantTimeoutMs ?? 6e4;
|
|
8380
8502
|
const startedAt = Date.now();
|
|
8381
8503
|
while (nativeBalance < requiredBalanceWei && Date.now() - startedAt < timeoutMs) {
|
|
8382
|
-
await
|
|
8504
|
+
await sleep3(pollIntervalMs);
|
|
8383
8505
|
nativeBalance = await provider.getBalance(address);
|
|
8384
8506
|
logger.log("[AesKeyProvider] Native COTI balance while waiting for grant", {
|
|
8385
8507
|
address,
|