@sundaeswap/sprinkles 0.3.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 (88) 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__/settings-persistence.test.js +120 -0
  8. package/dist/cjs/Sprinkle/__tests__/settings-persistence.test.js.map +1 -1
  9. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js +93 -7
  10. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  11. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js +21 -0
  12. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  13. package/dist/cjs/Sprinkle/encryption.js +131 -0
  14. package/dist/cjs/Sprinkle/encryption.js.map +1 -0
  15. package/dist/cjs/Sprinkle/index.js +318 -352
  16. package/dist/cjs/Sprinkle/index.js.map +1 -1
  17. package/dist/cjs/Sprinkle/prompts.js +393 -0
  18. package/dist/cjs/Sprinkle/prompts.js.map +1 -0
  19. package/dist/cjs/Sprinkle/schemas.js +97 -0
  20. package/dist/cjs/Sprinkle/schemas.js.map +1 -0
  21. package/dist/cjs/Sprinkle/tx-dialog.js +101 -0
  22. package/dist/cjs/Sprinkle/tx-dialog.js.map +1 -0
  23. package/dist/cjs/Sprinkle/type-guards.js +42 -0
  24. package/dist/cjs/Sprinkle/type-guards.js.map +1 -0
  25. package/dist/cjs/Sprinkle/types.js +49 -0
  26. package/dist/cjs/Sprinkle/types.js.map +1 -0
  27. package/dist/cjs/Sprinkle/wallet.js +98 -0
  28. package/dist/cjs/Sprinkle/wallet.js.map +1 -0
  29. package/dist/esm/Sprinkle/__tests__/encryption.test.js +20 -8
  30. package/dist/esm/Sprinkle/__tests__/encryption.test.js.map +1 -1
  31. package/dist/esm/Sprinkle/__tests__/enhancements.test.js +41 -16
  32. package/dist/esm/Sprinkle/__tests__/enhancements.test.js.map +1 -1
  33. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +85 -38
  34. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  35. package/dist/esm/Sprinkle/__tests__/settings-persistence.test.js +120 -0
  36. package/dist/esm/Sprinkle/__tests__/settings-persistence.test.js.map +1 -1
  37. package/dist/esm/Sprinkle/__tests__/show-menu.test.js +94 -8
  38. package/dist/esm/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  39. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js +21 -0
  40. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  41. package/dist/esm/Sprinkle/encryption.js +117 -0
  42. package/dist/esm/Sprinkle/encryption.js.map +1 -0
  43. package/dist/esm/Sprinkle/index.js +172 -337
  44. package/dist/esm/Sprinkle/index.js.map +1 -1
  45. package/dist/esm/Sprinkle/prompts.js +385 -0
  46. package/dist/esm/Sprinkle/prompts.js.map +1 -0
  47. package/dist/esm/Sprinkle/schemas.js +91 -0
  48. package/dist/esm/Sprinkle/schemas.js.map +1 -0
  49. package/dist/esm/Sprinkle/tx-dialog.js +90 -0
  50. package/dist/esm/Sprinkle/tx-dialog.js.map +1 -0
  51. package/dist/esm/Sprinkle/type-guards.js +24 -0
  52. package/dist/esm/Sprinkle/type-guards.js.map +1 -0
  53. package/dist/esm/Sprinkle/types.js +42 -0
  54. package/dist/esm/Sprinkle/types.js.map +1 -0
  55. package/dist/esm/Sprinkle/wallet.js +90 -0
  56. package/dist/esm/Sprinkle/wallet.js.map +1 -0
  57. package/dist/types/Sprinkle/encryption.d.ts +43 -0
  58. package/dist/types/Sprinkle/encryption.d.ts.map +1 -0
  59. package/dist/types/Sprinkle/index.d.ts +13 -174
  60. package/dist/types/Sprinkle/index.d.ts.map +1 -1
  61. package/dist/types/Sprinkle/prompts.d.ts +94 -0
  62. package/dist/types/Sprinkle/prompts.d.ts.map +1 -0
  63. package/dist/types/Sprinkle/schemas.d.ts +125 -0
  64. package/dist/types/Sprinkle/schemas.d.ts.map +1 -0
  65. package/dist/types/Sprinkle/tx-dialog.d.ts +37 -0
  66. package/dist/types/Sprinkle/tx-dialog.d.ts.map +1 -0
  67. package/dist/types/Sprinkle/type-guards.d.ts +22 -0
  68. package/dist/types/Sprinkle/type-guards.d.ts.map +1 -0
  69. package/dist/types/Sprinkle/types.d.ts +62 -0
  70. package/dist/types/Sprinkle/types.d.ts.map +1 -0
  71. package/dist/types/Sprinkle/wallet.d.ts +27 -0
  72. package/dist/types/Sprinkle/wallet.d.ts.map +1 -0
  73. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  74. package/package.json +1 -1
  75. package/src/Sprinkle/__tests__/encryption.test.ts +21 -8
  76. package/src/Sprinkle/__tests__/enhancements.test.ts +41 -15
  77. package/src/Sprinkle/__tests__/fill-in-struct.test.ts +104 -38
  78. package/src/Sprinkle/__tests__/settings-persistence.test.ts +108 -0
  79. package/src/Sprinkle/__tests__/show-menu.test.ts +96 -8
  80. package/src/Sprinkle/__tests__/tx-dialog.test.ts +21 -0
  81. package/src/Sprinkle/encryption.ts +130 -0
  82. package/src/Sprinkle/index.ts +265 -478
  83. package/src/Sprinkle/prompts.ts +481 -0
  84. package/src/Sprinkle/schemas.ts +111 -0
  85. package/src/Sprinkle/tx-dialog.ts +100 -0
  86. package/src/Sprinkle/type-guards.ts +51 -0
  87. package/src/Sprinkle/types.ts +73 -0
  88. 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);
