@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 +8 -21
- package/examples/anonymous-flow.js +33 -28
- package/package.json +1 -1
- package/src/anonymous-client.js +39 -34
package/README.md
CHANGED
|
@@ -572,28 +572,15 @@ try {
|
|
|
572
572
|
|
|
573
573
|
### Common Issues and Solutions
|
|
574
574
|
|
|
575
|
-
| Issue
|
|
576
|
-
|
|
|
577
|
-
| "Account does not exist"
|
|
578
|
-
| "Insufficient balance"
|
|
579
|
-
| "Account finalization timeout"
|
|
580
|
-
| "Proof generation failed"
|
|
581
|
-
| "Amount too small"
|
|
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
|
|
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 ?? "
|
|
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
|
-
|
|
240
|
-
|
|
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
|
-
|
|
265
|
-
|
|
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
package/src/anonymous-client.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
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
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1561
|
+
const [balance, allowance] = await Promise.all([
|
|
1562
|
+
tokenContract.balanceOf(depositorAddress),
|
|
1563
|
+
tokenContract.allowance(depositorAddress, this.diamondAddress),
|
|
1564
|
+
]);
|
|
1562
1565
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1566
|
+
if (balance < amountBig)
|
|
1567
|
+
throw new Error(
|
|
1568
|
+
`Insufficient fee token balance. Required: ${amountBig}, available: ${balance}`,
|
|
1569
|
+
);
|
|
1567
1570
|
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
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:
|
|
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:
|
|
1642
|
+
value: txValue,
|
|
1638
1643
|
};
|
|
1639
1644
|
}
|
|
1640
1645
|
|