@sundaeswap/sprinkles 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/cjs/Sprinkle/__tests__/encryption.test.js +20 -8
  2. package/dist/cjs/Sprinkle/__tests__/encryption.test.js.map +1 -1
  3. package/dist/cjs/Sprinkle/__tests__/enhancements.test.js +41 -16
  4. package/dist/cjs/Sprinkle/__tests__/enhancements.test.js.map +1 -1
  5. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +85 -38
  6. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  7. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js +93 -7
  8. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  9. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js +21 -0
  10. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  11. package/dist/cjs/Sprinkle/encryption.js +131 -0
  12. package/dist/cjs/Sprinkle/encryption.js.map +1 -0
  13. package/dist/cjs/Sprinkle/index.js +307 -362
  14. package/dist/cjs/Sprinkle/index.js.map +1 -1
  15. package/dist/cjs/Sprinkle/prompts.js +393 -0
  16. package/dist/cjs/Sprinkle/prompts.js.map +1 -0
  17. package/dist/cjs/Sprinkle/schemas.js +97 -0
  18. package/dist/cjs/Sprinkle/schemas.js.map +1 -0
  19. package/dist/cjs/Sprinkle/tx-dialog.js +101 -0
  20. package/dist/cjs/Sprinkle/tx-dialog.js.map +1 -0
  21. package/dist/cjs/Sprinkle/type-guards.js +42 -0
  22. package/dist/cjs/Sprinkle/type-guards.js.map +1 -0
  23. package/dist/cjs/Sprinkle/types.js +49 -0
  24. package/dist/cjs/Sprinkle/types.js.map +1 -0
  25. package/dist/cjs/Sprinkle/wallet.js +98 -0
  26. package/dist/cjs/Sprinkle/wallet.js.map +1 -0
  27. package/dist/esm/Sprinkle/__tests__/encryption.test.js +20 -8
  28. package/dist/esm/Sprinkle/__tests__/encryption.test.js.map +1 -1
  29. package/dist/esm/Sprinkle/__tests__/enhancements.test.js +41 -16
  30. package/dist/esm/Sprinkle/__tests__/enhancements.test.js.map +1 -1
  31. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +85 -38
  32. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  33. package/dist/esm/Sprinkle/__tests__/show-menu.test.js +94 -8
  34. package/dist/esm/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  35. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js +21 -0
  36. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  37. package/dist/esm/Sprinkle/encryption.js +117 -0
  38. package/dist/esm/Sprinkle/encryption.js.map +1 -0
  39. package/dist/esm/Sprinkle/index.js +161 -347
  40. package/dist/esm/Sprinkle/index.js.map +1 -1
  41. package/dist/esm/Sprinkle/prompts.js +385 -0
  42. package/dist/esm/Sprinkle/prompts.js.map +1 -0
  43. package/dist/esm/Sprinkle/schemas.js +91 -0
  44. package/dist/esm/Sprinkle/schemas.js.map +1 -0
  45. package/dist/esm/Sprinkle/tx-dialog.js +90 -0
  46. package/dist/esm/Sprinkle/tx-dialog.js.map +1 -0
  47. package/dist/esm/Sprinkle/type-guards.js +24 -0
  48. package/dist/esm/Sprinkle/type-guards.js.map +1 -0
  49. package/dist/esm/Sprinkle/types.js +42 -0
  50. package/dist/esm/Sprinkle/types.js.map +1 -0
  51. package/dist/esm/Sprinkle/wallet.js +90 -0
  52. package/dist/esm/Sprinkle/wallet.js.map +1 -0
  53. package/dist/types/Sprinkle/encryption.d.ts +43 -0
  54. package/dist/types/Sprinkle/encryption.d.ts.map +1 -0
  55. package/dist/types/Sprinkle/index.d.ts +11 -177
  56. package/dist/types/Sprinkle/index.d.ts.map +1 -1
  57. package/dist/types/Sprinkle/prompts.d.ts +94 -0
  58. package/dist/types/Sprinkle/prompts.d.ts.map +1 -0
  59. package/dist/types/Sprinkle/schemas.d.ts +125 -0
  60. package/dist/types/Sprinkle/schemas.d.ts.map +1 -0
  61. package/dist/types/Sprinkle/tx-dialog.d.ts +37 -0
  62. package/dist/types/Sprinkle/tx-dialog.d.ts.map +1 -0
  63. package/dist/types/Sprinkle/type-guards.d.ts +22 -0
  64. package/dist/types/Sprinkle/type-guards.d.ts.map +1 -0
  65. package/dist/types/Sprinkle/types.d.ts +62 -0
  66. package/dist/types/Sprinkle/types.d.ts.map +1 -0
  67. package/dist/types/Sprinkle/wallet.d.ts +27 -0
  68. package/dist/types/Sprinkle/wallet.d.ts.map +1 -0
  69. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  70. package/package.json +1 -1
  71. package/src/Sprinkle/__tests__/encryption.test.ts +21 -8
  72. package/src/Sprinkle/__tests__/enhancements.test.ts +41 -15
  73. package/src/Sprinkle/__tests__/fill-in-struct.test.ts +104 -38
  74. package/src/Sprinkle/__tests__/show-menu.test.ts +96 -8
  75. package/src/Sprinkle/__tests__/tx-dialog.test.ts +21 -0
  76. package/src/Sprinkle/encryption.ts +130 -0
  77. package/src/Sprinkle/index.ts +254 -496
  78. package/src/Sprinkle/prompts.ts +481 -0
  79. package/src/Sprinkle/schemas.ts +111 -0
  80. package/src/Sprinkle/tx-dialog.ts +100 -0
  81. package/src/Sprinkle/type-guards.ts +51 -0
  82. package/src/Sprinkle/types.ts +73 -0
  83. package/src/Sprinkle/wallet.ts +133 -0
@@ -4,18 +4,159 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  var _exportNames = {
7
+ Sprinkle: true,
8
+ UserCancelledError: true,
7
9
  NetworkSchema: true,
8
10
  MultisigScriptModule: true,
9
11
  MultisigScript: true,
10
12
  ProviderSettingsSchema: true,
11
13
  WalletSettingsSchema: true,
12
- Sprinkle: true
14
+ isOptional: true,
15
+ isImport: true,
16
+ isArray: true,
17
+ isBigInt: true,
18
+ isLiteral: true,
19
+ isObject: true,
20
+ isRef: true,
21
+ isString: true,
22
+ isThis: true,
23
+ isTuple: true,
24
+ isUnion: true,
25
+ isSensitive: true,
26
+ GetProvider: true,
27
+ GetWallet: true,
28
+ GetBlaze: true
13
29
  };
