@miden-sdk/miden-sdk 0.14.4 → 0.15.0-alpha.4

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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -9
  3. package/dist/{Cargo-Bwjf7IkR.js → Cargo-CVlXCH_2.js} +7105 -6141
  4. package/dist/Cargo-CVlXCH_2.js.map +1 -0
  5. package/dist/api-types.d.ts +17 -47
  6. package/dist/assets/miden_client_web.wasm +0 -0
  7. package/dist/crates/miden_client_web.d.ts +122 -76
  8. package/dist/docs-entry.d.ts +5 -2
  9. package/dist/eager.js +7 -4
  10. package/dist/eager.js.map +1 -1
  11. package/dist/index.d.ts +107 -7
  12. package/dist/index.js +534 -355
  13. package/dist/index.js.map +1 -1
  14. package/dist/wasm.js +1 -1
  15. package/dist/workers/{Cargo-Bwjf7IkR-Cz54YuXA.js → Cargo-CVlXCH_2-CWA-5vlh.js} +7105 -6141
  16. package/dist/workers/Cargo-CVlXCH_2-CWA-5vlh.js.map +1 -0
  17. package/dist/workers/assets/miden_client_web.wasm +0 -0
  18. package/dist/workers/web-client-methods-worker.js +7129 -6159
  19. package/dist/workers/web-client-methods-worker.js.map +1 -1
  20. package/dist/workers/web-client-methods-worker.module.js +23 -19
  21. package/dist/workers/web-client-methods-worker.module.js.map +1 -1
  22. package/js/client.js +327 -0
  23. package/js/node/client-factory.js +117 -0
  24. package/js/node/loader.js +138 -0
  25. package/js/node/napi-compat.js +238 -0
  26. package/js/node-index.js +195 -0
  27. package/js/resources/accounts.js +224 -0
  28. package/js/resources/compiler.js +74 -0
  29. package/js/resources/keystore.js +54 -0
  30. package/js/resources/notes.js +124 -0
  31. package/js/resources/settings.js +30 -0
  32. package/js/resources/tags.js +31 -0
  33. package/js/resources/transactions.js +533 -0
  34. package/js/standalone.js +109 -0
  35. package/js/utils.js +232 -0
  36. package/lazy/package.json +4 -0
  37. package/package.json +62 -40
  38. package/dist/Cargo-Bwjf7IkR.js.map +0 -1
  39. package/dist/workers/Cargo-Bwjf7IkR-Cz54YuXA.js.map +0 -1
