@coti-io/coti-wallet-plugin 0.2.7 → 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.mjs CHANGED
@@ -42,8 +42,8 @@ var init_coti = __esm({
42
42
  unlockStrategy: "snap",
43
43
  portalStrategy: "coti-bridge",
44
44
  addresses: {
45
- PrivateCoti: "0x6cE8907414986E73De9e7D28d62Ea2080F8E88E1",
46
- PrivacyBridgeCotiNative: "0x96117882328407B13A5f378de25764C4eD8477eA",
45
+ PrivateCoti: "0xF3FC0A3285a6C297682390b1Db76c3AF130FEb93",
46
+ PrivacyBridgeCotiNative: "0xabB1FC50ebD491c74CE7dfE3bD350bce10f89F2E",
47
47
  CotiPriceConsumer: "0xD5EeD24e909AdE249b688671e32dcc013B236B74",
48
48
  WETH: "0x8bca4e6bbE402DB4aD189A316137aD08206154FB",
49
49
  WBTC: "0x5dBDb2E5D51c3FFab5D6B862Caa11FCe1D83F492",
@@ -53,19 +53,19 @@ var init_coti = __esm({
53
53
  gCOTI: "0x878a42D3cB737DEC9E6c7e7774d973F46fd8ed4C",
54
54
  NIGHT: "0x918084eee42832f08b868Ea64Bba2d41A5F360c6",
55
55
  PrivacyBridgeNight: "0x025b0E54ae5fac3BF3ca6eDe7bd62fa684c25D29",
56
- "p.WETH": "0xF009BADb181d471995a1CFF406C3Db7B180F64eA",
57
- "p.WBTC": "0xB50F1680a4C69145ABc09A2A71c8D5b8051578cF",
58
- "p.USDT": "0xcEF137E96eDF68EE99D4CdEa7085f154d74895cD",
59
- "p.USDC_E": "0x37f78dcCd15876F74391EF1F01b76557D9FF1dea",
60
- "p.WADA": "0x1245f50a3E9129A219b4bf66D10fEaEA47467B69",
61
- "p.gCOTI": "0x1503b02a4Aa27812306c65116FD23b733603F142",
56
+ "p.WETH": "0x272968B0fC2710AF20e04d1dDc9a49E2FE5a9caa",
57
+ "p.WBTC": "0xB48119847B7469cbD4a192391287b9c20e6F361F",
58
+ "p.USDT": "0x288b5c8d3419EFD1c9971d0716bb89fAEBC04aBE",
59
+ "p.USDC_E": "0xB4d9f6B49Da5637a713cee8Dd6540f311334Fdea",
60
+ "p.WADA": "0x091Df52B5a7d5EE97132D07Ffd16A21d0eda95b8",
61
+ "p.gCOTI": "0xB71370A6f2Fa9c2184d0a632b6AaBDA034c4B3db",
62
62
  "p.NIGHT": "0xfb3A2F7ca2416e7BE312feA60a647f880B840957",
63
- PrivacyBridgeWETH: "0x6f1628D7F1D5d5aDF39b924a28acb10B5C9df283",
64
- PrivacyBridgeWBTC: "0x9EBEbC8F5Cff021459a56A681719dF1C0A7435cc",
65
- PrivacyBridgeUSDT: "0x549634daBE8237EBda7473d7aA2bB17459826781",
66
- PrivacyBridgeUSDCe: "0xaa63D41890D576F93d79272988e212d8B46CdD26",
67
- PrivacyBridgeWADA: "0x4AFe67D4aD7AF0a70ACe6f79FbfAB66C72211c9F",
68
- PrivacyBridgegCOTI: "0xDB54B4B1B8F9614567bd673A17a5cD31A3DD6033"
63
+ PrivacyBridgeWETH: "0xF2928e7D17ae11Cea8Ad32340e34F665f618fb92",
64
+ PrivacyBridgeWBTC: "0x8508e8cbDf24084Ab2D1F8b9e5BbF674742b95aC",
65
+ PrivacyBridgeUSDT: "0x90f6576Fb941a152427c4423034e869D88C9faA5",
66
+ PrivacyBridgeUSDCe: "0x8102139805fbFE96c8cBC09be3ae61B5983bCf48",
67
+ PrivacyBridgeWADA: "0x31A7dDA15c6eb9D88934F91d4F43C2F7bb32c767",
68
+ PrivacyBridgegCOTI: "0xcfd4C96dD6ff0EDc9Cd0849de2EF45542A71421f"
69
69
  },
70
70
  tokens: cotiTokenConfigs([COTI_TESTNET_CHAIN_ID, COTI_MAINNET_CHAIN_ID]),
71
71
  walletNetwork: {
@@ -5352,6 +5352,7 @@ init_utils();
5352
5352
  init_config();
5353
5353
  init_executePodPortalTransaction();
5354
5354
  init_chains();
5355
+ init_coti();
5355
5356
  import { useState as useState4, useCallback as useCallback7, useEffect as useEffect4, useRef as useRef5 } from "react";
5356
5357
  import { useAccount as useAccount3 } from "wagmi";
5357
5358
  import { ethers as ethers22 } from "ethers";
@@ -5968,6 +5969,30 @@ var onboardUser = async () => {
5968
5969
  };
5969
5970
 
5970
5971
  // src/hooks/privacyBridge/usePrivacyBridgeAllowance.ts
5972
+ var PRIVATE_ALLOWANCE_ABI = [
5973
+ "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))"
5974
+ ];
5975
+ var PRIVATE_ALLOWANCE_MUTATION_ABI = [
5976
+ "function approve(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (bool)",
5977
+ "function increaseAllowance(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) addedValue) returns (bool)",
5978
+ "function decreaseAllowance(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) subtractedValue) returns (bool)"
5979
+ ];
5980
+ var isCotiBridgeChain = (chainId) => chainId === COTI_TESTNET_CHAIN_ID || chainId === COTI_MAINNET_CHAIN_ID;
5981
+ function extractOwnerCiphertextFromAllowance(raw) {
5982
+ if (raw == null || typeof raw !== "object") return null;
5983
+ const row = raw;
5984
+ const ownerCt = row.ownerCiphertext ?? row[1];
5985
+ if (ownerCt == null || typeof ownerCt !== "object") return null;
5986
+ const limbs = ownerCt;
5987
+ const high = limbs.ciphertextHigh ?? limbs[0];
5988
+ const low = limbs.ciphertextLow ?? limbs[1];
5989
+ if (high === void 0 || low === void 0) return null;
5990
+ try {
5991
+ return { ciphertextHigh: BigInt(high), ciphertextLow: BigInt(low) };
5992
+ } catch {
5993
+ return null;
5994
+ }
5995
+ }
5971
5996
  var usePrivacyBridgeAllowance = ({
5972
5997
  isConnected,
5973
5998
  walletAddress,
@@ -6123,23 +6148,21 @@ var usePrivacyBridgeAllowance = ({
6123
6148
  );
6124
6149
  if (privTokCfg) privateDecimals = privTokCfg.decimals;
6125
6150
  try {
6126
- const tokenContract = new ethers22.Contract(privateTokenAddress, [
6127
- "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))"
6128
- ], provider);
6129
- const currentAllowance2 = await tokenContract.allowance(walletAddress, bridgeAddress);
6130
- if (currentAllowance2.ownerCiphertext.ciphertextHigh === 0n && currentAllowance2.ownerCiphertext.ciphertextLow === 0n) {
6151
+ const tokenContract = new ethers22.Contract(privateTokenAddress, PRIVATE_ALLOWANCE_ABI, provider);
6152
+ const rawAllowance = await tokenContract.allowance(walletAddress, bridgeAddress);
6153
+ const ownerCt = extractOwnerCiphertextFromAllowance(rawAllowance);
6154
+ if (!ownerCt || ownerCt.ciphertextHigh === 0n && ownerCt.ciphertextLow === 0n) {
6131
6155
  setAllowance("0");
6132
6156
  return;
6133
6157
  }
6134
6158
  if (hasSnap || sessionAesKey) {
6135
6159
  try {
6136
- const ciphertext = {
6137
- ciphertextHigh: currentAllowance2.ownerCiphertext.ciphertextHigh,
6138
- ciphertextLow: currentAllowance2.ownerCiphertext.ciphertextLow
6139
- };
6140
- const decryptedVal = sessionAesKey ? decryptCtUint256(ciphertext, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ciphertext, currentChainId, walletAddress);
6160
+ const decryptedVal = sessionAesKey ? decryptCtUint256(ownerCt, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ownerCt, currentChainId, walletAddress);
6141
6161
  if (decryptedVal === null) {
6142
- setAllowance("0");
6162
+ logger.warn(
6163
+ "Could not decrypt private allowance value; treating as unlimited for UI"
6164
+ );
6165
+ setAllowance(ethers22.formatUnits(ethers22.MaxUint256, privateDecimals));
6143
6166
  } else {
6144
6167
  setAllowance(ethers22.formatUnits(decryptedVal, privateDecimals));
6145
6168
  }
@@ -6298,33 +6321,79 @@ var usePrivacyBridgeAllowance = ({
6298
6321
  message: `Please approve the bridge to access your Private ${token.symbol} tokens.`
6299
6322
  });
6300
6323
  const amountToApprove2 = amount ? ethers22.parseUnits(amount, privateDecimals) : ethers22.MaxUint256;
6301
- const approveSig = ethers22.id("approve(address,((uint256,uint256),bytes))").slice(0, 10);
6324
+ let method = "approve";
6325
+ let encryptAmount = amountToApprove2;
6326
+ const readPrivateAllowanceWei = async () => {
6327
+ const allowanceReader = new ethers22.Contract(
6328
+ privateTokenAddress,
6329
+ PRIVATE_ALLOWANCE_ABI,
6330
+ provider
6331
+ );
6332
+ const raw = await allowanceReader.allowance(walletAddress, bridgeAddress);
6333
+ const ownerCt = extractOwnerCiphertextFromAllowance(raw);
6334
+ if (!ownerCt) {
6335
+ return null;
6336
+ }
6337
+ if (ownerCt.ciphertextHigh === 0n && ownerCt.ciphertextLow === 0n) {
6338
+ return 0n;
6339
+ }
6340
+ if (!sessionAesKey && !hasSnap) {
6341
+ throw new Error("Private approval requires unlock/onboarding first.");
6342
+ }
6343
+ const decrypted = sessionAesKey ? decryptCtUint256(ownerCt, sessionAesKey, { decimals: privateDecimals }) : await decryptCtUint256ViaSnap(ownerCt, currentChainId, walletAddress);
6344
+ return decrypted;
6345
+ };
6346
+ if (isCotiBridgeChain(currentChainId)) {
6347
+ const currentAllowanceWei = await readPrivateAllowanceWei();
6348
+ if (currentAllowanceWei === null) {
6349
+ throw new Error(
6350
+ "Could not read current private allowance. Please try again."
6351
+ );
6352
+ }
6353
+ if (currentAllowanceWei === 0n) {
6354
+ method = "approve";
6355
+ encryptAmount = amountToApprove2;
6356
+ } else if (amountToApprove2 > currentAllowanceWei) {
6357
+ method = "increaseAllowance";
6358
+ encryptAmount = amountToApprove2 - currentAllowanceWei;
6359
+ } else if (amountToApprove2 < currentAllowanceWei) {
6360
+ method = "decreaseAllowance";
6361
+ encryptAmount = currentAllowanceWei - amountToApprove2;
6362
+ } else {
6363
+ logger.log("\u{1F510} [Approve] Allowance already matches requested amount; skipping tx");
6364
+ setIsApproving(false);
6365
+ setToastState((prev) => ({ ...prev, visible: false }));
6366
+ await checkAllowance();
6367
+ return;
6368
+ }
6369
+ }
6370
+ const methodSig = ethers22.id(
6371
+ `${method}(address,((uint256,uint256),bytes))`
6372
+ ).slice(0, 10);
6302
6373
  const itValue = sessionAesKey ? await encryptValue256(
6303
- amountToApprove2,
6374
+ encryptAmount,
6304
6375
  sessionAesKey,
6305
6376
  privateTokenAddress,
6306
- approveSig,
6377
+ methodSig,
6307
6378
  walletAddress,
6308
6379
  signer
6309
6380
  ) : hasSnap ? await buildItUint256ViaSnap({
6310
- value: amountToApprove2,
6381
+ value: encryptAmount,
6311
6382
  tokenAddress: privateTokenAddress,
6312
- functionSelector: approveSig,
6383
+ functionSelector: methodSig,
6313
6384
  chainId: currentChainId,
6314
6385
  accountAddress: walletAddress
6315
6386
  }) : null;
6316
6387
  if (!itValue) {
6317
6388
  throw new Error("Private approval requires unlock/onboarding first.");
6318
6389
  }
6319
- logger.log("\u{1F510} [Approve] Encrypted approval payload ready, encoding calldata...");
6320
- const approveInterface = new ethers22.Interface([
6321
- "function approve(address spender, tuple(tuple(uint256 ciphertextHigh, uint256 ciphertextLow) ciphertext, bytes signature) value) returns (bool)"
6322
- ]);
6323
- const calldata = approveInterface.encodeFunctionData("approve", [
6390
+ logger.log("\u{1F510} [Approve] Encrypted approval payload ready", { method });
6391
+ const approveInterface = new ethers22.Interface(PRIVATE_ALLOWANCE_MUTATION_ABI);
6392
+ const calldata = approveInterface.encodeFunctionData(method, [
6324
6393
  bridgeAddress,
6325
6394
  [[itValue.ciphertext.ciphertextHigh, itValue.ciphertext.ciphertextLow], itValue.signature]
6326
6395
  ]);
6327
- logger.log("\u{1F510} [Approve] Sending approve tx (wallet confirmation expected)...");
6396
+ logger.log("\u{1F510} [Approve] Sending approve tx (wallet confirmation expected)...", { method });
6328
6397
  const rawTxHash = await injectedProvider.request({
6329
6398
  method: "eth_sendTransaction",
6330
6399
  params: [{
@@ -6344,6 +6413,29 @@ var usePrivacyBridgeAllowance = ({
6344
6413
  failed.txHash = typeof rawTxHash === "string" ? rawTxHash : receipt2?.hash;
6345
6414
  throw failed;
6346
6415
  }
6416
+ if (isCotiBridgeChain(currentChainId)) {
6417
+ try {
6418
+ const verified = await readPrivateAllowanceWei();
6419
+ if (verified !== null && verified < amountToApprove2) {
6420
+ throw new Error(
6421
+ "Approval completed but allowance is still insufficient. Please try again."
6422
+ );
6423
+ }
6424
+ if (verified === null) {
6425
+ logger.warn(
6426
+ "\u{1F510} [Approve] Post-tx allowance decrypt unavailable; trusting successful receipt"
6427
+ );
6428
+ }
6429
+ } catch (verifyErr) {
6430
+ if (verifyErr instanceof Error && verifyErr.message.includes("still insufficient")) {
6431
+ throw verifyErr;
6432
+ }
6433
+ logger.warn(
6434
+ "\u{1F510} [Approve] Post-tx allowance verification skipped",
6435
+ verifyErr
6436
+ );
6437
+ }
6438
+ }
6347
6439
  logger.log("\u{1F510} [Approve] Tx confirmed, refreshing allowance...");
6348
6440
  setIsApproving(false);
6349
6441
  setToastState((prev) => ({ ...prev, visible: false }));