14
- exports.WalletSettingsSchema = exports.Sprinkle = exports.ProviderSettingsSchema = exports.NetworkSchema = exports.MultisigScriptModule = exports.MultisigScript = void 0;
15
- var _query = require("@blaze-cardano/query");
30
+ Object.defineProperty(exports, "GetBlaze", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _wallet.GetBlaze;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "GetProvider", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _wallet.GetProvider;
40
+ }
41
+ });
42
+ Object.defineProperty(exports, "GetWallet", {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _wallet.GetWallet;
46
+ }
47
+ });
48
+ Object.defineProperty(exports, "MultisigScript", {
49
+ enumerable: true,
50
+ get: function () {
51
+ return _schemas.MultisigScript;
52
+ }
53
+ });
54
+ Object.defineProperty(exports, "MultisigScriptModule", {
55
+ enumerable: true,
56
+ get: function () {
57
+ return _schemas.MultisigScriptModule;
58
+ }
59
+ });
60
+ Object.defineProperty(exports, "NetworkSchema", {
61
+ enumerable: true,
62
+ get: function () {
63
+ return _schemas.NetworkSchema;
64
+ }
65
+ });
66
+ Object.defineProperty(exports, "ProviderSettingsSchema", {
67
+ enumerable: true,
68
+ get: function () {
69
+ return _schemas.ProviderSettingsSchema;
70
+ }
71
+ });
72
+ exports.Sprinkle = void 0;
73
+ Object.defineProperty(exports, "UserCancelledError", {
74
+ enumerable: true,
75
+ get: function () {
76
+ return _types.UserCancelledError;
77
+ }
78
+ });
79
+ Object.defineProperty(exports, "WalletSettingsSchema", {
80
+ enumerable: true,
81
+ get: function () {
82
+ return _schemas.WalletSettingsSchema;
83
+ }
84
+ });
85
+ Object.defineProperty(exports, "isArray", {
86
+ enumerable: true,
87
+ get: function () {
88
+ return _typeGuards.isArray;
89
+ }
90
+ });
91
+ Object.defineProperty(exports, "isBigInt", {
92
+ enumerable: true,
93
+ get: function () {
94
+ return _typeGuards.isBigInt;
95
+ }
96
+ });
97
+ Object.defineProperty(exports, "isImport", {
98
+ enumerable: true,
99
+ get: function () {
100
+ return _typeGuards.isImport;
101
+ }
102
+ });
103
+ Object.defineProperty(exports, "isLiteral", {
104
+ enumerable: true,
105
+ get: function () {
106
+ return _typeGuards.isLiteral;
107
+ }
108
+ });
109
+ Object.defineProperty(exports, "isObject", {
110
+ enumerable: true,
111
+ get: function () {
112
+ return _typeGuards.isObject;
113
+ }
114
+ });
115
+ Object.defineProperty(exports, "isOptional", {
116
+ enumerable: true,
117
+ get: function () {
118
+ return _typeGuards.isOptional;
119
+ }
120
+ });
121
+ Object.defineProperty(exports, "isRef", {
122
+ enumerable: true,
123
+ get: function () {
124
+ return _typeGuards.isRef;
125
+ }
126
+ });
127
+ Object.defineProperty(exports, "isSensitive", {
128
+ enumerable: true,
129
+ get: function () {
130
+ return _typeGuards.isSensitive;
131
+ }
132
+ });
133
+ Object.defineProperty(exports, "isString", {
134
+ enumerable: true,
135
+ get: function () {
136
+ return _typeGuards.isString;
137
+ }
138
+ });
139
+ Object.defineProperty(exports, "isThis", {
140
+ enumerable: true,
141
+ get: function () {
142
+ return _typeGuards.isThis;
143
+ }
144
+ });
145
+ Object.defineProperty(exports, "isTuple", {
146
+ enumerable: true,
147
+ get: function () {
148
+ return _typeGuards.isTuple;
149
+ }
150
+ });
151
+ Object.defineProperty(exports, "isUnion", {
152
+ enumerable: true,
153
+ get: function () {
154
+ return _typeGuards.isUnion;
155
+ }
156
+ });
16
157
  var _sdk = require("@blaze-cardano/sdk");
17
158
  var _core = require("@blaze-cardano/core");
18
- var _prompts = require("@inquirer/prompts");
159
+ var _prompts = require("./prompts.js");
19
160
  var _typebox = require("@sinclair/typebox");
