Skip to content

Commit 639701e

Browse files
authored
feat: Adding seed to web client creation (#688)
1 parent 8a5e265 commit 639701e

File tree

8 files changed

+74
-12
lines changed

8 files changed

+74
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* Created functions for creating standard notes and note scripts easily on the web client (#686).
1919
* [BREAKING] Renamed plural modules to singular (#687).
2020
* [BREAKING] Made `idxdb` only usable on WASM targets (#685).
21+
* Added fixed seed option for web client generation (#688)
2122
* [BREAKING] Updated `init` command in the CLI to receive a `--network` flag (#690).
2223

2324
### Fixes

crates/web-client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@demox-labs/miden-sdk",
3-
"version": "0.6.1-next.3",
3+
"version": "0.6.1-next.4",
44
"description": "Polygon Miden Wasm SDK",
55
"collaborators": [
66
"Polygon Miden",

crates/web-client/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,20 @@ impl WebClient {
5656
&mut self,
5757
node_url: Option<String>,
5858
prover_url: Option<String>,
59+
seed: Option<Vec<u8>>,
5960
) -> Result<JsValue, JsValue> {
60-
let mut rng = StdRng::from_entropy();
61+
let mut rng = match seed {
62+
Some(seed_bytes) => {
63+
if seed_bytes.len() == 32 {
64+
let mut seed_array = [0u8; 32];
65+
seed_array.copy_from_slice(&seed_bytes);
66+
StdRng::from_seed(seed_array)
67+
} else {
68+
return Err(JsValue::from_str("Seed must be exactly 32 bytes"));
69+
}
70+
},
71+
None => StdRng::from_entropy(),
72+
};
6173
let coin_seed: [u64; 4] = rng.gen();
6274

6375
let rng = RpoRandomCoin::new(coin_seed.map(Felt::new));

crates/web-client/test.html

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,13 @@
123123
});
124124
}
125125

126-
async function createMidenWebClient(dbName = "MidenClientDB") {
126+
async function createMidenWebClient(dbName = "MidenClientDB", initSeed) {
127127
try {
128128
// let rpc_url = "http://18.203.155.106:57291"
129129
let rpc_url = "http://localhost:57291";
130130
let envoy_proxy_url = "http://localhost:8080";
131131
const webClient = new WebClient();
132-
await webClient.create_client(rpc_url);
132+
await webClient.create_client(rpc_url, null, initSeed);
133133
return webClient;
134134
} catch (error) {
135135
console.error("Failed to create client with web store:", error);
@@ -421,10 +421,20 @@
421421

422422
// Done
423423
async function testCreateNewWallet() {
424-
console.log("testCreateNewWallet started");
425-
let webClient = await createMidenWebClient();
424+
const initSeed = new Uint8Array([
425+
223, 198, 73, 130, 93, 79, 220, 107, 25, 181, 91, 235, 101, 105, 136,
426+
172, 151, 161, 174, 73, 142, 81, 238, 192, 227, 93, 54, 113, 136, 223,
427+
75, 174,
428+
]);
426429

427-
// await createNewWallet(webClient, "Private", true);
430+
console.log("testCreateNewWallet started");
431+
const webClient = await createMidenWebClient("MidenClientDB", initSeed);
432+
const wallet = await webClient.new_wallet(
433+
AccountStorageMode.public(),
434+
true
435+
);
436+
console.log("Wallet id: ");
437+
console.log(wallet.id().to_string());
428438

429439
console.log("testCreateNewWallet finished");
430440
}

crates/web-client/test/global.test.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ declare global {
7777
TransactionRequestBuilder: typeof TransactionRequestBuilder;
7878
TransactionScriptInputPair: typeof TransactionScriptInputPair;
7979
TransactionScriptInputPairArray: typeof TransactionScriptInputPairArray;
80+
WebClient: typeof WebClient;
8081
Word: typeof Word;
8182
create_client: () => Promise<void>;
8283

@@ -87,6 +88,7 @@ declare global {
8788
maxWaitTime?: number,
8889
delayInterval?: number
8990
) => Promise<void>;
91+
refreshClient: (initSeed?: Uint8Array) => Promise<void>;
9092
};
9193
}
9294
}

crates/web-client/test/mocha.global.setup.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ before(async () => {
133133
window.TransactionRequestBuilder = TransactionRequestBuilder;
134134
window.TransactionScriptInputPair = TransactionScriptInputPair;
135135
window.TransactionScriptInputPairArray = TransactionScriptInputPairArray;
136+
window.WebClient = WebClient;
136137
window.Word = Word;
137138

138139
// Create a namespace for helper functions
@@ -166,6 +167,12 @@ before(async () => {
166167
timeWaited += delayInterval;
167168
}
168169
};
170+
171+
window.helpers.refreshClient = async (initSeed) => {
172+
const client = new WebClient();
173+
await client.create_client(rpc_url, prover_url, initSeed);
174+
window.client = client;
175+
};
169176
},
170177
LOCAL_MIDEN_NODE_PORT,
171178
env.REMOTE_PROVER ? REMOTE_TX_PROVER_PORT : null

crates/web-client/test/new_account.test.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,30 @@ interface NewAccountTestResult {
2525

2626
export const createNewWallet = async (
2727
storageMode: StorageMode,
28-
mutable: boolean
28+
mutable: boolean,
29+
clientSeed?: Uint8Array,
30+
isolatedClient?: boolean
2931
): Promise<NewAccountTestResult> => {
32+
// Serialize initSeed for Puppeteer
33+
const serializedClientSeed = clientSeed ? Array.from(clientSeed) : null;
34+
3035
return await testingPage.evaluate(
31-
async (_storageMode, _mutable) => {
32-
const client = window.client;
36+
async (_storageMode, _mutable, _serializedClientSeed, _isolatedClient) => {
37+
if (_isolatedClient) {
38+
// Reconstruct Uint8Array inside the browser context
39+
const _clientSeed = _serializedClientSeed
40+
? new Uint8Array(_serializedClientSeed)
41+
: undefined;
42+
43+
await window.helpers.refreshClient(_clientSeed);
44+
}
45+
46+
let client = window.client;
3347
const accountStorageMode =
3448
_storageMode === "private"
3549
? window.AccountStorageMode.private()
3650
: window.AccountStorageMode.public();
51+
3752
const newWallet = await client.new_wallet(accountStorageMode, _mutable);
3853

3954
return {
@@ -50,7 +65,9 @@ export const createNewWallet = async (
5065
};
5166
},
5267
storageMode,
53-
mutable
68+
mutable,
69+
serializedClientSeed,
70+
isolatedClient
5471
);
5572
};
5673

@@ -110,6 +127,19 @@ describe("new_wallet tests", () => {
110127
expect(result.is_new).to.equal(true);
111128
});
112129
});
130+
131+
it("Constructs the same account when given the same init seed", async () => {
132+
const clientSeed = new Uint8Array(32);
133+
crypto.getRandomValues(clientSeed);
134+
135+
// Isolate the client instance both times to ensure the outcome is deterministic
136+
await createNewWallet(StorageMode.PUBLIC, false, clientSeed, true);
137+
138+
// This should fail, as the wallet is already tracked within the same browser context
139+
await expect(
140+
createNewWallet(StorageMode.PUBLIC, false, clientSeed, true)
141+
).to.be.rejectedWith(/Failed to insert new wallet: AccountAlreadyTracked/);
142+
});
113143
});
114144

115145
// new_faucet tests

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"dependencies": {
3-
"prettier": "^3.3.3"
3+
"prettier": "^3.4.2"
44
},
55
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
66
}

0 commit comments

Comments
 (0)