@miden-sdk/miden-sdk 0.14.5 → 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.
- package/LICENSE +21 -0
- package/README.md +9 -9
- package/dist/{Cargo-M3382VZc.js → Cargo-CVlXCH_2.js} +7129 -6225
- package/dist/Cargo-CVlXCH_2.js.map +1 -0
- package/dist/api-types.d.ts +19 -65
- package/dist/assets/miden_client_web.wasm +0 -0
- package/dist/crates/miden_client_web.d.ts +122 -172
- package/dist/docs-entry.d.ts +5 -2
- package/dist/eager.js +7 -4
- package/dist/eager.js.map +1 -1
- package/dist/index.d.ts +107 -14
- package/dist/index.js +529 -415
- package/dist/index.js.map +1 -1
- package/dist/wasm.js +1 -1
- package/dist/workers/{Cargo-M3382VZc-Dfw4tXwh.js → Cargo-CVlXCH_2-CWA-5vlh.js} +7129 -6225
- package/dist/workers/Cargo-CVlXCH_2-CWA-5vlh.js.map +1 -0
- package/dist/workers/assets/miden_client_web.wasm +0 -0
- package/dist/workers/web-client-methods-worker.js +7153 -6243
- package/dist/workers/web-client-methods-worker.js.map +1 -1
- package/dist/workers/web-client-methods-worker.module.js +23 -19
- package/dist/workers/web-client-methods-worker.module.js.map +1 -1
- package/js/client.js +327 -0
- package/js/node/client-factory.js +117 -0
- package/js/node/loader.js +138 -0
- package/js/node/napi-compat.js +238 -0
- package/js/node-index.js +195 -0
- package/js/resources/accounts.js +224 -0
- package/js/resources/compiler.js +74 -0
- package/js/resources/keystore.js +54 -0
- package/js/resources/notes.js +124 -0
- package/js/resources/settings.js +30 -0
- package/js/resources/tags.js +31 -0
- package/js/resources/transactions.js +533 -0
- package/js/standalone.js +109 -0
- package/js/utils.js +232 -0
- package/lazy/package.json +4 -0
- package/package.json +62 -40
- package/dist/Cargo-M3382VZc.js.map +0 -1
- package/dist/workers/Cargo-M3382VZc-Dfw4tXwh.js.map +0 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-specific client factories that match the browser SDK's interface.
|
|
3
|
+
*
|
|
4
|
+
* The browser SDK creates clients with IndexedDB store names.
|
|
5
|
+
* Node.js uses SQLite file paths and filesystem keystores.
|
|
6
|
+
* These factories bridge the difference so MidenClient.create() works on both.
|
|
7
|
+
*/
|
|
8
|
+
import path from "path";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import os from "os";
|
|
11
|
+
import { wrapClient, normalizeArg } from "./napi-compat.js";
|
|
12
|
+
|
|
13
|
+
let _counter = 0;
|
|
14
|
+
|
|
15
|
+
function createTempDir(label) {
|
|
16
|
+
const dir = path.join(
|
|
17
|
+
os.tmpdir(),
|
|
18
|
+
`miden-${label}-${process.pid}-${Date.now()}-${++_counter}`
|
|
19
|
+
);
|
|
20
|
+
fs.mkdirSync(path.join(dir, "keystore"), { recursive: true });
|
|
21
|
+
return dir;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns a deterministic data directory for a given store name.
|
|
26
|
+
* Uses ~/.miden/stores/<storeName>/ so data persists across runs.
|
|
27
|
+
*/
|
|
28
|
+
function defaultDataDir(storeName) {
|
|
29
|
+
const dir = path.join(os.homedir(), ".miden", "stores", storeName);
|
|
30
|
+
fs.mkdirSync(path.join(dir, "keystore"), { recursive: true });
|
|
31
|
+
return dir;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function normBytes(val) {
|
|
35
|
+
if (val instanceof Uint8Array || Buffer.isBuffer(val)) return Array.from(val);
|
|
36
|
+
return val;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates the WasmWebClient factory for Node.js.
|
|
41
|
+
*
|
|
42
|
+
* Matches the browser interface:
|
|
43
|
+
* WasmWebClient.createClient(rpcUrl, noteTransportUrl, seed, storeName, debugMode)
|
|
44
|
+
* WasmWebClient.createClientWithExternalKeystore(rpcUrl, noteTransportUrl, seed, storeName, getKey, insertKey, sign, debugMode)
|
|
45
|
+
* WasmWebClient.buildSwapTag(...)
|
|
46
|
+
*
|
|
47
|
+
* @param {object} rawSdk - The raw napi SDK module.
|
|
48
|
+
* @param {object} [options]
|
|
49
|
+
* @param {string} [options.dataDir] - Base directory for SQLite stores. Defaults to os.tmpdir().
|
|
50
|
+
*/
|
|
51
|
+
export function createWasmWebClient(rawSdk, options) {
|
|
52
|
+
return {
|
|
53
|
+
buildSwapTag: (...args) =>
|
|
54
|
+
rawSdk.WebClient.buildSwapTag(...args.map(normalizeArg)),
|
|
55
|
+
|
|
56
|
+
createClient: async (
|
|
57
|
+
rpcUrl,
|
|
58
|
+
noteTransportUrl,
|
|
59
|
+
seed,
|
|
60
|
+
storeName,
|
|
61
|
+
debugMode
|
|
62
|
+
) => {
|
|
63
|
+
const dir = options?.dataDir
|
|
64
|
+
? path.join(options.dataDir, storeName || "default")
|
|
65
|
+
: storeName
|
|
66
|
+
? defaultDataDir(storeName)
|
|
67
|
+
: createTempDir("client");
|
|
68
|
+
|
|
69
|
+
const client = new rawSdk.WebClient();
|
|
70
|
+
await client.createClient(
|
|
71
|
+
rpcUrl ?? null,
|
|
72
|
+
noteTransportUrl ?? null,
|
|
73
|
+
normBytes(seed) ?? null,
|
|
74
|
+
path.join(dir, `${storeName || "store"}.db`),
|
|
75
|
+
path.join(dir, "keystore"),
|
|
76
|
+
debugMode ?? false
|
|
77
|
+
);
|
|
78
|
+
return wrapClient(client, storeName);
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
createClientWithExternalKeystore: async () => {
|
|
82
|
+
throw new Error(
|
|
83
|
+
"External keystores are not supported on Node.js. " +
|
|
84
|
+
"The Node.js backend uses a filesystem keystore automatically."
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Creates the MockWasmWebClient factory for Node.js.
|
|
92
|
+
*
|
|
93
|
+
* Matches the browser interface:
|
|
94
|
+
* MockWasmWebClient.createClient(serializedMockChain, serializedNoteTransport, seed)
|
|
95
|
+
*
|
|
96
|
+
* @param {object} rawSdk - The raw napi SDK module.
|
|
97
|
+
*/
|
|
98
|
+
export function createMockWasmWebClient(rawSdk) {
|
|
99
|
+
return {
|
|
100
|
+
createClient: async (
|
|
101
|
+
serializedMockChain,
|
|
102
|
+
serializedNoteTransport,
|
|
103
|
+
seed
|
|
104
|
+
) => {
|
|
105
|
+
const dir = createTempDir("mock");
|
|
106
|
+
const client = new rawSdk.WebClient();
|
|
107
|
+
await client.createMockClient(
|
|
108
|
+
path.join(dir, "store.db"),
|
|
109
|
+
path.join(dir, "keystore"),
|
|
110
|
+
normBytes(seed) ?? null,
|
|
111
|
+
normBytes(serializedMockChain) ?? null,
|
|
112
|
+
normBytes(serializedNoteTransport) ?? null
|
|
113
|
+
);
|
|
114
|
+
return wrapClient(client, "mock");
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds and loads the napi native module (.node binary).
|
|
3
|
+
*
|
|
4
|
+
* Search order:
|
|
5
|
+
* 1. MIDEN_MODULE_PATH environment variable (explicit override)
|
|
6
|
+
* 2. Platform-specific npm package (@miden-sdk/node-darwin-arm64, etc.)
|
|
7
|
+
* 3. Package prebuilds directory
|
|
8
|
+
* 4. Repo target directory (for local development)
|
|
9
|
+
*/
|
|
10
|
+
import { createRequire } from "module";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import fs from "fs";
|
|
13
|
+
import os from "os";
|
|
14
|
+
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
|
|
17
|
+
let _sdk = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Loads the napi SDK module. Caches the result after first load.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} [options]
|
|
23
|
+
* @param {string} [options.modulePath] - Explicit path to the .node file.
|
|
24
|
+
* @returns {object} The napi SDK module.
|
|
25
|
+
*/
|
|
26
|
+
export function loadNativeModule(options) {
|
|
27
|
+
if (_sdk) return _sdk;
|
|
28
|
+
|
|
29
|
+
// 1. Explicit path (option or env var)
|
|
30
|
+
const explicit = options?.modulePath || process.env.MIDEN_MODULE_PATH;
|
|
31
|
+
if (explicit) {
|
|
32
|
+
_sdk = require(explicit);
|
|
33
|
+
return _sdk;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2. Platform-specific npm package (installed via optionalDependencies)
|
|
37
|
+
const platformPackage = getPlatformPackageName();
|
|
38
|
+
if (platformPackage) {
|
|
39
|
+
try {
|
|
40
|
+
_sdk = require(platformPackage);
|
|
41
|
+
return _sdk;
|
|
42
|
+
} catch {
|
|
43
|
+
// Not installed -- fall through to other methods
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const archMap = { arm64: "aarch64", x64: "x86_64" };
|
|
48
|
+
const arch = archMap[os.arch()] || os.arch();
|
|
49
|
+
const platform =
|
|
50
|
+
os.platform() === "darwin" ? "apple-darwin" : "unknown-linux-gnu";
|
|
51
|
+
const target = `${arch}-${platform}`;
|
|
52
|
+
const ext = os.platform() === "darwin" ? "dylib" : "so";
|
|
53
|
+
const libName = `libmiden_client_web.${ext}`;
|
|
54
|
+
|
|
55
|
+
// 3. Package prebuilds directory
|
|
56
|
+
const packageRoot = path.resolve(import.meta.dirname, "..");
|
|
57
|
+
const prebuildCandidates = [
|
|
58
|
+
path.join(
|
|
59
|
+
packageRoot,
|
|
60
|
+
"prebuilds",
|
|
61
|
+
`${os.platform()}-${os.arch()}`,
|
|
62
|
+
"miden_client_web.node"
|
|
63
|
+
),
|
|
64
|
+
path.join(packageRoot, "prebuilds", "miden_client_web.node"),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
for (const p of prebuildCandidates) {
|
|
68
|
+
if (fs.existsSync(p)) {
|
|
69
|
+
_sdk = require(p);
|
|
70
|
+
return _sdk;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 4. Repo target directory (development)
|
|
75
|
+
const repoRoot = findRepoRoot(packageRoot);
|
|
76
|
+
if (repoRoot) {
|
|
77
|
+
const targetCandidates = [
|
|
78
|
+
path.join(repoRoot, "target", target, "release", libName),
|
|
79
|
+
path.join(repoRoot, "target", "release", libName),
|
|
80
|
+
path.join(repoRoot, "target", target, "debug", libName),
|
|
81
|
+
path.join(repoRoot, "target", "debug", libName),
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
for (const p of targetCandidates) {
|
|
85
|
+
if (fs.existsSync(p)) {
|
|
86
|
+
// napi requires a .node extension -- copy if needed
|
|
87
|
+
const nodeFile = path.join(path.dirname(p), "miden_client_web.node");
|
|
88
|
+
if (
|
|
89
|
+
!fs.existsSync(nodeFile) ||
|
|
90
|
+
fs.statSync(p).mtimeMs > fs.statSync(nodeFile).mtimeMs
|
|
91
|
+
) {
|
|
92
|
+
fs.copyFileSync(p, nodeFile);
|
|
93
|
+
}
|
|
94
|
+
_sdk = require(nodeFile);
|
|
95
|
+
return _sdk;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Miden napi module not found.\n\n` +
|
|
102
|
+
`Build it with:\n` +
|
|
103
|
+
` cargo build -p miden-client-web --no-default-features --features nodejs --release\n\n` +
|
|
104
|
+
`Or set MIDEN_MODULE_PATH to the .node file location.`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns the platform-specific npm package name for the current OS/arch,
|
|
110
|
+
* or null if the platform is not supported.
|
|
111
|
+
*/
|
|
112
|
+
function getPlatformPackageName() {
|
|
113
|
+
const platformMap = {
|
|
114
|
+
"darwin-arm64": "@miden-sdk/node-darwin-arm64",
|
|
115
|
+
"darwin-x64": "@miden-sdk/node-darwin-x64",
|
|
116
|
+
"linux-x64": "@miden-sdk/node-linux-x64-gnu",
|
|
117
|
+
};
|
|
118
|
+
return platformMap[`${os.platform()}-${os.arch()}`] || null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Walks up from startDir looking for the repo root (has Cargo.toml + crates/).
|
|
123
|
+
*/
|
|
124
|
+
function findRepoRoot(startDir) {
|
|
125
|
+
let dir = startDir;
|
|
126
|
+
for (let i = 0; i < 10; i++) {
|
|
127
|
+
if (
|
|
128
|
+
fs.existsSync(path.join(dir, "Cargo.toml")) &&
|
|
129
|
+
fs.existsSync(path.join(dir, "crates"))
|
|
130
|
+
) {
|
|
131
|
+
return dir;
|
|
132
|
+
}
|
|
133
|
+
const parent = path.dirname(dir);
|
|
134
|
+
if (parent === dir) break;
|
|
135
|
+
dir = parent;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NAPI compatibility layer.
|
|
3
|
+
*
|
|
4
|
+
* Normalizes differences between the napi (Node.js) and wasm-bindgen (browser)
|
|
5
|
+
* SDK surfaces so the shared MidenClient wrapper works on both platforms.
|
|
6
|
+
*
|
|
7
|
+
* Key normalizations:
|
|
8
|
+
* - Uint8Array/Buffer -> Array (napi's Vec<u8> expects plain arrays)
|
|
9
|
+
* - BigUint64Array/BigInt64Array -> Array (napi's Vec<u64>/Vec<BigInt> expects plain arrays)
|
|
10
|
+
* - null -> undefined (napi returns null for Option::None, wasm-bindgen returns undefined)
|
|
11
|
+
* - camelCase -> snake_case aliases (napi uses camelCase, wasm-bindgen uses snake_case)
|
|
12
|
+
* - Array type polyfills (browser has typed WASM arrays, napi accepts plain JS arrays)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// ── Argument normalization ───────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Normalizes a single argument for napi compatibility.
|
|
19
|
+
*
|
|
20
|
+
* `BigInt` values are passed through untouched — napi-rs accepts JS `BigInt`
|
|
21
|
+
* for `u64` parameters (via `napi::bindgen_prelude::BigInt`), so no conversion
|
|
22
|
+
* is needed. Typed arrays of BigInts and bytes are converted to plain arrays.
|
|
23
|
+
*/
|
|
24
|
+
export function normalizeArg(val) {
|
|
25
|
+
if (val instanceof BigUint64Array) return Array.from(val);
|
|
26
|
+
if (val instanceof BigInt64Array) return Array.from(val);
|
|
27
|
+
if (val instanceof Uint8Array || Buffer.isBuffer(val)) return Array.from(val);
|
|
28
|
+
return val;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── Class wrapping ───────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wraps a napi class so constructor and static method args are normalized.
|
|
35
|
+
*/
|
|
36
|
+
function wrapClass(Cls) {
|
|
37
|
+
if (!Cls) return Cls;
|
|
38
|
+
const Wrapper = function (...args) {
|
|
39
|
+
return new Cls(...args.map(normalizeArg));
|
|
40
|
+
};
|
|
41
|
+
Wrapper.prototype = Cls.prototype;
|
|
42
|
+
for (const key of Object.getOwnPropertyNames(Cls)) {
|
|
43
|
+
if (key === "prototype" || key === "length" || key === "name") continue;
|
|
44
|
+
const desc = Object.getOwnPropertyDescriptor(Cls, key);
|
|
45
|
+
if (desc && typeof desc.value === "function") {
|
|
46
|
+
Wrapper[key] = (...args) => desc.value.apply(Cls, args.map(normalizeArg));
|
|
47
|
+
} else if (desc) {
|
|
48
|
+
try {
|
|
49
|
+
Object.defineProperty(Wrapper, key, desc);
|
|
50
|
+
} catch {
|
|
51
|
+
/* skip non-configurable */
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return Wrapper;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Client wrapping ──────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Wraps a raw napi WebClient to normalize API differences with the browser SDK.
|
|
62
|
+
*
|
|
63
|
+
* - syncState() -> syncStateImpl() (no browser lock coordination needed)
|
|
64
|
+
* - syncStateWithTimeout() -> syncStateImpl() (timeout not applicable)
|
|
65
|
+
* - null -> undefined for Option<T> returns
|
|
66
|
+
* - BigInt/Uint8Array args normalized
|
|
67
|
+
*/
|
|
68
|
+
export function wrapClient(rawClient, storeName) {
|
|
69
|
+
return new Proxy(rawClient, {
|
|
70
|
+
get(target, prop) {
|
|
71
|
+
if (prop === "syncState") {
|
|
72
|
+
return (...args) => target.syncStateImpl(...args);
|
|
73
|
+
}
|
|
74
|
+
if (prop === "syncStateWithTimeout") {
|
|
75
|
+
return (_timeoutMs) => target.syncStateImpl();
|
|
76
|
+
}
|
|
77
|
+
if (prop === "storeName") {
|
|
78
|
+
return storeName || "default";
|
|
79
|
+
}
|
|
80
|
+
if (prop === "wasmWebClient") {
|
|
81
|
+
return target;
|
|
82
|
+
}
|
|
83
|
+
if (prop === "storeIdentifier") {
|
|
84
|
+
return () => target.storeIdentifier?.() ?? storeName ?? "unknown";
|
|
85
|
+
}
|
|
86
|
+
// terminate is a no-op on Node.js (no Web Worker to terminate)
|
|
87
|
+
if (prop === "terminate") {
|
|
88
|
+
return () => {};
|
|
89
|
+
}
|
|
90
|
+
// onStateChanged is browser-only (uses BroadcastChannel)
|
|
91
|
+
if (prop === "onStateChanged") {
|
|
92
|
+
return () => undefined;
|
|
93
|
+
}
|
|
94
|
+
if (prop === "newWallet") {
|
|
95
|
+
return (mode, mutable, authScheme, seed) => {
|
|
96
|
+
const normSeed =
|
|
97
|
+
seed instanceof Uint8Array || Buffer.isBuffer(seed)
|
|
98
|
+
? Array.from(seed)
|
|
99
|
+
: seed;
|
|
100
|
+
return target
|
|
101
|
+
.newWallet(mode, mutable, authScheme, normSeed ?? null)
|
|
102
|
+
.then((v) => (v === null ? undefined : v));
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const val = target[prop];
|
|
106
|
+
if (typeof val === "function") {
|
|
107
|
+
const bound = val.bind(target);
|
|
108
|
+
return (...args) => {
|
|
109
|
+
const result = bound(...args.map(normalizeArg));
|
|
110
|
+
if (result && typeof result.then === "function") {
|
|
111
|
+
return result.then((v) => (v === null ? undefined : v));
|
|
112
|
+
}
|
|
113
|
+
return result === null ? undefined : result;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return val;
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ── Prototype patching ───────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Patches the raw SDK module:
|
|
125
|
+
* - Adds snake_case aliases for camelCase methods
|
|
126
|
+
* - Converts null -> undefined for Option<T> returns
|
|
127
|
+
* - Aliases static methods
|
|
128
|
+
*/
|
|
129
|
+
function patchSdkPrototypes(rawSdk) {
|
|
130
|
+
// snake_case aliases for instance methods
|
|
131
|
+
/* eslint-disable camelcase */
|
|
132
|
+
for (const [cls, aliases] of [
|
|
133
|
+
[rawSdk.Account, { to_commitment: "toCommitment" }],
|
|
134
|
+
[rawSdk.AccountHeader, { to_commitment: "toCommitment" }],
|
|
135
|
+
]) {
|
|
136
|
+
if (!cls?.prototype) continue;
|
|
137
|
+
for (const [snake, camel] of Object.entries(aliases)) {
|
|
138
|
+
if (typeof cls.prototype[camel] === "function" && !cls.prototype[snake]) {
|
|
139
|
+
cls.prototype[snake] = cls.prototype[camel];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/* eslint-enable camelcase */
|
|
144
|
+
|
|
145
|
+
// null -> undefined for Option<T> return methods
|
|
146
|
+
for (const [cls, methods] of [
|
|
147
|
+
[rawSdk.AccountStorage, ["getItem", "getMapEntries", "getMapItem"]],
|
|
148
|
+
[rawSdk.NoteConsumability, ["consumableAfterBlock"]],
|
|
149
|
+
]) {
|
|
150
|
+
if (!cls?.prototype) continue;
|
|
151
|
+
for (const method of methods) {
|
|
152
|
+
const original = cls.prototype[method];
|
|
153
|
+
if (typeof original === "function") {
|
|
154
|
+
cls.prototype[method] = function (...args) {
|
|
155
|
+
const result = original.apply(this, args);
|
|
156
|
+
return result === null ? undefined : result;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// snake_case aliases for static methods
|
|
163
|
+
if (rawSdk.NoteScript) {
|
|
164
|
+
if (!rawSdk.NoteScript.p2id && rawSdk.NoteScript.p2Id)
|
|
165
|
+
rawSdk.NoteScript.p2id = rawSdk.NoteScript.p2Id;
|
|
166
|
+
if (!rawSdk.NoteScript.p2ide && rawSdk.NoteScript.p2Ide)
|
|
167
|
+
rawSdk.NoteScript.p2ide = rawSdk.NoteScript.p2Ide;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ── Array polyfills ──────────────────────────────────────────────────
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Creates polyfill constructors for WASM typed array types.
|
|
175
|
+
* napi accepts plain JS arrays directly, but the browser SDK requires
|
|
176
|
+
* typed wrappers (NoteAndArgsArray, FeltArray, etc.). These polyfills
|
|
177
|
+
* let `new sdk.FeltArray([a, b])` work on Node.js by returning a plain array.
|
|
178
|
+
*/
|
|
179
|
+
function makeArrayPolyfills() {
|
|
180
|
+
function polyfill(items) {
|
|
181
|
+
const arr =
|
|
182
|
+
items === undefined || items === null
|
|
183
|
+
? []
|
|
184
|
+
: Array.isArray(items)
|
|
185
|
+
? [...items]
|
|
186
|
+
: [items];
|
|
187
|
+
arr.get = (i) => arr[i];
|
|
188
|
+
arr.replaceAt = (i, val) => {
|
|
189
|
+
arr[i] = val;
|
|
190
|
+
return arr;
|
|
191
|
+
};
|
|
192
|
+
return arr;
|
|
193
|
+
}
|
|
194
|
+
const names = [
|
|
195
|
+
"AccountArray",
|
|
196
|
+
"AccountIdArray",
|
|
197
|
+
"FeltArray",
|
|
198
|
+
"ForeignAccountArray",
|
|
199
|
+
"NoteAndArgsArray",
|
|
200
|
+
"NoteArray",
|
|
201
|
+
"NoteDetailsAndTagArray",
|
|
202
|
+
"NoteIdAndArgsArray",
|
|
203
|
+
"NoteRecipientArray",
|
|
204
|
+
"OutputNoteArray",
|
|
205
|
+
"OutputNotesArray",
|
|
206
|
+
"StorageSlotArray",
|
|
207
|
+
"TransactionScriptInputPairArray",
|
|
208
|
+
];
|
|
209
|
+
const result = {};
|
|
210
|
+
for (const name of names) {
|
|
211
|
+
result[name] = polyfill;
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ── SDK wrapper ──────────────────────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Creates a wrapped SDK module suitable for use with the MidenClient wrapper.
|
|
220
|
+
* Applies all patches and returns an object that can be used as `getWasm()` return value.
|
|
221
|
+
*/
|
|
222
|
+
export function createSdkWrapper(rawSdk) {
|
|
223
|
+
patchSdkPrototypes(rawSdk);
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
...rawSdk,
|
|
227
|
+
// Wrap classes whose constructors/static methods accept BigInt or Uint8Array
|
|
228
|
+
AccountBuilder: wrapClass(rawSdk.AccountBuilder),
|
|
229
|
+
AccountComponent: wrapClass(rawSdk.AccountComponent),
|
|
230
|
+
AuthSecretKey: wrapClass(rawSdk.AuthSecretKey),
|
|
231
|
+
Felt: wrapClass(rawSdk.Felt),
|
|
232
|
+
FungibleAsset: wrapClass(rawSdk.FungibleAsset),
|
|
233
|
+
Word: wrapClass(rawSdk.Word),
|
|
234
|
+
NoteTag: wrapClass(rawSdk.NoteTag),
|
|
235
|
+
// Array type polyfills
|
|
236
|
+
...makeArrayPolyfills(),
|
|
237
|
+
};
|
|
238
|
+
}
|
package/js/node-index.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js entry point for @miden-sdk/miden-sdk.
|
|
3
|
+
*
|
|
4
|
+
* Loaded automatically when Node.js resolves the package import
|
|
5
|
+
* (via the "node" condition in package.json exports).
|
|
6
|
+
*
|
|
7
|
+
* Provides the same API as the browser entry point (index.js),
|
|
8
|
+
* backed by a native napi addon with SQLite storage.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { loadNativeModule } from "./node/loader.js";
|
|
12
|
+
import { createSdkWrapper } from "./node/napi-compat.js";
|
|
13
|
+
import {
|
|
14
|
+
createWasmWebClient,
|
|
15
|
+
createMockWasmWebClient,
|
|
16
|
+
} from "./node/client-factory.js";
|
|
17
|
+
import { MidenClient } from "./client.js";
|
|
18
|
+
import {
|
|
19
|
+
createP2IDNote,
|
|
20
|
+
createP2IDENote,
|
|
21
|
+
buildSwapTag,
|
|
22
|
+
_setWasm as _setStandaloneWasm,
|
|
23
|
+
_setWebClient as _setStandaloneWebClient,
|
|
24
|
+
} from "./standalone.js";
|
|
25
|
+
|
|
26
|
+
// ── Initialization ───────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
let _initialized = false;
|
|
29
|
+
let _rawSdk = null;
|
|
30
|
+
let _wrappedSdk = null;
|
|
31
|
+
let _WasmWebClient = null;
|
|
32
|
+
let _MockWasmWebClient = null;
|
|
33
|
+
|
|
34
|
+
function ensureInitialized() {
|
|
35
|
+
if (_initialized) return;
|
|
36
|
+
|
|
37
|
+
_rawSdk = loadNativeModule();
|
|
38
|
+
_wrappedSdk = createSdkWrapper(_rawSdk);
|
|
39
|
+
_WasmWebClient = createWasmWebClient(_rawSdk);
|
|
40
|
+
_MockWasmWebClient = createMockWasmWebClient(_rawSdk);
|
|
41
|
+
|
|
42
|
+
// Wire MidenClient statics
|
|
43
|
+
MidenClient._WasmWebClient = _WasmWebClient;
|
|
44
|
+
MidenClient._MockWasmWebClient = _MockWasmWebClient;
|
|
45
|
+
MidenClient._getWasmOrThrow = async () => _wrappedSdk;
|
|
46
|
+
|
|
47
|
+
// Wire standalone functions
|
|
48
|
+
_setStandaloneWasm(_wrappedSdk);
|
|
49
|
+
_setStandaloneWebClient(_WasmWebClient);
|
|
50
|
+
|
|
51
|
+
_initialized = true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Initialize on import
|
|
55
|
+
ensureInitialized();
|
|
56
|
+
|
|
57
|
+
// ── Enum constants (matching browser entry point) ────────────────────
|
|
58
|
+
|
|
59
|
+
export const AccountType = Object.freeze({
|
|
60
|
+
MutableWallet: "MutableWallet",
|
|
61
|
+
ImmutableWallet: "ImmutableWallet",
|
|
62
|
+
FungibleFaucet: "FungibleFaucet",
|
|
63
|
+
ImmutableContract: "ImmutableContract",
|
|
64
|
+
MutableContract: "MutableContract",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const AuthScheme = Object.freeze({
|
|
68
|
+
Falcon: "falcon",
|
|
69
|
+
ECDSA: "ecdsa",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export const NoteVisibility = Object.freeze({
|
|
73
|
+
Public: "public",
|
|
74
|
+
Private: "private",
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export const StorageMode = Object.freeze({
|
|
78
|
+
Public: "public",
|
|
79
|
+
Private: "private",
|
|
80
|
+
Network: "network",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// ── Re-exports ───────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
export { MidenClient };
|
|
86
|
+
export { createP2IDNote, createP2IDENote, buildSwapTag };
|
|
87
|
+
|
|
88
|
+
// Internal exports (matching browser entry point)
|
|
89
|
+
export {
|
|
90
|
+
_WasmWebClient as WasmWebClient,
|
|
91
|
+
_MockWasmWebClient as MockWasmWebClient,
|
|
92
|
+
_MockWasmWebClient as MockWebClient,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Re-export all napi SDK types (equivalent to browser's `export * from "../Cargo.toml"`).
|
|
96
|
+
// Since we can't statically export dynamic napi bindings, we re-export common types explicitly
|
|
97
|
+
// and provide getNativeModule()/getWrappedSdk() for anything else.
|
|
98
|
+
|
|
99
|
+
export function getNativeModule() {
|
|
100
|
+
ensureInitialized();
|
|
101
|
+
return _rawSdk;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getWrappedSdk() {
|
|
105
|
+
ensureInitialized();
|
|
106
|
+
return _wrappedSdk;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Re-export commonly used SDK types from the napi module.
|
|
110
|
+
// Uses a lazy getter pattern so the module is loaded on first access.
|
|
111
|
+
function _reexport(name) {
|
|
112
|
+
return {
|
|
113
|
+
get [name]() {
|
|
114
|
+
ensureInitialized();
|
|
115
|
+
return _wrappedSdk[name] ?? _rawSdk[name];
|
|
116
|
+
},
|
|
117
|
+
}[name];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Account types
|
|
121
|
+
export const Account = /* @__PURE__ */ _reexport("Account");
|
|
122
|
+
export const AccountBuilder = /* @__PURE__ */ _reexport("AccountBuilder");
|
|
123
|
+
export const AccountComponent = /* @__PURE__ */ _reexport("AccountComponent");
|
|
124
|
+
export const AccountFile = /* @__PURE__ */ _reexport("AccountFile");
|
|
125
|
+
export const AccountHeader = /* @__PURE__ */ _reexport("AccountHeader");
|
|
126
|
+
export const AccountId = /* @__PURE__ */ _reexport("AccountId");
|
|
127
|
+
export const AccountInterface = /* @__PURE__ */ _reexport("AccountInterface");
|
|
128
|
+
export const AccountStorage = /* @__PURE__ */ _reexport("AccountStorage");
|
|
129
|
+
export const AccountStorageMode =
|
|
130
|
+
/* @__PURE__ */ _reexport("AccountStorageMode");
|
|
131
|
+
export const AccountStorageRequirements = /* @__PURE__ */ _reexport(
|
|
132
|
+
"AccountStorageRequirements"
|
|
133
|
+
);
|
|
134
|
+
export const Address = /* @__PURE__ */ _reexport("Address");
|
|
135
|
+
|
|
136
|
+
// Auth types
|
|
137
|
+
export const AuthSchemeNative = /* @__PURE__ */ _reexport("AuthScheme");
|
|
138
|
+
export const AuthSecretKey = /* @__PURE__ */ _reexport("AuthSecretKey");
|
|
139
|
+
|
|
140
|
+
// Crypto types
|
|
141
|
+
export const Felt = /* @__PURE__ */ _reexport("Felt");
|
|
142
|
+
export const Word = /* @__PURE__ */ _reexport("Word");
|
|
143
|
+
export const Rpo = /* @__PURE__ */ _reexport("Rpo");
|
|
144
|
+
export const Rpo256 = /* @__PURE__ */ _reexport("Rpo256");
|
|
145
|
+
export const PublicKey = /* @__PURE__ */ _reexport("PublicKey");
|
|
146
|
+
export const Signature = /* @__PURE__ */ _reexport("Signature");
|
|
147
|
+
|
|
148
|
+
// Asset types
|
|
149
|
+
export const FungibleAsset = /* @__PURE__ */ _reexport("FungibleAsset");
|
|
150
|
+
|
|
151
|
+
// Note types
|
|
152
|
+
export const Note = /* @__PURE__ */ _reexport("Note");
|
|
153
|
+
export const NoteAssets = /* @__PURE__ */ _reexport("NoteAssets");
|
|
154
|
+
export const NoteAttachment = /* @__PURE__ */ _reexport("NoteAttachment");
|
|
155
|
+
export const NoteExportFormat = /* @__PURE__ */ _reexport("NoteExportFormat");
|
|
156
|
+
export const NoteExecutionHint = /* @__PURE__ */ _reexport("NoteExecutionHint");
|
|
157
|
+
export const NoteFile = /* @__PURE__ */ _reexport("NoteFile");
|
|
158
|
+
export const NoteFilter = /* @__PURE__ */ _reexport("NoteFilter");
|
|
159
|
+
export const NoteFilterTypes = /* @__PURE__ */ _reexport("NoteFilterTypes");
|
|
160
|
+
export const NoteId = /* @__PURE__ */ _reexport("NoteId");
|
|
161
|
+
export const NoteMetadata = /* @__PURE__ */ _reexport("NoteMetadata");
|
|
162
|
+
export const NoteRecipient = /* @__PURE__ */ _reexport("NoteRecipient");
|
|
163
|
+
export const NoteScript = /* @__PURE__ */ _reexport("NoteScript");
|
|
164
|
+
export const NoteStorage = /* @__PURE__ */ _reexport("NoteStorage");
|
|
165
|
+
export const NoteTag = /* @__PURE__ */ _reexport("NoteTag");
|
|
166
|
+
export const NoteType = /* @__PURE__ */ _reexport("NoteType");
|
|
167
|
+
export const OutputNote = /* @__PURE__ */ _reexport("OutputNote");
|
|
168
|
+
|
|
169
|
+
// Transaction types
|
|
170
|
+
export const TransactionFilter = /* @__PURE__ */ _reexport("TransactionFilter");
|
|
171
|
+
export const TransactionProver = /* @__PURE__ */ _reexport("TransactionProver");
|
|
172
|
+
export const TransactionRequestBuilder = /* @__PURE__ */ _reexport(
|
|
173
|
+
"TransactionRequestBuilder"
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// Network types
|
|
177
|
+
export const NetworkId = /* @__PURE__ */ _reexport("NetworkId");
|
|
178
|
+
export const RpcClient = /* @__PURE__ */ _reexport("RpcClient");
|
|
179
|
+
export const Endpoint = /* @__PURE__ */ _reexport("Endpoint");
|
|
180
|
+
|
|
181
|
+
// Transaction result / sync types
|
|
182
|
+
export const SyncSummary = /* @__PURE__ */ _reexport("SyncSummary");
|
|
183
|
+
export const TransactionResult = /* @__PURE__ */ _reexport("TransactionResult");
|
|
184
|
+
|
|
185
|
+
// Store import/export
|
|
186
|
+
export const exportStore = /* @__PURE__ */ _reexport("exportStore");
|
|
187
|
+
export const importStore = /* @__PURE__ */ _reexport("importStore");
|
|
188
|
+
|
|
189
|
+
// Misc
|
|
190
|
+
export const AdviceMap = /* @__PURE__ */ _reexport("AdviceMap");
|
|
191
|
+
export const ForeignAccount = /* @__PURE__ */ _reexport("ForeignAccount");
|
|
192
|
+
export const Package = /* @__PURE__*/ _reexport("Package");
|
|
193
|
+
export const StorageMap = /* @__PURE__ */ _reexport("StorageMap");
|
|
194
|
+
export const StorageSlot = /* @__PURE__ */ _reexport("StorageSlot");
|
|
195
|
+
export const TokenSymbol = /* @__PURE__ */ _reexport("TokenSymbol");
|