20
161
  Object.keys(_typebox).forEach(function (key) {
21
162
  if (key === "default" || key === "__esModule") return;
@@ -30,102 +171,22 @@ Object.keys(_typebox).forEach(function (key) {
30
171
  });
31
172
  var fs = _interopRequireWildcard(require("fs"));
32
173
  var path = _interopRequireWildcard(require("path"));
174
+ var _types = require("./types.js");
175
+ var _schemas = require("./schemas.js");
176
+ var _typeGuards = require("./type-guards.js");
177
+ var _wallet = require("./wallet.js");
178
+ var _encryption = require("./encryption.js");
179
+ var _txDialog = require("./tx-dialog.js");
33
180
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
34
181
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
35
182
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
36
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
37
- const isOptional = t => t[_typebox.OptionalKind] === "Optional";
38
- const isImport = t => t[_typebox.Kind] === "Import";
39
- const isArray = t => t[_typebox.Kind] === "Array";
40
- const isBigInt = t => t[_typebox.Kind] === "BigInt";
41
- // const isBoolean = (t: TSchema): t is TBoolean => t[Kind] === "Boolean";
42
- const isLiteral = t => t[_typebox.Kind] === "Literal";
43
- // const isNumber = (t: TSchema): t is TNumber => t[Kind] === "Number";
44
- const isObject = t => t[_typebox.Kind] === "Object";
45
- // const isRecord = (t: TSchema): t is TRecord => t[Kind] === "Record";
46
- const isRef = t => t[_typebox.Kind] === "Ref";
47
- const isString = t => t[_typebox.Kind] === "String";
48
- const isThis = t => t[_typebox.Kind] === "This";
49
- const isTuple = t => t[_typebox.Kind] === "Tuple";
50
- const isUnion = t => t[_typebox.Kind] === "Union";
51
- // const isAny = (t: TSchema): t is TAny => t[Kind] === "Any";
52
-
53
- const isSensitive = t => isString(t) && t.sensitive === true;
54
- const NetworkSchema = exports.NetworkSchema = _typebox.Type.Union([_typebox.Type.Literal("mainnet"), _typebox.Type.Literal("preview"), _typebox.Type.Literal("preprod")]);
55
- const MultisigScriptModule = exports.MultisigScriptModule = _typebox.Type.Module({
56
- MultisigScript: _typebox.Type.Union([_typebox.Type.Object({
57
- Signature: _typebox.Type.Object({
58
- key_hash: _typebox.Type.String()
59
- }, {
60
- ctor: 0n
61
- })
62
- }), _typebox.Type.Object({
63
- AllOf: _typebox.Type.Object({
64
- scripts: _typebox.Type.Array(_typebox.Type.Ref("MultisigScript"))
65
- }, {
66
- ctor: 1n
67
- })
68
- }), _typebox.Type.Object({
69
- AnyOf: _typebox.Type.Object({
70
- scripts: _typebox.Type.Array(_typebox.Type.Ref("MultisigScript"))
71
- }, {
72
- ctor: 2n
73
- })
74
- }), _typebox.Type.Object({
75
- AtLeast: _typebox.Type.Object({
76
- required: _typebox.Type.BigInt(),
77
- scripts: _typebox.Type.Array(_typebox.Type.Ref("MultisigScript"))
78
- }, {
79
- ctor: 3n
80
- })
81
- }), _typebox.Type.Object({
82
- Before: _typebox.Type.Object({
83
- time: _typebox.Type.BigInt()
84
- }, {
85
- ctor: 4n
86
- })
87
- }), _typebox.Type.Object({
88
- After: _typebox.Type.Object({
89
- time: _typebox.Type.BigInt()
90
- }, {
91
- ctor: 5n
92
- })
93
- }), _typebox.Type.Object({
94
- Script: _typebox.Type.Object({
95
- script_hash: _typebox.Type.String()
96
- }, {
97
- ctor: 6n
98
- })
99
- })])
100
- });
101
- const MultisigScript = exports.MultisigScript = MultisigScriptModule.Import("MultisigScript");
102
- const ProviderSettingsSchema = exports.ProviderSettingsSchema = _typebox.Type.Union([_typebox.Type.Object({
103
- type: _typebox.Type.Literal("blockfrost"),
104
- projectId: _typebox.Type.String({
105
- minLength: 1,
106
- title: "Blockfrost Project ID"
107
- })
108
- }), _typebox.Type.Object({
109
- type: _typebox.Type.Literal("maestro"),
110
- apiKey: _typebox.Type.String({
111
- minLength: 1,
112
- title: "Maestro API Key"
113
- })
114
- })]);
115
- const WalletSettingsSchema = exports.WalletSettingsSchema = _typebox.Type.Union([_typebox.Type.Object({
116
- type: _typebox.Type.Literal("hot"),
117
- privateKey: _typebox.Type.String({
118
- minLength: 1,
119
- title: "Hot Wallet Private Key",
120
- sensitive: true
121
- })
122
- }), _typebox.Type.Object({
123
- type: _typebox.Type.Literal("cold"),
124
- address: _typebox.Type.String({
125
- minLength: 1,
126
- title: "Cold Wallet Address"
127
- })
128
- })]);
183
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } // Re-export types from types.ts
184
+ // Re-export schemas from schemas.ts
185
+ // Import and re-export type guards
186
+ // Import schemas for use in this file
187
+ // Import and re-export wallet utilities
188
+ // Import encryption utilities
189
+ // Import tx-dialog utilities
129
190
  class Sprinkle {
130
191
  constructor(type, storagePath, options) {
131
192
  _defineProperty(this, "storagePath", void 0);
@@ -232,32 +293,42 @@ class Sprinkle {
232
293
  meta: this.profileMeta,
233
294
  settings: settingsToSave,
234
295
  defaults: this.defaults
235
- }, Sprinkle.bigIntReplacer, 2);
296
+ }, _encryption.bigIntReplacer, 2);
236
297
  fs.writeFileSync(filePath, jsonContent, "utf-8");
237
298
  }