@@ -0,0 +1,224 @@
1
+ import {
2
+ resolveAccountRef,
3
+ resolveStorageMode,
4
+ resolveAuthScheme,
5
+ resolveAccountMutability,
6
+ hashSeed,
7
+ } from "../utils.js";
8
+
9
+ export class AccountsResource {
10
+ #inner;
11
+ #getWasm;
12
+ #client;
13
+
14
+ constructor(inner, getWasm, client) {
15
+ this.#inner = inner;
16
+ this.#getWasm = getWasm;
17
+ this.#client = client;
18
+ }
19
+
20
+ async create(opts) {
21
+ this.#client.assertNotTerminated();
22
+ const wasm = await this.#getWasm();
23
+
24
+ const type = opts?.type;
25
+
26
+ if (
27
+ type === 0 ||
28
+ type === 1 ||
29
+ type === "FungibleFaucet" ||
30
+ type === "NonFungibleFaucet"
31
+ ) {
32
+ const storageMode = resolveStorageMode(opts.storage ?? "public", wasm);
33
+ const authScheme = resolveAuthScheme(opts.auth, wasm);
34
+ return await this.#inner.newFaucet(
35
+ storageMode,
36
+ type === 1 || type === "NonFungibleFaucet",
37
+ opts.symbol,
38
+ opts.decimals,
39
+ BigInt(opts.maxSupply),
40
+ authScheme
41
+ );
42
+ } else if (
43
+ type === "ImmutableContract" ||
44
+ type === "MutableContract" ||
45
+ opts?.components // Contracts are distinguished from wallets by having components
46
+ ) {
47
+ return await this.#createContract(opts, wasm);
48
+ } else {
49
+ // Default: wallet (mutable or immutable based on type)
50
+ const mutable = resolveAccountMutability(opts?.type);
51
+ const storageMode = resolveStorageMode(opts?.storage ?? "private", wasm);
52
+ const authScheme = resolveAuthScheme(opts?.auth, wasm);
53
+ const seed = opts?.seed ? await hashSeed(opts.seed) : undefined;
54
+ return await this.#inner.newWallet(
55
+ storageMode,
56
+ mutable,
57
+ authScheme,
58
+ seed
59
+ );
60
+ }
61
+ }
62
+
63
+ async #createContract(opts, wasm) {
64
+ if (!opts.seed)
65
+ throw new Error("Contract creation requires a 'seed' (Uint8Array)");
66
+ if (!opts.auth)
67
+ throw new Error("Contract creation requires an 'auth' (AuthSecretKey)");
68
+
69
+ // Default to immutable when type is omitted (safer for contracts)
70
+ const mutable = opts.type === "MutableContract" || opts.type === 3;
71
+ const accountTypeEnum = mutable
72
+ ? wasm.AccountType.RegularAccountUpdatableCode
73
+ : wasm.AccountType.RegularAccountImmutableCode;
74
+ const storageMode = resolveStorageMode(opts.storage ?? "public", wasm);
75
+ const authComponent =
76
+ wasm.AccountComponent.createAuthComponentFromSecretKey(opts.auth);
77
+
78
+ // Schema commitment from `build()` is not a substitute for contract code; require explicit
79
+ // `components` so auth-only contracts are rejected at this layer.
80
+ const components = opts.components ?? [];
81
+ if (components.length === 0) {
82
+ throw new Error(
83
+ "Contract accounts require at least one non-auth procedure: pass at least one entry in `components`."
84
+ );
85
+ }
86
+
87
+ let builder = new wasm.AccountBuilder(opts.seed)
88
+ .accountType(accountTypeEnum)
89
+ .storageMode(storageMode)
90
+ .withAuthComponent(authComponent);
91
+
92
+ for (const component of components) {
93
+ builder = builder.withComponent(component);
94
+ }
95
+
96
+ const built = builder.build();
97
+ const account = built.account;
98
+
99
+ await this.#inner.newAccountWithSecretKey(account, opts.auth);
100
+ return account;
101
+ }
102
+
103
+ async insert({ account, overwrite = false }) {
104
+ this.#client.assertNotTerminated();
105
+ await this.#inner.newAccount(account, overwrite);
106
+ }
107
+
108
+ async getOrImport(ref) {
109
+ this.#client.assertNotTerminated();
110
+ return (await this.get(ref)) ?? (await this.import(ref));
111
+ }
112
+
113
+ async get(ref) {
114
+ this.#client.assertNotTerminated();
115
+ const wasm = await this.#getWasm();
116
+ const id = resolveAccountRef(ref, wasm);
117
+ const account = await this.#inner.getAccount(id);
118
+ return account ?? null;
119
+ }
120
+
121
+ async list() {
122
+ this.#client.assertNotTerminated();
123
+ return await this.#inner.getAccounts();
124
+ }
125
+
126
+ async getDetails(ref) {
127
+ this.#client.assertNotTerminated();
128
+ const wasm = await this.#getWasm();
129
+ const id = resolveAccountRef(ref, wasm);
130
+ const account = await this.#inner.getAccount(id);
131
+ if (!account) {
132
+ throw new Error(`Account not found: ${id.toString()}`);
133
+ }
134
+ const keys = this.#inner.keystore
135
+ ? await this.#inner.keystore.getCommitments(id)
136
+ : await this.#inner.getPublicKeyCommitmentsOfAccount(id);
137
+ return {
138
+ account,
139
+ vault: account.vault(),
140
+ storage: account.storage(),
141
+ code: account.code() ?? null,
142
+ keys,
143
+ };
144
+ }
145
+
146
+ async getBalance(accountRef, tokenRef) {
147
+ this.#client.assertNotTerminated();
148
+ const wasm = await this.#getWasm();
149
+ const accountId = resolveAccountRef(accountRef, wasm);
150
+ const faucetId = resolveAccountRef(tokenRef, wasm);
151
+ const reader = await this.#inner.accountReader(accountId);
152
+ return await reader.getBalance(faucetId);
153
+ }
154
+
155
+ async import(input) {
156
+ this.#client.assertNotTerminated();
157
+ const wasm = await this.#getWasm();
158
+
159
+ // Early exit for string, Account, and AccountHeader types before property
160
+ // checks, preventing misrouting if a WASM object ever gains a .file or .seed
161
+ // property. Bare AccountId (no .id() method) falls through to the fallback.
162
+ if (typeof input === "string" || typeof input.id === "function") {
163
+ const id = resolveAccountRef(input, wasm);
164
+ await this.#inner.importAccountById(id);
165
+ return await this.#inner.getAccount(id);
166
+ }
167
+
168
+ if (input.file) {
169
+ // Extract accountId before importAccountFile — WASM consumes the
170
+ // AccountFile by value, invalidating the JS wrapper after the call.
171
+ const accountId =
172
+ typeof input.file.accountId === "function"
173
+ ? input.file.accountId()
174
+ : null;
175
+ await this.#inner.importAccountFile(input.file);
176
+ if (accountId) {
177
+ return await this.#inner.getAccount(accountId);
178
+ }
179
+ throw new Error(
180
+ "Could not determine account ID from AccountFile. " +
181
+ "Ensure the file contains a valid account."
182
+ );
183
+ }
184
+
185
+ if (input.seed) {
186
+ // Import public account from seed
187
+ const authScheme = resolveAuthScheme(input.auth, wasm);
188
+ const mutable = resolveAccountMutability(input.type);
189
+ return await this.#inner.importPublicAccountFromSeed(
190
+ input.seed,
191
+ mutable,
192
+ authScheme
193
+ );
194
+ }
195
+
196
+ // Fallback: treat as AccountRef (string, AccountId, Account, AccountHeader)
197
+ const id = resolveAccountRef(input, wasm);
198
+ await this.#inner.importAccountById(id);
199
+ return await this.#inner.getAccount(id);
200
+ }
201
+
202
+ async export(ref) {
203
+ this.#client.assertNotTerminated();
204
+ const wasm = await this.#getWasm();
205
+ const id = resolveAccountRef(ref, wasm);
206
+ return await this.#inner.exportAccountFile(id);
207
+ }
208
+
209
+ async addAddress(ref, addr) {
210
+ this.#client.assertNotTerminated();
211
+ const wasm = await this.#getWasm();
212
+ const id = resolveAccountRef(ref, wasm);
213
+ const address = wasm.Address.fromBech32(addr);
214
+ await this.#inner.insertAccountAddress(id, address);
215
+ }
216
+
217
+ async removeAddress(ref, addr) {
218
+ this.#client.assertNotTerminated();
219
+ const wasm = await this.#getWasm();
220
+ const id = resolveAccountRef(ref, wasm);
221
+ const address = wasm.Address.fromBech32(addr);
222
+ await this.#inner.removeAccountAddress(id, address);
223
+ }
224
+ }
@@ -0,0 +1,74 @@
1
+ export class CompilerResource {
2
+ #inner;
3
+ #getWasm;
4
+ #client;
5
+
6
+ constructor(inner, getWasm, client = null) {
7
+ this.#inner = inner;
8
+ this.#getWasm = getWasm;
9
+ this.#client = client;
10
+ }
11
+
12
+ /**
13
+ * Compiles MASM code + slots into an AccountComponent ready for accounts.create().
14
+ *
15
+ * @param {{ code: string, slots: StorageSlot[], supportAllTypes?: boolean }} opts
16
+ * @returns {Promise<AccountComponent>}
17
+ */
18
+ async component({ code, slots = [], supportAllTypes = true }) {
19
+ this.#client?.assertNotTerminated();
20
+ const wasm = await this.#getWasm();
21
+ const builder = await this.#inner.createCodeBuilder();
22
+ const compiled = builder.compileAccountComponentCode(code);
23
+ const component = wasm.AccountComponent.compile(compiled, slots);
24
+ return supportAllTypes ? component.withSupportsAllTypes() : component;
25
+ }
26
+
27
+ /**
28
+ * Compiles a transaction script, optionally linking named libraries inline.
29
+ *
30
+ * @param {{ code: string, libraries?: Array<{ namespace: string, code: string, linking?: "dynamic" | "static" }> }} opts
31
+ * @returns {Promise<TransactionScript>}
32
+ */
33
+ async txScript({ code, libraries = [] }) {
34
+ this.#client?.assertNotTerminated();
35
+ // Ensure WASM is initialized (result unused — only #inner needs it)
36
+ await this.#getWasm();
37
+ const builder = await this.#inner.createCodeBuilder();
38
+ linkLibraries(builder, libraries);
39
+ return builder.compileTxScript(code);
40
+ }
41
+
42
+ /**
43
+ * Compiles a note script, optionally linking named libraries inline.
44
+ *
45
+ * @param {{ code: string, libraries?: Array<{ namespace: string, code: string, linking?: "dynamic" | "static" }> }} opts
46
+ * @returns {Promise<NoteScript>}
47
+ */
48
+ async noteScript({ code, libraries = [] }) {
49
+ this.#client?.assertNotTerminated();
50
+ await this.#getWasm();
51
+ const builder = await this.#inner.createCodeBuilder();
52
+ linkLibraries(builder, libraries);
53
+ return builder.compileNoteScript(code);
54
+ }
55
+ }
56
+
57
+ // Builds and links each library entry against `builder`. Inline
58
+ // `{ namespace, code, linking? }` entries are built via `buildLibrary` and
59
+ // linked according to `linking` (defaulting to dynamic, matching tutorial
60
+ // behavior). Pre-built library objects are linked dynamically.
61
+ function linkLibraries(builder, libraries) {
62
+ for (const lib of libraries) {
63
+ if (lib && typeof lib.namespace === "string") {
64
+ const built = builder.buildLibrary(lib.namespace, lib.code);
65
+ if (lib.linking === "static") {
66
+ builder.linkStaticLibrary(built);
67
+ } else {
68
+ builder.linkDynamicLibrary(built);
69
+ }
70
+ } else {
71
+ builder.linkDynamicLibrary(lib);
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,54 @@
1
+ export class KeystoreResource {
2
+ #inner;
3
+ #client;
4
+
5
+ constructor(inner, client) {
6
+ this.#inner = inner;
7
+ this.#client = client;
8
+ }
9
+
10
+ async insert(accountId, secretKey) {
11
+ this.#client.assertNotTerminated();
12
+ if (this.#inner.keystore) {
13
+ return await this.#inner.keystore.insert(accountId, secretKey);
14
+ }
15
+ return await this.#inner.addAccountSecretKeyToWebStore(
16
+ accountId,
17
+ secretKey
18
+ );
19
+ }
20
+
21
+ async get(pubKeyCommitment) {
22
+ this.#client.assertNotTerminated();
23
+ if (this.#inner.keystore) {
24
+ return await this.#inner.keystore.get(pubKeyCommitment);
25
+ }
26
+ return await this.#inner.getAccountAuthByPubKeyCommitment(pubKeyCommitment);
27
+ }
28
+
29
+ async remove(pubKeyCommitment) {
30
+ this.#client.assertNotTerminated();
31
+ if (this.#inner.keystore) {
32
+ return await this.#inner.keystore.remove(pubKeyCommitment);
33
+ }
34
+ throw new Error("remove() is not supported on this platform");
35
+ }
36
+
37
+ async getCommitments(accountId) {
38
+ this.#client.assertNotTerminated();
39
+ if (this.#inner.keystore) {
40
+ return await this.#inner.keystore.getCommitments(accountId);
41
+ }
42
+ return await this.#inner.getPublicKeyCommitmentsOfAccount(accountId);
43
+ }
44
+
45
+ async getAccountId(pubKeyCommitment) {
46
+ this.#client.assertNotTerminated();
47
+ if (this.#inner.keystore) {
48
+ return await this.#inner.keystore.getAccountId(pubKeyCommitment);
49
+ }
50
+ const account =
51
+ await this.#inner.getAccountByKeyCommitment(pubKeyCommitment);
52
+ return account ? account.id() : undefined;
53
+ }
54
+ }
@@ -0,0 +1,124 @@
1
+ import {
2
+ resolveAccountRef,
3
+ resolveAddress,
4
+ resolveNoteIdHex,
5
+ } from "../utils.js";
6
+
7
+ export class NotesResource {
8
+ #inner;
9
+ #getWasm;
10
+ #client;
11
+
12
+ constructor(inner, getWasm, client) {
13
+ this.#inner = inner;
14
+ this.#getWasm = getWasm;
15
+ this.#client = client;
16
+ }
17
+
18
+ async list(query) {
19
+ this.#client.assertNotTerminated();
20
+ const wasm = await this.#getWasm();
21
+ const filter = buildNoteFilter(query, wasm);
22
+ return await this.#inner.getInputNotes(filter);
23
+ }
24
+
25
+ async get(noteId) {
26
+ this.#client.assertNotTerminated();
27
+ const result = await this.#inner.getInputNote(resolveNoteIdHex(noteId));
28
+ return result ?? null;
29
+ }
30
+
31
+ async listSent(query) {
32
+ this.#client.assertNotTerminated();
33
+ const wasm = await this.#getWasm();
34
+ const filter = buildNoteFilter(query, wasm);
35
+ return await this.#inner.getOutputNotes(filter);
36
+ }
37
+
38
+ async listAvailable(opts) {
39
+ this.#client.assertNotTerminated();
40
+ const wasm = await this.#getWasm();
41
+ const accountId = resolveAccountRef(opts.account, wasm);
42
+ const consumable = await this.#inner.getConsumableNotes(accountId);
43
+ return consumable.map((c) => c.inputNoteRecord());
44
+ }
45
+
46
+ async import(noteFile) {
47
+ this.#client.assertNotTerminated();
48
+ return await this.#inner.importNoteFile(noteFile);
49
+ }
50
+
51
+ async export(noteId, opts) {
52
+ this.#client.assertNotTerminated();
53
+ const wasm = await this.#getWasm();
54
+ const format = opts?.format ?? wasm.NoteExportFormat.Full;
55
+ return await this.#inner.exportNoteFile(resolveNoteIdHex(noteId), format);
56
+ }
57
+
58
+ async fetchPrivate(opts) {
59
+ this.#client.assertNotTerminated();
60
+ if (opts?.mode === "all") {
61
+ await this.#inner.fetchAllPrivateNotes();
62
+ } else {
63
+ await this.#inner.fetchPrivateNotes();
64
+ }
65
+ }
66
+
67
+ async sendPrivate(opts) {
68
+ this.#client.assertNotTerminated();
69
+ const wasm = await this.#getWasm();
70
+
71
+ let note;
72
+ const input = opts.note;
73
+ // Check if input is a Note object (has .id() and .assets() but not .toNote())
74
+ if (
75
+ input &&
76
+ typeof input === "object" &&
77
+ typeof input.id === "function" &&
78
+ typeof input.assets === "function" &&
79
+ typeof input.toNote !== "function"
80
+ ) {
81
+ note = input;
82
+ } else {
83
+ const noteHex = resolveNoteIdHex(input);
84
+ const noteRecord = await this.#inner.getInputNote(noteHex);
85
+ if (!noteRecord) {
86
+ throw new Error(`Note not found: ${noteHex}`);
87
+ }
88
+ note = noteRecord.toNote();
89
+ }
90
+
91
+ const address = resolveAddress(opts.to, wasm);
92
+ await this.#inner.sendPrivateNote(note, address);
93
+ }
94
+ }
95
+
96
+ function buildNoteFilter(query, wasm) {
97
+ if (!query) {
98
+ return new wasm.NoteFilter(wasm.NoteFilterTypes.All, undefined);
99
+ }
100
+
101
+ if (query.ids) {
102
+ const noteIds = query.ids.map((id) =>
103
+ wasm.NoteId.fromHex(resolveNoteIdHex(id))
104
+ );
105
+ return new wasm.NoteFilter(wasm.NoteFilterTypes.List, noteIds);
106
+ }
107
+
108
+ if (query.status) {
109
+ const statusMap = {
110
+ consumed: wasm.NoteFilterTypes.Consumed,
111
+ committed: wasm.NoteFilterTypes.Committed,
112
+ expected: wasm.NoteFilterTypes.Expected,
113
+ processing: wasm.NoteFilterTypes.Processing,
114
+ unverified: wasm.NoteFilterTypes.Unverified,
115
+ };
116
+ const filterType = statusMap[query.status];
117
+ if (filterType === undefined) {
118
+ throw new Error(`Unknown note status: ${query.status}`);
119
+ }
120
+ return new wasm.NoteFilter(filterType, undefined);
121
+ }
122
+
123
+ return new wasm.NoteFilter(wasm.NoteFilterTypes.All, undefined);
124
+ }
@@ -0,0 +1,30 @@
1
+ export class SettingsResource {
2
+ #inner;
3
+ #client;
4
+
5
+ constructor(inner, _getWasm, client) {
6
+ this.#inner = inner;
7
+ this.#client = client;
8
+ }
9
+
10
+ async get(key) {
11
+ this.#client.assertNotTerminated();
12
+ const value = await this.#inner.getSetting(key);
13
+ return value === undefined ? null : value;
14
+ }
15
+
16
+ async set(key, value) {
17
+ this.#client.assertNotTerminated();
18
+ await this.#inner.setSetting(key, value);
19
+ }
20
+
21
+ async remove(key) {
22
+ this.#client.assertNotTerminated();
23
+ await this.#inner.removeSetting(key);
24
+ }
25
+
26
+ async listKeys() {
27
+ this.#client.assertNotTerminated();
28
+ return await this.#inner.listSettingKeys();
29
+ }
30
+ }
@@ -0,0 +1,31 @@
1
+ export class TagsResource {
2
+ #inner;
3
+ #client;
4
+
5
+ constructor(inner, getWasm, client) {
6
+ this.#inner = inner;
7
+ this.#client = client;
8
+ }
9
+
10
+ async add(tag) {
11
+ this.#client.assertNotTerminated();
12
+ await this.#inner.addTag(String(tag));
13
+ }
14
+
15
+ async remove(tag) {
16
+ this.#client.assertNotTerminated();
17
+ await this.#inner.removeTag(String(tag));
18
+ }
19
+
20
+ async list() {
21
+ this.#client.assertNotTerminated();
22
+ const tags = await this.#inner.listTags();
23
+ return Array.from(tags).map((t) => {
24
+ const n = Number(t);
25
+ if (Number.isNaN(n)) {
26
+ throw new Error(`Invalid tag value: ${t}`);
27
+ }
28
+ return n;
29
+ });
30
+ }
31
+ }