@fairblock/stabletrust 2.0.6 → 2.0.7

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/README.md CHANGED
@@ -572,28 +572,15 @@ try {
572
572
 
573
573
  ### Common Issues and Solutions
574
574
 
575
- | Issue | Cause | Solution |
576
- | :----------------------------- | :------------------------------------------------------ | :------------------------------------------------------ |
577
- | "Account does not exist" | Recipient hasn't initialized their confidential account | Recipient must call `ensureAccount()` first |
578
- | "Insufficient balance" | Transfer amount exceeds available confidential balance | Deposit more tokens or reduce transfer amount |
579
- | "Account finalization timeout" | Account creation is still processing | Wait a few minutes and retry |
580
- | "Proof generation failed" | Invalid inputs or cryptographic operation error | Verify all parameters and ensure sufficient balance |
581
- | "Amount too small" | Amount rounds to 0 in contract scale | Use a larger amount (minimum depends on token decimals) |
575
+ | Issue | Cause | Solution |
576
+ | :--------------------------------- | :-------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ |
577
+ | "Account does not exist" | Recipient hasn't initialized their confidential account | Recipient must call `ensureAccount()` first |
578
+ | "Insufficient balance" | Transfer amount exceeds available confidential balance | Deposit more tokens or reduce transfer amount |
579
+ | "Account finalization timeout" | Account creation is still processing | Wait a few minutes and retry |
580
+ | "Proof generation failed" | Invalid inputs or cryptographic operation error | Verify all parameters and ensure sufficient balance |
581
+ | "Amount too small" | Amount rounds to 0 in contract scale | Use a larger amount (minimum depends on token decimals) |
582
582
  | "Insufficient prepaid fee balance" | Anonymous account's prepaid fee reserve is below the per-transfer fee | Call `depositFees(wallet, accountId, amount)` to top up; use `getFeeToken()`/`getFeeAmount()` to check requirements |
583
- | Fairycloak HTTP error | Relay unreachable or request rejected | Check the relay URL, API key, and account authorization |
584
-
585
- ---
586
-
587
- ## Performance Metrics
588
-
589
- The following are estimated execution times for standard operations. Durations may vary based on network congestion and hardware.
590
-
591
- | Operation | Avg Duration |
592
- | :--------------- | :----------- |
593
- | Account Creation | 45s |
594
- | Deposit | 63s |
595
- | Transfer | 58s |
596
- | Withdraw | 58s |
583
+ | Fairycloak HTTP error | Relay unreachable or request rejected | Check the relay URL, API key, and account authorization |
597
584
 
598
585
  ---
599
586
 
@@ -24,7 +24,7 @@ dotenv.config();
24
24
 
25
25
  const EVM_RPC = process.env.EVM_RPC ?? "http://127.0.0.1:8545";
26
26
  const FAIRYCLOAK_URL = process.env.FAIRYCLOAK_URL ?? "http://127.0.0.1:8080";
27
- const CHAIN_ID = Number(process.env.CHAIN_ID ?? "31337");
27
+ const CHAIN_ID = Number(process.env.CHAIN_ID ?? "5042002");
28
28
  const TOKEN_ADDRESS =
29
29
  process.env.TOKEN_ADDRESS ?? "0xE915164570b027C2A0FfadcB1B672192E35BF008";
30
30
  const TOKEN_DECIMALS = Number(process.env.TOKEN_DECIMALS ?? "6");
@@ -236,34 +236,39 @@ async function main() {
236
236
  log(" fee token :", feeToken);
237
237
  log(" fee/xfer :", fmt(feeAmount, TOKEN_DECIMALS), "tokens");
238
238
 
239
- const feeBalance = await client.getPrepaidFeeBalance(anon1Id, feeToken);
240
- log(" fee balance:", fmt(feeBalance, TOKEN_DECIMALS), "tokens");
241
-
242
- if (feeBalance < MIN_FEE_BALANCE) {
243
- log(
244
- ` balance < ${fmt(MIN_FEE_BALANCE, TOKEN_DECIMALS)}, depositing ${fmt(FEE_DEPOSIT_AMOUNT, TOKEN_DECIMALS)} fee tokens (anon1 pays gas) …`,
245
- );
246
- const fd = await client.depositFees(
247
- anon1Wallet,
248
- anon1Id,
249
- FEE_DEPOSIT_AMOUNT,
250
- );
251
- log(" request_id:", fd.request_id, " status:", fd.status);
252
- if (fd.error) log(" [!] Error:", fd.error);
253
- if (fd.tx_hash) log(" tx_hash :", fd.tx_hash);
254
-
255
- const fdFinal = await client.waitForRequest(fd.request_id, {
256
- timeoutMs: 180_000,
257
- });
258
- log(" status :", fdFinal.status, " tx_hash:", fdFinal.tx_hash ?? "—");
259
- if (fdFinal.error) log(" [!] Error:", fdFinal.error);
260
-
261
- const newFeeBalance = await client.getPrepaidFeeBalance(anon1Id, feeToken);
262
- log(" new fee balance:", fmt(newFeeBalance, TOKEN_DECIMALS), "tokens");
239
+ if (feeAmount === 0n) {
240
+ log(" no fee configured — transactions are free, skipping top-up.");
263
241
  } else {
264
- log(
265
- ` fee balance sufficient (${fmt(feeBalance, TOKEN_DECIMALS)} ≥ ${fmt(MIN_FEE_BALANCE, TOKEN_DECIMALS)}), skipping deposit.`,
266
- );
242
+ const feeBalance = await client.getPrepaidFeeBalance(anon1Id, feeToken);
243
+ log(" fee balance:", fmt(feeBalance, TOKEN_DECIMALS), "tokens");
244
+
245
+ if (feeBalance < MIN_FEE_BALANCE) {
246
+ const currency = feeToken === ethers.ZeroAddress ? "native" : "ERC-20";
247
+ log(
248
+ ` balance < ${fmt(MIN_FEE_BALANCE, TOKEN_DECIMALS)}, depositing ${fmt(FEE_DEPOSIT_AMOUNT, TOKEN_DECIMALS)} ${currency} fee tokens (anon1 pays gas) …`,
249
+ );
250
+ const fd = await client.depositFees(
251
+ anon1Wallet,
252
+ anon1Id,
253
+ FEE_DEPOSIT_AMOUNT,
254
+ );
255
+ log(" request_id:", fd.request_id, " status:", fd.status);
256
+ if (fd.error) log(" [!] Error:", fd.error);
257
+ if (fd.tx_hash) log(" tx_hash :", fd.tx_hash);
258
+
259
+ const fdFinal = await client.waitForRequest(fd.request_id, {
260
+ timeoutMs: 180_000,
261
+ });
262
+ log(" status :", fdFinal.status, " tx_hash:", fdFinal.tx_hash ?? "—");
263
+ if (fdFinal.error) log(" [!] Error:", fdFinal.error);
264
+
265
+ const newFeeBalance = await client.getPrepaidFeeBalance(anon1Id, feeToken);
266
+ log(" new fee balance:", fmt(newFeeBalance, TOKEN_DECIMALS), "tokens");
267
+ } else {
268
+ log(
269
+ ` fee balance sufficient (${fmt(feeBalance, TOKEN_DECIMALS)} ≥ ${fmt(MIN_FEE_BALANCE, TOKEN_DECIMALS)}), skipping deposit.`,
270
+ );
271
+ }
267
272
  }
268
273
 
269
274
  // ── [6] Transfer anon1 → anon2 ───────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairblock/stabletrust",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "SDK for confidential transfers using homomorphic encryption and zero-knowledge proofs",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -1488,8 +1488,6 @@ export class AnonymousTransferClient {
1488
1488
  ]);
1489
1489
  if (feeAmount === 0n) return; // no fee configured
1490
1490
 
1491
- if (feeToken === ethers.ZeroAddress) return; // fee token not set
1492
-
1493
1491
  const balance = await this.getPrepaidFeeBalance(accountId, feeToken);
1494
1492
  if (balance < feeAmount) {
1495
1493
  throw new Error(
@@ -1534,45 +1532,51 @@ export class AnonymousTransferClient {
1534
1532
  if (amountBig <= 0n) throw new Error("Amount must be greater than 0");
1535
1533
 
1536
1534
  const feeToken = await this.getFeeToken();
1537
- if (feeToken === ethers.ZeroAddress)
1538
- throw new Error(
1539
- "No fee token is currently configured on the contract. Contact the protocol operator.",
1540
- );
1535
+ const isNative = feeToken === ethers.ZeroAddress;
1541
1536
 
1542
1537
  const depositorAddress = await authWallet.getAddress();
1543
1538
  const walletWithProvider = authWallet.connect
1544
1539
  ? authWallet.connect(this.provider)
1545
1540
  : authWallet;
1546
1541
 
1547
- // 1. Approve if needed
1548
- const tokenContract = new ethers.Contract(
1549
- feeToken,
1550
- [
1551
- "function balanceOf(address) view returns (uint256)",
1552
- "function allowance(address,address) view returns (uint256)",
1553
- "function approve(address,uint256) returns (bool)",
1554
- ],
1555
- walletWithProvider,
1556
- );
1542
+ if (isNative) {
1543
+ // Native currency: check wallet balance, no ERC-20 approve needed
1544
+ const balance = await this.provider.getBalance(depositorAddress);
1545
+ if (balance < amountBig)
1546
+ throw new Error(
1547
+ `Insufficient native balance. Required: ${amountBig}, available: ${balance}`,
1548
+ );
1549
+ } else {
1550
+ // ERC-20: approve if needed
1551
+ const tokenContract = new ethers.Contract(
1552
+ feeToken,
1553
+ [
1554
+ "function balanceOf(address) view returns (uint256)",
1555
+ "function allowance(address,address) view returns (uint256)",
1556
+ "function approve(address,uint256) returns (bool)",
1557
+ ],
1558
+ walletWithProvider,
1559
+ );
1557
1560
 
1558
- const [balance, allowance] = await Promise.all([
1559
- tokenContract.balanceOf(depositorAddress),
1560
- tokenContract.allowance(depositorAddress, this.diamondAddress),
1561
- ]);
1561
+ const [balance, allowance] = await Promise.all([
1562
+ tokenContract.balanceOf(depositorAddress),
1563
+ tokenContract.allowance(depositorAddress, this.diamondAddress),
1564
+ ]);
1562
1565
 
1563
- if (balance < amountBig)
1564
- throw new Error(
1565
- `Insufficient fee token balance. Required: ${amountBig}, available: ${balance}`,
1566
- );
1566
+ if (balance < amountBig)
1567
+ throw new Error(
1568
+ `Insufficient fee token balance. Required: ${amountBig}, available: ${balance}`,
1569
+ );
1567
1570
 
1568
- if (allowance < amountBig) {
1569
- const approveTx = await tokenContract.approve(
1570
- this.diamondAddress,
1571
- ethers.MaxUint256,
1572
- );
1573
- const receipt = await approveTx.wait();
1574
- if (!receipt || receipt.status === 0)
1575
- throw new Error("Fee token approval failed");
1571
+ if (allowance < amountBig) {
1572
+ const approveTx = await tokenContract.approve(
1573
+ this.diamondAddress,
1574
+ ethers.MaxUint256,
1575
+ );
1576
+ const receipt = await approveTx.wait();
1577
+ if (!receipt || receipt.status === 0)
1578
+ throw new Error("Fee token approval failed");
1579
+ }
1576
1580
  }
1577
1581
 
1578
1582
  // 2. EIP-712 AnonymousAddFees signature
@@ -1614,6 +1618,7 @@ export class AnonymousTransferClient {
1614
1618
  this.provider.getFeeData(),
1615
1619
  ]);
1616
1620
 
1621
+ const txValue = isNative ? amountBig : 0n;
1617
1622
  let txObj;
1618
1623
  if (feeData.maxFeePerGas) {
1619
1624
  txObj = {
@@ -1624,7 +1629,7 @@ export class AnonymousTransferClient {
1624
1629
  gasLimit,
1625
1630
  maxFeePerGas: (feeData.maxFeePerGas * 12n) / 10n,
1626
1631
  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? 0n,
1627
- value: 0n,
1632
+ value: txValue,
1628
1633
  };
1629
1634
  } else {
1630
1635
  txObj = {
@@ -1634,7 +1639,7 @@ export class AnonymousTransferClient {
1634
1639
  chainId: BigInt(this.chainId),
1635
1640
  gasLimit,
1636
1641
  gasPrice: (feeData.gasPrice * 11n) / 10n,
1637
- value: 0n,
1642
+ value: txValue,
1638
1643
  };
1639
1644
  }
1640
1645