@coti-io/coti-wallet-plugin 0.2.6 → 0.2.8

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 CHANGED
@@ -64,8 +64,8 @@ var init_coti = __esm({
64
64
  unlockStrategy: "snap",
65
65
  portalStrategy: "coti-bridge",
66
66
  addresses: {
67
- PrivateCoti: "0x6cE8907414986E73De9e7D28d62Ea2080F8E88E1",
68
- PrivacyBridgeCotiNative: "0x96117882328407B13A5f378de25764C4eD8477eA",
67
+ PrivateCoti: "0xF3FC0A3285a6C297682390b1Db76c3AF130FEb93",
68
+ PrivacyBridgeCotiNative: "0xabB1FC50ebD491c74CE7dfE3bD350bce10f89F2E",
69
69
  CotiPriceConsumer: "0xD5EeD24e909AdE249b688671e32dcc013B236B74",
70
70
  WETH: "0x8bca4e6bbE402DB4aD189A316137aD08206154FB",
71
71
  WBTC: "0x5dBDb2E5D51c3FFab5D6B862Caa11FCe1D83F492",
@@ -75,19 +75,19 @@ var init_coti = __esm({
75
75
  gCOTI: "0x878a42D3cB737DEC9E6c7e7774d973F46fd8ed4C",
76
76
  NIGHT: "0x918084eee42832f08b868Ea64Bba2d41A5F360c6",
77
77
  PrivacyBridgeNight: "0x025b0E54ae5fac3BF3ca6eDe7bd62fa684c25D29",
78
- "p.WETH": "0xF009BADb181d471995a1CFF406C3Db7B180F64eA",
79
- "p.WBTC": "0xB50F1680a4C69145ABc09A2A71c8D5b8051578cF",
80
- "p.USDT": "0xcEF137E96eDF68EE99D4CdEa7085f154d74895cD",
81
- "p.USDC_E": "0x37f78dcCd15876F74391EF1F01b76557D9FF1dea",
82
- "p.WADA": "0x1245f50a3E9129A219b4bf66D10fEaEA47467B69",
83
- "p.gCOTI": "0x1503b02a4Aa27812306c65116FD23b733603F142",
78
+ "p.WETH": "0x272968B0fC2710AF20e04d1dDc9a49E2FE5a9caa",
79
+ "p.WBTC": "0xB48119847B7469cbD4a192391287b9c20e6F361F",
80
+ "p.USDT": "0x288b5c8d3419EFD1c9971d0716bb89fAEBC04aBE",
81
+ "p.USDC_E": "0xB4d9f6B49Da5637a713cee8Dd6540f311334Fdea",
82
+ "p.WADA": "0x091Df52B5a7d5EE97132D07Ffd16A21d0eda95b8",
83
+ "p.gCOTI": "0xB71370A6f2Fa9c2184d0a632b6AaBDA034c4B3db",
84
84
  "p.NIGHT": "0xfb3A2F7ca2416e7BE312feA60a647f880B840957",
85
- PrivacyBridgeWETH: "0x6f1628D7F1D5d5aDF39b924a28acb10B5C9df283",
86
- PrivacyBridgeWBTC: "0x9EBEbC8F5Cff021459a56A681719dF1C0A7435cc",
87
- PrivacyBridgeUSDT: "0x549634daBE8237EBda7473d7aA2bB17459826781",
88
- PrivacyBridgeUSDCe: "0xaa63D41890D576F93d79272988e212d8B46CdD26",
89
- PrivacyBridgeWADA: "0x4AFe67D4aD7AF0a70ACe6f79FbfAB66C72211c9F",
90
- PrivacyBridgegCOTI: "0xDB54B4B1B8F9614567bd673A17a5cD31A3DD6033"
85
+ PrivacyBridgeWETH: "0xF2928e7D17ae11Cea8Ad32340e34F665f618fb92",
86
+ PrivacyBridgeWBTC: "0x8508e8cbDf24084Ab2D1F8b9e5BbF674742b95aC",
87
+ PrivacyBridgeUSDT: "0x90f6576Fb941a152427c4423034e869D88C9faA5",
88
+ PrivacyBridgeUSDCe: "0x8102139805fbFE96c8cBC09be3ae61B5983bCf48",
89
+ PrivacyBridgeWADA: "0x31A7dDA15c6eb9D88934F91d4F43C2F7bb32c767",
90
+ PrivacyBridgegCOTI: "0xcfd4C96dD6ff0EDc9Cd0849de2EF45542A71421f"
91
91
  },
92
92
  tokens: cotiTokenConfigs([COTI_TESTNET_CHAIN_ID, COTI_MAINNET_CHAIN_ID]),
93
93
  walletNetwork: {
@@ -5513,6 +5513,7 @@ var import_ethers22 = require("ethers");
5513
5513
  init_config();
5514
5514
  init_executePodPortalTransaction();
5515
5515
  init_chains();
5516
+ init_coti();
5516
5517
  init_logger();
5517
5518
  init_rpcProvider();
5518
5519
  init_encryptValue256();
@@ -6126,6 +6127,30 @@ var onboardUser = async () => {
6126
6127
  };
6127
6128
 
6128
6129
  // src/hooks/privacyBridge/usePrivacyBridgeAllowance.ts
6130
+ var PRIVATE_ALLOWANCE_ABI = [
6131
+ "function allowance(address owner, address spender) view returns (tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ownerCiphertext, tuple(uint256 ciphertextHigh, uint256 ciphertextLow) spenderCiphertext))"
6132
+ ];
6133
+ var PRIVATE_ALLOWANCE_MUTATION_ABI = [
6134
+ "function approve(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (bool)",
6135
+ "function increaseAllowance(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) addedValue) returns (bool)",
6136
+ "function decreaseAllowance(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) subtractedValue) returns (bool)"
6137
+ ];
6138
+ var isCotiBridgeChain = (chainId) => chainId === COTI_TESTNET_CHAIN_ID || chainId === COTI_MAINNET_CHAIN_ID;
6139
+ function extractOwnerCiphertextFromAllowance(raw) {
6140
+ if (raw == null || typeof raw !== "object") return null;
6141
+ const row = raw;
6142
+ const ownerCt = row.ownerCiphertext ?? row[1];
6143
+ if (ownerCt == null || typeof ownerCt !== "object") return null;
6144
+ const limbs = ownerCt;
6145
+ const high = limbs.ciphertextHigh ?? limbs[0];
6146
+ const low = limbs.ciphertextLow ?? limbs[1];
6147
+ if (high === void 0 || low === void 0) return null;
6148
+ try {
6149
+ return { ciphertextHigh: BigInt(high), ciphertextLow: BigInt(low) };
6150
+ } catch {
6151
+ return null;
6152
+ }
6153
+ }
6129
6154
  var usePrivacyBridgeAllowance = ({
6130
6155
  isConnected,
6131
6156
  walletAddress,
@@ -6281,23 +6306,21 @@ var usePrivacyBridgeAllowance = ({
6281
6306
  );
6282
6307
  if (privTokCfg) privateDecimals = privTokCfg.decimals;
6283
6308
  try {
6284
- const tokenContract = new import_ethers22.ethers.Contract(privateTokenAddress, [
6285
- "function allowance(address owner, address spender) view returns (tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ownerCiphertext, tuple(uint256 ciphertextHigh, uint256 ciphertextLow) spenderCiphertext))"
6286
- ], provider);
6287
- const currentAllowance2 = await tokenContract.allowance(walletAddress, bridgeAddress);
6288
- if (currentAllowance2.ownerCiphertext.ciphertextHigh === 0n && currentAllowance2.ownerCiphertext.ciphertextLow === 0n) {
6309
+ const tokenContract = new import_ethers22.ethers.Contract(privateTokenAddress, PRIVATE_ALLOWANCE_ABI, provider);
6310
+ const rawAllowance = await tokenContract.allowance(walletAddress, bridgeAddress);
6311
+ const ownerCt = extractOwnerCiphertextFromAllowance(rawAllowance);
6312
+ if (!ownerCt || ownerCt.ciphertextHigh === 0n && ownerCt.ciphertextLow === 0n) {
6289
6313
  setAllowance("0");
6290
6314
  return;
6291
6315
  }
6292
6316
  if (hasSnap || sessionAesKey) {
6293
6317
  try {
6294
- const ciphertext = {
6295
- ciphertextHigh: currentAllowance2.ownerCiphertext.ciphertextHigh,
6296
- ciphertextLow: currentAllowance2.ownerCiphertext.ciphertextLow
6297
- };
6298
- const decryptedVal = sessionAesKey ? decryptCtUint256(ciphertext, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ciphertext, currentChainId, walletAddress);
6318
+ const decryptedVal = sessionAesKey ? decryptCtUint256(ownerCt, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ownerCt, currentChainId, walletAddress);
6299
6319
  if (decryptedVal === null) {
6300
- setAllowance("0");
6320
+ logger.warn(
6321
+ "Could not decrypt private allowance value; treating as unlimited for UI"
6322
+ );
6323
+ setAllowance(import_ethers22.ethers.formatUnits(import_ethers22.ethers.MaxUint256, privateDecimals));
6301
6324
  } else {
6302
6325
  setAllowance(import_ethers22.ethers.formatUnits(decryptedVal, privateDecimals));
6303
6326
  }
@@ -6456,33 +6479,79 @@ var usePrivacyBridgeAllowance = ({
6456
6479
  message: `Please approve the bridge to access your Private ${token.symbol} tokens.`
6457
6480
  });
6458
6481
  const amountToApprove2 = amount ? import_ethers22.ethers.parseUnits(amount, privateDecimals) : import_ethers22.ethers.MaxUint256;
6459
- const approveSig = import_ethers22.ethers.id("approve(address,((uint256,uint256),bytes))").slice(0, 10);
6482
+ let method = "approve";
6483
+ let encryptAmount = amountToApprove2;
6484
+ const readPrivateAllowanceWei = async () => {
6485
+ const allowanceReader = new import_ethers22.ethers.Contract(
6486
+ privateTokenAddress,
6487
+ PRIVATE_ALLOWANCE_ABI,
6488
+ provider
6489
+ );
6490
+ const raw = await allowanceReader.allowance(walletAddress, bridgeAddress);
6491
+ const ownerCt = extractOwnerCiphertextFromAllowance(raw);
6492
+ if (!ownerCt) {
6493
+ return null;
6494
+ }
6495
+ if (ownerCt.ciphertextHigh === 0n && ownerCt.ciphertextLow === 0n) {
6496
+ return 0n;
6497
+ }
6498
+ if (!sessionAesKey && !hasSnap) {
6499
+ throw new Error("Private approval requires unlock/onboarding first.");
6500
+ }
6501
+ const decrypted = sessionAesKey ? decryptCtUint256(ownerCt, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ownerCt, currentChainId, walletAddress);
6502
+ return decrypted;
6503
+ };
6504
+ if (isCotiBridgeChain(currentChainId)) {
6505
+ const currentAllowanceWei = await readPrivateAllowanceWei();
6506
+ if (currentAllowanceWei === null) {
6507
+ throw new Error(
6508
+ "Could not read current private allowance. Please try again."
6509
+ );
6510
+ }
6511
+ if (currentAllowanceWei === 0n) {
6512
+ method = "approve";
6513
+ encryptAmount = amountToApprove2;
6514
+ } else if (amountToApprove2 > currentAllowanceWei) {
6515
+ method = "increaseAllowance";
6516
+ encryptAmount = amountToApprove2 - currentAllowanceWei;
6517
+ } else if (amountToApprove2 < currentAllowanceWei) {
6518
+ method = "decreaseAllowance";
6519
+ encryptAmount = currentAllowanceWei - amountToApprove2;
6520
+ } else {
6521
+ logger.log("\u{1F510} [Approve] Allowance already matches requested amount; skipping tx");
6522
+ setIsApproving(false);
6523
+ setToastState((prev) => ({ ...prev, visible: false }));
6524
+ await checkAllowance();
6525
+ return;
6526
+ }
6527
+ }
6528
+ const methodSig = import_ethers22.ethers.id(
6529
+ `${method}(address,((uint256,uint256),bytes))`
6530
+ ).slice(0, 10);
6460
6531
  const itValue = sessionAesKey ? await encryptValue256(
6461
- amountToApprove2,
6532
+ encryptAmount,
6462
6533
  sessionAesKey,
6463
6534
  privateTokenAddress,
6464
- approveSig,
6535
+ methodSig,
6465
6536
  walletAddress,
6466
6537
  signer
6467
6538
  ) : hasSnap ? await buildItUint256ViaSnap({
6468
- value: amountToApprove2,
6539
+ value: encryptAmount,
6469
6540
  tokenAddress: privateTokenAddress,
6470
- functionSelector: approveSig,
6541
+ functionSelector: methodSig,
6471
6542
  chainId: currentChainId,
6472
6543
  accountAddress: walletAddress
6473
6544
  }) : null;
6474
6545
  if (!itValue) {
6475
6546
  throw new Error("Private approval requires unlock/onboarding first.");
6476
6547
  }
6477
- logger.log("\u{1F510} [Approve] Encrypted approval payload ready, encoding calldata...");
6478
- const approveInterface = new import_ethers22.ethers.Interface([
6479
- "function approve(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (bool)"
6480
- ]);
6481
- const calldata = approveInterface.encodeFunctionData("approve", [
6548
+ logger.log("\u{1F510} [Approve] Encrypted approval payload ready", { method });
6549
+ const approveInterface = new import_ethers22.ethers.Interface(PRIVATE_ALLOWANCE_MUTATION_ABI);
6550
+ const calldata = approveInterface.encodeFunctionData(method, [
6482
6551
  bridgeAddress,
6483
6552
  [[itValue.ciphertext.ciphertextHigh, itValue.ciphertext.ciphertextLow], itValue.signature]
6484
6553
  ]);
6485
- logger.log("\u{1F510} [Approve] Sending approve tx (wallet confirmation expected)...");
6554
+ logger.log("\u{1F510} [Approve] Sending approve tx (wallet confirmation expected)...", { method });
6486
6555
  const rawTxHash = await injectedProvider.request({
6487
6556
  method: "eth_sendTransaction",
6488
6557
  params: [{
@@ -6494,9 +6563,37 @@ var usePrivacyBridgeAllowance = ({
6494
6563
  }]
6495
6564
  });
6496
6565
  logger.log("\u{1F510} [Approve] Tx submitted, waiting for confirmation", { txHash: shortHash(rawTxHash) });
6497
- await waitForTransactionResilient(currentChainId, rawTxHash, {
6566
+ const receipt2 = await waitForTransactionResilient(currentChainId, rawTxHash, {
6498
6567
  primary: provider
6499
6568
  });
6569
+ if (!receipt2 || receipt2.status !== 1) {
6570
+ const failed = new Error("Approval transaction failed");
6571
+ failed.txHash = typeof rawTxHash === "string" ? rawTxHash : receipt2?.hash;
6572
+ throw failed;
6573
+ }
6574
+ if (isCotiBridgeChain(currentChainId)) {
6575
+ try {
6576
+ const verified = await readPrivateAllowanceWei();
6577
+ if (verified !== null && verified < amountToApprove2) {
6578
+ throw new Error(
6579
+ "Approval completed but allowance is still insufficient. Please try again."
6580
+ );
6581
+ }
6582
+ if (verified === null) {
6583
+ logger.warn(
6584
+ "\u{1F510} [Approve] Post-tx allowance decrypt unavailable; trusting successful receipt"
6585
+ );
6586
+ }
6587
+ } catch (verifyErr) {
6588
+ if (verifyErr instanceof Error && verifyErr.message.includes("still insufficient")) {
6589
+ throw verifyErr;
6590
+ }
6591
+ logger.warn(
6592
+ "\u{1F510} [Approve] Post-tx allowance verification skipped",
6593
+ verifyErr
6594
+ );
6595
+ }
6596
+ }
6500
6597
  logger.log("\u{1F510} [Approve] Tx confirmed, refreshing allowance...");
6501
6598
  setIsApproving(false);
6502
6599
  setToastState((prev) => ({ ...prev, visible: false }));
@@ -6513,9 +6610,14 @@ var usePrivacyBridgeAllowance = ({
6513
6610
  title: "Approving...",
6514
6611
  message: "Waiting for allowance confirmation..."
6515
6612
  });
6516
- await waitForTransactionResilient(currentChainId, tx.hash, {
6613
+ const receipt = await waitForTransactionResilient(currentChainId, tx.hash, {
6517
6614
  primary: provider
6518
6615
  });
6616
+ if (!receipt || receipt.status !== 1) {
6617
+ const failed = new Error("Approval transaction failed");
6618
+ failed.txHash = tx.hash || receipt?.hash;
6619
+ throw failed;
6620
+ }
6519
6621
  await checkAllowance();
6520
6622
  setIsApproving(false);
6521
6623
  setToastState((prev) => ({ ...prev, visible: false }));