@fairblock/stabletrust 1.0.12 → 1.0.14

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
@@ -38,12 +38,12 @@ The following contract addresses are available for confidential transfers on tes
38
38
 
39
39
  | Network(Testnet) | Chain ID | Contract Address |
40
40
  | :--------------- | :------- | :------------------------------------------- |
41
- | Stable | 2201 | `0x29E4fd434758b1677c10854Fa81C2fc496D76E62` |
42
- | Arc | 1244 | `0xf085e801a6FD9d03b09566a738734B7e2Bb065De` |
43
- | Base | 84532 | `0x6FE45A71F5232a4E5e583Ae31A538360fB1e6aDb` |
44
- | Ethereum | 11155111 | `0x81a2c161c0327464430658516eE74A669feFC7bC` |
45
- | Arbitrum | 421614 | `0xa59462200F6E438c538b914eB5F980B3Fa723aA0` |
46
- | Tempo | 42431 | `0xB7bdce025c8a25e341Cb55795f8ba865AB3e392C` |
41
+ | Stable | 2201 | `0xb0b461aFA69b715d842c7fAb602f50D4cef83fe5` |
42
+ | Arc | 1244 | `0xEa837218c7Ccd9eA1BCfB640e5c6aFE59952b4FA` |
43
+ | Base | 84532 | `0x1a06530765e942a1D26B74d9558e9a1EdA615867` |
44
+ | Ethereum | 11155111 | `0xABEa3399873b80f528Ee76286087b45ed38Fbf97` |
45
+ | Arbitrum | 421614 | `0x2131De660C6be8b535E6f17E171bFf7143E9E9F4` |
46
+ | Tempo | 42431 | `0xF3525FF8F592883f8fA2d89EfBe85637955Df487` |
47
47
 
48
48
  ## Usage
49
49
 
@@ -13,7 +13,7 @@ dotenv.config();
13
13
 
14
14
  // Optional override for custom confidential contract deployments.
15
15
  const CONTRACT_ADDRESS =
16
- process.env.CONTRACT_ADDRESS || "0x29E4fd434758b1677c10854Fa81C2fc496D76E62";
16
+ process.env.CONTRACT_ADDRESS || "0xb0b461aFA69b715d842c7fAb602f50D4cef83fe5";
17
17
  // Standard ERC20 token contract. Any ERC20 on this chain ID can be used.
18
18
  const TOKEN_ADDRESS =
