diff --git a/packages/neptune-wasm/.gitignore b/packages/neptune-wasm/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/packages/neptune-wasm/neptune_wasm.d.ts b/packages/neptune-wasm/neptune_wasm.d.ts new file mode 100644 index 0000000..981cae6 --- /dev/null +++ b/packages/neptune-wasm/neptune_wasm.d.ts @@ -0,0 +1,209 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Generate a new random seed phrase (18 words, 192 bits entropy) + * This is completely offline - uses browser's crypto.getRandomValues() + */ +export function generate_seed(): string; +/** + * Get view key and address from seed phrase (offline) - COMPATIBLE WITH NEPTUNE-CORE + * + * This derives the view key from a BIP39 seed phrase using neptune-crypto-core. + * The view key can be used with wallet_getUtxosFromViewKey RPC method. + * + * Input: JSON string with seed_phrase array and network ("mainnet" or "testnet") + * Output: JSON string with receiver_identifier, view_key (hex), and address (bech32m) + * + * Example: + * ```javascript + * const result = get_viewkey('["word1", "word2", ...]', "testnet"); + * const { receiver_identifier, view_key, address } = JSON.parse(result); + * console.log('View key:', view_key); // Compatible with neptune-core! + * ``` + */ +export function get_viewkey(seed_phrase_json: string, network: string): string; +/** + * Get receiving address from seed phrase (offline) + * Input: JSON string with seed_phrase array and network + * Output: bech32m encoded address string + */ +export function address_from_seed(seed_phrase_json: string, network: string): string; +/** + * Validate a seed phrase (offline) + */ +export function validate_seed_phrase(seed_phrase_json: string): boolean; +/** + * Decode view key from hex string (offline) + */ +export function decode_viewkey(view_key_hex: string): string; +/** + * Prepare transaction data for server-side signing + * + * This prepares transaction details but does NOT sign locally. + * Instead, it exports the spending key seed so the server can sign. + * + * Input: JSON string with BuildTxRequest + * Output: JSON string with SignedTxData (contains seed for server signing) + * + * Example: + * ```javascript + * const request = { + * seed_phrase: ["word1", "word2", ...], + * inputs: [{addition_record: "0xabc..."}], + * outputs: [{address: "nep1...", amount: "50.0"}], + * fee: "0.01", + * network: "testnet" + * }; + * const txData = build_and_sign_tx(JSON.stringify(request)); + * // Now broadcast via JSON-RPC: wallet_broadcastSignedTransaction(txData) + * ``` + */ +export function build_and_sign_tx(request_json: string): string; +/** + * Get wallet balance via JSON-RPC (Neptune core ext format) + * Uses wallet_balance method from Wallet namespace + */ +export function get_balance(rpc_url: string): Promise; +/** + * Send transaction via JSON-RPC + * Note: Neptune core ext may not have direct "send" method in public RPC + * This is a placeholder - check actual available methods + */ +export function send_tx_jsonrpc(rpc_url: string, to_address: string, amount: string, fee: string): Promise; +/** + * Get block height via JSON-RPC (Neptune core ext format) + * Uses chain_height method from Chain namespace + */ +export function get_block_height(rpc_url: string): Promise; +/** + * Get network info via JSON-RPC (Neptune core ext format) + * Uses node_network method from Node namespace + */ +export function get_network_info(rpc_url: string): Promise; +/** + * Get wallet addresses from Neptune core (PRODUCTION - EXACT Neptune addresses!) + * Returns both generation_address and symmetric_address + */ +export function get_wallet_address(rpc_url: string): Promise; +/** + * Get view key from Neptune core (RECOMMENDED) + * This exports the proper view key format from Neptune core's wallet + * Returns a hex-encoded view key that can be used with wallet_getUtxosFromViewKey + */ +export function get_viewkey_from_neptune(rpc_url: string): Promise; +/** + * Get UTXOs from view key (scan blockchain) + * This calls Neptune core's wallet_getUtxosFromViewKey JSON-RPC method + * + * Input: view_key (hex string from neptune-core format), start_block, end_block (optional) + * Output: JSON string with list of UTXOs + */ +export function get_utxos_from_viewkey(rpc_url: string, view_key_hex: string, start_block: bigint, end_block?: bigint | null): Promise; +/** + * Generate viewkey from BIP39 seed phrase + * + * # Arguments + * * `phrase` - Space-separated BIP39 seed phrase (12-24 words) + * * `key_index` - Key derivation index (default: 0) + * + * # Returns + * Hex-encoded viewkey compatible with neptune-core + */ +export function generate_viewkey_from_phrase(phrase: string, key_index: bigint): string; +/** + * Generate receiving address from BIP39 seed phrase + * + * # Arguments + * * `phrase` - Space-separated BIP39 seed phrase (12-24 words) + * * `key_index` - Key derivation index (default: 0) + * * `testnet` - Use testnet network (true) or mainnet (false) + * + * # Returns + * Bech32m-encoded receiving address + */ +export function generate_address_from_phrase(phrase: string, key_index: bigint, testnet: boolean): string; +/** + * Get receiver identifier from viewkey hex + */ +export function get_receiver_id_from_viewkey(viewkey_hex: string): string; +/** + * Debug: Get detailed key derivation info + */ +export function debug_key_derivation(phrase: string, key_index: bigint): string; +/** + * Sign transaction offline (WASM client-side signing) + * This creates lock_script_and_witness WITHOUT exposing spending key to server + * + * # Arguments + * * `phrase` - BIP39 seed phrase (18 words) + * * `utxos_json` - JSON array of UTXOs from get_utxos (with addition_record) + * * `outputs_json` - JSON array of outputs [{address, amount}, ...] + * * `fee` - Transaction fee as string + * * `key_index` - Key derivation index (usually 0) + * * `testnet` - Network selection + * + * # Returns + * JSON containing: + * - lock_script_and_witness: hex-encoded signature + * - view_key: hex-encoded view key + * - inputs: array of addition_records + * - outputs: array of {address, amount} + * - fee: fee string + */ +export function sign_transaction_offline(phrase: string, utxos_json: string, outputs_json: string, fee: string, key_index: bigint, testnet: boolean): string; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly generate_seed: () => [number, number, number, number]; + readonly get_viewkey: (a: number, b: number, c: number, d: number) => [number, number, number, number]; + readonly address_from_seed: (a: number, b: number, c: number, d: number) => [number, number, number, number]; + readonly validate_seed_phrase: (a: number, b: number) => [number, number, number]; + readonly decode_viewkey: (a: number, b: number) => [number, number, number, number]; + readonly build_and_sign_tx: (a: number, b: number) => [number, number, number, number]; + readonly get_balance: (a: number, b: number) => any; + readonly send_tx_jsonrpc: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => any; + readonly get_block_height: (a: number, b: number) => any; + readonly get_network_info: (a: number, b: number) => any; + readonly get_wallet_address: (a: number, b: number) => any; + readonly get_viewkey_from_neptune: (a: number, b: number) => any; + readonly get_utxos_from_viewkey: (a: number, b: number, c: number, d: number, e: bigint, f: number, g: bigint) => any; + readonly generate_viewkey_from_phrase: (a: number, b: number, c: bigint) => [number, number, number, number]; + readonly generate_address_from_phrase: (a: number, b: number, c: bigint, d: number) => [number, number, number, number]; + readonly get_receiver_id_from_viewkey: (a: number, b: number) => [number, number, number, number]; + readonly debug_key_derivation: (a: number, b: number, c: bigint) => [number, number, number, number]; + readonly sign_transaction_offline: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: bigint, j: number) => [number, number, number, number]; + readonly __wbindgen_exn_store: (a: number) => void; + readonly __externref_table_alloc: () => number; + readonly __wbindgen_export_2: WebAssembly.Table; + readonly __wbindgen_export_3: WebAssembly.Table; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __externref_table_dealloc: (a: number) => void; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly closure49_externref_shim: (a: number, b: number, c: any) => void; + readonly closure268_externref_shim: (a: number, b: number, c: any, d: any) => void; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. +* +* @returns {InitOutput} +*/ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. +* +* @returns {Promise} +*/ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/packages/neptune-wasm/neptune_wasm.js b/packages/neptune-wasm/neptune_wasm.js new file mode 100644 index 0000000..af83718 --- /dev/null +++ b/packages/neptune-wasm/neptune_wasm.js @@ -0,0 +1,984 @@ +let wasm; + +function addToExternrefTable0(obj) { + const idx = wasm.__externref_table_alloc(); + wasm.__wbindgen_export_2.set(idx, obj); + return idx; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + const idx = addToExternrefTable0(e); + wasm.__wbindgen_exn_store(idx); + } +} + +let cachedUint8ArrayMemory0 = null; + +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => { + wasm.__wbindgen_export_3.get(state.dtor)(state.a, state.b) +}); + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_3.get(state.dtor)(a, state.b); + CLOSURE_DTORS.unregister(state); + } else { + state.a = a; + } + } + }; + real.original = state; + CLOSURE_DTORS.register(real, state, state); + return real; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches && builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +let cachedDataViewMemory0 = null; + +function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; +} + +function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_export_2.get(idx); + wasm.__externref_table_dealloc(idx); + return value; +} +/** + * Generate a new random seed phrase (18 words, 192 bits entropy) + * This is completely offline - uses browser's crypto.getRandomValues() + * @returns {string} + */ +export function generate_seed() { + let deferred2_0; + let deferred2_1; + try { + const ret = wasm.generate_seed(); + var ptr1 = ret[0]; + var len1 = ret[1]; + if (ret[3]) { + ptr1 = 0; len1 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred2_0 = ptr1; + deferred2_1 = len1; + return getStringFromWasm0(ptr1, len1); + } finally { + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} + +/** + * Get view key and address from seed phrase (offline) - COMPATIBLE WITH NEPTUNE-CORE + * + * This derives the view key from a BIP39 seed phrase using neptune-crypto-core. + * The view key can be used with wallet_getUtxosFromViewKey RPC method. + * + * Input: JSON string with seed_phrase array and network ("mainnet" or "testnet") + * Output: JSON string with receiver_identifier, view_key (hex), and address (bech32m) + * + * Example: + * ```javascript + * const result = get_viewkey('["word1", "word2", ...]', "testnet"); + * const { receiver_identifier, view_key, address } = JSON.parse(result); + * console.log('View key:', view_key); // Compatible with neptune-core! + * ``` + * @param {string} seed_phrase_json + * @param {string} network + * @returns {string} + */ +export function get_viewkey(seed_phrase_json, network) { + let deferred4_0; + let deferred4_1; + try { + const ptr0 = passStringToWasm0(seed_phrase_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.get_viewkey(ptr0, len0, ptr1, len1); + var ptr3 = ret[0]; + var len3 = ret[1]; + if (ret[3]) { + ptr3 = 0; len3 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** + * Get receiving address from seed phrase (offline) + * Input: JSON string with seed_phrase array and network + * Output: bech32m encoded address string + * @param {string} seed_phrase_json + * @param {string} network + * @returns {string} + */ +export function address_from_seed(seed_phrase_json, network) { + let deferred4_0; + let deferred4_1; + try { + const ptr0 = passStringToWasm0(seed_phrase_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.address_from_seed(ptr0, len0, ptr1, len1); + var ptr3 = ret[0]; + var len3 = ret[1]; + if (ret[3]) { + ptr3 = 0; len3 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + +/** + * Validate a seed phrase (offline) + * @param {string} seed_phrase_json + * @returns {boolean} + */ +export function validate_seed_phrase(seed_phrase_json) { + const ptr0 = passStringToWasm0(seed_phrase_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.validate_seed_phrase(ptr0, len0); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return ret[0] !== 0; +} + +/** + * Decode view key from hex string (offline) + * @param {string} view_key_hex + * @returns {string} + */ +export function decode_viewkey(view_key_hex) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(view_key_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.decode_viewkey(ptr0, len0); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Prepare transaction data for server-side signing + * + * This prepares transaction details but does NOT sign locally. + * Instead, it exports the spending key seed so the server can sign. + * + * Input: JSON string with BuildTxRequest + * Output: JSON string with SignedTxData (contains seed for server signing) + * + * Example: + * ```javascript + * const request = { + * seed_phrase: ["word1", "word2", ...], + * inputs: [{addition_record: "0xabc..."}], + * outputs: [{address: "nep1...", amount: "50.0"}], + * fee: "0.01", + * network: "testnet" + * }; + * const txData = build_and_sign_tx(JSON.stringify(request)); + * // Now broadcast via JSON-RPC: wallet_broadcastSignedTransaction(txData) + * ``` + * @param {string} request_json + * @returns {string} + */ +export function build_and_sign_tx(request_json) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(request_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.build_and_sign_tx(ptr0, len0); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Get wallet balance via JSON-RPC (Neptune core ext format) + * Uses wallet_balance method from Wallet namespace + * @param {string} rpc_url + * @returns {Promise} + */ +export function get_balance(rpc_url) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_balance(ptr0, len0); + return ret; +} + +/** + * Send transaction via JSON-RPC + * Note: Neptune core ext may not have direct "send" method in public RPC + * This is a placeholder - check actual available methods + * @param {string} rpc_url + * @param {string} to_address + * @param {string} amount + * @param {string} fee + * @returns {Promise} + */ +export function send_tx_jsonrpc(rpc_url, to_address, amount, fee) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(to_address, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(amount, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passStringToWasm0(fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.send_tx_jsonrpc(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3); + return ret; +} + +/** + * Get block height via JSON-RPC (Neptune core ext format) + * Uses chain_height method from Chain namespace + * @param {string} rpc_url + * @returns {Promise} + */ +export function get_block_height(rpc_url) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_block_height(ptr0, len0); + return ret; +} + +/** + * Get network info via JSON-RPC (Neptune core ext format) + * Uses node_network method from Node namespace + * @param {string} rpc_url + * @returns {Promise} + */ +export function get_network_info(rpc_url) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_network_info(ptr0, len0); + return ret; +} + +/** + * Get wallet addresses from Neptune core (PRODUCTION - EXACT Neptune addresses!) + * Returns both generation_address and symmetric_address + * @param {string} rpc_url + * @returns {Promise} + */ +export function get_wallet_address(rpc_url) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_wallet_address(ptr0, len0); + return ret; +} + +/** + * Get view key from Neptune core (RECOMMENDED) + * This exports the proper view key format from Neptune core's wallet + * Returns a hex-encoded view key that can be used with wallet_getUtxosFromViewKey + * @param {string} rpc_url + * @returns {Promise} + */ +export function get_viewkey_from_neptune(rpc_url) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_viewkey_from_neptune(ptr0, len0); + return ret; +} + +/** + * Get UTXOs from view key (scan blockchain) + * This calls Neptune core's wallet_getUtxosFromViewKey JSON-RPC method + * + * Input: view_key (hex string from neptune-core format), start_block, end_block (optional) + * Output: JSON string with list of UTXOs + * @param {string} rpc_url + * @param {string} view_key_hex + * @param {bigint} start_block + * @param {bigint | null} [end_block] + * @returns {Promise} + */ +export function get_utxos_from_viewkey(rpc_url, view_key_hex, start_block, end_block) { + const ptr0 = passStringToWasm0(rpc_url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(view_key_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.get_utxos_from_viewkey(ptr0, len0, ptr1, len1, start_block, !isLikeNone(end_block), isLikeNone(end_block) ? BigInt(0) : end_block); + return ret; +} + +/** + * Generate viewkey from BIP39 seed phrase + * + * # Arguments + * * `phrase` - Space-separated BIP39 seed phrase (12-24 words) + * * `key_index` - Key derivation index (default: 0) + * + * # Returns + * Hex-encoded viewkey compatible with neptune-core + * @param {string} phrase + * @param {bigint} key_index + * @returns {string} + */ +export function generate_viewkey_from_phrase(phrase, key_index) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(phrase, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.generate_viewkey_from_phrase(ptr0, len0, key_index); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Generate receiving address from BIP39 seed phrase + * + * # Arguments + * * `phrase` - Space-separated BIP39 seed phrase (12-24 words) + * * `key_index` - Key derivation index (default: 0) + * * `testnet` - Use testnet network (true) or mainnet (false) + * + * # Returns + * Bech32m-encoded receiving address + * @param {string} phrase + * @param {bigint} key_index + * @param {boolean} testnet + * @returns {string} + */ +export function generate_address_from_phrase(phrase, key_index, testnet) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(phrase, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.generate_address_from_phrase(ptr0, len0, key_index, testnet); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Get receiver identifier from viewkey hex + * @param {string} viewkey_hex + * @returns {string} + */ +export function get_receiver_id_from_viewkey(viewkey_hex) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(viewkey_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.get_receiver_id_from_viewkey(ptr0, len0); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Debug: Get detailed key derivation info + * @param {string} phrase + * @param {bigint} key_index + * @returns {string} + */ +export function debug_key_derivation(phrase, key_index) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passStringToWasm0(phrase, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.debug_key_derivation(ptr0, len0, key_index); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } +} + +/** + * Sign transaction offline (WASM client-side signing) + * This creates lock_script_and_witness WITHOUT exposing spending key to server + * + * # Arguments + * * `phrase` - BIP39 seed phrase (18 words) + * * `utxos_json` - JSON array of UTXOs from get_utxos (with addition_record) + * * `outputs_json` - JSON array of outputs [{address, amount}, ...] + * * `fee` - Transaction fee as string + * * `key_index` - Key derivation index (usually 0) + * * `testnet` - Network selection + * + * # Returns + * JSON containing: + * - lock_script_and_witness: hex-encoded signature + * - view_key: hex-encoded view key + * - inputs: array of addition_records + * - outputs: array of {address, amount} + * - fee: fee string + * @param {string} phrase + * @param {string} utxos_json + * @param {string} outputs_json + * @param {string} fee + * @param {bigint} key_index + * @param {boolean} testnet + * @returns {string} + */ +export function sign_transaction_offline(phrase, utxos_json, outputs_json, fee, key_index, testnet) { + let deferred6_0; + let deferred6_1; + try { + const ptr0 = passStringToWasm0(phrase, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(utxos_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(outputs_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passStringToWasm0(fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.sign_transaction_offline(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, key_index, testnet); + var ptr5 = ret[0]; + var len5 = ret[1]; + if (ret[3]) { + ptr5 = 0; len5 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred6_0 = ptr5; + deferred6_1 = len5; + return getStringFromWasm0(ptr5, len5); + } finally { + wasm.__wbindgen_free(deferred6_0, deferred6_1, 1); + } +} + +function __wbg_adapter_24(arg0, arg1, arg2) { + wasm.closure49_externref_shim(arg0, arg1, arg2); +} + +function __wbg_adapter_83(arg0, arg1, arg2, arg3) { + wasm.closure268_externref_shim(arg0, arg1, arg2, arg3); +} + +const __wbindgen_enum_RequestMode = ["same-origin", "no-cors", "cors", "navigate"]; + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.call(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_call_7cccdd69e0791ae2 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.call(arg1, arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_error_524f506f44df1645 = function(arg0) { + console.error(arg0); + }; + imports.wbg.__wbg_fetch_b7bf320f681242d2 = function(arg0, arg1) { + const ret = arg0.fetch(arg1); + return ret; + }; + imports.wbg.__wbg_getRandomValues_bb689d73e9ab7af6 = function(arg0, arg1) { + crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_headers_7852a8ea641c1379 = function(arg0) { + const ret = arg0.headers; + return ret; + }; + imports.wbg.__wbg_instanceof_Response_f2cc20d9f7dfd644 = function(arg0) { + let result; + try { + result = arg0 instanceof Response; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_Window_def73ea0955fc569 = function(arg0) { + let result; + try { + result = arg0 instanceof Window; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_log_7fbbb36c3875e666 = function(arg0, arg1) { + console.log(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_log_c222819a41e063d3 = function(arg0) { + console.log(arg0); + }; + imports.wbg.__wbg_new_23a2665fac83c611 = function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return __wbg_adapter_83(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return ret; + } finally { + state0.a = state0.b = 0; + } + }; + imports.wbg.__wbg_new_405e22f390576ce2 = function() { + const ret = new Object(); + return ret; + }; + imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return ret; + }; + imports.wbg.__wbg_newwithstrandinit_06c535e0a867c635 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) { + queueMicrotask(arg0); + }; + imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) { + const ret = arg0.queueMicrotask; + return ret; + }; + imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) { + const ret = Promise.resolve(arg0); + return ret; + }; + imports.wbg.__wbg_set_11cd83f45504cedf = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + arg0.set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_setbody_5923b78a95eedf29 = function(arg0, arg1) { + arg0.body = arg1; + }; + imports.wbg.__wbg_setmethod_3c5280fe5d890842 = function(arg0, arg1, arg2) { + arg0.method = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_setmode_5dc300b865044b65 = function(arg0, arg1) { + arg0.mode = __wbindgen_enum_RequestMode[arg1]; + }; + imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { + const ret = typeof global === 'undefined' ? null : global; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { + const ret = typeof globalThis === 'undefined' ? null : globalThis; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { + const ret = typeof self === 'undefined' ? null : self; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { + const ret = typeof window === 'undefined' ? null : window; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_text_7805bea50de2af49 = function() { return handleError(function (arg0) { + const ret = arg0.text(); + return ret; + }, arguments) }; + imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) { + const ret = arg0.then(arg1); + return ret; + }; + imports.wbg.__wbg_then_48b406749878a531 = function(arg0, arg1, arg2) { + const ret = arg0.then(arg1, arg2); + return ret; + }; + imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { + const ret = BigInt.asUintN(64, arg0); + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = arg0.original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper214 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50, __wbg_adapter_24); + return ret; + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(arg1); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbindgen_init_externref_table = function() { + const table = wasm.__wbindgen_export_2; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + ; + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(arg0) === 'function'; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = arg0 === undefined; + return ret; + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = arg1; + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + return imports; +} + +function __wbg_init_memory(imports, memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedDataViewMemory0 = null; + cachedUint8ArrayMemory0 = null; + + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (typeof module !== 'undefined') { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (typeof module_or_path !== 'undefined') { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + if (typeof module_or_path === 'undefined') { + module_or_path = new URL('neptune_wasm_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync }; +export default __wbg_init; diff --git a/packages/neptune-wasm/neptune_wasm_bg.wasm b/packages/neptune-wasm/neptune_wasm_bg.wasm new file mode 100644 index 0000000..4c31c9b Binary files /dev/null and b/packages/neptune-wasm/neptune_wasm_bg.wasm differ diff --git a/packages/neptune-wasm/neptune_wasm_bg.wasm.d.ts b/packages/neptune-wasm/neptune_wasm_bg.wasm.d.ts new file mode 100644 index 0000000..a62746d --- /dev/null +++ b/packages/neptune-wasm/neptune_wasm_bg.wasm.d.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export const generate_seed: () => [number, number, number, number]; +export const get_viewkey: (a: number, b: number, c: number, d: number) => [number, number, number, number]; +export const address_from_seed: (a: number, b: number, c: number, d: number) => [number, number, number, number]; +export const validate_seed_phrase: (a: number, b: number) => [number, number, number]; +export const decode_viewkey: (a: number, b: number) => [number, number, number, number]; +export const build_and_sign_tx: (a: number, b: number) => [number, number, number, number]; +export const get_balance: (a: number, b: number) => any; +export const send_tx_jsonrpc: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => any; +export const get_block_height: (a: number, b: number) => any; +export const get_network_info: (a: number, b: number) => any; +export const get_wallet_address: (a: number, b: number) => any; +export const get_viewkey_from_neptune: (a: number, b: number) => any; +export const get_utxos_from_viewkey: (a: number, b: number, c: number, d: number, e: bigint, f: number, g: bigint) => any; +export const generate_viewkey_from_phrase: (a: number, b: number, c: bigint) => [number, number, number, number]; +export const generate_address_from_phrase: (a: number, b: number, c: bigint, d: number) => [number, number, number, number]; +export const get_receiver_id_from_viewkey: (a: number, b: number) => [number, number, number, number]; +export const debug_key_derivation: (a: number, b: number, c: bigint) => [number, number, number, number]; +export const sign_transaction_offline: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: bigint, j: number) => [number, number, number, number]; +export const __wbindgen_exn_store: (a: number) => void; +export const __externref_table_alloc: () => number; +export const __wbindgen_export_2: WebAssembly.Table; +export const __wbindgen_export_3: WebAssembly.Table; +export const __wbindgen_malloc: (a: number, b: number) => number; +export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; +export const __externref_table_dealloc: (a: number) => void; +export const __wbindgen_free: (a: number, b: number, c: number) => void; +export const closure49_externref_shim: (a: number, b: number, c: any) => void; +export const closure268_externref_shim: (a: number, b: number, c: any, d: any) => void; +export const __wbindgen_start: () => void; diff --git a/packages/neptune-wasm/package.json b/packages/neptune-wasm/package.json new file mode 100644 index 0000000..a25e288 --- /dev/null +++ b/packages/neptune-wasm/package.json @@ -0,0 +1,16 @@ +{ + "name": "@neptune/wasm", + "type": "module", + "version": "0.1.0", + "license": "Apache-2.0", + "files": [ + "neptune_wasm_bg.wasm", + "neptune_wasm.js", + "neptune_wasm.d.ts" + ], + "main": "neptune_wasm.js", + "types": "neptune_wasm.d.ts", + "sideEffects": [ + "./snippets/*" + ] +}