@@ -144,6 +205,16 @@ class Sprinkle {
144
205
  this.options = options ?? {};
145
206
  }
146
207
 
208
+ // --- Current Profile Accessor ---
209
+
210
+ get currentProfile() {
211
+ if (!this.profileId) return null;
212
+ return {
213
+ id: this.profileId,
214
+ ...this.profileMeta
215
+ };
216
+ }
217
+
147
218
  // --- Profile path helpers ---
148
219
 
149
220
  static sanitizeProfileId(name) {
@@ -222,32 +293,42 @@ class Sprinkle {
222
293
  meta: this.profileMeta,
223
294
  settings: settingsToSave,
224
295
  defaults: this.defaults
225
- }, Sprinkle.bigIntReplacer, 2);
296
+ }, _encryption.bigIntReplacer, 2);
226
297
  fs.writeFileSync(filePath, jsonContent, "utf-8");
227
298
  }
228
299
  async promptProfileMeta(defaultName, defaultDescription) {
229
- const name = await (0, _prompts.input)({
300
+ const name = await (0, _prompts.inputCancellable)({
230
301
  message: "Profile name:",
231
302
  default: defaultName,
232
303
  validate: v => v.trim().length > 0 ? true : "Name cannot be empty"
233
304
  });
234
- const description = await (0, _prompts.input)({
305
+ if (name === null) return null; // User cancelled
306
+ const description = await (0, _prompts.inputCancellable)({
235
307
  message: "Profile description (optional):",
236
308
  default: defaultDescription ?? ""
237
309
  });
310
+ if (description === null) return null; // User cancelled
238
311
  return {
239
312
  name,
240
313
  description: description || undefined
241
314
  };
242
315
  }
243
316
  async createProfile() {
317
+ const result = await this.promptProfileMeta();
318
+ if (result === null) return; // User cancelled
244
319
  const {
245
320
  name,
246
321
  description
247
- } = await this.promptProfileMeta();
322
+ } = result;
248
323
  const profilesDir = Sprinkle.profilesDir(this.storagePath);
249
324
  const id = Sprinkle.findAvailableId(profilesDir, Sprinkle.sanitizeProfileId(name));
250
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;
251
332
  this.profileId = id;
252
333
  this.profileMeta = {
253
334
  name,
@@ -256,7 +337,19 @@ class Sprinkle {
256
337
  updatedAt: now
257
338
  };
258
339
  this.defaults = {};
259
- 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
+ }
260
353
  this.saveProfile();
261
354
  fs.writeFileSync(Sprinkle.activeProfilePath(this.storagePath), id, "utf-8");
262
355
  }
@@ -281,7 +374,7 @@ class Sprinkle {
281
374
  fs.mkdirSync(profilesDir, {
282
375
  recursive: true
283
376
  });
284
- 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");
285
378
  fs.writeFileSync(Sprinkle.activeProfilePath(this.storagePath), "default", "utf-8");
286
379
  // Backup legacy file
287
380
  fs.renameSync(legacyPath, `${legacyPath}.bak`);
@@ -318,23 +411,26 @@ class Sprinkle {
318
411
  }
319
412
  async selectProfile(profiles) {
320
413
  const available = profiles ?? this.scanProfiles();
321
- const selection = await (0, _prompts.select)({
414
+ const selection = await (0, _prompts.selectCancellable)({
322
415
  message: "Select a profile:",
323
416
  choices: available.map(p => ({
324
417
  name: p.meta.description ? `${p.meta.name} - ${p.meta.description}` : p.meta.name,
325
418
  value: p.id
326
419
  }))
327
420
  });
421
+ if (selection === null) return; // User cancelled
328
422
  await this.loadProfile(selection);
329
423
  }
330
424
 
331
425
  // --- Profile management (CRUD) ---
332
426
 
333
427
  async duplicateProfile() {
428
+ const result = await this.promptProfileMeta(`${this.profileMeta.name} (copy)`, this.profileMeta.description);
429
+ if (result === null) return; // User cancelled
334
430
  const {
335
431
  name,
336
432
  description
337
- } = await this.promptProfileMeta(`${this.profileMeta.name} (copy)`, this.profileMeta.description);
433
+ } = result;
338
434
  const profilesDir = Sprinkle.profilesDir(this.storagePath);
339
435
  const id = Sprinkle.findAvailableId(profilesDir, Sprinkle.sanitizeProfileId(name));
340
436
  const now = new Date().toISOString();
@@ -349,15 +445,17 @@ class Sprinkle {
349
445
  },
350
446
  settings: settingsToSave,
351
447
  defaults: this.defaults
352
- }, Sprinkle.bigIntReplacer, 2);
448
+ }, _encryption.bigIntReplacer, 2);
353
449
  fs.writeFileSync(path.join(profilesDir, `${id}.json`), jsonContent, "utf-8");
354
450
  console.log(`Profile "${name}" created as a copy.`);
355
451
  }
356
452
  async renameProfile() {
453
+ const result = await this.promptProfileMeta(this.profileMeta.name, this.profileMeta.description);
454
+ if (result === null) return; // User cancelled
357
455
  const {
358
456
  name,
359
457
  description
360
- } = await this.promptProfileMeta(this.profileMeta.name, this.profileMeta.description);
458
+ } = result;
361
459
  const newId = Sprinkle.sanitizeProfileId(name);
362
460
  const oldId = this.profileId;
363
461
  this.profileMeta.name = name;
@@ -385,25 +483,26 @@ class Sprinkle {
385
483
  console.log("Cannot delete the only profile.");
386
484
  return;
387
485
  }
388
- const toDelete = await (0, _prompts.select)({
486
+ const toDelete = await (0, _prompts.selectCancellable)({
389
487
  message: "Select a profile to delete:",
390
- choices: [...others.map(p => ({
488
+ choices: others.map(p => ({
391
489
  name: p.meta.description ? `${p.meta.name} - ${p.meta.description}` : p.meta.name,
392
490
  value: p.id
393
- })), {
394
- name: "Cancel",
395
- value: "__cancel__"
396
- }]
491
+ }))
397
492
  });
398
- if (toDelete === "__cancel__") return;
399
- const profileToDelete = others.find(p => p.id === toDelete);
400
- const confirmed = await (0, _prompts.confirm)({
401
- 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.`,
402
499
  default: false
403
500
  });
501
+ if (confirmed === null) return; // User cancelled
502
+
404
503
  if (confirmed) {
405
- fs.unlinkSync(Sprinkle.profilePath(this.storagePath, toDelete));
406
- 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.`);
407
506
  }
408
507
  }
409
508
 
@@ -444,14 +543,24 @@ class Sprinkle {
444
543
  value: -1
445
544
  });
446
545
  }