19
19
  process.env.TOKEN_ADDRESS || "0x78Cf24370174180738C5B8E352B6D14c83a6c9A9";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairblock/stabletrust",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
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",
package/src/client.js CHANGED
@@ -74,6 +74,9 @@ export class ConfidentialTransferClient {
74
74
  // WASM will be auto-initialized on first use
75
75
  this._wasmModule = null;
76
76
 
77
+ // Cache for derived keys — deterministic per wallet+chain+contract, safe to reuse
78
+ this._keyCache = new Map();
79
+
77
80
  try {
78
81
  this.provider = new ethers.JsonRpcProvider(this.config.rpcUrl);
79
82
  this.contract = new ethers.Contract(
@@ -118,8 +121,12 @@ export class ConfidentialTransferClient {
118
121
  if (!wallet) {
119
122
  throw new Error("Wallet is required");
120
123
  }
124
+ const address = await wallet.getAddress();
125
+ if (this._keyCache.has(address)) {
126
+ return this._keyCache.get(address);
127
+ }
121
128
  const wasm = await this._getWasm();
122
- return await deriveKeys(
129
+ const keys = await deriveKeys(
123
130
  wallet,
124
131
  {
125
132
  chainId: this.config.chainId,
@@ -127,6 +134,8 @@ export class ConfidentialTransferClient {
127
134
  },
128
135
  wasm.generate_deterministic_keypair,
129
136
  );
137
+ this._keyCache.set(address, keys);
138
+ return keys;
130
139
  } catch (error) {
131
140
  throw new Error(`Failed to derive keys: ${error.message}`);
132
141
  }
@@ -354,20 +363,17 @@ export class ConfidentialTransferClient {
354
363
  const depositAmount = BigInt(amount);
355
364
  const tokenContract = this._getTokenContract(tokenAddress);
356
365
 
357
- // Check token balance
358
- const tokenBalance = await tokenContract.balanceOf(address);
366
+ // Check token balance and allowance in parallel
367
+ const [tokenBalance, allowance] = await Promise.all([
368
+ tokenContract.balanceOf(address),
369
+ tokenContract.allowance(address, this.config.contractAddress),
370
+ ]);
359
371
  if (tokenBalance < depositAmount) {
360
372
  throw new Error(
361
373
  `Insufficient token balance. Required: ${depositAmount}, Available: ${tokenBalance}`,
362
374
  );
363
375
  }
364
376
 
365
- // Check and approve if needed
366
- const allowance = await tokenContract.allowance(
367
- address,
368
- this.config.contractAddress,
369
- );
370
-
371
377
  if (allowance < depositAmount) {
372
378
  const approveTx = await tokenContract
373
379
  .connect(wallet)
@@ -439,14 +445,15 @@ export class ConfidentialTransferClient {
439
445
 
440
446
  const senderAddress = await senderWallet.getAddress();
441
447
 
442
- // Auto-derive sender keys
443
- const derivedSenderKeys = await this._deriveKeys(senderWallet);
448
+ // Derive sender keys and fetch recipient account info in parallel
449
+ const [derivedSenderKeys, recipientAccountInfo] = await Promise.all([
450
+ this._deriveKeys(senderWallet),
451
+ this.getAccountInfo(recipientAddress),
452
+ ]);
444
453
  if (!derivedSenderKeys?.privateKey) {
445
454
  throw new Error("Failed to derive sender keys");
446
455
  }
447
456
 
448
- // Auto-derive recipient public key
449
- const recipientAccountInfo = await this.getAccountInfo(recipientAddress);
450
457
  if (!recipientAccountInfo.exists) {
451
458
  throw new Error(
452
459
  `Recipient account does not exist. Address: ${recipientAddress}`,
@@ -474,12 +481,14 @@ export class ConfidentialTransferClient {
474
481
  "transfer",
475
482
  );
476
483
 
477
- const balanceSummary = await this.getConfidentialBalance(
478
- senderAddress,
479
- derivedSenderKeys.privateKey,
480
- tokenAddress,
481
- );
482
- const fee = await this.getFeeAmount();
484
+ const [balanceSummary, fee] = await Promise.all([
485
+ this.getConfidentialBalance(
486
+ senderAddress,
487
+ derivedSenderKeys.privateKey,
488
+ tokenAddress,
489
+ ),
490
+ this.getFeeAmount(),
491
+ ]);
483
492
  const derivedCurrentBalanceCiphertext =
484
493
  balanceSummary.available.ciphertext;
485
494
  const derivedCurrentBalance = balanceSummary.available.amount;
@@ -882,6 +891,7 @@ export class ConfidentialTransferClient {
882
891
  async _waitForGlobalState(address, actionLabel) {
883
892
  let attempts = 0;
884
893
  const maxAttempts = 450; // 450 * 200ms = 90 seconds max wait
894
+ await sleep(2000);
885
895
 
886
896
  while (attempts < maxAttempts) {
887
897
  try {
@@ -923,6 +933,7 @@ export class ConfidentialTransferClient {
923
933
  options = {},
924
934
  ) {
925
935
  const { maxAttempts = 225, intervalMs = 400 } = options;
936
+ await sleep(1000);
926
937
 
927
938
  try {
928
939
  for (let i = 0; i < maxAttempts; i++) {
package/src/constants.js CHANGED
@@ -24,12 +24,12 @@ export const TEMPO_FEE_TOKEN_ADDRESS =
24
24
  "0x20c0000000000000000000000000000000000000";
25
25
 
26
26
  export const STABLETRUST_CONTRACTS_BY_CHAIN_ID = Object.freeze({
27
- 2201: "0x29E4fd434758b1677c10854Fa81C2fc496D76E62",
28
- 1244: "0xf085e801a6FD9d03b09566a738734B7e2Bb065De",
29
- 84532: "0x6FE45A71F5232a4E5e583Ae31A538360fB1e6aDb",
30
- 11155111: "0x81a2c161c0327464430658516eE74A669feFC7bC",
31
- 421614: "0xa59462200F6E438c538b914eB5F980B3Fa723aA0",
32
- 42431: "0xB7bdce025c8a25e341Cb55795f8ba865AB3e392C",
27
+ 2201: "0xb0b461aFA69b715d842c7fAb602f50D4cef83fe5", //Stable
28
+ 1244: "0xEa837218c7Ccd9eA1BCfB640e5c6aFE59952b4FA", //Arc
29
+ 84532: "0x1a06530765e942a1D26B74d9558e9a1EdA615867", //Base
30
+ 11155111: "0xABEa3399873b80f528Ee76286087b45ed38Fbf97", //Ethereum
31
+ 421614: "0x2131De660C6be8b535E6f17E171bFf7143E9E9F4", //Arbitrum
32
+ 42431: "0xF3525FF8F592883f8fA2d89EfBe85637955Df487", //Tempo
33
33
  });
34
34
 
35
35
  export function getStableTrustContractAddress(chainId) {