@unlink-xyz/node 0.1.5 → 0.1.7-canary.252b8ea
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/dist/index.cjs +18 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -27
- package/dist/index.d.ts +32 -27
- package/dist/index.js +18 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,10 +36,13 @@ __export(index_exports, {
|
|
|
36
36
|
TERMINAL_TX_STATES: () => TERMINAL_TX_STATES,
|
|
37
37
|
TimeoutError: () => TimeoutError,
|
|
38
38
|
TransactionFailedError: () => TransactionFailedError,
|
|
39
|
+
Unlink: () => import_core3.Unlink,
|
|
39
40
|
UnlinkWallet: () => import_core3.UnlinkWallet,
|
|
41
|
+
createEmitter: () => createEmitter,
|
|
40
42
|
createMemoryStorage: () => import_core3.createMemoryStorage,
|
|
41
43
|
createSqliteStorage: () => createSqliteStorage,
|
|
42
44
|
createWalletEmitter: () => createWalletEmitter,
|
|
45
|
+
initUnlink: () => initUnlink,
|
|
43
46
|
initWallet: () => initWallet,
|
|
44
47
|
pollRelayStatus: () => pollRelayStatus,
|
|
45
48
|
waitForConfirmation: () => waitForConfirmation
|
|
@@ -50,11 +53,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
50
53
|
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
51
54
|
var import_core = require("@unlink-xyz/core");
|
|
52
55
|
var nodeRng = (n) => new Uint8Array(import_node_crypto.default.randomBytes(n));
|
|
53
|
-
async function
|
|
56
|
+
async function initUnlink(config) {
|
|
54
57
|
const { setup, sync, ...coreConfig } = config;
|
|
55
58
|
void setup;
|
|
56
59
|
void sync;
|
|
57
|
-
const
|
|
60
|
+
const unlink = await import_core.Unlink.create({
|
|
58
61
|
...coreConfig,
|
|
59
62
|
storage: config.storage ?? (0, import_core.createMemoryStorage)(),
|
|
60
63
|
rng: config.rng ?? nodeRng,
|
|
@@ -62,20 +65,21 @@ async function initWallet(config) {
|
|
|
62
65
|
fetch: config.fetch ?? globalThis.fetch
|
|
63
66
|
});
|
|
64
67
|
if (config.setup !== false) {
|
|
65
|
-
const hasSeed = await
|
|
68
|
+
const hasSeed = await unlink.seed.exists();
|
|
66
69
|
if (!hasSeed) {
|
|
67
|
-
await
|
|
70
|
+
await unlink.seed.create();
|
|
68
71
|
}
|
|
69
|
-
const accounts = await
|
|
72
|
+
const accounts = await unlink.accounts.list();
|
|
70
73
|
if (accounts.length === 0) {
|
|
71
|
-
await
|
|
74
|
+
await unlink.accounts.create();
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
if (config.sync !== false) {
|
|
75
|
-
await
|
|
78
|
+
await unlink.sync();
|
|
76
79
|
}
|
|
77
|
-
return
|
|
80
|
+
return unlink;
|
|
78
81
|
}
|
|
82
|
+
var initWallet = initUnlink;
|
|
79
83
|
|
|
80
84
|
// src/errors.ts
|
|
81
85
|
var TERMINAL_TX_STATES = [
|
|
@@ -171,14 +175,15 @@ async function* pollRelayStatus(wallet, txId, opts) {
|
|
|
171
175
|
|
|
172
176
|
// src/events.ts
|
|
173
177
|
var import_node_events = require("events");
|
|
174
|
-
function
|
|
178
|
+
function createEmitter(unlink) {
|
|
175
179
|
const emitter = new import_node_events.EventEmitter();
|
|
176
|
-
const unsubscribe =
|
|
180
|
+
const unsubscribe = unlink.on((event) => {
|
|
177
181
|
emitter.emit(event.type, event);
|
|
178
182
|
emitter.emit("*", event);
|
|
179
183
|
});
|
|
180
184
|
return { emitter, unsubscribe };
|
|
181
185
|
}
|
|
186
|
+
var createWalletEmitter = createEmitter;
|
|
182
187
|
|
|
183
188
|
// src/storage/sqlite.ts
|
|
184
189
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
@@ -309,10 +314,13 @@ var import_core3 = require("@unlink-xyz/core");
|
|
|
309
314
|
TERMINAL_TX_STATES,
|
|
310
315
|
TimeoutError,
|
|
311
316
|
TransactionFailedError,
|
|
317
|
+
Unlink,
|
|
312
318
|
UnlinkWallet,
|
|
319
|
+
createEmitter,
|
|
313
320
|
createMemoryStorage,
|
|
314
321
|
createSqliteStorage,
|
|
315
322
|
createWalletEmitter,
|
|
323
|
+
initUnlink,
|
|
316
324
|
initWallet,
|
|
317
325
|
pollRelayStatus,
|
|
318
326
|
waitForConfirmation
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/init.ts","../src/errors.ts","../src/confirmation.ts","../src/events.ts","../src/storage/sqlite.ts"],"sourcesContent":["// Init\nexport { initWallet } from \"./init.js\";\n\n// Confirmation\nexport { waitForConfirmation, pollRelayStatus } from \"./confirmation.js\";\n\n// Events\nexport { createWalletEmitter } from \"./events.js\";\n\n// Storage\nexport {\n createSqliteStorage,\n type SqliteStorageOptions,\n} from \"./storage/sqlite.js\";\n\n// Errors\nexport {\n TimeoutError,\n TransactionFailedError,\n TERMINAL_TX_STATES,\n FAILED_TX_STATES,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_POLL_INTERVAL_MS,\n} from \"./errors.js\";\n\n// Types\nexport type {\n NodeWalletConfig,\n TxStatus,\n WaitOptions,\n PollOptions,\n} from \"./types.js\";\n\n// Re-export commonly needed core types so consumers don't need @unlink-xyz/core\nexport { UnlinkWallet, createMemoryStorage } from \"@unlink-xyz/core\";\n\nexport type {\n Account,\n AccountInfo,\n AccountView,\n DepositRelayResult,\n Environment,\n HistoryEntry,\n NoteRecord,\n RelayState,\n RelayStatusResponse,\n Storage,\n TransactRelayResult,\n TransferPlanResult,\n TransferResult,\n WalletSDKEvent,\n WithdrawPlanResult,\n WithdrawResult,\n} from \"@unlink-xyz/core\";\n","import crypto from \"node:crypto\";\nimport { createMemoryStorage, UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport type { NodeWalletConfig } from \"./types.js\";\n\nconst nodeRng = (n: number): Uint8Array =>\n new Uint8Array(crypto.randomBytes(n));\n\n/**\n * Initialize an Unlink wallet with Node.js-friendly defaults.\n *\n * Compared to `UnlinkWallet.create()`, this:\n * - Defaults storage to in-memory (no IndexedDB required)\n * - Defaults RNG to `node:crypto`\n * - Defaults autoSync to `false`\n * - Optionally creates seed + first account automatically\n * - Optionally syncs notes from blockchain\n *\n * @example\n * ```ts\n * // Minimal — ready to use in one call:\n * const wallet = await initWallet({\n * chainId: 11155111,\n * environment: \"testnet\",\n * });\n *\n * // Skip auto-setup (e.g., to import an existing mnemonic):\n * const wallet = await initWallet({\n * chainId: 11155111,\n * environment: \"testnet\",\n * setup: false,\n * sync: false,\n * });\n * await wallet.seed.importMnemonic(\"your mnemonic ...\");\n * await wallet.accounts.create();\n * await wallet.sync();\n * ```\n */\nexport async function initWallet(\n config: NodeWalletConfig,\n): Promise<UnlinkWallet> {\n // Strip node-specific fields before passing to core\n const { setup, sync, ...coreConfig } = config;\n void setup;\n void sync;\n\n const wallet = await UnlinkWallet.create({\n ...coreConfig,\n storage: config.storage ?? createMemoryStorage(),\n rng: config.rng ?? nodeRng,\n autoSync: config.autoSync ?? false,\n fetch: config.fetch ?? globalThis.fetch,\n });\n\n if (config.setup !== false) {\n const hasSeed = await wallet.seed.exists();\n if (!hasSeed) {\n await wallet.seed.create();\n }\n\n const accounts = await wallet.accounts.list();\n if (accounts.length === 0) {\n await wallet.accounts.create();\n }\n }\n\n if (config.sync !== false) {\n await wallet.sync();\n }\n\n return wallet;\n}\n","import type { RelayState } from \"@unlink-xyz/core\";\n\n/** Terminal relay states — the transaction has finished processing. */\nexport const TERMINAL_TX_STATES: readonly RelayState[] = [\n \"succeeded\",\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Failed relay states — the transaction did not succeed. */\nexport const FAILED_TX_STATES: readonly RelayState[] = [\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Default timeout for `waitForConfirmation` (5 minutes). */\nexport const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Default initial poll interval (2 seconds). */\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\n\n/** Maximum poll interval after backoff (30 seconds). */\nexport const MAX_POLL_INTERVAL_MS = 30_000;\n\n/** Backoff multiplier for exponential polling. */\nexport const BACKOFF_FACTOR = 1.5;\n\n/** Thrown when relay polling exceeds the configured timeout. */\nexport class TimeoutError extends Error {\n readonly txId: string;\n readonly timeout: number;\n\n constructor(txId: string, timeout: number) {\n super(`Transaction ${txId} did not confirm within ${timeout}ms`);\n this.name = \"TimeoutError\";\n this.txId = txId;\n this.timeout = timeout;\n }\n}\n\n/** Thrown when a transaction reaches a failed terminal state. */\nexport class TransactionFailedError extends Error {\n readonly txId: string;\n readonly state: RelayState;\n readonly reason?: string;\n\n constructor(txId: string, state: RelayState, reason?: string) {\n super(\n `Transaction ${txId} failed with state: ${state}${reason ? ` — ${reason}` : \"\"}`,\n );\n this.name = \"TransactionFailedError\";\n this.txId = txId;\n this.state = state;\n this.reason = reason;\n }\n}\n","import type { UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport {\n BACKOFF_FACTOR,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n FAILED_TX_STATES,\n MAX_POLL_INTERVAL_MS,\n TERMINAL_TX_STATES,\n TimeoutError,\n TransactionFailedError,\n} from \"./errors.js\";\nimport type { PollOptions, TxStatus, WaitOptions } from \"./types.js\";\n\nfunction toTxStatus(\n txId: string,\n raw: Awaited<ReturnType<UnlinkWallet[\"getTxStatus\"]>>,\n): TxStatus {\n return {\n txId,\n state: raw.state,\n txHash: raw.txHash ?? undefined,\n blockNumber: raw.receipt?.blockNumber ?? undefined,\n error: raw.error ?? undefined,\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll relay status until the transaction reaches a terminal state.\n *\n * Resolves with `TxStatus` on success (`\"succeeded\"`).\n * Throws `TransactionFailedError` on failure (`\"reverted\"`, `\"failed\"`, `\"dead\"`).\n * Throws `TimeoutError` if the timeout is exceeded.\n *\n * Uses exponential backoff: 2s → 3s → 4.5s → ... capped at 30s.\n *\n * @example\n * ```ts\n * const result = await wallet.transfer({ transfers: [{ token, recipient, amount }] });\n * const status = await waitForConfirmation(wallet, result.relayId);\n * console.log(status.state); // \"succeeded\"\n * ```\n */\nexport async function waitForConfirmation(\n wallet: UnlinkWallet,\n txId: string,\n opts?: WaitOptions,\n): Promise<TxStatus> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n if (status.state === \"succeeded\") {\n return status;\n }\n\n if (FAILED_TX_STATES.includes(status.state)) {\n throw new TransactionFailedError(txId, status.state, status.error);\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n\n throw new TimeoutError(txId, timeout);\n}\n\n/**\n * Async generator that yields `TxStatus` on each poll until a terminal state.\n *\n * Useful for streaming status updates (e.g., logging, progress bars).\n *\n * @example\n * ```ts\n * for await (const status of pollRelayStatus(wallet, relayId)) {\n * console.log(status.state); // \"pending\" → \"broadcasting\" → \"submitted\" → \"succeeded\"\n * }\n * ```\n */\nexport async function* pollRelayStatus(\n wallet: UnlinkWallet,\n txId: string,\n opts?: PollOptions,\n): AsyncGenerator<TxStatus, void, unknown> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n yield status;\n\n if (TERMINAL_TX_STATES.includes(status.state)) {\n return;\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) return;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { UnlinkWallet, WalletSDKEvent } from \"@unlink-xyz/core\";\n\n/**\n * Wrap an UnlinkWallet's event system with a Node.js `EventEmitter`.\n *\n * Events are emitted by their `type` field (e.g., `\"notes-updated\"`,\n * `\"tx-status-changed\"`). A wildcard `\"*\"` event is also emitted for\n * every event.\n *\n * @returns An `EventEmitter` and an `unsubscribe` function to detach from the wallet.\n *\n * @example\n * ```ts\n * const { emitter, unsubscribe } = createWalletEmitter(wallet);\n *\n * emitter.on(\"notes-updated\", (event) => {\n * console.log(\"Notes updated on chain\", event.chainId);\n * });\n *\n * emitter.on(\"tx-status-changed\", (event) => {\n * console.log(`TX ${event.txId}: ${event.state}`);\n * });\n *\n * // Listen to all events\n * emitter.on(\"*\", (event) => console.log(event));\n *\n * // Cleanup when done\n * unsubscribe();\n * ```\n */\nexport function createWalletEmitter(wallet: UnlinkWallet): {\n emitter: EventEmitter;\n unsubscribe: () => void;\n} {\n const emitter = new EventEmitter();\n\n const unsubscribe = wallet.on((event: WalletSDKEvent) => {\n emitter.emit(event.type, event);\n emitter.emit(\"*\", event);\n });\n\n return { emitter, unsubscribe };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n BatchOp,\n Bytes,\n IterOptions,\n KvPair,\n Storage,\n} from \"@unlink-xyz/core\";\nimport { validateKey } from \"@unlink-xyz/core\";\nimport Database from \"better-sqlite3\";\n\nexport type SqliteStorageOptions = {\n /** Full path to the .db file */\n path: string;\n};\n\nexport function createSqliteStorage(opts: SqliteStorageOptions): Storage {\n let db: Database.Database | null = null;\n let stmtGet: Database.Statement;\n let stmtPut: Database.Statement;\n let stmtDel: Database.Statement;\n let stmtGetSchema: Database.Statement;\n let stmtUpsertSchema: Database.Statement;\n\n return {\n async open() {\n const dir = path.dirname(opts.path);\n fs.mkdirSync(dir, { recursive: true });\n\n db = new Database(opts.path);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.exec(`\n CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value BLOB NOT NULL);\n CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER NOT NULL);\n `);\n\n stmtGet = db.prepare(\"SELECT value FROM kv WHERE key = ?\");\n stmtPut = db.prepare(\n \"INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)\",\n );\n stmtDel = db.prepare(\"DELETE FROM kv WHERE key = ?\");\n stmtGetSchema = db.prepare(\n \"SELECT value FROM meta WHERE key = 'schema_version'\",\n );\n stmtUpsertSchema = db.prepare(\n \"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\",\n );\n },\n\n async get(key: string): Promise<Bytes | null> {\n validateKey(key);\n const row = stmtGet.get(key) as { value: Buffer } | undefined;\n return row ? new Uint8Array(row.value) : null;\n },\n\n async put(key: string, value: Bytes): Promise<void> {\n validateKey(key);\n stmtPut.run(key, Buffer.from(value));\n },\n\n async delete(key: string): Promise<void> {\n validateKey(key);\n stmtDel.run(key);\n },\n\n async batch(ops: BatchOp[]): Promise<void> {\n const runBatch = db!.transaction(() => {\n for (const op of ops) {\n if (op.put) {\n const [k, v] = op.put;\n validateKey(k);\n stmtPut.run(k, Buffer.from(v));\n }\n if (op.del) {\n validateKey(op.del);\n stmtDel.run(op.del);\n }\n }\n });\n runBatch();\n },\n\n async iter(o: IterOptions = {}): Promise<KvPair[]> {\n if (o.start && o.end && o.start > o.end) {\n throw new Error(\"iter start bound must not exceed end bound\");\n }\n\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (o.prefix) {\n // Escape SQL LIKE wildcards in the prefix\n const escaped = o.prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n conditions.push(\"key LIKE ? ESCAPE '\\\\'\");\n params.push(escaped + \"%\");\n }\n if (o.start) {\n conditions.push(\"key >= ?\");\n params.push(o.start);\n }\n if (o.end) {\n conditions.push(\"key <= ?\");\n params.push(o.end);\n }\n\n let sql = \"SELECT key, value FROM kv\";\n if (conditions.length > 0) {\n sql += \" WHERE \" + conditions.join(\" AND \");\n }\n sql += o.reverse ? \" ORDER BY key DESC\" : \" ORDER BY key ASC\";\n if (o.limit != null) {\n sql += \" LIMIT ?\";\n params.push(o.limit);\n }\n\n const rows = db!.prepare(sql).all(...params) as Array<{\n key: string;\n value: Buffer;\n }>;\n\n return rows.map((row) => ({\n key: row.key,\n value: new Uint8Array(row.value),\n }));\n },\n\n async count(prefix?: string): Promise<number> {\n let sql = \"SELECT COUNT(*) as cnt FROM kv\";\n const params: string[] = [];\n if (prefix) {\n const escaped = prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n sql += \" WHERE key LIKE ? ESCAPE '\\\\'\";\n params.push(escaped + \"%\");\n }\n const row = db!.prepare(sql).get(...params) as { cnt: number };\n return row.cnt;\n },\n\n async getSchemaVersion(): Promise<number> {\n const row = stmtGetSchema.get() as { value: number } | undefined;\n return row?.value ?? 0;\n },\n\n async setSchemaVersion(v: number): Promise<void> {\n stmtUpsertSchema.run(v);\n },\n };\n}\n"],"mappings":"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","names":["crypto","import_core","path","fs","Database","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/init.ts","../src/errors.ts","../src/confirmation.ts","../src/events.ts","../src/storage/sqlite.ts"],"sourcesContent":["// Init\nexport { initUnlink, initWallet } from \"./init.js\";\n\n// Confirmation\nexport { waitForConfirmation, pollRelayStatus } from \"./confirmation.js\";\n\n// Events\nexport { createEmitter, createWalletEmitter } from \"./events.js\";\n\n// Storage\nexport {\n createSqliteStorage,\n type SqliteStorageOptions,\n} from \"./storage/sqlite.js\";\n\n// Errors\nexport {\n TimeoutError,\n TransactionFailedError,\n TERMINAL_TX_STATES,\n FAILED_TX_STATES,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_POLL_INTERVAL_MS,\n} from \"./errors.js\";\n\n// Types\nexport type {\n InitUnlinkConfig,\n NodeWalletConfig,\n TxStatus,\n WaitOptions,\n PollOptions,\n} from \"./types.js\";\n\n// Re-export commonly needed core types so consumers don't need @unlink-xyz/core\nexport { Unlink, UnlinkWallet, createMemoryStorage } from \"@unlink-xyz/core\";\n\nexport type {\n Account,\n AccountInfo,\n AccountView,\n ChainConfig,\n DepositRelayResult,\n HistoryEntry,\n NoteRecord,\n RelayState,\n RelayStatusResponse,\n Storage,\n SupportedChain,\n TransactRelayResult,\n SendPlanResult,\n SendResult,\n UnlinkEvent,\n WalletSDKEvent,\n WithdrawPlanResult,\n WithdrawResult,\n} from \"@unlink-xyz/core\";\n","import crypto from \"node:crypto\";\nimport { createMemoryStorage, Unlink } from \"@unlink-xyz/core\";\n\nimport type { InitUnlinkConfig } from \"./types.js\";\n\nconst nodeRng = (n: number): Uint8Array =>\n new Uint8Array(crypto.randomBytes(n));\n\n/**\n * Initialize an Unlink instance with Node.js-friendly defaults.\n *\n * Compared to `Unlink.create()`, this:\n * - Defaults storage to in-memory (no IndexedDB required)\n * - Defaults RNG to `node:crypto`\n * - Defaults autoSync to `false`\n * - Optionally creates seed + first account automatically\n * - Optionally syncs notes from blockchain\n *\n * @example\n * ```ts\n * // Minimal — ready to use in one call:\n * const unlink = await initUnlink({\n * chain: \"monad-testnet\",\n * });\n *\n * // Skip auto-setup (e.g., to import an existing mnemonic):\n * const unlink = await initUnlink({\n * chain: \"monad-testnet\",\n * setup: false,\n * sync: false,\n * });\n * await unlink.seed.importMnemonic(\"your mnemonic ...\");\n * await unlink.accounts.create();\n * await unlink.sync();\n * ```\n */\nexport async function initUnlink(config: InitUnlinkConfig): Promise<Unlink> {\n // Strip node-specific fields before passing to core\n const { setup, sync, ...coreConfig } = config;\n void setup;\n void sync;\n\n const unlink = await Unlink.create({\n ...coreConfig,\n storage: config.storage ?? createMemoryStorage(),\n rng: config.rng ?? nodeRng,\n autoSync: config.autoSync ?? false,\n fetch: config.fetch ?? globalThis.fetch,\n });\n\n if (config.setup !== false) {\n const hasSeed = await unlink.seed.exists();\n if (!hasSeed) {\n await unlink.seed.create();\n }\n\n const accounts = await unlink.accounts.list();\n if (accounts.length === 0) {\n await unlink.accounts.create();\n }\n }\n\n if (config.sync !== false) {\n await unlink.sync();\n }\n\n return unlink;\n}\n\n/** @deprecated Use {@link initUnlink} instead. */\nexport const initWallet = initUnlink;\n","import type { RelayState } from \"@unlink-xyz/core\";\n\n/** Terminal relay states — the transaction has finished processing. */\nexport const TERMINAL_TX_STATES: readonly RelayState[] = [\n \"succeeded\",\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Failed relay states — the transaction did not succeed. */\nexport const FAILED_TX_STATES: readonly RelayState[] = [\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Default timeout for `waitForConfirmation` (5 minutes). */\nexport const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Default initial poll interval (2 seconds). */\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\n\n/** Maximum poll interval after backoff (30 seconds). */\nexport const MAX_POLL_INTERVAL_MS = 30_000;\n\n/** Backoff multiplier for exponential polling. */\nexport const BACKOFF_FACTOR = 1.5;\n\n/** Thrown when relay polling exceeds the configured timeout. */\nexport class TimeoutError extends Error {\n readonly txId: string;\n readonly timeout: number;\n\n constructor(txId: string, timeout: number) {\n super(`Transaction ${txId} did not confirm within ${timeout}ms`);\n this.name = \"TimeoutError\";\n this.txId = txId;\n this.timeout = timeout;\n }\n}\n\n/** Thrown when a transaction reaches a failed terminal state. */\nexport class TransactionFailedError extends Error {\n readonly txId: string;\n readonly state: RelayState;\n readonly reason?: string;\n\n constructor(txId: string, state: RelayState, reason?: string) {\n super(\n `Transaction ${txId} failed with state: ${state}${reason ? ` — ${reason}` : \"\"}`,\n );\n this.name = \"TransactionFailedError\";\n this.txId = txId;\n this.state = state;\n this.reason = reason;\n }\n}\n","import type { UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport {\n BACKOFF_FACTOR,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n FAILED_TX_STATES,\n MAX_POLL_INTERVAL_MS,\n TERMINAL_TX_STATES,\n TimeoutError,\n TransactionFailedError,\n} from \"./errors.js\";\nimport type { PollOptions, TxStatus, WaitOptions } from \"./types.js\";\n\nfunction toTxStatus(\n txId: string,\n raw: Awaited<ReturnType<UnlinkWallet[\"getTxStatus\"]>>,\n): TxStatus {\n return {\n txId,\n state: raw.state,\n txHash: raw.txHash ?? undefined,\n blockNumber: raw.receipt?.blockNumber ?? undefined,\n error: raw.error ?? undefined,\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll relay status until the transaction reaches a terminal state.\n *\n * Resolves with `TxStatus` on success (`\"succeeded\"`).\n * Throws `TransactionFailedError` on failure (`\"reverted\"`, `\"failed\"`, `\"dead\"`).\n * Throws `TimeoutError` if the timeout is exceeded.\n *\n * Uses exponential backoff: 2s → 3s → 4.5s → ... capped at 30s.\n *\n * @example\n * ```ts\n * const result = await wallet.send({ transfers: [{ token, recipient, amount }] });\n * const status = await waitForConfirmation(wallet, result.relayId);\n * console.log(status.state); // \"succeeded\"\n * ```\n */\nexport async function waitForConfirmation(\n wallet: UnlinkWallet,\n txId: string,\n opts?: WaitOptions,\n): Promise<TxStatus> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n if (status.state === \"succeeded\") {\n return status;\n }\n\n if (FAILED_TX_STATES.includes(status.state)) {\n throw new TransactionFailedError(txId, status.state, status.error);\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n\n throw new TimeoutError(txId, timeout);\n}\n\n/**\n * Async generator that yields `TxStatus` on each poll until a terminal state.\n *\n * Useful for streaming status updates (e.g., logging, progress bars).\n *\n * @example\n * ```ts\n * for await (const status of pollRelayStatus(wallet, relayId)) {\n * console.log(status.state); // \"pending\" → \"broadcasting\" → \"submitted\" → \"succeeded\"\n * }\n * ```\n */\nexport async function* pollRelayStatus(\n wallet: UnlinkWallet,\n txId: string,\n opts?: PollOptions,\n): AsyncGenerator<TxStatus, void, unknown> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n yield status;\n\n if (TERMINAL_TX_STATES.includes(status.state)) {\n return;\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) return;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Unlink, UnlinkEvent } from \"@unlink-xyz/core\";\n\n/**\n * Wrap an Unlink instance's event system with a Node.js `EventEmitter`.\n *\n * Events are emitted by their `type` field (e.g., `\"notes-updated\"`,\n * `\"tx-status-changed\"`). A wildcard `\"*\"` event is also emitted for\n * every event.\n *\n * @returns An `EventEmitter` and an `unsubscribe` function to detach from the instance.\n *\n * @example\n * ```ts\n * const { emitter, unsubscribe } = createEmitter(unlink);\n *\n * emitter.on(\"notes-updated\", (event) => {\n * console.log(\"Notes updated on chain\", event.chainId);\n * });\n *\n * emitter.on(\"tx-status-changed\", (event) => {\n * console.log(`TX ${event.txId}: ${event.state}`);\n * });\n *\n * // Listen to all events\n * emitter.on(\"*\", (event) => console.log(event));\n *\n * // Cleanup when done\n * unsubscribe();\n * ```\n */\nexport function createEmitter(unlink: Unlink): {\n emitter: EventEmitter;\n unsubscribe: () => void;\n} {\n const emitter = new EventEmitter();\n\n const unsubscribe = unlink.on((event: UnlinkEvent) => {\n emitter.emit(event.type, event);\n emitter.emit(\"*\", event);\n });\n\n return { emitter, unsubscribe };\n}\n\n/** @deprecated Use {@link createEmitter} instead. */\nexport const createWalletEmitter = createEmitter;\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n BatchOp,\n Bytes,\n IterOptions,\n KvPair,\n Storage,\n} from \"@unlink-xyz/core\";\nimport { validateKey } from \"@unlink-xyz/core\";\nimport Database from \"better-sqlite3\";\n\nexport type SqliteStorageOptions = {\n /** Full path to the .db file */\n path: string;\n};\n\nexport function createSqliteStorage(opts: SqliteStorageOptions): Storage {\n let db: Database.Database | null = null;\n let stmtGet: Database.Statement;\n let stmtPut: Database.Statement;\n let stmtDel: Database.Statement;\n let stmtGetSchema: Database.Statement;\n let stmtUpsertSchema: Database.Statement;\n\n return {\n async open() {\n const dir = path.dirname(opts.path);\n fs.mkdirSync(dir, { recursive: true });\n\n db = new Database(opts.path);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.exec(`\n CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value BLOB NOT NULL);\n CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER NOT NULL);\n `);\n\n stmtGet = db.prepare(\"SELECT value FROM kv WHERE key = ?\");\n stmtPut = db.prepare(\n \"INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)\",\n );\n stmtDel = db.prepare(\"DELETE FROM kv WHERE key = ?\");\n stmtGetSchema = db.prepare(\n \"SELECT value FROM meta WHERE key = 'schema_version'\",\n );\n stmtUpsertSchema = db.prepare(\n \"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\",\n );\n },\n\n async get(key: string): Promise<Bytes | null> {\n validateKey(key);\n const row = stmtGet.get(key) as { value: Buffer } | undefined;\n return row ? new Uint8Array(row.value) : null;\n },\n\n async put(key: string, value: Bytes): Promise<void> {\n validateKey(key);\n stmtPut.run(key, Buffer.from(value));\n },\n\n async delete(key: string): Promise<void> {\n validateKey(key);\n stmtDel.run(key);\n },\n\n async batch(ops: BatchOp[]): Promise<void> {\n const runBatch = db!.transaction(() => {\n for (const op of ops) {\n if (op.put) {\n const [k, v] = op.put;\n validateKey(k);\n stmtPut.run(k, Buffer.from(v));\n }\n if (op.del) {\n validateKey(op.del);\n stmtDel.run(op.del);\n }\n }\n });\n runBatch();\n },\n\n async iter(o: IterOptions = {}): Promise<KvPair[]> {\n if (o.start && o.end && o.start > o.end) {\n throw new Error(\"iter start bound must not exceed end bound\");\n }\n\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (o.prefix) {\n // Escape SQL LIKE wildcards in the prefix\n const escaped = o.prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n conditions.push(\"key LIKE ? ESCAPE '\\\\'\");\n params.push(escaped + \"%\");\n }\n if (o.start) {\n conditions.push(\"key >= ?\");\n params.push(o.start);\n }\n if (o.end) {\n conditions.push(\"key <= ?\");\n params.push(o.end);\n }\n\n let sql = \"SELECT key, value FROM kv\";\n if (conditions.length > 0) {\n sql += \" WHERE \" + conditions.join(\" AND \");\n }\n sql += o.reverse ? \" ORDER BY key DESC\" : \" ORDER BY key ASC\";\n if (o.limit != null) {\n sql += \" LIMIT ?\";\n params.push(o.limit);\n }\n\n const rows = db!.prepare(sql).all(...params) as Array<{\n key: string;\n value: Buffer;\n }>;\n\n return rows.map((row) => ({\n key: row.key,\n value: new Uint8Array(row.value),\n }));\n },\n\n async count(prefix?: string): Promise<number> {\n let sql = \"SELECT COUNT(*) as cnt FROM kv\";\n const params: string[] = [];\n if (prefix) {\n const escaped = prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n sql += \" WHERE key LIKE ? ESCAPE '\\\\'\";\n params.push(escaped + \"%\");\n }\n const row = db!.prepare(sql).get(...params) as { cnt: number };\n return row.cnt;\n },\n\n async getSchemaVersion(): Promise<number> {\n const row = stmtGetSchema.get() as { value: number } | undefined;\n return row?.value ?? 0;\n },\n\n async setSchemaVersion(v: number): Promise<void> {\n stmtUpsertSchema.run(v);\n },\n };\n}\n"],"mappings":"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","names":["crypto","import_core","path","fs","Database","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { Storage,
|
|
2
|
-
export { Account, AccountInfo, AccountView,
|
|
1
|
+
import { Storage, SupportedChain, RelayState, Unlink, UnlinkWallet } from '@unlink-xyz/core';
|
|
2
|
+
export { Account, AccountInfo, AccountView, ChainConfig, DepositRelayResult, HistoryEntry, NoteRecord, RelayState, RelayStatusResponse, SendPlanResult, SendResult, Storage, SupportedChain, TransactRelayResult, Unlink, UnlinkEvent, UnlinkWallet, WalletSDKEvent, WithdrawPlanResult, WithdrawResult, createMemoryStorage } from '@unlink-xyz/core';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Configuration for `
|
|
6
|
+
* Configuration for `initUnlink()`.
|
|
7
7
|
*
|
|
8
|
-
* Extends core
|
|
8
|
+
* Extends core config with Node.js-friendly defaults:
|
|
9
9
|
* - `storage` defaults to in-memory
|
|
10
10
|
* - `rng` defaults to `node:crypto`
|
|
11
11
|
* - `autoSync` defaults to `false`
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
14
|
-
chainId: number;
|
|
13
|
+
type InitUnlinkConfig = {
|
|
15
14
|
/** Storage backend. Defaults to `createMemoryStorage()`. */
|
|
16
15
|
storage?: Storage;
|
|
17
16
|
/** Random number generator. Defaults to `node:crypto.randomBytes`. */
|
|
@@ -41,11 +40,13 @@ type NodeWalletConfig = {
|
|
|
41
40
|
*/
|
|
42
41
|
sync?: boolean;
|
|
43
42
|
} & ({
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
/** Override pool address (defaults to
|
|
43
|
+
/** Supported chain name — resolves chainId, gateway, pool, artifacts. */
|
|
44
|
+
chain: SupportedChain;
|
|
45
|
+
/** Override pool address (defaults to chain config). */
|
|
47
46
|
poolAddress?: string;
|
|
48
47
|
} | {
|
|
48
|
+
/** Chain ID for the target blockchain. */
|
|
49
|
+
chainId: number;
|
|
49
50
|
/** Explicit gateway URL. */
|
|
50
51
|
gatewayUrl: string;
|
|
51
52
|
/** Pool contract address (required with explicit gatewayUrl). */
|
|
@@ -73,11 +74,13 @@ type PollOptions = {
|
|
|
73
74
|
/** Timeout in milliseconds. Defaults to 5 minutes. */
|
|
74
75
|
timeout?: number;
|
|
75
76
|
};
|
|
77
|
+
/** @deprecated Use {@link InitUnlinkConfig} instead. */
|
|
78
|
+
type NodeWalletConfig = InitUnlinkConfig;
|
|
76
79
|
|
|
77
80
|
/**
|
|
78
|
-
* Initialize an Unlink
|
|
81
|
+
* Initialize an Unlink instance with Node.js-friendly defaults.
|
|
79
82
|
*
|
|
80
|
-
* Compared to `
|
|
83
|
+
* Compared to `Unlink.create()`, this:
|
|
81
84
|
* - Defaults storage to in-memory (no IndexedDB required)
|
|
82
85
|
* - Defaults RNG to `node:crypto`
|
|
83
86
|
* - Defaults autoSync to `false`
|
|
@@ -87,24 +90,24 @@ type PollOptions = {
|
|
|
87
90
|
* @example
|
|
88
91
|
* ```ts
|
|
89
92
|
* // Minimal — ready to use in one call:
|
|
90
|
-
* const
|
|
91
|
-
*
|
|
92
|
-
* environment: "testnet",
|
|
93
|
+
* const unlink = await initUnlink({
|
|
94
|
+
* chain: "monad-testnet",
|
|
93
95
|
* });
|
|
94
96
|
*
|
|
95
97
|
* // Skip auto-setup (e.g., to import an existing mnemonic):
|
|
96
|
-
* const
|
|
97
|
-
*
|
|
98
|
-
* environment: "testnet",
|
|
98
|
+
* const unlink = await initUnlink({
|
|
99
|
+
* chain: "monad-testnet",
|
|
99
100
|
* setup: false,
|
|
100
101
|
* sync: false,
|
|
101
102
|
* });
|
|
102
|
-
* await
|
|
103
|
-
* await
|
|
104
|
-
* await
|
|
103
|
+
* await unlink.seed.importMnemonic("your mnemonic ...");
|
|
104
|
+
* await unlink.accounts.create();
|
|
105
|
+
* await unlink.sync();
|
|
105
106
|
* ```
|
|
106
107
|
*/
|
|
107
|
-
declare function
|
|
108
|
+
declare function initUnlink(config: InitUnlinkConfig): Promise<Unlink>;
|
|
109
|
+
/** @deprecated Use {@link initUnlink} instead. */
|
|
110
|
+
declare const initWallet: typeof initUnlink;
|
|
108
111
|
|
|
109
112
|
/**
|
|
110
113
|
* Poll relay status until the transaction reaches a terminal state.
|
|
@@ -117,7 +120,7 @@ declare function initWallet(config: NodeWalletConfig): Promise<UnlinkWallet>;
|
|
|
117
120
|
*
|
|
118
121
|
* @example
|
|
119
122
|
* ```ts
|
|
120
|
-
* const result = await wallet.
|
|
123
|
+
* const result = await wallet.send({ transfers: [{ token, recipient, amount }] });
|
|
121
124
|
* const status = await waitForConfirmation(wallet, result.relayId);
|
|
122
125
|
* console.log(status.state); // "succeeded"
|
|
123
126
|
* ```
|
|
@@ -138,17 +141,17 @@ declare function waitForConfirmation(wallet: UnlinkWallet, txId: string, opts?:
|
|
|
138
141
|
declare function pollRelayStatus(wallet: UnlinkWallet, txId: string, opts?: PollOptions): AsyncGenerator<TxStatus, void, unknown>;
|
|
139
142
|
|
|
140
143
|
/**
|
|
141
|
-
* Wrap an
|
|
144
|
+
* Wrap an Unlink instance's event system with a Node.js `EventEmitter`.
|
|
142
145
|
*
|
|
143
146
|
* Events are emitted by their `type` field (e.g., `"notes-updated"`,
|
|
144
147
|
* `"tx-status-changed"`). A wildcard `"*"` event is also emitted for
|
|
145
148
|
* every event.
|
|
146
149
|
*
|
|
147
|
-
* @returns An `EventEmitter` and an `unsubscribe` function to detach from the
|
|
150
|
+
* @returns An `EventEmitter` and an `unsubscribe` function to detach from the instance.
|
|
148
151
|
*
|
|
149
152
|
* @example
|
|
150
153
|
* ```ts
|
|
151
|
-
* const { emitter, unsubscribe } =
|
|
154
|
+
* const { emitter, unsubscribe } = createEmitter(unlink);
|
|
152
155
|
*
|
|
153
156
|
* emitter.on("notes-updated", (event) => {
|
|
154
157
|
* console.log("Notes updated on chain", event.chainId);
|
|
@@ -165,10 +168,12 @@ declare function pollRelayStatus(wallet: UnlinkWallet, txId: string, opts?: Poll
|
|
|
165
168
|
* unsubscribe();
|
|
166
169
|
* ```
|
|
167
170
|
*/
|
|
168
|
-
declare function
|
|
171
|
+
declare function createEmitter(unlink: Unlink): {
|
|
169
172
|
emitter: EventEmitter;
|
|
170
173
|
unsubscribe: () => void;
|
|
171
174
|
};
|
|
175
|
+
/** @deprecated Use {@link createEmitter} instead. */
|
|
176
|
+
declare const createWalletEmitter: typeof createEmitter;
|
|
172
177
|
|
|
173
178
|
type SqliteStorageOptions = {
|
|
174
179
|
/** Full path to the .db file */
|
|
@@ -198,4 +203,4 @@ declare class TransactionFailedError extends Error {
|
|
|
198
203
|
constructor(txId: string, state: RelayState, reason?: string);
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
export { DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, FAILED_TX_STATES, type NodeWalletConfig, type PollOptions, type SqliteStorageOptions, TERMINAL_TX_STATES, TimeoutError, TransactionFailedError, type TxStatus, type WaitOptions, createSqliteStorage, createWalletEmitter, initWallet, pollRelayStatus, waitForConfirmation };
|
|
206
|
+
export { DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, FAILED_TX_STATES, type InitUnlinkConfig, type NodeWalletConfig, type PollOptions, type SqliteStorageOptions, TERMINAL_TX_STATES, TimeoutError, TransactionFailedError, type TxStatus, type WaitOptions, createEmitter, createSqliteStorage, createWalletEmitter, initUnlink, initWallet, pollRelayStatus, waitForConfirmation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { Storage,
|
|
2
|
-
export { Account, AccountInfo, AccountView,
|
|
1
|
+
import { Storage, SupportedChain, RelayState, Unlink, UnlinkWallet } from '@unlink-xyz/core';
|
|
2
|
+
export { Account, AccountInfo, AccountView, ChainConfig, DepositRelayResult, HistoryEntry, NoteRecord, RelayState, RelayStatusResponse, SendPlanResult, SendResult, Storage, SupportedChain, TransactRelayResult, Unlink, UnlinkEvent, UnlinkWallet, WalletSDKEvent, WithdrawPlanResult, WithdrawResult, createMemoryStorage } from '@unlink-xyz/core';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Configuration for `
|
|
6
|
+
* Configuration for `initUnlink()`.
|
|
7
7
|
*
|
|
8
|
-
* Extends core
|
|
8
|
+
* Extends core config with Node.js-friendly defaults:
|
|
9
9
|
* - `storage` defaults to in-memory
|
|
10
10
|
* - `rng` defaults to `node:crypto`
|
|
11
11
|
* - `autoSync` defaults to `false`
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
14
|
-
chainId: number;
|
|
13
|
+
type InitUnlinkConfig = {
|
|
15
14
|
/** Storage backend. Defaults to `createMemoryStorage()`. */
|
|
16
15
|
storage?: Storage;
|
|
17
16
|
/** Random number generator. Defaults to `node:crypto.randomBytes`. */
|
|
@@ -41,11 +40,13 @@ type NodeWalletConfig = {
|
|
|
41
40
|
*/
|
|
42
41
|
sync?: boolean;
|
|
43
42
|
} & ({
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
/** Override pool address (defaults to
|
|
43
|
+
/** Supported chain name — resolves chainId, gateway, pool, artifacts. */
|
|
44
|
+
chain: SupportedChain;
|
|
45
|
+
/** Override pool address (defaults to chain config). */
|
|
47
46
|
poolAddress?: string;
|
|
48
47
|
} | {
|
|
48
|
+
/** Chain ID for the target blockchain. */
|
|
49
|
+
chainId: number;
|
|
49
50
|
/** Explicit gateway URL. */
|
|
50
51
|
gatewayUrl: string;
|
|
51
52
|
/** Pool contract address (required with explicit gatewayUrl). */
|
|
@@ -73,11 +74,13 @@ type PollOptions = {
|
|
|
73
74
|
/** Timeout in milliseconds. Defaults to 5 minutes. */
|
|
74
75
|
timeout?: number;
|
|
75
76
|
};
|
|
77
|
+
/** @deprecated Use {@link InitUnlinkConfig} instead. */
|
|
78
|
+
type NodeWalletConfig = InitUnlinkConfig;
|
|
76
79
|
|
|
77
80
|
/**
|
|
78
|
-
* Initialize an Unlink
|
|
81
|
+
* Initialize an Unlink instance with Node.js-friendly defaults.
|
|
79
82
|
*
|
|
80
|
-
* Compared to `
|
|
83
|
+
* Compared to `Unlink.create()`, this:
|
|
81
84
|
* - Defaults storage to in-memory (no IndexedDB required)
|
|
82
85
|
* - Defaults RNG to `node:crypto`
|
|
83
86
|
* - Defaults autoSync to `false`
|
|
@@ -87,24 +90,24 @@ type PollOptions = {
|
|
|
87
90
|
* @example
|
|
88
91
|
* ```ts
|
|
89
92
|
* // Minimal — ready to use in one call:
|
|
90
|
-
* const
|
|
91
|
-
*
|
|
92
|
-
* environment: "testnet",
|
|
93
|
+
* const unlink = await initUnlink({
|
|
94
|
+
* chain: "monad-testnet",
|
|
93
95
|
* });
|
|
94
96
|
*
|
|
95
97
|
* // Skip auto-setup (e.g., to import an existing mnemonic):
|
|
96
|
-
* const
|
|
97
|
-
*
|
|
98
|
-
* environment: "testnet",
|
|
98
|
+
* const unlink = await initUnlink({
|
|
99
|
+
* chain: "monad-testnet",
|
|
99
100
|
* setup: false,
|
|
100
101
|
* sync: false,
|
|
101
102
|
* });
|
|
102
|
-
* await
|
|
103
|
-
* await
|
|
104
|
-
* await
|
|
103
|
+
* await unlink.seed.importMnemonic("your mnemonic ...");
|
|
104
|
+
* await unlink.accounts.create();
|
|
105
|
+
* await unlink.sync();
|
|
105
106
|
* ```
|
|
106
107
|
*/
|
|
107
|
-
declare function
|
|
108
|
+
declare function initUnlink(config: InitUnlinkConfig): Promise<Unlink>;
|
|
109
|
+
/** @deprecated Use {@link initUnlink} instead. */
|
|
110
|
+
declare const initWallet: typeof initUnlink;
|
|
108
111
|
|
|
109
112
|
/**
|
|
110
113
|
* Poll relay status until the transaction reaches a terminal state.
|
|
@@ -117,7 +120,7 @@ declare function initWallet(config: NodeWalletConfig): Promise<UnlinkWallet>;
|
|
|
117
120
|
*
|
|
118
121
|
* @example
|
|
119
122
|
* ```ts
|
|
120
|
-
* const result = await wallet.
|
|
123
|
+
* const result = await wallet.send({ transfers: [{ token, recipient, amount }] });
|
|
121
124
|
* const status = await waitForConfirmation(wallet, result.relayId);
|
|
122
125
|
* console.log(status.state); // "succeeded"
|
|
123
126
|
* ```
|
|
@@ -138,17 +141,17 @@ declare function waitForConfirmation(wallet: UnlinkWallet, txId: string, opts?:
|
|
|
138
141
|
declare function pollRelayStatus(wallet: UnlinkWallet, txId: string, opts?: PollOptions): AsyncGenerator<TxStatus, void, unknown>;
|
|
139
142
|
|
|
140
143
|
/**
|
|
141
|
-
* Wrap an
|
|
144
|
+
* Wrap an Unlink instance's event system with a Node.js `EventEmitter`.
|
|
142
145
|
*
|
|
143
146
|
* Events are emitted by their `type` field (e.g., `"notes-updated"`,
|
|
144
147
|
* `"tx-status-changed"`). A wildcard `"*"` event is also emitted for
|
|
145
148
|
* every event.
|
|
146
149
|
*
|
|
147
|
-
* @returns An `EventEmitter` and an `unsubscribe` function to detach from the
|
|
150
|
+
* @returns An `EventEmitter` and an `unsubscribe` function to detach from the instance.
|
|
148
151
|
*
|
|
149
152
|
* @example
|
|
150
153
|
* ```ts
|
|
151
|
-
* const { emitter, unsubscribe } =
|
|
154
|
+
* const { emitter, unsubscribe } = createEmitter(unlink);
|
|
152
155
|
*
|
|
153
156
|
* emitter.on("notes-updated", (event) => {
|
|
154
157
|
* console.log("Notes updated on chain", event.chainId);
|
|
@@ -165,10 +168,12 @@ declare function pollRelayStatus(wallet: UnlinkWallet, txId: string, opts?: Poll
|
|
|
165
168
|
* unsubscribe();
|
|
166
169
|
* ```
|
|
167
170
|
*/
|
|
168
|
-
declare function
|
|
171
|
+
declare function createEmitter(unlink: Unlink): {
|
|
169
172
|
emitter: EventEmitter;
|
|
170
173
|
unsubscribe: () => void;
|
|
171
174
|
};
|
|
175
|
+
/** @deprecated Use {@link createEmitter} instead. */
|
|
176
|
+
declare const createWalletEmitter: typeof createEmitter;
|
|
172
177
|
|
|
173
178
|
type SqliteStorageOptions = {
|
|
174
179
|
/** Full path to the .db file */
|
|
@@ -198,4 +203,4 @@ declare class TransactionFailedError extends Error {
|
|
|
198
203
|
constructor(txId: string, state: RelayState, reason?: string);
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
export { DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, FAILED_TX_STATES, type NodeWalletConfig, type PollOptions, type SqliteStorageOptions, TERMINAL_TX_STATES, TimeoutError, TransactionFailedError, type TxStatus, type WaitOptions, createSqliteStorage, createWalletEmitter, initWallet, pollRelayStatus, waitForConfirmation };
|
|
206
|
+
export { DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, FAILED_TX_STATES, type InitUnlinkConfig, type NodeWalletConfig, type PollOptions, type SqliteStorageOptions, TERMINAL_TX_STATES, TimeoutError, TransactionFailedError, type TxStatus, type WaitOptions, createEmitter, createSqliteStorage, createWalletEmitter, initUnlink, initWallet, pollRelayStatus, waitForConfirmation };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/init.ts
|
|
2
2
|
import crypto from "crypto";
|
|
3
|
-
import { createMemoryStorage,
|
|
3
|
+
import { createMemoryStorage, Unlink } from "@unlink-xyz/core";
|
|
4
4
|
var nodeRng = (n) => new Uint8Array(crypto.randomBytes(n));
|
|
5
|
-
async function
|
|
5
|
+
async function initUnlink(config) {
|
|
6
6
|
const { setup, sync, ...coreConfig } = config;
|
|
7
7
|
void setup;
|
|
8
8
|
void sync;
|
|
9
|
-
const
|
|
9
|
+
const unlink = await Unlink.create({
|
|
10
10
|
...coreConfig,
|
|
11
11
|
storage: config.storage ?? createMemoryStorage(),
|
|
12
12
|
rng: config.rng ?? nodeRng,
|
|
@@ -14,20 +14,21 @@ async function initWallet(config) {
|
|
|
14
14
|
fetch: config.fetch ?? globalThis.fetch
|
|
15
15
|
});
|
|
16
16
|
if (config.setup !== false) {
|
|
17
|
-
const hasSeed = await
|
|
17
|
+
const hasSeed = await unlink.seed.exists();
|
|
18
18
|
if (!hasSeed) {
|
|
19
|
-
await
|
|
19
|
+
await unlink.seed.create();
|
|
20
20
|
}
|
|
21
|
-
const accounts = await
|
|
21
|
+
const accounts = await unlink.accounts.list();
|
|
22
22
|
if (accounts.length === 0) {
|
|
23
|
-
await
|
|
23
|
+
await unlink.accounts.create();
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
if (config.sync !== false) {
|
|
27
|
-
await
|
|
27
|
+
await unlink.sync();
|
|
28
28
|
}
|
|
29
|
-
return
|
|
29
|
+
return unlink;
|
|
30
30
|
}
|
|
31
|
+
var initWallet = initUnlink;
|
|
31
32
|
|
|
32
33
|
// src/errors.ts
|
|
33
34
|
var TERMINAL_TX_STATES = [
|
|
@@ -123,14 +124,15 @@ async function* pollRelayStatus(wallet, txId, opts) {
|
|
|
123
124
|
|
|
124
125
|
// src/events.ts
|
|
125
126
|
import { EventEmitter } from "events";
|
|
126
|
-
function
|
|
127
|
+
function createEmitter(unlink) {
|
|
127
128
|
const emitter = new EventEmitter();
|
|
128
|
-
const unsubscribe =
|
|
129
|
+
const unsubscribe = unlink.on((event) => {
|
|
129
130
|
emitter.emit(event.type, event);
|
|
130
131
|
emitter.emit("*", event);
|
|
131
132
|
});
|
|
132
133
|
return { emitter, unsubscribe };
|
|
133
134
|
}
|
|
135
|
+
var createWalletEmitter = createEmitter;
|
|
134
136
|
|
|
135
137
|
// src/storage/sqlite.ts
|
|
136
138
|
import fs from "fs";
|
|
@@ -252,7 +254,7 @@ function createSqliteStorage(opts) {
|
|
|
252
254
|
}
|
|
253
255
|
|
|
254
256
|
// src/index.ts
|
|
255
|
-
import {
|
|
257
|
+
import { Unlink as Unlink2, UnlinkWallet, createMemoryStorage as createMemoryStorage2 } from "@unlink-xyz/core";
|
|
256
258
|
export {
|
|
257
259
|
DEFAULT_POLL_INTERVAL_MS,
|
|
258
260
|
DEFAULT_TIMEOUT_MS,
|
|
@@ -260,10 +262,13 @@ export {
|
|
|
260
262
|
TERMINAL_TX_STATES,
|
|
261
263
|
TimeoutError,
|
|
262
264
|
TransactionFailedError,
|
|
263
|
-
|
|
265
|
+
Unlink2 as Unlink,
|
|
266
|
+
UnlinkWallet,
|
|
267
|
+
createEmitter,
|
|
264
268
|
createMemoryStorage2 as createMemoryStorage,
|
|
265
269
|
createSqliteStorage,
|
|
266
270
|
createWalletEmitter,
|
|
271
|
+
initUnlink,
|
|
267
272
|
initWallet,
|
|
268
273
|
pollRelayStatus,
|
|
269
274
|
waitForConfirmation
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/init.ts","../src/errors.ts","../src/confirmation.ts","../src/events.ts","../src/storage/sqlite.ts","../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport { createMemoryStorage, UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport type { NodeWalletConfig } from \"./types.js\";\n\nconst nodeRng = (n: number): Uint8Array =>\n new Uint8Array(crypto.randomBytes(n));\n\n/**\n * Initialize an Unlink wallet with Node.js-friendly defaults.\n *\n * Compared to `UnlinkWallet.create()`, this:\n * - Defaults storage to in-memory (no IndexedDB required)\n * - Defaults RNG to `node:crypto`\n * - Defaults autoSync to `false`\n * - Optionally creates seed + first account automatically\n * - Optionally syncs notes from blockchain\n *\n * @example\n * ```ts\n * // Minimal — ready to use in one call:\n * const wallet = await initWallet({\n * chainId: 11155111,\n * environment: \"testnet\",\n * });\n *\n * // Skip auto-setup (e.g., to import an existing mnemonic):\n * const wallet = await initWallet({\n * chainId: 11155111,\n * environment: \"testnet\",\n * setup: false,\n * sync: false,\n * });\n * await wallet.seed.importMnemonic(\"your mnemonic ...\");\n * await wallet.accounts.create();\n * await wallet.sync();\n * ```\n */\nexport async function initWallet(\n config: NodeWalletConfig,\n): Promise<UnlinkWallet> {\n // Strip node-specific fields before passing to core\n const { setup, sync, ...coreConfig } = config;\n void setup;\n void sync;\n\n const wallet = await UnlinkWallet.create({\n ...coreConfig,\n storage: config.storage ?? createMemoryStorage(),\n rng: config.rng ?? nodeRng,\n autoSync: config.autoSync ?? false,\n fetch: config.fetch ?? globalThis.fetch,\n });\n\n if (config.setup !== false) {\n const hasSeed = await wallet.seed.exists();\n if (!hasSeed) {\n await wallet.seed.create();\n }\n\n const accounts = await wallet.accounts.list();\n if (accounts.length === 0) {\n await wallet.accounts.create();\n }\n }\n\n if (config.sync !== false) {\n await wallet.sync();\n }\n\n return wallet;\n}\n","import type { RelayState } from \"@unlink-xyz/core\";\n\n/** Terminal relay states — the transaction has finished processing. */\nexport const TERMINAL_TX_STATES: readonly RelayState[] = [\n \"succeeded\",\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Failed relay states — the transaction did not succeed. */\nexport const FAILED_TX_STATES: readonly RelayState[] = [\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Default timeout for `waitForConfirmation` (5 minutes). */\nexport const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Default initial poll interval (2 seconds). */\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\n\n/** Maximum poll interval after backoff (30 seconds). */\nexport const MAX_POLL_INTERVAL_MS = 30_000;\n\n/** Backoff multiplier for exponential polling. */\nexport const BACKOFF_FACTOR = 1.5;\n\n/** Thrown when relay polling exceeds the configured timeout. */\nexport class TimeoutError extends Error {\n readonly txId: string;\n readonly timeout: number;\n\n constructor(txId: string, timeout: number) {\n super(`Transaction ${txId} did not confirm within ${timeout}ms`);\n this.name = \"TimeoutError\";\n this.txId = txId;\n this.timeout = timeout;\n }\n}\n\n/** Thrown when a transaction reaches a failed terminal state. */\nexport class TransactionFailedError extends Error {\n readonly txId: string;\n readonly state: RelayState;\n readonly reason?: string;\n\n constructor(txId: string, state: RelayState, reason?: string) {\n super(\n `Transaction ${txId} failed with state: ${state}${reason ? ` — ${reason}` : \"\"}`,\n );\n this.name = \"TransactionFailedError\";\n this.txId = txId;\n this.state = state;\n this.reason = reason;\n }\n}\n","import type { UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport {\n BACKOFF_FACTOR,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n FAILED_TX_STATES,\n MAX_POLL_INTERVAL_MS,\n TERMINAL_TX_STATES,\n TimeoutError,\n TransactionFailedError,\n} from \"./errors.js\";\nimport type { PollOptions, TxStatus, WaitOptions } from \"./types.js\";\n\nfunction toTxStatus(\n txId: string,\n raw: Awaited<ReturnType<UnlinkWallet[\"getTxStatus\"]>>,\n): TxStatus {\n return {\n txId,\n state: raw.state,\n txHash: raw.txHash ?? undefined,\n blockNumber: raw.receipt?.blockNumber ?? undefined,\n error: raw.error ?? undefined,\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll relay status until the transaction reaches a terminal state.\n *\n * Resolves with `TxStatus` on success (`\"succeeded\"`).\n * Throws `TransactionFailedError` on failure (`\"reverted\"`, `\"failed\"`, `\"dead\"`).\n * Throws `TimeoutError` if the timeout is exceeded.\n *\n * Uses exponential backoff: 2s → 3s → 4.5s → ... capped at 30s.\n *\n * @example\n * ```ts\n * const result = await wallet.transfer({ transfers: [{ token, recipient, amount }] });\n * const status = await waitForConfirmation(wallet, result.relayId);\n * console.log(status.state); // \"succeeded\"\n * ```\n */\nexport async function waitForConfirmation(\n wallet: UnlinkWallet,\n txId: string,\n opts?: WaitOptions,\n): Promise<TxStatus> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n if (status.state === \"succeeded\") {\n return status;\n }\n\n if (FAILED_TX_STATES.includes(status.state)) {\n throw new TransactionFailedError(txId, status.state, status.error);\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n\n throw new TimeoutError(txId, timeout);\n}\n\n/**\n * Async generator that yields `TxStatus` on each poll until a terminal state.\n *\n * Useful for streaming status updates (e.g., logging, progress bars).\n *\n * @example\n * ```ts\n * for await (const status of pollRelayStatus(wallet, relayId)) {\n * console.log(status.state); // \"pending\" → \"broadcasting\" → \"submitted\" → \"succeeded\"\n * }\n * ```\n */\nexport async function* pollRelayStatus(\n wallet: UnlinkWallet,\n txId: string,\n opts?: PollOptions,\n): AsyncGenerator<TxStatus, void, unknown> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n yield status;\n\n if (TERMINAL_TX_STATES.includes(status.state)) {\n return;\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) return;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { UnlinkWallet, WalletSDKEvent } from \"@unlink-xyz/core\";\n\n/**\n * Wrap an UnlinkWallet's event system with a Node.js `EventEmitter`.\n *\n * Events are emitted by their `type` field (e.g., `\"notes-updated\"`,\n * `\"tx-status-changed\"`). A wildcard `\"*\"` event is also emitted for\n * every event.\n *\n * @returns An `EventEmitter` and an `unsubscribe` function to detach from the wallet.\n *\n * @example\n * ```ts\n * const { emitter, unsubscribe } = createWalletEmitter(wallet);\n *\n * emitter.on(\"notes-updated\", (event) => {\n * console.log(\"Notes updated on chain\", event.chainId);\n * });\n *\n * emitter.on(\"tx-status-changed\", (event) => {\n * console.log(`TX ${event.txId}: ${event.state}`);\n * });\n *\n * // Listen to all events\n * emitter.on(\"*\", (event) => console.log(event));\n *\n * // Cleanup when done\n * unsubscribe();\n * ```\n */\nexport function createWalletEmitter(wallet: UnlinkWallet): {\n emitter: EventEmitter;\n unsubscribe: () => void;\n} {\n const emitter = new EventEmitter();\n\n const unsubscribe = wallet.on((event: WalletSDKEvent) => {\n emitter.emit(event.type, event);\n emitter.emit(\"*\", event);\n });\n\n return { emitter, unsubscribe };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n BatchOp,\n Bytes,\n IterOptions,\n KvPair,\n Storage,\n} from \"@unlink-xyz/core\";\nimport { validateKey } from \"@unlink-xyz/core\";\nimport Database from \"better-sqlite3\";\n\nexport type SqliteStorageOptions = {\n /** Full path to the .db file */\n path: string;\n};\n\nexport function createSqliteStorage(opts: SqliteStorageOptions): Storage {\n let db: Database.Database | null = null;\n let stmtGet: Database.Statement;\n let stmtPut: Database.Statement;\n let stmtDel: Database.Statement;\n let stmtGetSchema: Database.Statement;\n let stmtUpsertSchema: Database.Statement;\n\n return {\n async open() {\n const dir = path.dirname(opts.path);\n fs.mkdirSync(dir, { recursive: true });\n\n db = new Database(opts.path);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.exec(`\n CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value BLOB NOT NULL);\n CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER NOT NULL);\n `);\n\n stmtGet = db.prepare(\"SELECT value FROM kv WHERE key = ?\");\n stmtPut = db.prepare(\n \"INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)\",\n );\n stmtDel = db.prepare(\"DELETE FROM kv WHERE key = ?\");\n stmtGetSchema = db.prepare(\n \"SELECT value FROM meta WHERE key = 'schema_version'\",\n );\n stmtUpsertSchema = db.prepare(\n \"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\",\n );\n },\n\n async get(key: string): Promise<Bytes | null> {\n validateKey(key);\n const row = stmtGet.get(key) as { value: Buffer } | undefined;\n return row ? new Uint8Array(row.value) : null;\n },\n\n async put(key: string, value: Bytes): Promise<void> {\n validateKey(key);\n stmtPut.run(key, Buffer.from(value));\n },\n\n async delete(key: string): Promise<void> {\n validateKey(key);\n stmtDel.run(key);\n },\n\n async batch(ops: BatchOp[]): Promise<void> {\n const runBatch = db!.transaction(() => {\n for (const op of ops) {\n if (op.put) {\n const [k, v] = op.put;\n validateKey(k);\n stmtPut.run(k, Buffer.from(v));\n }\n if (op.del) {\n validateKey(op.del);\n stmtDel.run(op.del);\n }\n }\n });\n runBatch();\n },\n\n async iter(o: IterOptions = {}): Promise<KvPair[]> {\n if (o.start && o.end && o.start > o.end) {\n throw new Error(\"iter start bound must not exceed end bound\");\n }\n\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (o.prefix) {\n // Escape SQL LIKE wildcards in the prefix\n const escaped = o.prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n conditions.push(\"key LIKE ? ESCAPE '\\\\'\");\n params.push(escaped + \"%\");\n }\n if (o.start) {\n conditions.push(\"key >= ?\");\n params.push(o.start);\n }\n if (o.end) {\n conditions.push(\"key <= ?\");\n params.push(o.end);\n }\n\n let sql = \"SELECT key, value FROM kv\";\n if (conditions.length > 0) {\n sql += \" WHERE \" + conditions.join(\" AND \");\n }\n sql += o.reverse ? \" ORDER BY key DESC\" : \" ORDER BY key ASC\";\n if (o.limit != null) {\n sql += \" LIMIT ?\";\n params.push(o.limit);\n }\n\n const rows = db!.prepare(sql).all(...params) as Array<{\n key: string;\n value: Buffer;\n }>;\n\n return rows.map((row) => ({\n key: row.key,\n value: new Uint8Array(row.value),\n }));\n },\n\n async count(prefix?: string): Promise<number> {\n let sql = \"SELECT COUNT(*) as cnt FROM kv\";\n const params: string[] = [];\n if (prefix) {\n const escaped = prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n sql += \" WHERE key LIKE ? ESCAPE '\\\\'\";\n params.push(escaped + \"%\");\n }\n const row = db!.prepare(sql).get(...params) as { cnt: number };\n return row.cnt;\n },\n\n async getSchemaVersion(): Promise<number> {\n const row = stmtGetSchema.get() as { value: number } | undefined;\n return row?.value ?? 0;\n },\n\n async setSchemaVersion(v: number): Promise<void> {\n stmtUpsertSchema.run(v);\n },\n };\n}\n","// Init\nexport { initWallet } from \"./init.js\";\n\n// Confirmation\nexport { waitForConfirmation, pollRelayStatus } from \"./confirmation.js\";\n\n// Events\nexport { createWalletEmitter } from \"./events.js\";\n\n// Storage\nexport {\n createSqliteStorage,\n type SqliteStorageOptions,\n} from \"./storage/sqlite.js\";\n\n// Errors\nexport {\n TimeoutError,\n TransactionFailedError,\n TERMINAL_TX_STATES,\n FAILED_TX_STATES,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_POLL_INTERVAL_MS,\n} from \"./errors.js\";\n\n// Types\nexport type {\n NodeWalletConfig,\n TxStatus,\n WaitOptions,\n PollOptions,\n} from \"./types.js\";\n\n// Re-export commonly needed core types so consumers don't need @unlink-xyz/core\nexport { UnlinkWallet, createMemoryStorage } from \"@unlink-xyz/core\";\n\nexport type {\n Account,\n AccountInfo,\n AccountView,\n DepositRelayResult,\n Environment,\n HistoryEntry,\n NoteRecord,\n RelayState,\n RelayStatusResponse,\n Storage,\n TransactRelayResult,\n TransferPlanResult,\n TransferResult,\n WalletSDKEvent,\n WithdrawPlanResult,\n WithdrawResult,\n} from \"@unlink-xyz/core\";\n"],"mappings":"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","names":["UnlinkWallet","createMemoryStorage"]}
|
|
1
|
+
{"version":3,"sources":["../src/init.ts","../src/errors.ts","../src/confirmation.ts","../src/events.ts","../src/storage/sqlite.ts","../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport { createMemoryStorage, Unlink } from \"@unlink-xyz/core\";\n\nimport type { InitUnlinkConfig } from \"./types.js\";\n\nconst nodeRng = (n: number): Uint8Array =>\n new Uint8Array(crypto.randomBytes(n));\n\n/**\n * Initialize an Unlink instance with Node.js-friendly defaults.\n *\n * Compared to `Unlink.create()`, this:\n * - Defaults storage to in-memory (no IndexedDB required)\n * - Defaults RNG to `node:crypto`\n * - Defaults autoSync to `false`\n * - Optionally creates seed + first account automatically\n * - Optionally syncs notes from blockchain\n *\n * @example\n * ```ts\n * // Minimal — ready to use in one call:\n * const unlink = await initUnlink({\n * chain: \"monad-testnet\",\n * });\n *\n * // Skip auto-setup (e.g., to import an existing mnemonic):\n * const unlink = await initUnlink({\n * chain: \"monad-testnet\",\n * setup: false,\n * sync: false,\n * });\n * await unlink.seed.importMnemonic(\"your mnemonic ...\");\n * await unlink.accounts.create();\n * await unlink.sync();\n * ```\n */\nexport async function initUnlink(config: InitUnlinkConfig): Promise<Unlink> {\n // Strip node-specific fields before passing to core\n const { setup, sync, ...coreConfig } = config;\n void setup;\n void sync;\n\n const unlink = await Unlink.create({\n ...coreConfig,\n storage: config.storage ?? createMemoryStorage(),\n rng: config.rng ?? nodeRng,\n autoSync: config.autoSync ?? false,\n fetch: config.fetch ?? globalThis.fetch,\n });\n\n if (config.setup !== false) {\n const hasSeed = await unlink.seed.exists();\n if (!hasSeed) {\n await unlink.seed.create();\n }\n\n const accounts = await unlink.accounts.list();\n if (accounts.length === 0) {\n await unlink.accounts.create();\n }\n }\n\n if (config.sync !== false) {\n await unlink.sync();\n }\n\n return unlink;\n}\n\n/** @deprecated Use {@link initUnlink} instead. */\nexport const initWallet = initUnlink;\n","import type { RelayState } from \"@unlink-xyz/core\";\n\n/** Terminal relay states — the transaction has finished processing. */\nexport const TERMINAL_TX_STATES: readonly RelayState[] = [\n \"succeeded\",\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Failed relay states — the transaction did not succeed. */\nexport const FAILED_TX_STATES: readonly RelayState[] = [\n \"reverted\",\n \"failed\",\n \"dead\",\n] as const;\n\n/** Default timeout for `waitForConfirmation` (5 minutes). */\nexport const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Default initial poll interval (2 seconds). */\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\n\n/** Maximum poll interval after backoff (30 seconds). */\nexport const MAX_POLL_INTERVAL_MS = 30_000;\n\n/** Backoff multiplier for exponential polling. */\nexport const BACKOFF_FACTOR = 1.5;\n\n/** Thrown when relay polling exceeds the configured timeout. */\nexport class TimeoutError extends Error {\n readonly txId: string;\n readonly timeout: number;\n\n constructor(txId: string, timeout: number) {\n super(`Transaction ${txId} did not confirm within ${timeout}ms`);\n this.name = \"TimeoutError\";\n this.txId = txId;\n this.timeout = timeout;\n }\n}\n\n/** Thrown when a transaction reaches a failed terminal state. */\nexport class TransactionFailedError extends Error {\n readonly txId: string;\n readonly state: RelayState;\n readonly reason?: string;\n\n constructor(txId: string, state: RelayState, reason?: string) {\n super(\n `Transaction ${txId} failed with state: ${state}${reason ? ` — ${reason}` : \"\"}`,\n );\n this.name = \"TransactionFailedError\";\n this.txId = txId;\n this.state = state;\n this.reason = reason;\n }\n}\n","import type { UnlinkWallet } from \"@unlink-xyz/core\";\n\nimport {\n BACKOFF_FACTOR,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n FAILED_TX_STATES,\n MAX_POLL_INTERVAL_MS,\n TERMINAL_TX_STATES,\n TimeoutError,\n TransactionFailedError,\n} from \"./errors.js\";\nimport type { PollOptions, TxStatus, WaitOptions } from \"./types.js\";\n\nfunction toTxStatus(\n txId: string,\n raw: Awaited<ReturnType<UnlinkWallet[\"getTxStatus\"]>>,\n): TxStatus {\n return {\n txId,\n state: raw.state,\n txHash: raw.txHash ?? undefined,\n blockNumber: raw.receipt?.blockNumber ?? undefined,\n error: raw.error ?? undefined,\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll relay status until the transaction reaches a terminal state.\n *\n * Resolves with `TxStatus` on success (`\"succeeded\"`).\n * Throws `TransactionFailedError` on failure (`\"reverted\"`, `\"failed\"`, `\"dead\"`).\n * Throws `TimeoutError` if the timeout is exceeded.\n *\n * Uses exponential backoff: 2s → 3s → 4.5s → ... capped at 30s.\n *\n * @example\n * ```ts\n * const result = await wallet.send({ transfers: [{ token, recipient, amount }] });\n * const status = await waitForConfirmation(wallet, result.relayId);\n * console.log(status.state); // \"succeeded\"\n * ```\n */\nexport async function waitForConfirmation(\n wallet: UnlinkWallet,\n txId: string,\n opts?: WaitOptions,\n): Promise<TxStatus> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n if (status.state === \"succeeded\") {\n return status;\n }\n\n if (FAILED_TX_STATES.includes(status.state)) {\n throw new TransactionFailedError(txId, status.state, status.error);\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n\n throw new TimeoutError(txId, timeout);\n}\n\n/**\n * Async generator that yields `TxStatus` on each poll until a terminal state.\n *\n * Useful for streaming status updates (e.g., logging, progress bars).\n *\n * @example\n * ```ts\n * for await (const status of pollRelayStatus(wallet, relayId)) {\n * console.log(status.state); // \"pending\" → \"broadcasting\" → \"submitted\" → \"succeeded\"\n * }\n * ```\n */\nexport async function* pollRelayStatus(\n wallet: UnlinkWallet,\n txId: string,\n opts?: PollOptions,\n): AsyncGenerator<TxStatus, void, unknown> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n let interval = opts?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const raw = await wallet.getTxStatus(txId);\n const status = toTxStatus(txId, raw);\n\n yield status;\n\n if (TERMINAL_TX_STATES.includes(status.state)) {\n return;\n }\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) return;\n\n await sleep(Math.min(interval, remaining));\n interval = Math.min(interval * BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Unlink, UnlinkEvent } from \"@unlink-xyz/core\";\n\n/**\n * Wrap an Unlink instance's event system with a Node.js `EventEmitter`.\n *\n * Events are emitted by their `type` field (e.g., `\"notes-updated\"`,\n * `\"tx-status-changed\"`). A wildcard `\"*\"` event is also emitted for\n * every event.\n *\n * @returns An `EventEmitter` and an `unsubscribe` function to detach from the instance.\n *\n * @example\n * ```ts\n * const { emitter, unsubscribe } = createEmitter(unlink);\n *\n * emitter.on(\"notes-updated\", (event) => {\n * console.log(\"Notes updated on chain\", event.chainId);\n * });\n *\n * emitter.on(\"tx-status-changed\", (event) => {\n * console.log(`TX ${event.txId}: ${event.state}`);\n * });\n *\n * // Listen to all events\n * emitter.on(\"*\", (event) => console.log(event));\n *\n * // Cleanup when done\n * unsubscribe();\n * ```\n */\nexport function createEmitter(unlink: Unlink): {\n emitter: EventEmitter;\n unsubscribe: () => void;\n} {\n const emitter = new EventEmitter();\n\n const unsubscribe = unlink.on((event: UnlinkEvent) => {\n emitter.emit(event.type, event);\n emitter.emit(\"*\", event);\n });\n\n return { emitter, unsubscribe };\n}\n\n/** @deprecated Use {@link createEmitter} instead. */\nexport const createWalletEmitter = createEmitter;\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n BatchOp,\n Bytes,\n IterOptions,\n KvPair,\n Storage,\n} from \"@unlink-xyz/core\";\nimport { validateKey } from \"@unlink-xyz/core\";\nimport Database from \"better-sqlite3\";\n\nexport type SqliteStorageOptions = {\n /** Full path to the .db file */\n path: string;\n};\n\nexport function createSqliteStorage(opts: SqliteStorageOptions): Storage {\n let db: Database.Database | null = null;\n let stmtGet: Database.Statement;\n let stmtPut: Database.Statement;\n let stmtDel: Database.Statement;\n let stmtGetSchema: Database.Statement;\n let stmtUpsertSchema: Database.Statement;\n\n return {\n async open() {\n const dir = path.dirname(opts.path);\n fs.mkdirSync(dir, { recursive: true });\n\n db = new Database(opts.path);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.exec(`\n CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value BLOB NOT NULL);\n CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER NOT NULL);\n `);\n\n stmtGet = db.prepare(\"SELECT value FROM kv WHERE key = ?\");\n stmtPut = db.prepare(\n \"INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)\",\n );\n stmtDel = db.prepare(\"DELETE FROM kv WHERE key = ?\");\n stmtGetSchema = db.prepare(\n \"SELECT value FROM meta WHERE key = 'schema_version'\",\n );\n stmtUpsertSchema = db.prepare(\n \"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\",\n );\n },\n\n async get(key: string): Promise<Bytes | null> {\n validateKey(key);\n const row = stmtGet.get(key) as { value: Buffer } | undefined;\n return row ? new Uint8Array(row.value) : null;\n },\n\n async put(key: string, value: Bytes): Promise<void> {\n validateKey(key);\n stmtPut.run(key, Buffer.from(value));\n },\n\n async delete(key: string): Promise<void> {\n validateKey(key);\n stmtDel.run(key);\n },\n\n async batch(ops: BatchOp[]): Promise<void> {\n const runBatch = db!.transaction(() => {\n for (const op of ops) {\n if (op.put) {\n const [k, v] = op.put;\n validateKey(k);\n stmtPut.run(k, Buffer.from(v));\n }\n if (op.del) {\n validateKey(op.del);\n stmtDel.run(op.del);\n }\n }\n });\n runBatch();\n },\n\n async iter(o: IterOptions = {}): Promise<KvPair[]> {\n if (o.start && o.end && o.start > o.end) {\n throw new Error(\"iter start bound must not exceed end bound\");\n }\n\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (o.prefix) {\n // Escape SQL LIKE wildcards in the prefix\n const escaped = o.prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n conditions.push(\"key LIKE ? ESCAPE '\\\\'\");\n params.push(escaped + \"%\");\n }\n if (o.start) {\n conditions.push(\"key >= ?\");\n params.push(o.start);\n }\n if (o.end) {\n conditions.push(\"key <= ?\");\n params.push(o.end);\n }\n\n let sql = \"SELECT key, value FROM kv\";\n if (conditions.length > 0) {\n sql += \" WHERE \" + conditions.join(\" AND \");\n }\n sql += o.reverse ? \" ORDER BY key DESC\" : \" ORDER BY key ASC\";\n if (o.limit != null) {\n sql += \" LIMIT ?\";\n params.push(o.limit);\n }\n\n const rows = db!.prepare(sql).all(...params) as Array<{\n key: string;\n value: Buffer;\n }>;\n\n return rows.map((row) => ({\n key: row.key,\n value: new Uint8Array(row.value),\n }));\n },\n\n async count(prefix?: string): Promise<number> {\n let sql = \"SELECT COUNT(*) as cnt FROM kv\";\n const params: string[] = [];\n if (prefix) {\n const escaped = prefix.replace(/[%_\\\\]/g, \"\\\\$&\");\n sql += \" WHERE key LIKE ? ESCAPE '\\\\'\";\n params.push(escaped + \"%\");\n }\n const row = db!.prepare(sql).get(...params) as { cnt: number };\n return row.cnt;\n },\n\n async getSchemaVersion(): Promise<number> {\n const row = stmtGetSchema.get() as { value: number } | undefined;\n return row?.value ?? 0;\n },\n\n async setSchemaVersion(v: number): Promise<void> {\n stmtUpsertSchema.run(v);\n },\n };\n}\n","// Init\nexport { initUnlink, initWallet } from \"./init.js\";\n\n// Confirmation\nexport { waitForConfirmation, pollRelayStatus } from \"./confirmation.js\";\n\n// Events\nexport { createEmitter, createWalletEmitter } from \"./events.js\";\n\n// Storage\nexport {\n createSqliteStorage,\n type SqliteStorageOptions,\n} from \"./storage/sqlite.js\";\n\n// Errors\nexport {\n TimeoutError,\n TransactionFailedError,\n TERMINAL_TX_STATES,\n FAILED_TX_STATES,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_POLL_INTERVAL_MS,\n} from \"./errors.js\";\n\n// Types\nexport type {\n InitUnlinkConfig,\n NodeWalletConfig,\n TxStatus,\n WaitOptions,\n PollOptions,\n} from \"./types.js\";\n\n// Re-export commonly needed core types so consumers don't need @unlink-xyz/core\nexport { Unlink, UnlinkWallet, createMemoryStorage } from \"@unlink-xyz/core\";\n\nexport type {\n Account,\n AccountInfo,\n AccountView,\n ChainConfig,\n DepositRelayResult,\n HistoryEntry,\n NoteRecord,\n RelayState,\n RelayStatusResponse,\n Storage,\n SupportedChain,\n TransactRelayResult,\n SendPlanResult,\n SendResult,\n UnlinkEvent,\n WalletSDKEvent,\n WithdrawPlanResult,\n WithdrawResult,\n} from \"@unlink-xyz/core\";\n"],"mappings":"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","names":["Unlink","createMemoryStorage"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unlink-xyz/node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7-canary.252b8ea",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"test:coverage": "vitest run --coverage"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@unlink-xyz/core": "0.1.
|
|
38
|
+
"@unlink-xyz/core": "0.1.7-canary.252b8ea",
|
|
39
39
|
"better-sqlite3": "^11.10.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|