@fairblock/stabletrust 1.0.3 → 1.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/examples/complete-flow.js +7 -6
- package/examples/simple-snippets.js +4 -4
- package/package.json +8 -3
- package/src/client.js +0 -7
- package/src/index.d.ts +1 -7
- package/src/wasm-loader.js +61 -35
|
@@ -11,18 +11,19 @@ dotenv.config();
|
|
|
11
11
|
* https://docs.fairblock.network/docs/confidential_transfers/technical_overview
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
// Currently configured for
|
|
14
|
+
// Currently configured for Ethereum Sepolia confidential mirror contract.
|
|
15
15
|
// You can deploy your own confidential contract on any EVM network and use that.
|
|
16
16
|
const CONTRACT_ADDRESS =
|
|
17
|
-
process.env.CONTRACT_ADDRESS || "
|
|
17
|
+
process.env.CONTRACT_ADDRESS || "0xD765Dff7D734ABE09f88991A46BAb73ACa8910EF";
|
|
18
18
|
// Standard ERC20 token contract. Any ERC20 on this chain ID can be used.
|
|
19
19
|
const TOKEN_ADDRESS =
|
|
20
|
-
process.env.TOKEN_ADDRESS || "
|
|
20
|
+
process.env.TOKEN_ADDRESS || "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
|
|
21
21
|
const RPC_URL =
|
|
22
|
-
process.env.
|
|
22
|
+
process.env.ETHEREUM_RPC_URL || "https://ethereum-sepolia-rpc.publicnode.com";
|
|
23
23
|
const EXPLORER_URL =
|
|
24
|
-
process.env.EXPLORER_URL || "https://sepolia.
|
|
25
|
-
const CHAIN_ID = process.env.CHAIN_ID ||
|
|
24
|
+
process.env.EXPLORER_URL || "https://sepolia.etherscan.io/tx/";
|
|
25
|
+
const CHAIN_ID = process.env.CHAIN_ID || 11155111;
|
|
26
|
+
1;
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Performance Utility: Tracks execution time and provides timestamps
|
|
@@ -3,14 +3,14 @@ import dotenv from "dotenv";
|
|
|
3
3
|
import { ConfidentialTransferClient } from "@fairblock/stabletrust";
|
|
4
4
|
dotenv.config();
|
|
5
5
|
const RPC_URL =
|
|
6
|
-
process.env.
|
|
6
|
+
process.env.RPC_URL || "https://ethereum-sepolia-rpc.publicnode.com";
|
|
7
7
|
const EXPLORER_URL =
|
|
8
|
-
process.env.EXPLORER_URL || "https://sepolia.
|
|
8
|
+
process.env.EXPLORER_URL || "https://sepolia.etherscan.io/tx/";
|
|
9
9
|
async function minimalFlow() {
|
|
10
10
|
// 1. Setup Client & Wallets
|
|
11
11
|
const client = new ConfidentialTransferClient(
|
|
12
12
|
RPC_URL,
|
|
13
|
-
"
|
|
13
|
+
"0xD765Dff7D734ABE09f88991A46BAb73ACa8910EF",
|
|
14
14
|
421614,
|
|
15
15
|
);
|
|
16
16
|
|
|
@@ -25,7 +25,7 @@ async function minimalFlow() {
|
|
|
25
25
|
await client.ensureAccount(sender);
|
|
26
26
|
await client.ensureAccount(recipient);
|
|
27
27
|
|
|
28
|
-
const TOKEN = "
|
|
28
|
+
const TOKEN = "0xD765Dff7D734ABE09f88991A46BAb73ACa8910EF";
|
|
29
29
|
const amount = ethers.parseUnits("0.001", 6);
|
|
30
30
|
let res;
|
|
31
31
|
// 3. DEPOSIT: Move public ERC20 into the confidential contract
|
package/package.json
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fairblock/stabletrust",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.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",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"sideEffects": [
|
|
9
|
+
"**/*.wasm"
|
|
10
|
+
],
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
13
|
"types": "./src/index.d.ts",
|
|
11
|
-
"import": "./src/index.js"
|
|
14
|
+
"import": "./src/index.js",
|
|
15
|
+
"default": "./src/index.js"
|
|
12
16
|
},
|
|
13
|
-
"./wasm": "./pkg/confidential_transfer_proof_generation.js"
|
|
17
|
+
"./wasm": "./pkg/confidential_transfer_proof_generation.js",
|
|
18
|
+
"./pkg/*.wasm": "./pkg/*.wasm"
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
16
21
|
"src/",
|
package/src/client.js
CHANGED
|
@@ -311,10 +311,6 @@ export class ConfidentialTransferClient {
|
|
|
311
311
|
* @param {string} recipientAddress - Recipient's address
|
|
312
312
|
* @param {string} tokenAddress - Token address to transfer
|
|
313
313
|
* @param {number} amount - Amount to transfer
|
|
314
|
-
* @param {Object} senderKeys - Sender's encryption keys
|
|
315
|
-
* @param {string} recipientPublicKey - Recipient's public key
|
|
316
|
-
* @param {string} currentBalanceCiphertext - Current balance ciphertext
|
|
317
|
-
* @param {number} currentBalance - Current balance (decrypted)
|
|
318
314
|
* @param {Object} [options] - Options
|
|
319
315
|
* @param {boolean} [options.useOffchainVerify=false] - Use offchain verification
|
|
320
316
|
* @param {boolean} [options.waitForFinalization=true] - Wait for transfer finalization
|
|
@@ -658,9 +654,6 @@ export class ConfidentialTransferClient {
|
|
|
658
654
|
* @param {ethers.Wallet|ethers.Signer} wallet - The wallet to withdraw from
|
|
659
655
|
* @param {string} tokenAddress - Token address to withdraw
|
|
660
656
|
* @param {number} amount - Amount to withdraw
|
|
661
|
-
* @param {Object} keys - Encryption keys
|
|
662
|
-
* @param {string} currentBalanceCiphertext - Current balance ciphertext
|
|
663
|
-
* @param {number} currentBalance - Current balance (decrypted)
|
|
664
657
|
* @param {Object} [options] - Options
|
|
665
658
|
* @param {boolean} [options.useOffchainVerify=false] - Use offchain verification
|
|
666
659
|
* @param {boolean} [options.waitForFinalization=true] - Wait for withdrawal finalization
|
package/src/index.d.ts
CHANGED
|
@@ -90,7 +90,7 @@ declare module "@fairblock/stabletrust" {
|
|
|
90
90
|
* @param contractAddress Confidential transfer contract address
|
|
91
91
|
* @param chainId Chain ID
|
|
92
92
|
*/
|
|
93
|
-
constructor(rpcUrl: string, contractAddress: string, chainId
|
|
93
|
+
constructor(rpcUrl: string, contractAddress: string, chainId: number);
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Derive encryption keys for a wallet
|
|
@@ -168,18 +168,12 @@ declare module "@fairblock/stabletrust" {
|
|
|
168
168
|
* @param wallet Wallet to withdraw to
|
|
169
169
|
* @param tokenAddress Token contract address to withdraw
|
|
170
170
|
* @param amount Amount to withdraw
|
|
171
|
-
* @param keys Encryption keys
|
|
172
|
-
* @param currentBalanceCiphertext Current balance ciphertext
|
|
173
|
-
* @param currentBalance Current balance (decrypted)
|
|
174
171
|
* @param options Withdrawal options
|
|
175
172
|
*/
|
|
176
173
|
withdraw(
|
|
177
174
|
wallet: ethers.Wallet | ethers.Signer,
|
|
178
175
|
tokenAddress: string,
|
|
179
176
|
amount: number,
|
|
180
|
-
keys: Keys,
|
|
181
|
-
currentBalanceCiphertext: string,
|
|
182
|
-
currentBalance: number,
|
|
183
177
|
options?: WithdrawOptions,
|
|
184
178
|
): Promise<ethers.ContractTransactionReceipt>;
|
|
185
179
|
|
package/src/wasm-loader.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
1
|
import init, {
|
|
5
2
|
generate_deterministic_keypair,
|
|
6
3
|
generate_transfer_proof,
|
|
@@ -8,19 +5,31 @@ import init, {
|
|
|
8
5
|
decrypt_ciphertext,
|
|
9
6
|
} from "../pkg/confidential_transfer_proof_generation.js";
|
|
10
7
|
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = path.dirname(__filename);
|
|
13
|
-
|
|
14
8
|
let isInitialized = false;
|
|
9
|
+
let initPromise = null;
|
|
15
10
|
|
|
16
11
|
/**
|
|
17
12
|
* Initialize the WASM module
|
|
18
13
|
* This must be called before using the SDK
|
|
19
14
|
*
|
|
20
|
-
*
|
|
15
|
+
* In browsers, the WASM file is automatically loaded using bundler's asset handling.
|
|
16
|
+
* In Node.js, the WASM file is loaded from the filesystem.
|
|
17
|
+
*
|
|
18
|
+
* @param {Buffer|Uint8Array|string|URL} [input] - Optional custom WASM file path, URL, or buffer
|
|
21
19
|
* @returns {Promise<Object>} WASM module functions
|
|
22
20
|
*/
|
|
23
|
-
export async function initializeWasm(
|
|
21
|
+
export async function initializeWasm(input) {
|
|
22
|
+
// Return existing initialization if already in progress or complete
|
|
23
|
+
if (initPromise) {
|
|
24
|
+
await initPromise;
|
|
25
|
+
return {
|
|
26
|
+
generate_deterministic_keypair,
|
|
27
|
+
generate_transfer_proof,
|
|
28
|
+
generate_withdraw_proof,
|
|
29
|
+
decrypt_ciphertext,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
if (isInitialized) {
|
|
25
34
|
return {
|
|
26
35
|
generate_deterministic_keypair,
|
|
@@ -30,40 +39,57 @@ export async function initializeWasm(wasmPath) {
|
|
|
30
39
|
};
|
|
31
40
|
}
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
// Create initialization promise
|
|
43
|
+
initPromise = (async () => {
|
|
44
|
+
try {
|
|
45
|
+
// Detect Node.js environment
|
|
46
|
+
const isNode =
|
|
47
|
+
typeof process !== "undefined" &&
|
|
48
|
+
process.versions != null &&
|
|
49
|
+
process.versions.node != null;
|
|
35
50
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
if (input) {
|
|
52
|
+
// User provided custom input
|
|
53
|
+
await init(input);
|
|
54
|
+
} else if (isNode) {
|
|
55
|
+
// Node.js: Load from filesystem
|
|
56
|
+
const fs = await import("fs");
|
|
57
|
+
const path = await import("path");
|
|
58
|
+
const { fileURLToPath } = await import("url");
|
|
59
|
+
|
|
60
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
61
|
+
const __dirname = path.dirname(__filename);
|
|
62
|
+
const wasmPath = path.resolve(
|
|
63
|
+
__dirname,
|
|
64
|
+
"../pkg/confidential_transfer_proof_generation_bg.wasm",
|
|
65
|
+
);
|
|
66
|
+
const wasmBuffer = fs.readFileSync(wasmPath);
|
|
67
|
+
|
|
68
|
+
await init(wasmBuffer);
|
|
40
69
|
} else {
|
|
41
|
-
|
|
70
|
+
// Browser: Let the generated code handle it automatically
|
|
71
|
+
// It will use new URL(..., import.meta.url) which bundlers handle correctly
|
|
72
|
+
await init();
|
|
42
73
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
74
|
+
|
|
75
|
+
isInitialized = true;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
initPromise = null; // Reset on failure so it can be retried
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Failed to initialize WASM module: ${error.message}. ` +
|
|
80
|
+
`Make sure the WASM file exists at the expected location.`,
|
|
48
81
|
);
|
|
49
|
-
wasmBuffer = fs.readFileSync(defaultWasmPath);
|
|
50
82
|
}
|
|
83
|
+
})();
|
|
51
84
|
|
|
52
|
-
|
|
53
|
-
isInitialized = true;
|
|
85
|
+
await initPromise;
|
|
54
86
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} catch (error) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Failed to initialize WASM module: ${error.message}. ` +
|
|
64
|
-
`Make sure the WASM file exists at the expected location.`,
|
|
65
|
-
);
|
|
66
|
-
}
|
|
87
|
+
return {
|
|
88
|
+
generate_deterministic_keypair,
|
|
89
|
+
generate_transfer_proof,
|
|
90
|
+
generate_withdraw_proof,
|
|
91
|
+
decrypt_ciphertext,
|
|
92
|
+
};
|
|
67
93
|
}
|
|
68
94
|
|
|
69
95
|
/**
|