447
- const selection = await (0, _prompts.select)({
546
+ const selectionResult = await (0, _prompts.selectCancellable)({
448
547
  message: "Select an option:",
449
548
  choices: choices
450
549
  });
550
+ // Handle escape (null) as Back
551
+ if (selectionResult === null) {
552
+ return;
553
+ }
554
+ const selection = selectionResult;
451
555
  if (selection === -5) {
452
556
  const settingsMenu = {
453
557
  title: "Settings & Profiles",
454
558
  items: [{
559
+ title: "View settings",
560
+ action: async () => {
561
+ console.log(JSON.stringify(this.getDisplaySettings(), _encryption.bigIntReplacer, 2));
562
+ }
563
+ }, {
455
564
  title: "Edit settings",
456
565
  action: async () => {
457
566
  this.settings = await this.EditStruct(this.type, this.settings);
@@ -519,40 +628,13 @@ class Sprinkle {
519
628
  return sprinkle;
520
629
  }
521
630
  static async GetProvider(network, settings) {
522
- switch (settings.type) {
523
- case "blockfrost":
524
- return new _query.Blockfrost({
525
- network: `cardano-${network}`,
526
- projectId: settings.projectId
527
- });
528
- case "maestro":
529
- // Dynamic import - Maestro may or may not be exported depending on @blaze-cardano/query version
530
- const queryModule = await Promise.resolve().then(() => _interopRequireWildcard(require("@blaze-cardano/query")));
531
- if (!queryModule.Maestro) {
532
- throw new Error("Maestro is not available in the installed version of @blaze-cardano/query. Please install a version that includes Maestro support.");
533
- }
534
- return new queryModule.Maestro({
535
- network: network,
536
- apiKey: settings.apiKey
537
- });
538
- default:
539
- throw new Error("Invalid provider type");
540
- }
631
+ return (0, _wallet.GetProvider)(network, settings);
541
632
  }
542
633
  static async GetWallet(settings, provider) {
543
- switch (settings.type) {
544
- case "hot":
545
- return _sdk.HotWallet.fromMasterkey(_sdk.Core.Bip32PrivateKeyHex(settings.privateKey), provider, provider.network);
546
- case "cold":
547
- return new _sdk.ColdWallet(_sdk.Core.Address.fromBech32(settings.address), provider.network, provider);
548
- default:
549
- throw new Error("Invalid wallet type");
550
- }
634
+ return (0, _wallet.GetWallet)(settings, provider);
551
635
  }
552
636
  static async GetBlaze(network, providerSettings, walletSettings) {
553
- const provider = await Sprinkle.GetProvider(network, providerSettings);
554
- const wallet = await Sprinkle.GetWallet(walletSettings, provider);
555
- return _sdk.Blaze.from(provider, wallet);
637
+ return (0, _wallet.GetBlaze)(network, providerSettings, walletSettings);
556
638
  }
557
639
 
558
640
  /**
@@ -561,30 +643,10 @@ class Sprinkle {
561
643
  * @returns The Bip32PrivateKey hex string for storage
562
644
  */
563
645
  static async generateWalletFromMnemonic() {
564
- const mnemonic = _sdk.Core.generateMnemonic(_core.wordlist, 256); // 24 words
565
- const words = mnemonic.split(" ");
566
- console.log("\n=== NEW WALLET GENERATED ===\n");
567
- console.log("IMPORTANT: Save these 24 words in a secure location.");
568
- console.log("This is the ONLY way to recover your wallet.\n");
569
-
570
- // Display in 4 columns
571
- for (let i = 0; i < 6; i++) {
572
- 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]}`);
573
- }
574
- console.log("");
575
- const confirmed = await (0, _prompts.confirm)({
576
- message: "Have you saved your recovery phrase?",
577
- default: false
578
- });
579
- if (!confirmed) {
580
- throw new Error("Wallet generation cancelled - recovery phrase not saved");
581
- }
582
- const entropy = _sdk.Core.mnemonicToEntropy(mnemonic, _core.wordlist);
583
- const masterKey = _sdk.Core.Bip32PrivateKey.fromBip39Entropy(Buffer.from(entropy), "");
584
- return masterKey.hex();
646
+ return (0, _wallet.generateWalletFromMnemonic)();
585
647
  }
586
648
  static async SearchSelect(opts) {
587
- return (0, _prompts.search)(opts);
649
+ return (0, _prompts.searchCancellable)(opts);
588
650
  }
589
651
  static SettingsPath(storagePath) {
590
652
  return `${storagePath}${path.sep}settings.json`;
@@ -608,155 +670,21 @@ class Sprinkle {
608
670
  }
609
671
  }
610
672
  static bigIntReviver(key, value) {
611
- if (typeof value === "string" && /^\d+n$/.test(value)) {
612
- return BigInt(value.slice(0, -1));
613
- }
614
- return value;
615
- }
616
- static bigIntReplacer(_key, value) {
617
- return typeof value === "bigint" ? `${value.toString()}n` : value;
618
- }
619
- static collectSensitivePaths(type, prefix = "") {
620
- const paths = [];
621
- if (isObject(type)) {
622
- const fields = type["properties"];
623
- for (const [field, fieldType] of Object.entries(fields)) {
624
- const fieldPath = prefix ? `${prefix}.${field}` : field;
625
- if (isSensitive(fieldType)) {
626
- paths.push(fieldPath);
627
- }
628
- paths.push(...Sprinkle.collectSensitivePaths(fieldType, fieldPath));
629
- }
630
- }
631
- if (isUnion(type)) {
632
- for (const variant of type.anyOf) {
633
- paths.push(...Sprinkle.collectSensitivePaths(variant, prefix));
634
- }
635
- }
636
- return paths;
637
- }
638
- static getNestedValue(obj, path) {
639
- return path.split(".").reduce((o, k) => o?.[k], obj);
640
- }
641
- static setNestedValue(obj, path, value) {
642
- const keys = path.split(".");
643
- const last = keys.pop();
644
- const parent = keys.reduce((o, k) => o?.[k], obj);
645
- if (parent && typeof parent === "object") {
646
- parent[last] = value;
647
- }
673
+ return (0, _encryption.bigIntReviver)(key, value);
648
674
  }
649
675
  encryptSettings(settings) {
650
676
  if (!this.options.encryption) return settings;
651
- const clone = JSON.parse(JSON.stringify(settings, Sprinkle.bigIntReplacer), Sprinkle.bigIntReviver);
652
- const sensitivePaths = Sprinkle.collectSensitivePaths(this.type);
653
- for (const p of sensitivePaths) {
654
- const value = Sprinkle.getNestedValue(clone, p);
655
- if (typeof value === "string" && value.length > 0) {
656
- Sprinkle.setNestedValue(clone, p, this.options.encryption.encrypt(value));
657
- }
658
- }
659
- return clone;
677
+ return (0, _encryption.encryptSensitiveFields)(settings, this.type, this.options.encryption);
660
678
  }
661
679
  async decryptSettings(settings) {
662
680
  if (!this.options.encryption) return settings;
663
- const clone = JSON.parse(JSON.stringify(settings, Sprinkle.bigIntReplacer), Sprinkle.bigIntReviver);
664
- const sensitivePaths = Sprinkle.collectSensitivePaths(this.type);
665
- for (const p of sensitivePaths) {
666
- const value = Sprinkle.getNestedValue(clone, p);
667
- if (typeof value === "string" && value.length > 0) {
668
- Sprinkle.setNestedValue(clone, p, await this.options.encryption.decrypt(value));
669
- }
670
- }
671
- return clone;
681
+ return (0, _encryption.decryptSensitiveFields)(settings, this.type, this.options.encryption);
672
682
  }
673
683
  saveSettings() {
674
684
  this.saveProfile();
675
685
  }
676
-
677
- // --- TxDialog Helpers ---
678
-
679
- /**
680
- * Get the payment key hash from a HotWallet's first address
681
- */
682
- async getWalletPaymentKeyHash(wallet) {
683
- try {
684
- const addresses = await wallet.getUsedAddresses();
685
- const address = addresses[0];
686
- if (!address) return null;
687
- const paymentCredential = address.asBase()?.getPaymentCredential();
688
- return paymentCredential?.hash?.toString() ?? null;
689
- } catch {
690
- return null;
691
- }
692
- }
693
-
694
- /**
695
- * Count the number of vkey signatures in a transaction's witness set
696
- */
697
- countSignatures(tx) {
698
- const vkeys = tx.witnessSet().vkeys();
699
- return vkeys ? vkeys.size() : 0;
700
- }
701
-
702
- /**
703
- * Check if a specific public key has already signed the transaction
704
- * Compares by vkey (public key bytes)
705
- */
706
- hasVkeySigned(tx, vkeyHex) {
707
- const vkeys = tx.witnessSet().vkeys();
708
- if (!vkeys) return false;
709
- const vkeyArray = vkeys.toCore();
710
- return vkeyArray.some(([vkey]) => vkey === vkeyHex);
711
- }
712
-
713
- /**
714
- * Get the list of required signer key hashes from the transaction body
715
- */
716
- getRequiredSigners(tx) {
717
- const requiredSigners = tx.body().requiredSigners();
718
- if (!requiredSigners) return [];
719
- return Array.from(requiredSigners.values()).map(s => s.toString());
720
- }
721
-
722
- /**
723
- * Compute the transaction body hash for display
724
- */
725
- getTxBodyHash(tx) {
726
- const bodyCbor = tx.body().toCbor();
727
- return (0, _core.blake2b_256)(bodyCbor);
728
- }
729
-
730
- /**
731
- * Format a hash for display: first 8 chars + ... + last 8 chars
732
- */
733
- formatHash(hash) {
734
- if (hash.length <= 20) return hash;
735
- return `${hash.slice(0, 8)}...${hash.slice(-8)}`;
736
- }
737
-
738
- /**
739
- * Merge signatures from source transaction into target transaction.
740
- * Prevents duplicate signatures by comparing vkey (public key).
741
- * Returns the count of newly added signatures.
742
- */
743
- mergeSignatures(target, source) {
744
- const targetWs = target.witnessSet();
745
- const sourceWs = source.witnessSet();
746
- const targetVkeys = targetWs.vkeys()?.toCore() ?? [];
747
- const sourceVkeys = sourceWs.vkeys()?.toCore() ?? [];
748
-
749
- // Find vkeys in source that aren't in target (by comparing public key)
750
- const existingPubKeys = new Set(targetVkeys.map(([vkey]) => vkey));
751
- const newVkeys = sourceVkeys.filter(([vkey]) => !existingPubKeys.has(vkey));
752
- if (newVkeys.length === 0) {
753
- return 0;
754
- }
755
-
756
- // Merge the new vkeys into target
757
- targetWs.setVkeys(_core.CborSet.fromCore([...targetVkeys, ...newVkeys], _core.VkeyWitness.fromCore));
758
- target.setWitnessSet(targetWs);
759
- return newVkeys.length;
686
+ getDisplaySettings() {
687
+ return (0, _encryption.maskSensitiveFields)(this.settings, this.type);
760
688
  }
761
689
  async TxDialog(blaze, tx, opts) {
762
690
  let currentTx = tx;
@@ -784,16 +712,16 @@ class Sprinkle {
784
712
  }
785
713
  while (true) {
786
714
  // Display transaction status
787
- const txHash = this.getTxBodyHash(currentTx);
788
- const sigCount = this.countSignatures(currentTx);
789
- 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);
790
718
  console.log("");
791
- console.log(`Transaction: ${this.formatHash(txHash)}`);
719
+ console.log(`Transaction: ${(0, _txDialog.formatHash)(txHash)}`);
792
720
  if (requiredSigners.length > 0) {
793
721
  console.log(`Signatures: ${sigCount} of ${requiredSigners.length} required`);
794
722
  console.log("Required signers:");
795
723
  for (const signer of requiredSigners) {
796
- console.log(` - ${this.formatHash(signer)}`);
724
+ console.log(` - ${(0, _txDialog.formatHash)(signer)}`);
797
725
  }
798
726
  } else {
799
727
  console.log(`Signatures: ${sigCount}`);
@@ -843,11 +771,25 @@ class Sprinkle {
843
771
  name: "Cancel",
844
772
  value: "cancel"
845
773
  });
846
- const selection = await (0, _prompts.select)({
774
+ const selection = await (0, _prompts.selectCancellable)({
847
775
  message: "Select an option:",
848
776
  choices
849
777
  });
850
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
+
851
793
  // Handle selection
852
794
  if (selection === "sign") {
853
795
  if (opts?.beforeSign) {
@@ -913,7 +855,7 @@ class Sprinkle {
913
855
  } else {
914
856
  const signedTx = await blaze.signTransaction(currentTx);
915
857
  // Merge signatures from signed tx into current tx
916
- const added = this.mergeSignatures(currentTx, signedTx);
858
+ const added = (0, _txDialog.mergeSignatures)(currentTx, signedTx);
917
859
  if (added > 0) {
918
860
  console.log(`Added ${added} signature(s).`);
919
861
  hasSignedThisSession = true;
@@ -945,10 +887,10 @@ class Sprinkle {
945
887
  continue;
946
888
  }
947
889
  if (selection === "import") {
948
- const cborInput = await (0, _prompts.input)({
890
+ const cborInput = await (0, _prompts.inputCancellable)({
949
891
  message: "Paste transaction CBOR (hex):"
950
892
  });
951
- if (!cborInput || cborInput.trim() === "") {
893
+ if (cborInput === null || cborInput.trim() === "") {
952
894
  console.log("No CBOR provided.");
953
895
  continue;
954
896
  }
@@ -956,21 +898,21 @@ class Sprinkle {
956
898
  const importedTx = _sdk.Core.Transaction.fromCbor((0, _core.TxCBOR)(cborInput.trim()));
957
899
 
958
900
  // Validate body hash matches
959
- const currentHash = this.getTxBodyHash(currentTx);
960
- const importedHash = this.getTxBodyHash(importedTx);
901
+ const currentHash = (0, _txDialog.getTxBodyHash)(currentTx);
902
+ const importedHash = (0, _txDialog.getTxBodyHash)(importedTx);
961
903
  if (currentHash !== importedHash) {
962
- const proceed = await (0, _prompts.confirm)({
963
- 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?`,
964
906
  default: false
965
907
  });
966
- if (!proceed) {
908
+ if (proceed === null || !proceed) {
967
909
  console.log("Import cancelled.");
968
910
  continue;
969
911
  }
970
912
  }
971
913
 
972
914
  // Merge signatures
973
- const added = this.mergeSignatures(currentTx, importedTx);
915
+ const added = (0, _txDialog.mergeSignatures)(currentTx, importedTx);
974
916
  const sourceVkeys = importedTx.witnessSet().vkeys();
975
917
  const sourceCount = sourceVkeys ? sourceVkeys.size() : 0;
976
918
  const skipped = sourceCount - added;
@@ -989,13 +931,13 @@ class Sprinkle {
989
931
  continue;
990
932
  }
991
933
  if (selection === "submit") {
992
- const sigCount = this.countSignatures(currentTx);
934
+ const sigCount = (0, _txDialog.countSignatures)(currentTx);
993
935
  if (sigCount === 0) {
994
- const proceed = await (0, _prompts.confirm)({
936
+ const proceed = await (0, _prompts.confirmCancellable)({
995
937
  message: "Warning: Transaction has no signatures. Submit anyway?",
996
938
  default: false
997
939
  });
998
- if (!proceed) {
940
+ if (proceed === null || !proceed) {
999
941
  continue;
1000
942
  }
1001
943
  }
@@ -1031,7 +973,7 @@ class Sprinkle {
1031
973
  return this._editStruct(type, ["root"], current);
1032
974
  }
1033
975
  async _editStruct(type, path, current) {
1034
- if (isObject(type)) {
976
+ if ((0, _typeGuards.isObject)(type)) {
1035
977
  const obj = {};
1036
978
  const fields = type["properties"];
1037
979
  const menuItems = [];
@@ -1041,7 +983,7 @@ class Sprinkle {
1041
983
  obj[field] = currentRecord[field];
1042
984
  }
1043
985
  const menuTitle = Sprinkle.ExtractMessage(fieldType, `Edit ${field} at ${path.join(".")}`);
1044
- if (isOptional(fieldType) && current && currentRecord[field] !== undefined) {
986
+ if ((0, _typeGuards.isOptional)(fieldType) && current && currentRecord[field] !== undefined) {
1045
987
  menuItems.push({
1046
988
  title: `Clear ${field}`,
1047
989
  action: async sprinkle => {
@@ -1083,8 +1025,8 @@ class Sprinkle {
1083
1025
  }
1084
1026
  return this._fillInStruct(resolvedType, path, defs, def);
1085
1027
  }
1086
- if (isOptional(type)) {
1087
- const shouldSet = await (0, _prompts.select)({
1028
+ if ((0, _typeGuards.isOptional)(type)) {
1029
+ const shouldSet = await (0, _prompts.selectCancellable)({
1088
1030
  message: Sprinkle.ExtractMessage(type, `Set value for ${path.join(".")}?`),
1089
1031
  choices: [{
1090
1032
  name: "Yes",
@@ -1095,6 +1037,9 @@ class Sprinkle {
1095
1037
  }],
1096
1038
  default: def !== undefined
1097
1039
  });
1040
+ if (shouldSet === null) {
1041
+ throw new _types.UserCancelledError();
1042
+ }
1098
1043
  if (!shouldSet) {
1099
1044
  return undefined;
1100
1045
  }
@@ -1105,7 +1050,7 @@ class Sprinkle {
1105
1050
  delete innerType[_typebox.OptionalKind];
1106
1051
  return this._fillInStruct(innerType, path, defs, def);
1107
1052
  }
1108
- if (isUnion(type)) {
1053
+ if ((0, _typeGuards.isUnion)(type)) {
1109
1054
  const choices = [];
1110
1055
  const resolved = this.resolveType(type, path, defs);
1111
1056
  for (const variant of resolved.anyOf) {
@@ -1114,17 +1059,21 @@ class Sprinkle {
1114
1059
  value: variant
1115
1060
  });
1116
1061
  }
1117
- const selection = await (0, _prompts.select)({
1062
+ const selectionResult = await (0, _prompts.selectCancellable)({
1118
1063
  message: Sprinkle.ExtractMessage(resolved, `Enter a choice for ${path.join(".")}`),
1119
1064
  choices: choices,
1120
1065
  default: def ? `${def}` : undefined
1121
1066
  });
1067
+ if (selectionResult === null) {
1068
+ throw new _types.UserCancelledError();
1069
+ }
1070
+ const selection = selectionResult;
1122
1071
  return this._fillInStruct(selection, path, defs);
1123
1072
  }
1124
- if (isString(type)) {
1073
+ if ((0, _typeGuards.isString)(type)) {
1125
1074
  // Special handling for hot wallet private key - offer generation option
1126
1075
  if (type.title === "Hot Wallet Private Key") {
1127
- const choice = await (0, _prompts.select)({
1076
+ const choice = await (0, _prompts.selectCancellable)({
1128
1077
  message: "Hot wallet setup:",
1129
1078
  choices: [{
1130
1079
  name: "Enter existing private key",
@@ -1134,33 +1083,44 @@ class Sprinkle {
1134
1083
  value: "generate"
1135
1084
  }]
1136
1085
  });
1086
+ if (choice === null) {
1087
+ throw new _types.UserCancelledError();
1088
+ }
1137
1089
  if (choice === "generate") {
1138
1090
  return Sprinkle.generateWalletFromMnemonic();
1139
1091
  }
1140
1092
  // Fall through to password prompt for "existing" choice
1141
- const answer = await (0, _prompts.password)({
1093
+ const answer = await (0, _prompts.passwordCancellable)({
1142
1094
  message: "Enter your private key:"
1143
1095
  });
1096
+ if (answer === null) {
1097
+ throw new _types.UserCancelledError();
1098
+ }
1144
1099
  return answer;
1145
1100
  }
1146
1101
  const defaultString = def ? def : this.defaults["string"];
1147
1102
  const message = Sprinkle.ExtractMessage(type, `Enter a string for ${path.join(".")}`);
1148
1103
  let answer;
1149
- if (isSensitive(type)) {
1150
- answer = await (0, _prompts.password)({
1104
+ if ((0, _typeGuards.isSensitive)(type)) {
1105
+ answer = await (0, _prompts.passwordCancellable)({
1151
1106
  message
1152
1107
  });
1153
1108
  } else {
1154
- answer = await (0, _prompts.input)({
1109
+ answer = await (0, _prompts.inputCancellable)({
1155
1110
  message,
1156
1111
  default: defaultString
1157
1112
  });
1158
- this.defaults["string"] = answer;
1113
+ if (answer !== null) {
1114
+ this.defaults["string"] = answer;
1115
+ }
1116
+ }
1117
+ if (answer === null) {
1118
+ throw new _types.UserCancelledError();
1159
1119
  }
1160
1120
  return answer;
1161
1121
  }
1162
- if (isBigInt(type)) {
1163
- const answer = await (0, _prompts.input)({
1122
+ if ((0, _typeGuards.isBigInt)(type)) {
1123
+ const answer = await (0, _prompts.inputCancellable)({
1164
1124
  message: Sprinkle.ExtractMessage(type, `Enter a bigint for ${path.join(".")}`),
1165
1125
  default: def ? def.toString() : undefined,
1166
1126
  validate: s => {
@@ -1172,12 +1132,15 @@ class Sprinkle {
1172
1132
  }
1173
1133
  }
1174
1134
  });
1135
+ if (answer === null) {
1136
+ throw new _types.UserCancelledError();
1137
+ }
1175
1138
  return BigInt(answer);
1176
1139
  }
1177
- if (isLiteral(type)) {
1140
+ if ((0, _typeGuards.isLiteral)(type)) {
1178
1141
  return type.const;
1179
1142
  }
1180
- if (isObject(type)) {
1143
+ if ((0, _typeGuards.isObject)(type)) {
1181
1144
  const obj = {};
1182
1145
  const fields = type["properties"];
1183
1146
  for (const [field, fieldType] of Object.entries(fields)) {
@@ -1188,14 +1151,14 @@ class Sprinkle {
1188
1151
  }
1189
1152
 
1190
1153
  //TODO: support starting with default values for arrays and allow removal of items
1191
- if (isArray(type)) {
1154
+ if ((0, _typeGuards.isArray)(type)) {
1192
1155
  const arr = [];
1193
1156
  const itemType = type.items;
1194
1157
  let addMore = true;
1195
1158
  while (addMore) {
1196
1159
  const itemValue = await this._fillInStruct(itemType, path.concat([`[${arr.length}]`]), defs);
1197
1160
  arr.push(itemValue);
1198
- const continueAnswer = await (0, _prompts.select)({
1161
+ const continueAnswer = await (0, _prompts.selectCancellable)({
1199
1162
  message: `Add another item to ${path.join(".")}?`,
1200
1163
  choices: [{
1201
1164
  name: "Yes",
@@ -1205,11 +1168,14 @@ class Sprinkle {
1205
1168
  value: false
1206
1169
  }]
1207
1170
  });
1171
+ if (continueAnswer === null) {
1172
+ throw new _types.UserCancelledError();
1173
+ }
1208
1174
  addMore = continueAnswer;
1209
1175
  }
1210
1176
  return arr;
1211
1177
  }
1212
- if (isTuple(type)) {
1178
+ if ((0, _typeGuards.isTuple)(type)) {
1213
1179
  const items = type.items ?? [];
1214
1180
  const result = [];
1215
1181
  for (let i = 0; i < items.length; i++) {
@@ -1222,7 +1188,7 @@ class Sprinkle {
1222
1188
  throw new Error(`Unable to fill in struct for type at path ${path.join(".")}`);
1223
1189
  }
1224
1190
  resolveType(type, path, defs) {
1225
- if (isRef(type) || isThis(type) || isImport(type)) {
1191
+ if ((0, _typeGuards.isRef)(type) || (0, _typeGuards.isThis)(type) || (0, _typeGuards.isImport)(type)) {
1226
1192
  defs = {
1227
1193
  ...defs,
1228
1194
  ...type.$defs
@@ -1242,10 +1208,10 @@ class Sprinkle {
1242
1208
  if ("description" in type) {
1243
1209
  return type.description;
1244
1210
  }
1245
- if (isLiteral(type)) {
1211
+ if ((0, _typeGuards.isLiteral)(type)) {
1246
1212
  return `${type.const}`;
1247
1213
  }
1248
- if (isObject(type)) {
1214
+ if ((0, _typeGuards.isObject)(type)) {
1249
1215
  const fields = type["properties"];
1250
1216
  if ("type" in fields) {
1251
1217
  return Sprinkle.ExtractMessage(fields["type"], def);