238
299
  async promptProfileMeta(defaultName, defaultDescription) {
239
- const name = await (0, _prompts.input)({
300
+ const name = await (0, _prompts.inputCancellable)({
240
301
  message: "Profile name:",
241
302
  default: defaultName,
242
303
  validate: v => v.trim().length > 0 ? true : "Name cannot be empty"
243
304
  });
244
- const description = await (0, _prompts.input)({
305
+ if (name === null) return null; // User cancelled
306
+ const description = await (0, _prompts.inputCancellable)({
245
307
  message: "Profile description (optional):",
246
308
  default: defaultDescription ?? ""
247
309
  });
310
+ if (description === null) return null; // User cancelled
248
311
  return {
249
312
  name,
250
313
  description: description || undefined
251
314
  };
252
315
  }
253
316
  async createProfile() {
317
+ const result = await this.promptProfileMeta();
318
+ if (result === null) return; // User cancelled
254
319
  const {
255
320
  name,
256
321
  description
257
- } = await this.promptProfileMeta();
322
+ } = result;
258
323
  const profilesDir = Sprinkle.profilesDir(this.storagePath);
259
324
  const id = Sprinkle.findAvailableId(profilesDir, Sprinkle.sanitizeProfileId(name));
260
325
  const now = new Date().toISOString();
326
+
327
+ // Snapshot current state in case we need to restore on cancellation
328
+ const prevProfileId = this.profileId;
329
+ const prevProfileMeta = this.profileMeta;
330
+ const prevDefaults = this.defaults;
331
+ const prevSettings = this.settings;
261
332
  this.profileId = id;
262
333
  this.profileMeta = {
263
334
  name,
@@ -266,7 +337,19 @@ class Sprinkle {
266
337
  updatedAt: now
267
338
  };
268
339
  this.defaults = {};
269
- this.settings = await this.FillInStruct(this.type);
340
+ try {
341
+ this.settings = await this.FillInStruct(this.type);
342
+ } catch (e) {
343
+ // Restore previous state on cancellation
344
+ if (e instanceof _types.UserCancelledError) {
345
+ this.profileId = prevProfileId;
346
+ this.profileMeta = prevProfileMeta;
347
+ this.defaults = prevDefaults;
348
+ this.settings = prevSettings;
349
+ return;
350
+ }
351
+ throw e;
352
+ }
270
353
  this.saveProfile();
271
354
  fs.writeFileSync(Sprinkle.activeProfilePath(this.storagePath), id, "utf-8");
272
355
  }
@@ -291,7 +374,7 @@ class Sprinkle {
291
374
  fs.mkdirSync(profilesDir, {
292
375
  recursive: true
293
376
  });
294
- fs.writeFileSync(Sprinkle.profilePath(this.storagePath, "default"), JSON.stringify(profileData, Sprinkle.bigIntReplacer, 2), "utf-8");
377
+ fs.writeFileSync(Sprinkle.profilePath(this.storagePath, "default"), JSON.stringify(profileData, _encryption.bigIntReplacer, 2), "utf-8");
295
378
  fs.writeFileSync(Sprinkle.activeProfilePath(this.storagePath), "default", "utf-8");
296
379
  // Backup legacy file
297
380
  fs.renameSync(legacyPath, `${legacyPath}.bak`);
@@ -328,23 +411,26 @@ class Sprinkle {
328
411
  }
329
412
  async selectProfile(profiles) {
330
413
  const available = profiles ?? this.scanProfiles();
331
- const selection = await (0, _prompts.select)({
414
+ const selection = await (0, _prompts.selectCancellable)({
332
415
  message: "Select a profile:",
333
416
  choices: available.map(p => ({
334
417
  name: p.meta.description ? `${p.meta.name} - ${p.meta.description}` : p.meta.name,
335
418
  value: p.id
336
419
  }))
337
420
  });
421
+ if (selection === null) return; // User cancelled
338
422
  await this.loadProfile(selection);
339
423
  }
340
424
 
341
425
  // --- Profile management (CRUD) ---
342
426
 
343
427
  async duplicateProfile() {
428
+ const result = await this.promptProfileMeta(`${this.profileMeta.name} (copy)`, this.profileMeta.description);
429
+ if (result === null) return; // User cancelled
344
430
  const {
345
431
  name,
346
432
  description
347
- } = await this.promptProfileMeta(`${this.profileMeta.name} (copy)`, this.profileMeta.description);
433
+ } = result;
348
434
  const profilesDir = Sprinkle.profilesDir(this.storagePath);
349
435
  const id = Sprinkle.findAvailableId(profilesDir, Sprinkle.sanitizeProfileId(name));
350
436
  const now = new Date().toISOString();
@@ -359,15 +445,17 @@ class Sprinkle {
359
445
  },
360
446
  settings: settingsToSave,
361
447
  defaults: this.defaults
362
- }, Sprinkle.bigIntReplacer, 2);
448
+ }, _encryption.bigIntReplacer, 2);
363
449
  fs.writeFileSync(path.join(profilesDir, `${id}.json`), jsonContent, "utf-8");
364
450
  console.log(`Profile "${name}" created as a copy.`);
365
451
  }
366
452
  async renameProfile() {
453
+ const result = await this.promptProfileMeta(this.profileMeta.name, this.profileMeta.description);
454
+ if (result === null) return; // User cancelled
367
455
  const {
368
456
  name,
369
457
  description
370
- } = await this.promptProfileMeta(this.profileMeta.name, this.profileMeta.description);
458
+ } = result;
371
459
  const newId = Sprinkle.sanitizeProfileId(name);
372
460
  const oldId = this.profileId;
373
461
  this.profileMeta.name = name;
@@ -395,25 +483,26 @@ class Sprinkle {
395
483
  console.log("Cannot delete the only profile.");
396
484
  return;
397
485
  }
398
- const toDelete = await (0, _prompts.select)({
486
+ const toDelete = await (0, _prompts.selectCancellable)({
399
487
  message: "Select a profile to delete:",
400
- choices: [...others.map(p => ({
488
+ choices: others.map(p => ({
401
489
  name: p.meta.description ? `${p.meta.name} - ${p.meta.description}` : p.meta.name,
402
490
  value: p.id
403
- })), {
404
- name: "Cancel",
405
- value: "__cancel__"
406
- }]
491
+ }))
407
492
  });
408
- if (toDelete === "__cancel__") return;
409
- const profileToDelete = others.find(p => p.id === toDelete);
410
- const confirmed = await (0, _prompts.confirm)({
411
- message: `Delete profile "${profileToDelete?.meta.name ?? toDelete}"? This cannot be undone.`,
493
+ if (toDelete === null) return; // User cancelled
494
+
495
+ const profileId = toDelete;
496
+ const profileToDelete = others.find(p => p.id === profileId);
497
+ const confirmed = await (0, _prompts.confirmCancellable)({
498
+ message: `Delete profile "${profileToDelete?.meta.name ?? profileId}"? This cannot be undone.`,
412
499
  default: false
413
500
  });
501
+ if (confirmed === null) return; // User cancelled
502
+
414
503
  if (confirmed) {
415
- fs.unlinkSync(Sprinkle.profilePath(this.storagePath, toDelete));
416
- console.log(`Profile "${profileToDelete?.meta.name ?? toDelete}" deleted.`);
504
+ fs.unlinkSync(Sprinkle.profilePath(this.storagePath, profileId));
505
+ console.log(`Profile "${profileToDelete?.meta.name ?? profileId}" deleted.`);
417
506
  }
418
507
  }
419
508
 
@@ -454,14 +543,24 @@ class Sprinkle {
454
543
  value: -1
455
544
  });
456
545
  }
457
- const selection = await (0, _prompts.select)({
546
+ const selectionResult = await (0, _prompts.selectCancellable)({
458
547
  message: "Select an option:",
459
548
  choices: choices
460
549
  });
550
+ // Handle escape (null) as Back
551
+ if (selectionResult === null) {
552
+ return;
553
+ }
554
+ const selection = selectionResult;
461
555
  if (selection === -5) {
462
556
  const settingsMenu = {
463
557
  title: "Settings & Profiles",
464
558
  items: [{
559
+ title: "View settings",
560
+ action: async () => {
561
+ console.log(JSON.stringify(this.getDisplaySettings(), _encryption.bigIntReplacer, 2));
562
+ }
563
+ }, {
465
564
  title: "Edit settings",
466
565
  action: async () => {
467
566
  this.settings = await this.EditStruct(this.type, this.settings);
@@ -529,40 +628,13 @@ class Sprinkle {
529
628
  return sprinkle;
530
629
  }
531
630
  static async GetProvider(network, settings) {
532
- switch (settings.type) {
533
- case "blockfrost":
534
- return new _query.Blockfrost({
535
- network: `cardano-${network}`,
536
- projectId: settings.projectId
537
- });
538
- case "maestro":
539
- // Dynamic import - Maestro may or may not be exported depending on @blaze-cardano/query version
540
- const queryModule = await Promise.resolve().then(() => _interopRequireWildcard(require("@blaze-cardano/query")));
541
- if (!queryModule.Maestro) {
542
- throw new Error("Maestro is not available in the installed version of @blaze-cardano/query. Please install a version that includes Maestro support.");
543
- }
544
- return new queryModule.Maestro({
545
- network: network,
546
- apiKey: settings.apiKey
547
- });
548
- default:
549
- throw new Error("Invalid provider type");
550
- }
631
+ return (0, _wallet.GetProvider)(network, settings);
551
632
  }
552
633
  static async GetWallet(settings, provider) {
553
- switch (settings.type) {
554
- case "hot":
555
- return _sdk.HotWallet.fromMasterkey(_sdk.Core.Bip32PrivateKeyHex(settings.privateKey), provider, provider.network);
556
- case "cold":
557
- return new _sdk.ColdWallet(_sdk.Core.Address.fromBech32(settings.address), provider.network, provider);
558
- default:
559
- throw new Error("Invalid wallet type");
560
- }
634
+ return (0, _wallet.GetWallet)(settings, provider);
561
635
  }
562
636
  static async GetBlaze(network, providerSettings, walletSettings) {
563
- const provider = await Sprinkle.GetProvider(network, providerSettings);
564
- const wallet = await Sprinkle.GetWallet(walletSettings, provider);
565
- return _sdk.Blaze.from(provider, wallet);
637
+ return (0, _wallet.GetBlaze)(network, providerSettings, walletSettings);
566
638
  }
567
639
 
568
640
  /**
@@ -571,30 +643,10 @@ class Sprinkle {
571
643
  * @returns The Bip32PrivateKey hex string for storage
572
644
  */
573
645
  static async generateWalletFromMnemonic() {
574
- const mnemonic = _sdk.Core.generateMnemonic(_core.wordlist, 256); // 24 words
575
- const words = mnemonic.split(" ");
576
- console.log("\n=== NEW WALLET GENERATED ===\n");
577
- console.log("IMPORTANT: Save these 24 words in a secure location.");
578
- console.log("This is the ONLY way to recover your wallet.\n");
579
-
580
- // Display in 4 columns
581
- for (let i = 0; i < 6; i++) {
582
- console.log(`${(i + 1).toString().padStart(2)}. ${words[i].padEnd(12)} ` + `${(i + 7).toString().padStart(2)}. ${words[i + 6].padEnd(12)} ` + `${(i + 13).toString().padStart(2)}. ${words[i + 12].padEnd(12)} ` + `${(i + 19).toString().padStart(2)}. ${words[i + 18]}`);
583
- }
584
- console.log("");
585
- const confirmed = await (0, _prompts.confirm)({
586
- message: "Have you saved your recovery phrase?",
587
- default: false
588
- });
589
- if (!confirmed) {
590
- throw new Error("Wallet generation cancelled - recovery phrase not saved");
591
- }
592
- const entropy = _sdk.Core.mnemonicToEntropy(mnemonic, _core.wordlist);
593
- const masterKey = _sdk.Core.Bip32PrivateKey.fromBip39Entropy(Buffer.from(entropy), "");
594
- return masterKey.hex();
646
+ return (0, _wallet.generateWalletFromMnemonic)();
595
647
  }
596
648
  static async SearchSelect(opts) {
597
- return (0, _prompts.search)(opts);
649
+ return (0, _prompts.searchCancellable)(opts);
598
650
  }
599
651
  static SettingsPath(storagePath) {
600
652
  return `${storagePath}${path.sep}settings.json`;
@@ -618,166 +670,21 @@ class Sprinkle {
618
670
  }
619
671
  }
620
672
  static bigIntReviver(key, value) {
621
- if (typeof value === "string" && /^\d+n$/.test(value)) {
622
- return BigInt(value.slice(0, -1));
623
- }
624
- return value;
625
- }
626
- static bigIntReplacer(_key, value) {
627
- return typeof value === "bigint" ? `${value.toString()}n` : value;
628
- }
629
- static collectSensitivePaths(type, prefix = "") {
630
- const paths = [];
631
- if (isObject(type)) {
632
- const fields = type["properties"];
633
- for (const [field, fieldType] of Object.entries(fields)) {
634
- const fieldPath = prefix ? `${prefix}.${field}` : field;
635
- if (isSensitive(fieldType)) {
636
- paths.push(fieldPath);
637
- }
638
- paths.push(...Sprinkle.collectSensitivePaths(fieldType, fieldPath));
639
- }
640
- }
641
- if (isUnion(type)) {
642
- for (const variant of type.anyOf) {
643
- paths.push(...Sprinkle.collectSensitivePaths(variant, prefix));
644
- }
645
- }
646
- return paths;
647
- }
648
- static getNestedValue(obj, path) {
649
- return path.split(".").reduce((o, k) => o?.[k], obj);
650
- }
651
- static setNestedValue(obj, path, value) {
652
- const keys = path.split(".");
653
- const last = keys.pop();
654
- const parent = keys.reduce((o, k) => o?.[k], obj);
655
- if (parent && typeof parent === "object") {
656
- parent[last] = value;
657
- }
673
+ return (0, _encryption.bigIntReviver)(key, value);
658
674
  }
659
675
  encryptSettings(settings) {
660
676
  if (!this.options.encryption) return settings;
661
- const clone = JSON.parse(JSON.stringify(settings, Sprinkle.bigIntReplacer), Sprinkle.bigIntReviver);
662
- const sensitivePaths = Sprinkle.collectSensitivePaths(this.type);
663
- for (const p of sensitivePaths) {
664
- const value = Sprinkle.getNestedValue(clone, p);
665
- if (typeof value === "string" && value.length > 0) {
666
- Sprinkle.setNestedValue(clone, p, this.options.encryption.encrypt(value));
667
- }
668
- }
669
- return clone;
677
+ return (0, _encryption.encryptSensitiveFields)(settings, this.type, this.options.encryption);
670
678
  }
671
679
  async decryptSettings(settings) {
672
680
  if (!this.options.encryption) return settings;
673
- const clone = JSON.parse(JSON.stringify(settings, Sprinkle.bigIntReplacer), Sprinkle.bigIntReviver);
674
- const sensitivePaths = Sprinkle.collectSensitivePaths(this.type);
675
- for (const p of sensitivePaths) {
676
- const value = Sprinkle.getNestedValue(clone, p);
677
- if (typeof value === "string" && value.length > 0) {
678
- Sprinkle.setNestedValue(clone, p, await this.options.encryption.decrypt(value));
679
- }
680
- }
681
- return clone;
681
+ return (0, _encryption.decryptSensitiveFields)(settings, this.type, this.options.encryption);
682
682
  }
683
683
  saveSettings() {
684
684
  this.saveProfile();
685
685
  }
686
686
  getDisplaySettings() {
687
- const clone = JSON.parse(JSON.stringify(this.settings, Sprinkle.bigIntReplacer), Sprinkle.bigIntReviver);
688
- const sensitivePaths = Sprinkle.collectSensitivePaths(this.type);
689
- for (const p of sensitivePaths) {
690
- const value = Sprinkle.getNestedValue(clone, p);
691
- if (typeof value === "string" && value.length > 0) {
692
- Sprinkle.setNestedValue(clone, p, "********");
693
- }
694
- }
695
- return clone;
696
- }
697
-
698
- // --- TxDialog Helpers ---
699
-
700
- /**
701
- * Get the payment key hash from a HotWallet's first address
702
- */
703
- async getWalletPaymentKeyHash(wallet) {
704
- try {
705
- const addresses = await wallet.getUsedAddresses();
706
- const address = addresses[0];
707
- if (!address) return null;
708
- const paymentCredential = address.asBase()?.getPaymentCredential();
709
- return paymentCredential?.hash?.toString() ?? null;
710
- } catch {
711
- return null;
712
- }
713
- }
714
-
715
- /**
716
- * Count the number of vkey signatures in a transaction's witness set
717
- */
718
- countSignatures(tx) {
719
- const vkeys = tx.witnessSet().vkeys();
720
- return vkeys ? vkeys.size() : 0;
721
- }
722
-
723
- /**
724
- * Check if a specific public key has already signed the transaction
725
- * Compares by vkey (public key bytes)
726
- */
727
- hasVkeySigned(tx, vkeyHex) {
728
- const vkeys = tx.witnessSet().vkeys();
729
- if (!vkeys) return false;
730
- const vkeyArray = vkeys.toCore();
731
- return vkeyArray.some(([vkey]) => vkey === vkeyHex);
732
- }
733
-
734
- /**
735
- * Get the list of required signer key hashes from the transaction body
736
- */
737
- getRequiredSigners(tx) {
738
- const requiredSigners = tx.body().requiredSigners();
739
- if (!requiredSigners) return [];
740
- return Array.from(requiredSigners.values()).map(s => s.toString());
741
- }
742
-
743
- /**
744
- * Compute the transaction body hash for display
745
- */
746
- getTxBodyHash(tx) {
747
- const bodyCbor = tx.body().toCbor();
748
- return (0, _core.blake2b_256)(bodyCbor);
749
- }
750
-
751
- /**
752
- * Format a hash for display: first 8 chars + ... + last 8 chars
753
- */
754
- formatHash(hash) {
755
- if (hash.length <= 20) return hash;
756
- return `${hash.slice(0, 8)}...${hash.slice(-8)}`;
757
- }
758
-
759
- /**
760
- * Merge signatures from source transaction into target transaction.
761
- * Prevents duplicate signatures by comparing vkey (public key).
762
- * Returns the count of newly added signatures.
763
- */
764
- mergeSignatures(target, source) {
765
- const targetWs = target.witnessSet();
766
- const sourceWs = source.witnessSet();
767
- const targetVkeys = targetWs.vkeys()?.toCore() ?? [];
768
- const sourceVkeys = sourceWs.vkeys()?.toCore() ?? [];
769
-
770
- // Find vkeys in source that aren't in target (by comparing public key)
771
- const existingPubKeys = new Set(targetVkeys.map(([vkey]) => vkey));
772
- const newVkeys = sourceVkeys.filter(([vkey]) => !existingPubKeys.has(vkey));
773
- if (newVkeys.length === 0) {
774
- return 0;
775
- }
776
-
777
- // Merge the new vkeys into target
778
- targetWs.setVkeys(_core.CborSet.fromCore([...targetVkeys, ...newVkeys], _core.VkeyWitness.fromCore));
779
- target.setWitnessSet(targetWs);
780
- return newVkeys.length;
687
+ return (0, _encryption.maskSensitiveFields)(this.settings, this.type);
781
688
  }
782
689
  async TxDialog(blaze, tx, opts) {
783
690
  let currentTx = tx;
@@ -805,16 +712,16 @@ class Sprinkle {
805
712
  }
806
713
  while (true) {
807
714
  // Display transaction status
808
- const txHash = this.getTxBodyHash(currentTx);
809
- const sigCount = this.countSignatures(currentTx);
810
- const requiredSigners = this.getRequiredSigners(currentTx);
715
+ const txHash = (0, _txDialog.getTxBodyHash)(currentTx);
716
+ const sigCount = (0, _txDialog.countSignatures)(currentTx);
717
+ const requiredSigners = (0, _txDialog.getRequiredSigners)(currentTx);
811
718
  console.log("");
812
- console.log(`Transaction: ${this.formatHash(txHash)}`);
719
+ console.log(`Transaction: ${(0, _txDialog.formatHash)(txHash)}`);
813
720
  if (requiredSigners.length > 0) {
814
721
  console.log(`Signatures: ${sigCount} of ${requiredSigners.length} required`);
815
722
  console.log("Required signers:");
816
723
  for (const signer of requiredSigners) {
817
- console.log(` - ${this.formatHash(signer)}`);
724
+ console.log(` - ${(0, _txDialog.formatHash)(signer)}`);
818
725
  }
819
726
  } else {
820
727
  console.log(`Signatures: ${sigCount}`);
@@ -864,11 +771,25 @@ class Sprinkle {
864
771
  name: "Cancel",
865
772
  value: "cancel"
866
773
  });
867
- const selection = await (0, _prompts.select)({
774
+ const selection = await (0, _prompts.selectCancellable)({
868
775
  message: "Select an option:",
869
776
  choices
870
777
  });
871
778
 
779
+ // Handle escape/cancel as cancel action
780
+ if (selection === null) {
781
+ if (hasSignedThisSession) {
782
+ return {
783
+ action: "signed",
784
+ tx: currentTx
785
+ };
786
+ }
787
+ return {
788
+ action: "cancelled",
789
+ tx: currentTx
790
+ };
791
+ }
792
+
872
793
  // Handle selection
873
794
  if (selection === "sign") {
874
795
  if (opts?.beforeSign) {
@@ -934,7 +855,7 @@ class Sprinkle {
934
855
  } else {
935
856
  const signedTx = await blaze.signTransaction(currentTx);
936
857
  // Merge signatures from signed tx into current tx
937
- const added = this.mergeSignatures(currentTx, signedTx);
858
+ const added = (0, _txDialog.mergeSignatures)(currentTx, signedTx);
938
859
  if (added > 0) {
939
860
  console.log(`Added ${added} signature(s).`);
940
861
  hasSignedThisSession = true;
@@ -966,10 +887,10 @@ class Sprinkle {
966
887
  continue;
967
888
  }
968
889
  if (selection === "import") {
969
- const cborInput = await (0, _prompts.input)({
890
+ const cborInput = await (0, _prompts.inputCancellable)({
970
891
  message: "Paste transaction CBOR (hex):"
971
892
  });
972
- if (!cborInput || cborInput.trim() === "") {
893
+ if (cborInput === null || cborInput.trim() === "") {
973
894
  console.log("No CBOR provided.");
974
895
  continue;
975
896
  }
@@ -977,21 +898,21 @@ class Sprinkle {
977
898
  const importedTx = _sdk.Core.Transaction.fromCbor((0, _core.TxCBOR)(cborInput.trim()));
978
899
 
979
900
  // Validate body hash matches
980
- const currentHash = this.getTxBodyHash(currentTx);
981
- const importedHash = this.getTxBodyHash(importedTx);
901
+ const currentHash = (0, _txDialog.getTxBodyHash)(currentTx);
902
+ const importedHash = (0, _txDialog.getTxBodyHash)(importedTx);
982
903
  if (currentHash !== importedHash) {
983
- const proceed = await (0, _prompts.confirm)({
984
- message: `Warning: Imported transaction has different body hash.\nCurrent: ${this.formatHash(currentHash)}\nImported: ${this.formatHash(importedHash)}\nProceed anyway?`,
904
+ const proceed = await (0, _prompts.confirmCancellable)({
905
+ message: `Warning: Imported transaction has different body hash.\nCurrent: ${(0, _txDialog.formatHash)(currentHash)}\nImported: ${(0, _txDialog.formatHash)(importedHash)}\nProceed anyway?`,
985
906
  default: false
986
907
  });
987
- if (!proceed) {
908
+ if (proceed === null || !proceed) {
988
909
  console.log("Import cancelled.");
989
910
  continue;
990
911
  }
991
912
  }
992
913
 
993
914
  // Merge signatures
994
- const added = this.mergeSignatures(currentTx, importedTx);
915
+ const added = (0, _txDialog.mergeSignatures)(currentTx, importedTx);
995
916
  const sourceVkeys = importedTx.witnessSet().vkeys();
996
917
  const sourceCount = sourceVkeys ? sourceVkeys.size() : 0;
997
918
  const skipped = sourceCount - added;
@@ -1010,13 +931,13 @@ class Sprinkle {
1010
931
  continue;
1011
932
  }
1012
933
  if (selection === "submit") {
1013
- const sigCount = this.countSignatures(currentTx);
934
+ const sigCount = (0, _txDialog.countSignatures)(currentTx);
1014
935
  if (sigCount === 0) {
1015
- const proceed = await (0, _prompts.confirm)({
936
+ const proceed = await (0, _prompts.confirmCancellable)({
1016
937
  message: "Warning: Transaction has no signatures. Submit anyway?",
1017
938
  default: false
1018
939
  });
1019
- if (!proceed) {
940
+ if (proceed === null || !proceed) {
1020
941
  continue;
1021
942
  }
1022
943
  }
@@ -1052,7 +973,7 @@ class Sprinkle {
1052
973
  return this._editStruct(type, ["root"], current);
1053
974
  }
1054
975
  async _editStruct(type, path, current) {
1055
- if (isObject(type)) {
976
+ if ((0, _typeGuards.isObject)(type)) {
1056
977
  const obj = {};
1057
978
  const fields = type["properties"];
1058
979
  const menuItems = [];
@@ -1062,7 +983,7 @@ class Sprinkle {
1062
983
  obj[field] = currentRecord[field];
1063
984
  }
1064
985
  const menuTitle = Sprinkle.ExtractMessage(fieldType, `Edit ${field} at ${path.join(".")}`);
1065
- if (isOptional(fieldType) && current && currentRecord[field] !== undefined) {
986
+ if ((0, _typeGuards.isOptional)(fieldType) && current && currentRecord[field] !== undefined) {
1066
987
  menuItems.push({
1067
988
  title: `Clear ${field}`,
1068
989
  action: async sprinkle => {
@@ -1104,8 +1025,8 @@ class Sprinkle {
1104
1025
  }
1105
1026
  return this._fillInStruct(resolvedType, path, defs, def);
1106
1027
  }
1107
- if (isOptional(type)) {
1108
- const shouldSet = await (0, _prompts.select)({
1028
+ if ((0, _typeGuards.isOptional)(type)) {
1029
+ const shouldSet = await (0, _prompts.selectCancellable)({
1109
1030
  message: Sprinkle.ExtractMessage(type, `Set value for ${path.join(".")}?`),
1110
1031
  choices: [{
1111
1032
  name: "Yes",
@@ -1116,6 +1037,9 @@ class Sprinkle {
1116
1037
  }],
1117
1038
  default: def !== undefined
1118
1039
  });
1040
+ if (shouldSet === null) {
1041
+ throw new _types.UserCancelledError();
1042
+ }
1119
1043
  if (!shouldSet) {
1120
1044
  return undefined;
1121
1045
  }
@@ -1126,7 +1050,7 @@ class Sprinkle {
1126
1050
  delete innerType[_typebox.OptionalKind];
1127
1051
  return this._fillInStruct(innerType, path, defs, def);
1128
1052
  }
1129
- if (isUnion(type)) {
1053
+ if ((0, _typeGuards.isUnion)(type)) {
1130
1054
  const choices = [];
1131
1055
  const resolved = this.resolveType(type, path, defs);
1132
1056
  for (const variant of resolved.anyOf) {
@@ -1135,17 +1059,21 @@ class Sprinkle {
1135
1059
  value: variant
1136
1060
  });
1137
1061
  }
1138
- const selection = await (0, _prompts.select)({
1062
+ const selectionResult = await (0, _prompts.selectCancellable)({
1139
1063
  message: Sprinkle.ExtractMessage(resolved, `Enter a choice for ${path.join(".")}`),
1140
1064
  choices: choices,
1141
1065
  default: def ? `${def}` : undefined
1142
1066
  });
1067
+ if (selectionResult === null) {
1068
+ throw new _types.UserCancelledError();
1069
+ }
1070
+ const selection = selectionResult;
1143
1071
  return this._fillInStruct(selection, path, defs);
1144
1072
  }
1145
- if (isString(type)) {
1073
+ if ((0, _typeGuards.isString)(type)) {
1146
1074
  // Special handling for hot wallet private key - offer generation option
1147
1075
  if (type.title === "Hot Wallet Private Key") {
1148
- const choice = await (0, _prompts.select)({
1076
+ const choice = await (0, _prompts.selectCancellable)({
1149
1077
  message: "Hot wallet setup:",
1150
1078
  choices: [{
1151
1079
  name: "Enter existing private key",
@@ -1155,33 +1083,44 @@ class Sprinkle {
1155
1083
  value: "generate"
1156
1084
  }]
1157
1085
  });
1086
+ if (choice === null) {
1087
+ throw new _types.UserCancelledError();
1088
+ }
1158
1089
  if (choice === "generate") {
1159
1090
  return Sprinkle.generateWalletFromMnemonic();
1160
1091
  }
1161
1092
  // Fall through to password prompt for "existing" choice
1162
- const answer = await (0, _prompts.password)({
1093
+ const answer = await (0, _prompts.passwordCancellable)({
1163
1094
  message: "Enter your private key:"
1164
1095
  });
1096
+ if (answer === null) {
1097
+ throw new _types.UserCancelledError();
1098
+ }
1165
1099
  return answer;
1166
1100
  }
1167
1101
  const defaultString = def ? def : this.defaults["string"];
1168
1102
  const message = Sprinkle.ExtractMessage(type, `Enter a string for ${path.join(".")}`);
1169
1103
  let answer;
1170
- if (isSensitive(type)) {
1171
- answer = await (0, _prompts.password)({
1104
+ if ((0, _typeGuards.isSensitive)(type)) {
1105
+ answer = await (0, _prompts.passwordCancellable)({
1172
1106
  message
1173
1107
  });
1174
1108
  } else {
1175
- answer = await (0, _prompts.input)({
1109
+ answer = await (0, _prompts.inputCancellable)({
1176
1110
  message,
1177
1111
  default: defaultString
1178
1112
  });
1179
- this.defaults["string"] = answer;
1113
+ if (answer !== null) {
1114
+ this.defaults["string"] = answer;
1115
+ }
1116
+ }
1117
+ if (answer === null) {
1118
+ throw new _types.UserCancelledError();
1180
1119
  }
1181
1120
  return answer;
1182
1121
  }
1183
- if (isBigInt(type)) {
1184
- const answer = await (0, _prompts.input)({
1122
+ if ((0, _typeGuards.isBigInt)(type)) {
1123
+ const answer = await (0, _prompts.inputCancellable)({
1185
1124
  message: Sprinkle.ExtractMessage(type, `Enter a bigint for ${path.join(".")}`),
1186
1125
  default: def ? def.toString() : undefined,
1187
1126
  validate: s => {
@@ -1193,12 +1132,15 @@ class Sprinkle {
1193
1132
  }
1194
1133
  }
1195
1134
  });
1135
+ if (answer === null) {
1136
+ throw new _types.UserCancelledError();
1137
+ }
1196
1138
  return BigInt(answer);
1197
1139
  }
1198
- if (isLiteral(type)) {
1140
+ if ((0, _typeGuards.isLiteral)(type)) {
1199
1141
  return type.const;
1200
1142
  }
1201
- if (isObject(type)) {
1143
+ if ((0, _typeGuards.isObject)(type)) {
1202
1144
  const obj = {};
1203
1145
  const fields = type["properties"];
1204
1146
  for (const [field, fieldType] of Object.entries(fields)) {
@@ -1209,14 +1151,14 @@ class Sprinkle {
1209
1151
  }
1210
1152
 
1211
1153
  //TODO: support starting with default values for arrays and allow removal of items
1212
- if (isArray(type)) {
1154
+ if ((0, _typeGuards.isArray)(type)) {
1213
1155
  const arr = [];
1214
1156
  const itemType = type.items;
1215
1157
  let addMore = true;
1216
1158
  while (addMore) {
1217
1159
  const itemValue = await this._fillInStruct(itemType, path.concat([`[${arr.length}]`]), defs);
1218
1160
  arr.push(itemValue);
1219
- const continueAnswer = await (0, _prompts.select)({
1161
+ const continueAnswer = await (0, _prompts.selectCancellable)({
1220
1162
  message: `Add another item to ${path.join(".")}?`,
1221
1163
  choices: [{
1222
1164
  name: "Yes",
@@ -1226,11 +1168,14 @@ class Sprinkle {
1226
1168
  value: false
1227
1169
  }]
1228
1170
  });
1171
+ if (continueAnswer === null) {
1172
+ throw new _types.UserCancelledError();
1173
+ }
1229
1174
  addMore = continueAnswer;
1230
1175
  }
1231
1176
  return arr;
1232
1177
  }
1233
- if (isTuple(type)) {
1178
+ if ((0, _typeGuards.isTuple)(type)) {
1234
1179
  const items = type.items ?? [];
1235
1180
  const result = [];
1236
1181
  for (let i = 0; i < items.length; i++) {
@@ -1243,7 +1188,7 @@ class Sprinkle {
1243
1188
  throw new Error(`Unable to fill in struct for type at path ${path.join(".")}`);
1244
1189
  }
1245
1190
  resolveType(type, path, defs) {
1246
- if (isRef(type) || isThis(type) || isImport(type)) {
1191
+ if ((0, _typeGuards.isRef)(type) || (0, _typeGuards.isThis)(type) || (0, _typeGuards.isImport)(type)) {
1247
1192
  defs = {
1248
1193
  ...defs,
1249
1194
  ...type.$defs
@@ -1263,10 +1208,10 @@ class Sprinkle {
1263
1208
  if ("description" in type) {
1264
1209
  return type.description;
1265
1210
  }
1266
- if (isLiteral(type)) {
1211
+ if ((0, _typeGuards.isLiteral)(type)) {
1267
1212
  return `${type.const}`;
1268
1213
  }
1269
- if (isObject(type)) {
1214
+ if ((0, _typeGuards.isObject)(type)) {
1270
1215
  const fields = type["properties"];
1271
1216
  if ("type" in fields) {
1272
1217
  return Sprinkle.ExtractMessage(fields["type"], def);