@dynamic-labs-wallet/node-midnight 0.0.0 → 1.0.115

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/index.esm.js ADDED
@@ -0,0 +1,1058 @@
1
+ import { createLogError, DynamicWalletClient, getMPCChainConfig } from '@dynamic-labs-wallet/node';
2
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
3
+ import { MidnightBech32m, ShieldedAddress, ShieldedCoinPublicKey, ShieldedEncryptionPublicKey, DustAddress, mainnet } from '@midnight-ntwrk/wallet-sdk-address-format';
4
+ import { HDKey } from '@scure/bip32';
5
+ import { bech32m } from 'bech32';
6
+
7
+ /**
8
+ * Facade network tag: which Midnight network the wallet runtime (relay, indexer,
9
+ * proof server, sync state) operates against. Distinct from the numeric
10
+ * replay-protection id below.
11
+ */ // 0 = non-mainnet, 1 = Mainnet — baked into the transaction hash to prevent
12
+ // cross-network replay.
13
+ var MIDNIGHT_NETWORK_IDS = {
14
+ mainnet: 1,
15
+ preview: 0,
16
+ preprod: 0,
17
+ undeployed: 0
18
+ };
19
+ /**
20
+ * Resolves a caller-supplied network identifier (numeric 0/1, network name, or
21
+ * `midnight:<network>` chainId) to the facade network tag. Defaults to 'preview'.
22
+ */ var resolveMidnightNetworkTag = function(networkId) {
23
+ if (networkId === undefined || networkId === null) return 'preview';
24
+ if (typeof networkId === 'number') return networkId === 1 ? 'mainnet' : 'preview';
25
+ var name = networkId.includes(':') ? networkId.split(':')[1] : networkId;
26
+ return name === 'mainnet' ? 'mainnet' : 'preview';
27
+ };
28
+ var ERROR_KEYGEN_FAILED = 'Error with keygen';
29
+ var ERROR_CREATE_WALLET_ACCOUNT = 'Error creating midnight wallet account';
30
+ var ERROR_IMPORT_PRIVATE_KEY = 'Error importing private key';
31
+ var ERROR_EXPORT_PRIVATE_KEY = 'Error exporting private key';
32
+ var ERROR_SIGN_MESSAGE = 'Error signing message';
33
+ var ERROR_ACCOUNT_ADDRESS_REQUIRED = 'Account address is required';
34
+
35
+ function _array_like_to_array$1(arr, len) {
36
+ if (len == null || len > arr.length) len = arr.length;
37
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
38
+ return arr2;
39
+ }
40
+ function _array_with_holes$1(arr) {
41
+ if (Array.isArray(arr)) return arr;
42
+ }
43
+ function _iterable_to_array_limit$1(arr, i) {
44
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
45
+ if (_i == null) return;
46
+ var _arr = [];
47
+ var _n = true;
48
+ var _d = false;
49
+ var _s, _e;
50
+ try {
51
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
52
+ _arr.push(_s.value);
53
+ if (i && _arr.length === i) break;
54
+ }
55
+ } catch (err) {
56
+ _d = true;
57
+ _e = err;
58
+ } finally{
59
+ try {
60
+ if (!_n && _i["return"] != null) _i["return"]();
61
+ } finally{
62
+ if (_d) throw _e;
63
+ }
64
+ }
65
+ return _arr;
66
+ }
67
+ function _non_iterable_rest$1() {
68
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
69
+ }
70
+ function _sliced_to_array$1(arr, i) {
71
+ return _array_with_holes$1(arr) || _iterable_to_array_limit$1(arr, i) || _unsupported_iterable_to_array$1(arr, i) || _non_iterable_rest$1();
72
+ }
73
+ function _unsupported_iterable_to_array$1(o, minLen) {
74
+ if (!o) return;
75
+ if (typeof o === "string") return _array_like_to_array$1(o, minLen);
76
+ var n = Object.prototype.toString.call(o).slice(8, -1);
77
+ if (n === "Object" && o.constructor) n = o.constructor.name;
78
+ if (n === "Map" || n === "Set") return Array.from(n);
79
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$1(o, minLen);
80
+ }
81
+ /** Bech32m HRPs (BIP-0350) for Midnight unshielded addresses, per network. */ var ADDRESS_PREFIXES = {
82
+ mainnet: 'mn_addr',
83
+ preview: 'mn_addr_preview',
84
+ preprod: 'mn_addr_preprod',
85
+ undeployed: 'mn_addr_undeployed'
86
+ };
87
+ /**
88
+ * Encodes a 32-byte Midnight address hash as a bech32m address.
89
+ *
90
+ * The input is the *address hash* (`ledger.addressFromKey()` — a Poseidon hash
91
+ * of the verifying key), not the raw public key. Use {@link addressHashFromPublicKey}
92
+ * to produce it.
93
+ */ var deriveMidnightAddress = function(param) {
94
+ var addressHashHex = param.addressHashHex, _param_network = param.network, network = _param_network === void 0 ? 'preview' : _param_network;
95
+ var bytes = Buffer.from(addressHashHex, 'hex');
96
+ if (bytes.length !== 32) {
97
+ throw new Error("Invalid address hash length: ".concat(bytes.length, ", expected 32"));
98
+ }
99
+ return bech32m.encode(ADDRESS_PREFIXES[network], bech32m.toWords(bytes));
100
+ };
101
+ // `'mn_addr'` is a strict prefix of every other value in ADDRESS_PREFIXES,
102
+ // so naive `startsWith` checks hit `mainnet` for any Midnight address. Always
103
+ // check longest prefix first (descending).
104
+ var PREFIX_ENTRIES_LONGEST_FIRST = Object.entries(ADDRESS_PREFIXES).slice().sort(function(a, b) {
105
+ return b[1].length - a[1].length;
106
+ });
107
+ var isValidMidnightAddress = function(address) {
108
+ try {
109
+ var hasValidPrefix = PREFIX_ENTRIES_LONGEST_FIRST.some(function(param) {
110
+ var _param = _sliced_to_array$1(param, 2), prefix = _param[1];
111
+ return address.startsWith(prefix);
112
+ });
113
+ if (!hasValidPrefix) return false;
114
+ var decoded = bech32m.decode(address, 120);
115
+ return Buffer.from(bech32m.fromWords(decoded.words)).length === 32;
116
+ } catch (e) {
117
+ return false;
118
+ }
119
+ };
120
+ var decodeMidnightAddress = function(address) {
121
+ if (!isValidMidnightAddress(address)) {
122
+ throw new Error('Invalid Midnight address');
123
+ }
124
+ var decoded = bech32m.decode(address, 120);
125
+ return Buffer.from(bech32m.fromWords(decoded.words));
126
+ };
127
+ var getNetworkFromAddress = function(address) {
128
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
129
+ try {
130
+ for(var _iterator = PREFIX_ENTRIES_LONGEST_FIRST[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
131
+ var _step_value = _sliced_to_array$1(_step.value, 2), network = _step_value[0], prefix = _step_value[1];
132
+ if (address.startsWith(prefix)) {
133
+ return network;
134
+ }
135
+ }
136
+ } catch (err) {
137
+ _didIteratorError = true;
138
+ _iteratorError = err;
139
+ } finally{
140
+ try {
141
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
142
+ _iterator.return();
143
+ }
144
+ } finally{
145
+ if (_didIteratorError) {
146
+ throw _iteratorError;
147
+ }
148
+ }
149
+ }
150
+ throw new Error('Unknown network prefix in Midnight address');
151
+ };
152
+ /**
153
+ * Normalizes an MPC-returned BIP340 public key to the 32-byte x-only hex form
154
+ * that `ledger.addressFromKey()` expects, dropping the 02/03 parity byte if the
155
+ * key arrived in 33-byte compressed form.
156
+ */ var toXOnlyPublicKeyHex = function(publicKeyHex) {
157
+ var normalized = publicKeyHex.startsWith('0x') ? publicKeyHex.slice(2) : publicKeyHex;
158
+ if (normalized.length === 66 && (normalized.startsWith('02') || normalized.startsWith('03'))) {
159
+ return normalized.slice(2);
160
+ }
161
+ if (normalized.length === 64) {
162
+ return normalized;
163
+ }
164
+ throw new Error("Invalid BIP340 public key length: ".concat(normalized.length, " hex chars, expected 64 or 66"));
165
+ };
166
+
167
+ function _array_like_to_array(arr, len) {
168
+ if (len == null || len > arr.length) len = arr.length;
169
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
170
+ return arr2;
171
+ }
172
+ function _array_with_holes(arr) {
173
+ if (Array.isArray(arr)) return arr;
174
+ }
175
+ function _assert_this_initialized(self) {
176
+ if (self === void 0) {
177
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
178
+ }
179
+ return self;
180
+ }
181
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
182
+ try {
183
+ var info = gen[key](arg);
184
+ var value = info.value;
185
+ } catch (error) {
186
+ reject(error);
187
+ return;
188
+ }
189
+ if (info.done) {
190
+ resolve(value);
191
+ } else {
192
+ Promise.resolve(value).then(_next, _throw);
193
+ }
194
+ }
195
+ function _async_to_generator(fn) {
196
+ return function() {
197
+ var self = this, args = arguments;
198
+ return new Promise(function(resolve, reject) {
199
+ var gen = fn.apply(self, args);
200
+ function _next(value) {
201
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
202
+ }
203
+ function _throw(err) {
204
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
205
+ }
206
+ _next(undefined);
207
+ });
208
+ };
209
+ }
210
+ function _call_super(_this, derived, args) {
211
+ derived = _get_prototype_of(derived);
212
+ return _possible_constructor_return(_this, _is_native_reflect_construct() ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) : derived.apply(_this, args));
213
+ }
214
+ function _class_call_check(instance, Constructor) {
215
+ if (!(instance instanceof Constructor)) {
216
+ throw new TypeError("Cannot call a class as a function");
217
+ }
218
+ }
219
+ function _defineProperties(target, props) {
220
+ for(var i = 0; i < props.length; i++){
221
+ var descriptor = props[i];
222
+ descriptor.enumerable = descriptor.enumerable || false;
223
+ descriptor.configurable = true;
224
+ if ("value" in descriptor) descriptor.writable = true;
225
+ Object.defineProperty(target, descriptor.key, descriptor);
226
+ }
227
+ }
228
+ function _create_class(Constructor, protoProps, staticProps) {
229
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
230
+ return Constructor;
231
+ }
232
+ function _define_property(obj, key, value) {
233
+ if (key in obj) {
234
+ Object.defineProperty(obj, key, {
235
+ value: value,
236
+ enumerable: true,
237
+ configurable: true,
238
+ writable: true
239
+ });
240
+ } else {
241
+ obj[key] = value;
242
+ }
243
+ return obj;
244
+ }
245
+ function _get_prototype_of(o) {
246
+ _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
247
+ return o.__proto__ || Object.getPrototypeOf(o);
248
+ };
249
+ return _get_prototype_of(o);
250
+ }
251
+ function _inherits(subClass, superClass) {
252
+ if (typeof superClass !== "function" && superClass !== null) {
253
+ throw new TypeError("Super expression must either be null or a function");
254
+ }
255
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
256
+ constructor: {
257
+ value: subClass,
258
+ writable: true,
259
+ configurable: true
260
+ }
261
+ });
262
+ if (superClass) _set_prototype_of(subClass, superClass);
263
+ }
264
+ function _instanceof(left, right) {
265
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
266
+ return !!right[Symbol.hasInstance](left);
267
+ } else {
268
+ return left instanceof right;
269
+ }
270
+ }
271
+ function _iterable_to_array_limit(arr, i) {
272
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
273
+ if (_i == null) return;
274
+ var _arr = [];
275
+ var _n = true;
276
+ var _d = false;
277
+ var _s, _e;
278
+ try {
279
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
280
+ _arr.push(_s.value);
281
+ if (i && _arr.length === i) break;
282
+ }
283
+ } catch (err) {
284
+ _d = true;
285
+ _e = err;
286
+ } finally{
287
+ try {
288
+ if (!_n && _i["return"] != null) _i["return"]();
289
+ } finally{
290
+ if (_d) throw _e;
291
+ }
292
+ }
293
+ return _arr;
294
+ }
295
+ function _non_iterable_rest() {
296
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
297
+ }
298
+ function _possible_constructor_return(self, call) {
299
+ if (call && (_type_of(call) === "object" || typeof call === "function")) {
300
+ return call;
301
+ }
302
+ return _assert_this_initialized(self);
303
+ }
304
+ function _set_prototype_of(o, p) {
305
+ _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
306
+ o.__proto__ = p;
307
+ return o;
308
+ };
309
+ return _set_prototype_of(o, p);
310
+ }
311
+ function _sliced_to_array(arr, i) {
312
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
313
+ }
314
+ function _type_of(obj) {
315
+ "@swc/helpers - typeof";
316
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
317
+ }
318
+ function _unsupported_iterable_to_array(o, minLen) {
319
+ if (!o) return;
320
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
321
+ var n = Object.prototype.toString.call(o).slice(8, -1);
322
+ if (n === "Object" && o.constructor) n = o.constructor.name;
323
+ if (n === "Map" || n === "Set") return Array.from(n);
324
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
325
+ }
326
+ function _is_native_reflect_construct() {
327
+ try {
328
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
329
+ } catch (_) {}
330
+ return (_is_native_reflect_construct = function() {
331
+ return !!result;
332
+ })();
333
+ }
334
+ function _ts_generator(thisArg, body) {
335
+ var f, y, t, g, _ = {
336
+ label: 0,
337
+ sent: function() {
338
+ if (t[0] & 1) throw t[1];
339
+ return t[1];
340
+ },
341
+ trys: [],
342
+ ops: []
343
+ };
344
+ return g = {
345
+ next: verb(0),
346
+ "throw": verb(1),
347
+ "return": verb(2)
348
+ }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
349
+ return this;
350
+ }), g;
351
+ function verb(n) {
352
+ return function(v) {
353
+ return step([
354
+ n,
355
+ v
356
+ ]);
357
+ };
358
+ }
359
+ function step(op) {
360
+ if (f) throw new TypeError("Generator is already executing.");
361
+ while(_)try {
362
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
363
+ if (y = 0, t) op = [
364
+ op[0] & 2,
365
+ t.value
366
+ ];
367
+ switch(op[0]){
368
+ case 0:
369
+ case 1:
370
+ t = op;
371
+ break;
372
+ case 4:
373
+ _.label++;
374
+ return {
375
+ value: op[1],
376
+ done: false
377
+ };
378
+ case 5:
379
+ _.label++;
380
+ y = op[1];
381
+ op = [
382
+ 0
383
+ ];
384
+ continue;
385
+ case 7:
386
+ op = _.ops.pop();
387
+ _.trys.pop();
388
+ continue;
389
+ default:
390
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
391
+ _ = 0;
392
+ continue;
393
+ }
394
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
395
+ _.label = op[1];
396
+ break;
397
+ }
398
+ if (op[0] === 6 && _.label < t[1]) {
399
+ _.label = t[1];
400
+ t = op;
401
+ break;
402
+ }
403
+ if (t && _.label < t[2]) {
404
+ _.label = t[2];
405
+ _.ops.push(op);
406
+ break;
407
+ }
408
+ if (t[2]) _.ops.pop();
409
+ _.trys.pop();
410
+ continue;
411
+ }
412
+ op = body.call(thisArg, _);
413
+ } catch (e) {
414
+ op = [
415
+ 6,
416
+ e
417
+ ];
418
+ y = 0;
419
+ } finally{
420
+ f = t = 0;
421
+ }
422
+ if (op[0] & 5) throw op[1];
423
+ return {
424
+ value: op[0] ? op[1] : void 0,
425
+ done: true
426
+ };
427
+ }
428
+ }
429
+ var logError = createLogError('node-midnight');
430
+ // Unshielded is NON-hardened to match the server's MPC signing path (Sodot's
431
+ // derivePrivateKeyFromXpriv is non-hardened-only). Shielded and dust are hardened Midnight-canonical paths; those roles are signed
432
+ // entirely client-side, so the Sodot constraint does not apply.
433
+ var ROLE_DERIVATION_PATHS = {
434
+ unshielded: 'm/44/2400/0/0/0',
435
+ shielded: "m/44'/2400'/0'/3/0",
436
+ dust: "m/44'/2400'/0'/2/0"
437
+ };
438
+ var DynamicMidnightWalletClient = /*#__PURE__*/ function(DynamicWalletClient) {
439
+ _inherits(DynamicMidnightWalletClient, DynamicWalletClient);
440
+ function DynamicMidnightWalletClient(param) {
441
+ var environmentId = param.environmentId, baseApiUrl = param.baseApiUrl, baseMPCRelayApiUrl = param.baseMPCRelayApiUrl, debug = param.debug, enableMPCAccelerator = param.enableMPCAccelerator, logger = param.logger, _param_network = param.network, network = _param_network === void 0 ? 'preview' : _param_network;
442
+ _class_call_check(this, DynamicMidnightWalletClient);
443
+ var _this;
444
+ _this = _call_super(this, DynamicMidnightWalletClient, [
445
+ {
446
+ environmentId: environmentId,
447
+ baseApiUrl: baseApiUrl,
448
+ baseMPCRelayApiUrl: baseMPCRelayApiUrl,
449
+ debug: debug,
450
+ enableMPCAccelerator: enableMPCAccelerator,
451
+ logger: logger
452
+ }
453
+ ]), _define_property(_this, "chainName", 'MIDNIGHT'), _define_property(_this, "network", void 0), /**
454
+ * Derives the bech32m unshielded account address from a BIP340 public key.
455
+ * The address is the Poseidon hash of the verifying key, not the key itself.
456
+ */ _define_property(_this, "deriveAccountAddress", function(param) {
457
+ var publicKeyHex = param.publicKeyHex, network = param.network;
458
+ var addressHashHex = ledger.addressFromKey(toXOnlyPublicKeyHex(publicKeyHex));
459
+ return deriveMidnightAddress({
460
+ addressHashHex: addressHashHex,
461
+ network: network !== null && network !== void 0 ? network : _this.network
462
+ });
463
+ });
464
+ _this.network = network;
465
+ return _this;
466
+ }
467
+ _create_class(DynamicMidnightWalletClient, [
468
+ {
469
+ key: "createWalletAccount",
470
+ value: /**
471
+ * Creates a new wallet account.
472
+ * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
473
+ * @param password - The password to use for the wallet.
474
+ * @param onError - The function to call if an error occurs.
475
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
476
+ * @returns The walletMetadata, public key hex, raw public key, and external server key shares.
477
+ */ function createWalletAccount(param) {
478
+ var thresholdSignatureScheme = param.thresholdSignatureScheme, password = param.password, onError = param.onError, _param_backUpToDynamic = param.backUpToDynamic, backUpToDynamic = _param_backUpToDynamic === void 0 ? false : _param_backUpToDynamic;
479
+ var _this = this;
480
+ return _async_to_generator(function() {
481
+ var resolvedWalletId, resolvedShareSetId, serverAccountAddress, ceremonyCompleteResolver, ceremonyCompletePromise, _ref, rawPublicKey, externalServerKeyShares, publicKeyHex, accountAddress, chainConfig, walletMetadata, _ref1, keySharesWithBackupStatus, backupInfo, error;
482
+ return _ts_generator(this, function(_state) {
483
+ switch(_state.label){
484
+ case 0:
485
+ _state.trys.push([
486
+ 0,
487
+ 4,
488
+ ,
489
+ 5
490
+ ]);
491
+ ceremonyCompletePromise = new Promise(function(resolve) {
492
+ ceremonyCompleteResolver = resolve;
493
+ });
494
+ return [
495
+ 4,
496
+ _this.keyGen({
497
+ thresholdSignatureScheme: thresholdSignatureScheme,
498
+ chainName: _this.chainName,
499
+ password: password,
500
+ backUpToDynamic: backUpToDynamic,
501
+ onError: onError,
502
+ onCeremonyComplete: function(accountAddress, walletId, shareSetId) {
503
+ resolvedWalletId = walletId;
504
+ resolvedShareSetId = shareSetId;
505
+ serverAccountAddress = accountAddress;
506
+ ceremonyCompleteResolver(undefined);
507
+ }
508
+ })
509
+ ];
510
+ case 1:
511
+ _ref = _state.sent(), rawPublicKey = _ref.rawPublicKey, externalServerKeyShares = _ref.externalServerKeyShares;
512
+ return [
513
+ 4,
514
+ ceremonyCompletePromise
515
+ ];
516
+ case 2:
517
+ _state.sent();
518
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId || !(typeof rawPublicKey === 'string' || _instanceof(rawPublicKey, Uint8Array))) {
519
+ throw new Error(ERROR_KEYGEN_FAILED);
520
+ }
521
+ publicKeyHex = typeof rawPublicKey === 'string' ? rawPublicKey : Buffer.from(rawPublicKey).toString('hex');
522
+ accountAddress = _this.deriveAccountAddress({
523
+ publicKeyHex: publicKeyHex
524
+ });
525
+ // The browser client takes the server's address verbatim because the
526
+ // Poseidon hash is WASM-only there; in Node we derive it locally. Warn
527
+ // rather than throw on divergence — the server's is authoritative.
528
+ if (serverAccountAddress && serverAccountAddress !== accountAddress) {
529
+ _this.logger.warn("[Midnight] Locally derived address ".concat(accountAddress, " differs from server address ").concat(serverAccountAddress));
530
+ }
531
+ chainConfig = getMPCChainConfig(_this.chainName);
532
+ walletMetadata = {
533
+ walletId: resolvedWalletId,
534
+ accountAddress: accountAddress,
535
+ chainName: _this.chainName,
536
+ thresholdSignatureScheme: thresholdSignatureScheme,
537
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map(function(value, index) {
538
+ return [
539
+ index,
540
+ value
541
+ ];
542
+ }))),
543
+ shareSetId: resolvedShareSetId
544
+ };
545
+ return [
546
+ 4,
547
+ _this.storeEncryptedBackupByWalletWithRetry({
548
+ accountAddress: accountAddress,
549
+ externalServerKeyShares: externalServerKeyShares,
550
+ password: password,
551
+ backUpToDynamic: backUpToDynamic,
552
+ walletMetadata: walletMetadata
553
+ })
554
+ ];
555
+ case 3:
556
+ _ref1 = _state.sent(), keySharesWithBackupStatus = _ref1.keySharesWithBackupStatus, backupInfo = _ref1.backupInfo;
557
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
558
+ return [
559
+ 2,
560
+ {
561
+ walletMetadata: walletMetadata,
562
+ publicKeyHex: publicKeyHex,
563
+ rawPublicKey: rawPublicKey,
564
+ externalServerKeyShares: externalServerKeyShares,
565
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
566
+ }
567
+ ];
568
+ case 4:
569
+ error = _state.sent();
570
+ logError({
571
+ message: ERROR_CREATE_WALLET_ACCOUNT,
572
+ error: error,
573
+ context: {}
574
+ });
575
+ throw new Error(ERROR_CREATE_WALLET_ACCOUNT, {
576
+ cause: error
577
+ });
578
+ case 5:
579
+ return [
580
+ 2
581
+ ];
582
+ }
583
+ });
584
+ })();
585
+ }
586
+ },
587
+ {
588
+ key: "signMessage",
589
+ value: /**
590
+ * Signs a message using MPC
591
+ * @param message - The message to sign
592
+ * @param walletMetadata - Wallet metadata (the full object returned by createWalletAccount/importPrivateKey, with backupInfo merged from any subsequent updatePassword/refresh/reshare)
593
+ * @param password - The password for encrypted backup shares
594
+ * @param externalServerKeyShares - The external server key shares
595
+ * @param onError - The function to call if an error occurs
596
+ * @returns The signature as a base64 string
597
+ */ function signMessage(param) {
598
+ var message = param.message, walletMetadata = param.walletMetadata, _param_password = param.password, password = _param_password === void 0 ? undefined : _param_password, externalServerKeyShares = param.externalServerKeyShares, onError = param.onError;
599
+ var _this = this;
600
+ return _async_to_generator(function() {
601
+ var accountAddress, messageHex, signature, error;
602
+ return _ts_generator(this, function(_state) {
603
+ switch(_state.label){
604
+ case 0:
605
+ accountAddress = walletMetadata.accountAddress;
606
+ if (!accountAddress) {
607
+ throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
608
+ }
609
+ _state.label = 1;
610
+ case 1:
611
+ _state.trys.push([
612
+ 1,
613
+ 3,
614
+ ,
615
+ 4
616
+ ]);
617
+ // The signing API expects hex; policy validation needs the original bytes.
618
+ messageHex = Buffer.from(message).toString('hex');
619
+ return [
620
+ 4,
621
+ _this.sign({
622
+ message: messageHex,
623
+ accountAddress: accountAddress,
624
+ chainName: _this.chainName,
625
+ password: password,
626
+ externalServerKeyShares: externalServerKeyShares,
627
+ onError: onError,
628
+ walletMetadata: walletMetadata,
629
+ context: {
630
+ midnightMessage: message
631
+ }
632
+ })
633
+ ];
634
+ case 2:
635
+ signature = _state.sent();
636
+ return [
637
+ 2,
638
+ Buffer.from(signature).toString('base64')
639
+ ];
640
+ case 3:
641
+ error = _state.sent();
642
+ logError({
643
+ message: ERROR_SIGN_MESSAGE,
644
+ error: error,
645
+ context: {
646
+ accountAddress: accountAddress
647
+ }
648
+ });
649
+ throw new Error(ERROR_SIGN_MESSAGE, {
650
+ cause: error
651
+ });
652
+ case 4:
653
+ return [
654
+ 2
655
+ ];
656
+ }
657
+ });
658
+ })();
659
+ }
660
+ },
661
+ {
662
+ key: "exportPrivateKey",
663
+ value: /**
664
+ * Exports the private key for a given wallet.
665
+ *
666
+ * Returns the unshielded (role 0) key at the wallet's derivation path. The
667
+ * shielded and dust role keys need the master xprv, which `exportKey` does
668
+ * not surface — see the package README.
669
+ *
670
+ * @param walletMetadata - Wallet metadata (the full object returned by createWalletAccount/importPrivateKey, with backupInfo merged from any subsequent updatePassword/refresh/reshare)
671
+ * @param password - The password for encrypted backup shares
672
+ * @param externalServerKeyShares - The external server key shares
673
+ * @returns The private key as a hex string
674
+ */ function exportPrivateKey(param) {
675
+ var walletMetadata = param.walletMetadata, _param_password = param.password, password = _param_password === void 0 ? undefined : _param_password, externalServerKeyShares = param.externalServerKeyShares;
676
+ var _this = this;
677
+ return _async_to_generator(function() {
678
+ var accountAddress, derivedPrivateKey, error;
679
+ return _ts_generator(this, function(_state) {
680
+ switch(_state.label){
681
+ case 0:
682
+ accountAddress = walletMetadata.accountAddress;
683
+ _state.label = 1;
684
+ case 1:
685
+ _state.trys.push([
686
+ 1,
687
+ 3,
688
+ ,
689
+ 4
690
+ ]);
691
+ return [
692
+ 4,
693
+ _this.exportKey({
694
+ accountAddress: accountAddress,
695
+ chainName: _this.chainName,
696
+ password: password,
697
+ externalServerKeyShares: externalServerKeyShares,
698
+ walletMetadata: walletMetadata
699
+ })
700
+ ];
701
+ case 2:
702
+ derivedPrivateKey = _state.sent().derivedPrivateKey;
703
+ if (!derivedPrivateKey) {
704
+ throw new Error('Derived private key is undefined');
705
+ }
706
+ return [
707
+ 2,
708
+ derivedPrivateKey.slice(0, 64)
709
+ ];
710
+ case 3:
711
+ error = _state.sent();
712
+ logError({
713
+ message: ERROR_EXPORT_PRIVATE_KEY,
714
+ error: error,
715
+ context: {
716
+ accountAddress: accountAddress
717
+ }
718
+ });
719
+ throw new Error(ERROR_EXPORT_PRIVATE_KEY);
720
+ case 4:
721
+ return [
722
+ 2
723
+ ];
724
+ }
725
+ });
726
+ })();
727
+ }
728
+ },
729
+ {
730
+ key: "offlineExportPrivateKey",
731
+ value: /**
732
+ * Exports the private key offline using key shares
733
+ * @param keyShares - The key shares to export the private key for
734
+ * @param derivationPath - The derivation path
735
+ * @returns The derived private key
736
+ *
737
+ * `derivationPath` is the JSON-serialized index map that
738
+ * `walletMetadata.derivationPath` carries (e.g. `'{"0":44,"1":2400,"2":0,"3":0,"4":0}'`
739
+ * or `'[44,2400,0,0,0]'`). BIP-32 strings such as `"m/44'/2400'/0'/0/0"` are rejected.
740
+ * Omit it to export without path derivation.
741
+ */ function offlineExportPrivateKey(param) {
742
+ var keyShares = param.keyShares, derivationPath = param.derivationPath;
743
+ var _this = this;
744
+ return _async_to_generator(function() {
745
+ var derivedPrivateKey;
746
+ return _ts_generator(this, function(_state) {
747
+ switch(_state.label){
748
+ case 0:
749
+ return [
750
+ 4,
751
+ _this.offlineExportKey({
752
+ chainName: _this.chainName,
753
+ keyShares: keyShares,
754
+ derivationPath: derivationPath
755
+ })
756
+ ];
757
+ case 1:
758
+ derivedPrivateKey = _state.sent().derivedPrivateKey;
759
+ return [
760
+ 2,
761
+ {
762
+ derivedPrivateKey: derivedPrivateKey
763
+ }
764
+ ];
765
+ }
766
+ });
767
+ })();
768
+ }
769
+ },
770
+ {
771
+ key: "importPrivateKey",
772
+ value: /**
773
+ * Imports a private key.
774
+ * @param privateKey - The private key to import.
775
+ * @param chainName - The chain name to use for the wallet.
776
+ * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
777
+ * @param password - The password to use for the wallet.
778
+ * @param onError - The function to call if an error occurs.
779
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service.
780
+ * @param publicAddressCheck - Optional public address to verify against the derived address.
781
+ * @returns The walletMetadata, public key hex, raw public key, and external server key shares.
782
+ */ function importPrivateKey(param) {
783
+ var privateKey = param.privateKey, chainName = param.chainName, thresholdSignatureScheme = param.thresholdSignatureScheme, password = param.password, onError = param.onError, _param_backUpToDynamic = param.backUpToDynamic, backUpToDynamic = _param_backUpToDynamic === void 0 ? false : _param_backUpToDynamic, publicAddressCheck = param.publicAddressCheck;
784
+ var _this = this;
785
+ return _async_to_generator(function() {
786
+ var resolvedWalletId, resolvedShareSetId, ceremonyCompleteResolver, ceremonyCompletePromise, formattedPrivateKey, derivedAddress, _ref, rawPublicKey, externalServerKeyShares, resultPublicKeyHex, accountAddress, chainConfig, walletMetadata, _ref1, keySharesWithBackupStatus, backupInfo, error;
787
+ return _ts_generator(this, function(_state) {
788
+ switch(_state.label){
789
+ case 0:
790
+ _state.trys.push([
791
+ 0,
792
+ 4,
793
+ ,
794
+ 5
795
+ ]);
796
+ ceremonyCompletePromise = new Promise(function(resolve) {
797
+ ceremonyCompleteResolver = resolve;
798
+ });
799
+ formattedPrivateKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;
800
+ derivedAddress = _this.deriveAccountAddress({
801
+ publicKeyHex: _this.getPublicKeyFromPrivateKey(formattedPrivateKey)
802
+ });
803
+ if (publicAddressCheck && derivedAddress !== publicAddressCheck) {
804
+ throw new Error("Public address mismatch: derived address ".concat(derivedAddress, " !== public address ").concat(publicAddressCheck));
805
+ }
806
+ return [
807
+ 4,
808
+ _this.importRawPrivateKey({
809
+ chainName: chainName,
810
+ thresholdSignatureScheme: thresholdSignatureScheme,
811
+ privateKey: formattedPrivateKey,
812
+ password: password,
813
+ backUpToDynamic: backUpToDynamic,
814
+ onCeremonyComplete: function(_accountAddress, walletId, shareSetId) {
815
+ resolvedWalletId = walletId;
816
+ resolvedShareSetId = shareSetId;
817
+ ceremonyCompleteResolver(undefined);
818
+ },
819
+ onError: function(e) {
820
+ logError({
821
+ message: 'importPrivateKey: onError',
822
+ error: e,
823
+ context: {}
824
+ });
825
+ onError === null || onError === void 0 ? void 0 : onError(e);
826
+ }
827
+ })
828
+ ];
829
+ case 1:
830
+ _ref = _state.sent(), rawPublicKey = _ref.rawPublicKey, externalServerKeyShares = _ref.externalServerKeyShares;
831
+ return [
832
+ 4,
833
+ ceremonyCompletePromise
834
+ ];
835
+ case 2:
836
+ _state.sent();
837
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId || !(typeof rawPublicKey === 'string' || _instanceof(rawPublicKey, Uint8Array))) {
838
+ throw new Error(ERROR_IMPORT_PRIVATE_KEY);
839
+ }
840
+ resultPublicKeyHex = typeof rawPublicKey === 'string' ? rawPublicKey : Buffer.from(rawPublicKey).toString('hex');
841
+ accountAddress = _this.deriveAccountAddress({
842
+ publicKeyHex: resultPublicKeyHex
843
+ });
844
+ if (accountAddress !== derivedAddress) {
845
+ throw new Error("Public key mismatch: derived address ".concat(accountAddress, " !== expected ").concat(derivedAddress));
846
+ }
847
+ chainConfig = getMPCChainConfig(_this.chainName);
848
+ walletMetadata = {
849
+ walletId: resolvedWalletId,
850
+ accountAddress: accountAddress,
851
+ chainName: _this.chainName,
852
+ thresholdSignatureScheme: thresholdSignatureScheme,
853
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map(function(value, index) {
854
+ return [
855
+ index,
856
+ value
857
+ ];
858
+ }))),
859
+ shareSetId: resolvedShareSetId
860
+ };
861
+ return [
862
+ 4,
863
+ _this.storeEncryptedBackupByWalletWithRetry({
864
+ accountAddress: accountAddress,
865
+ externalServerKeyShares: externalServerKeyShares,
866
+ password: password,
867
+ backUpToDynamic: backUpToDynamic,
868
+ walletMetadata: walletMetadata
869
+ })
870
+ ];
871
+ case 3:
872
+ _ref1 = _state.sent(), keySharesWithBackupStatus = _ref1.keySharesWithBackupStatus, backupInfo = _ref1.backupInfo;
873
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
874
+ return [
875
+ 2,
876
+ {
877
+ walletMetadata: walletMetadata,
878
+ publicKeyHex: resultPublicKeyHex,
879
+ rawPublicKey: rawPublicKey,
880
+ externalServerKeyShares: externalServerKeyShares,
881
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
882
+ }
883
+ ];
884
+ case 4:
885
+ error = _state.sent();
886
+ logError({
887
+ message: ERROR_IMPORT_PRIVATE_KEY,
888
+ error: error,
889
+ context: {}
890
+ });
891
+ onError === null || onError === void 0 ? void 0 : onError(error);
892
+ throw new Error(ERROR_IMPORT_PRIVATE_KEY);
893
+ case 5:
894
+ return [
895
+ 2
896
+ ];
897
+ }
898
+ });
899
+ })();
900
+ }
901
+ },
902
+ {
903
+ /**
904
+ * Derives the BIP340 verifying key from a private key
905
+ * @param privateKeyHex - The private key as a hex string
906
+ * @returns The verifying key as a hex string
907
+ */ key: "getPublicKeyFromPrivateKey",
908
+ value: function getPublicKeyFromPrivateKey(privateKeyHex) {
909
+ try {
910
+ var privateKeyBytes = Buffer.from(privateKeyHex, 'hex');
911
+ if (privateKeyBytes.length !== 32) {
912
+ throw new Error("Invalid private key length: ".concat(privateKeyBytes.length, ", expected 32"));
913
+ }
914
+ return ledger.signatureVerifyingKey(privateKeyHex);
915
+ } catch (error) {
916
+ // Deliberately not logging the error: it originates from a WASM call that
917
+ // received the private key, so its message could echo key material into
918
+ // logs. The error is re-thrown intact for the caller to inspect.
919
+ this.logger.debug('[Midnight] getPublicKeyFromPrivateKey failed');
920
+ throw error;
921
+ }
922
+ }
923
+ },
924
+ {
925
+ key: "getRoleKeys",
926
+ value: /**
927
+ * Derives the unshielded, shielded, and dust role keys from the wallet's MPC
928
+ * master xprv.
929
+ *
930
+ * Deliberately not persisted: these are plaintext secrets, and writing them
931
+ * to disk or a cache would trade a per-session MPC export for a durable
932
+ * exfiltration target. Callers should hold the result only as long as the
933
+ * operation needs it.
934
+ *
935
+ * @returns The three role private keys as hex strings
936
+ */ function getRoleKeys(param) {
937
+ var walletMetadata = param.walletMetadata, _param_password = param.password, password = _param_password === void 0 ? undefined : _param_password, externalServerKeyShares = param.externalServerKeyShares, elevatedAccessToken = param.elevatedAccessToken;
938
+ var _this = this;
939
+ return _async_to_generator(function() {
940
+ var keyExportRaw, master, roleKeys;
941
+ return _ts_generator(this, function(_state) {
942
+ switch(_state.label){
943
+ case 0:
944
+ return [
945
+ 4,
946
+ _this.exportMasterKeyMaterial({
947
+ accountAddress: walletMetadata.accountAddress,
948
+ chainName: _this.chainName,
949
+ password: password,
950
+ externalServerKeyShares: externalServerKeyShares,
951
+ elevatedAccessToken: elevatedAccessToken,
952
+ walletMetadata: walletMetadata
953
+ })
954
+ ];
955
+ case 1:
956
+ keyExportRaw = _state.sent().keyExportRaw;
957
+ master = HDKey.fromExtendedKey(keyExportRaw);
958
+ roleKeys = Object.entries(ROLE_DERIVATION_PATHS).map(function(param) {
959
+ var _param = _sliced_to_array(param, 2), role = _param[0], path = _param[1];
960
+ var privateKey = master.derive(path).privateKey;
961
+ if (!privateKey) {
962
+ throw new Error("BIP32 derivation returned null privateKey for the ".concat(role, " role"));
963
+ }
964
+ return [
965
+ role,
966
+ Buffer.from(privateKey).toString('hex')
967
+ ];
968
+ });
969
+ return [
970
+ 2,
971
+ Object.fromEntries(roleKeys)
972
+ ];
973
+ }
974
+ });
975
+ })();
976
+ }
977
+ },
978
+ {
979
+ key: "getAddresses",
980
+ value: /**
981
+ * Derives the wallet's three receiving addresses.
982
+ *
983
+ * Only the unshielded address comes from the MPC keygen (secp256k1/BIP340);
984
+ * shielded uses JubJub and dust BLS12-381, so both are derived client-side
985
+ * from the role keys. Requires an MPC export, but no facade or sync.
986
+ *
987
+ * @returns bech32m addresses for the requested network
988
+ */ function getAddresses(access) {
989
+ var _this = this;
990
+ return _async_to_generator(function() {
991
+ var network, encodeId, roleKeys, shieldedSecretKeys, shielded, dust, dustSecretKey;
992
+ return _ts_generator(this, function(_state) {
993
+ switch(_state.label){
994
+ case 0:
995
+ network = resolveMidnightNetworkTag(access.networkId);
996
+ // Preview keeps the bare tag; mainnet is the library's `mainnet` symbol.
997
+ encodeId = network === 'mainnet' ? mainnet : 'preview';
998
+ return [
999
+ 4,
1000
+ _this.getRoleKeys(access)
1001
+ ];
1002
+ case 1:
1003
+ roleKeys = _state.sent();
1004
+ shieldedSecretKeys = ledger.ZswapSecretKeys.fromSeed(new Uint8Array(Buffer.from(roleKeys.shielded, 'hex')));
1005
+ shielded = MidnightBech32m.encode(encodeId, new ShieldedAddress(new ShieldedCoinPublicKey(Buffer.from(shieldedSecretKeys.coinPublicKey, 'hex')), new ShieldedEncryptionPublicKey(Buffer.from(shieldedSecretKeys.encryptionPublicKey, 'hex')))).toString();
1006
+ try {
1007
+ dustSecretKey = ledger.DustSecretKey.fromSeed(new Uint8Array(Buffer.from(roleKeys.dust, 'hex')));
1008
+ dust = MidnightBech32m.encode(encodeId, new DustAddress(dustSecretKey.publicKey)).toString();
1009
+ } catch (err) {
1010
+ _this.logger.warn('[Midnight] getAddresses: dust address derivation failed', err);
1011
+ }
1012
+ return [
1013
+ 2,
1014
+ {
1015
+ unshielded: access.walletMetadata.accountAddress,
1016
+ shielded: shielded,
1017
+ dust: dust
1018
+ }
1019
+ ];
1020
+ }
1021
+ });
1022
+ })();
1023
+ }
1024
+ },
1025
+ {
1026
+ key: "getMidnightWallets",
1027
+ value: /**
1028
+ * Gets all Midnight wallets
1029
+ * @returns Array of Midnight wallets
1030
+ */ function getMidnightWallets() {
1031
+ var _this = this;
1032
+ return _async_to_generator(function() {
1033
+ var wallets;
1034
+ return _ts_generator(this, function(_state) {
1035
+ switch(_state.label){
1036
+ case 0:
1037
+ return [
1038
+ 4,
1039
+ _this.getWallets()
1040
+ ];
1041
+ case 1:
1042
+ wallets = _state.sent();
1043
+ return [
1044
+ 2,
1045
+ wallets.filter(function(wallet) {
1046
+ return wallet.chainName === _this.chainName;
1047
+ })
1048
+ ];
1049
+ }
1050
+ });
1051
+ })();
1052
+ }
1053
+ }
1054
+ ]);
1055
+ return DynamicMidnightWalletClient;
1056
+ }(DynamicWalletClient);
1057
+
1058
+ export { DynamicMidnightWalletClient, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_CREATE_WALLET_ACCOUNT, ERROR_EXPORT_PRIVATE_KEY, ERROR_IMPORT_PRIVATE_KEY, ERROR_KEYGEN_FAILED, ERROR_SIGN_MESSAGE, MIDNIGHT_NETWORK_IDS, decodeMidnightAddress, deriveMidnightAddress, getNetworkFromAddress, isValidMidnightAddress, resolveMidnightNetworkTag, toXOnlyPublicKeyHex };