@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
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.countSignatures = countSignatures;
7
+ exports.formatHash = formatHash;
8
+ exports.getRequiredSigners = getRequiredSigners;
9
+ exports.getTxBodyHash = getTxBodyHash;
10
+ exports.getWalletPaymentKeyHash = getWalletPaymentKeyHash;
11
+ exports.hasVkeySigned = hasVkeySigned;
12
+ exports.mergeSignatures = mergeSignatures;
13
+ var _core = require("@blaze-cardano/core");
14
+ /**
15
+ * Transaction dialog helper utilities.
16
+ * Functions for working with transaction signatures and display.
17
+ */
18
+
19
+ /**
20
+ * Get the payment key hash from a HotWallet's first address.
21
+ */
22
+ async function getWalletPaymentKeyHash(wallet) {
23
+ try {
24
+ const addresses = await wallet.getUsedAddresses();
25
+ const address = addresses[0];
26
+ if (!address) return null;
27
+ const paymentCredential = address.asBase()?.getPaymentCredential();
28
+ return paymentCredential?.hash?.toString() ?? null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Count the number of vkey signatures in a transaction's witness set.
36
+ */
37
+ function countSignatures(tx) {
38
+ const vkeys = tx.witnessSet().vkeys();
39
+ return vkeys ? vkeys.size() : 0;
40
+ }
41
+
42
+ /**
43
+ * Check if a specific public key has already signed the transaction.
44
+ * Compares by vkey (public key bytes).
45
+ */
46
+ function hasVkeySigned(tx, vkeyHex) {
47
+ const vkeys = tx.witnessSet().vkeys();
48
+ if (!vkeys) return false;
49
+ const vkeyArray = vkeys.toCore();
50
+ return vkeyArray.some(([vkey]) => vkey === vkeyHex);
51
+ }
52
+
53
+ /**
54
+ * Get the list of required signer key hashes from the transaction body.
55
+ */
56
+ function getRequiredSigners(tx) {
57
+ const requiredSigners = tx.body().requiredSigners();
58
+ if (!requiredSigners) return [];
59
+ return Array.from(requiredSigners.values()).map(s => s.toString());
60
+ }
61
+
62
+ /**
63
+ * Compute the transaction body hash for display.
64
+ */
65
+ function getTxBodyHash(tx) {
66
+ const bodyCbor = tx.body().toCbor();
67
+ return (0, _core.blake2b_256)(bodyCbor);
68
+ }
69
+
70
+ /**
71
+ * Format a hash for display: first 8 chars + ... + last 8 chars.
72
+ */
73
+ function formatHash(hash) {
74
+ if (hash.length <= 20) return hash;
75
+ return `${hash.slice(0, 8)}...${hash.slice(-8)}`;
76
+ }
77
+
78
+ /**
79
+ * Merge signatures from source transaction into target transaction.
80
+ * Prevents duplicate signatures by comparing vkey (public key).
81
+ * Returns the count of newly added signatures.
82
+ */
83
+ function mergeSignatures(target, source) {
84
+ const targetWs = target.witnessSet();
85
+ const sourceWs = source.witnessSet();
86
+ const targetVkeys = targetWs.vkeys()?.toCore() ?? [];
87
+ const sourceVkeys = sourceWs.vkeys()?.toCore() ?? [];
88
+
89
+ // Find vkeys in source that aren't in target (by comparing public key)
90
+ const existingPubKeys = new Set(targetVkeys.map(([vkey]) => vkey));
91
+ const newVkeys = sourceVkeys.filter(([vkey]) => !existingPubKeys.has(vkey));
92
+ if (newVkeys.length === 0) {
93
+ return 0;
94
+ }
95
+
96
+ // Merge the new vkeys into target
97
+ targetWs.setVkeys(_core.CborSet.fromCore([...targetVkeys, ...newVkeys], _core.VkeyWitness.fromCore));
98
+ target.setWitnessSet(targetWs);
99
+ return newVkeys.length;
100
+ }
101
+ //# sourceMappingURL=tx-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-dialog.js","names":["_core","require","getWalletPaymentKeyHash","wallet","addresses","getUsedAddresses","address","paymentCredential","asBase","getPaymentCredential","hash","toString","countSignatures","tx","vkeys","witnessSet","size","hasVkeySigned","vkeyHex","vkeyArray","toCore","some","vkey","getRequiredSigners","requiredSigners","body","Array","from","values","map","s","getTxBodyHash","bodyCbor","toCbor","blake2b_256","formatHash","length","slice","mergeSignatures","target","source","targetWs","sourceWs","targetVkeys","sourceVkeys","existingPubKeys","Set","newVkeys","filter","has","setVkeys","CborSet","fromCore","VkeyWitness","setWitnessSet"],"sources":["../../../src/Sprinkle/tx-dialog.ts"],"sourcesContent":["/**\n * Transaction dialog helper utilities.\n * Functions for working with transaction signatures and display.\n */\n\nimport { Core, HotWallet } from \"@blaze-cardano/sdk\";\nimport { CborSet, VkeyWitness, blake2b_256 } from \"@blaze-cardano/core\";\n\n/**\n * Get the payment key hash from a HotWallet's first address.\n */\nexport async function getWalletPaymentKeyHash(\n wallet: HotWallet,\n): Promise<string | null> {\n try {\n const addresses = await wallet.getUsedAddresses();\n const address = addresses[0];\n if (!address) return null;\n const paymentCredential = address.asBase()?.getPaymentCredential();\n return paymentCredential?.hash?.toString() ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Count the number of vkey signatures in a transaction's witness set.\n */\nexport function countSignatures(tx: Core.Transaction): number {\n const vkeys = tx.witnessSet().vkeys();\n return vkeys ? vkeys.size() : 0;\n}\n\n/**\n * Check if a specific public key has already signed the transaction.\n * Compares by vkey (public key bytes).\n */\nexport function hasVkeySigned(tx: Core.Transaction, vkeyHex: string): boolean {\n const vkeys = tx.witnessSet().vkeys();\n if (!vkeys) return false;\n const vkeyArray = vkeys.toCore();\n return vkeyArray.some(([vkey]) => vkey === vkeyHex);\n}\n\n/**\n * Get the list of required signer key hashes from the transaction body.\n */\nexport function getRequiredSigners(tx: Core.Transaction): string[] {\n const requiredSigners = tx.body().requiredSigners();\n if (!requiredSigners) return [];\n return Array.from(requiredSigners.values()).map((s) => s.toString());\n}\n\n/**\n * Compute the transaction body hash for display.\n */\nexport function getTxBodyHash(tx: Core.Transaction): string {\n const bodyCbor = tx.body().toCbor();\n return blake2b_256(bodyCbor);\n}\n\n/**\n * Format a hash for display: first 8 chars + ... + last 8 chars.\n */\nexport function formatHash(hash: string): string {\n if (hash.length <= 20) return hash;\n return `${hash.slice(0, 8)}...${hash.slice(-8)}`;\n}\n\n/**\n * Merge signatures from source transaction into target transaction.\n * Prevents duplicate signatures by comparing vkey (public key).\n * Returns the count of newly added signatures.\n */\nexport function mergeSignatures(\n target: Core.Transaction,\n source: Core.Transaction,\n): number {\n const targetWs = target.witnessSet();\n const sourceWs = source.witnessSet();\n\n const targetVkeys = targetWs.vkeys()?.toCore() ?? [];\n const sourceVkeys = sourceWs.vkeys()?.toCore() ?? [];\n\n // Find vkeys in source that aren't in target (by comparing public key)\n const existingPubKeys = new Set(targetVkeys.map(([vkey]) => vkey));\n const newVkeys = sourceVkeys.filter(([vkey]) => !existingPubKeys.has(vkey));\n\n if (newVkeys.length === 0) {\n return 0;\n }\n\n // Merge the new vkeys into target\n targetWs.setVkeys(\n CborSet.fromCore([...targetVkeys, ...newVkeys], VkeyWitness.fromCore),\n );\n target.setWitnessSet(targetWs);\n\n return newVkeys.length;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isUnion = exports.isTuple = exports.isThis = exports.isString = exports.isSensitive = exports.isRef = exports.isOptional = exports.isObject = exports.isLiteral = exports.isImport = exports.isBigInt = exports.isArray = void 0;
7
+ var _typebox = require("@sinclair/typebox");
8
+ /**
9
+ * Type guard utilities for TypeBox schema types.
10
+ * These are internal helpers used by FillInStruct, encryption, and other modules.
11
+ */
12
+
13
+ const isOptional = t => t[_typebox.OptionalKind] === "Optional";
14
+ exports.isOptional = isOptional;
15
+ const isImport = t => t[_typebox.Kind] === "Import";
16
+ exports.isImport = isImport;
17
+ const isArray = t => t[_typebox.Kind] === "Array";
18
+ exports.isArray = isArray;
19
+ const isBigInt = t => t[_typebox.Kind] === "BigInt";
20
+ exports.isBigInt = isBigInt;
21
+ const isLiteral = t => t[_typebox.Kind] === "Literal";
22
+ exports.isLiteral = isLiteral;
23
+ const isObject = t => t[_typebox.Kind] === "Object";
24
+ exports.isObject = isObject;
25
+ const isRef = t => t[_typebox.Kind] === "Ref";
26
+ exports.isRef = isRef;
27
+ const isString = t => t[_typebox.Kind] === "String";
28
+ exports.isString = isString;
29
+ const isThis = t => t[_typebox.Kind] === "This";
30
+ exports.isThis = isThis;
31
+ const isTuple = t => t[_typebox.Kind] === "Tuple";
32
+ exports.isTuple = isTuple;
33
+ const isUnion = t => t[_typebox.Kind] === "Union";
34
+
35
+ /**
36
+ * Check if a schema field is marked as sensitive.
37
+ * Sensitive fields are encrypted when saved and masked when displayed.
38
+ */
39
+ exports.isUnion = isUnion;
40
+ const isSensitive = t => isString(t) && t.sensitive === true;
41
+ exports.isSensitive = isSensitive;
42
+ //# sourceMappingURL=type-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.js","names":["_typebox","require","isOptional","t","OptionalKind","exports","isImport","Kind","isArray","isBigInt","isLiteral","isObject","isRef","isString","isThis","isTuple","isUnion","isSensitive","sensitive"],"sources":["../../../src/Sprinkle/type-guards.ts"],"sourcesContent":["/**\n * Type guard utilities for TypeBox schema types.\n * These are internal helpers used by FillInStruct, encryption, and other modules.\n */\n\nimport {\n Kind,\n type TBigInt,\n type TLiteral,\n type TObject,\n type TSchema,\n type TString,\n type TTuple,\n type TUnion,\n type TArray,\n type TThis,\n type TRef,\n type TImport,\n type TOptional,\n OptionalKind,\n} from \"@sinclair/typebox\";\n\nexport const isOptional = <T extends TSchema>(t: T): t is TOptional<T> =>\n t[OptionalKind] === \"Optional\";\n\nexport const isImport = (t: TSchema): t is TImport => t[Kind] === \"Import\";\n\nexport const isArray = (t: TSchema): t is TArray => t[Kind] === \"Array\";\n\nexport const isBigInt = (t: TSchema): t is TBigInt => t[Kind] === \"BigInt\";\n\nexport const isLiteral = (t: TSchema): t is TLiteral => t[Kind] === \"Literal\";\n\nexport const isObject = (t: TSchema): t is TObject => t[Kind] === \"Object\";\n\nexport const isRef = (t: TSchema): t is TRef => t[Kind] === \"Ref\";\n\nexport const isString = (t: TSchema): t is TString => t[Kind] === \"String\";\n\nexport const isThis = (t: TSchema): t is TThis => t[Kind] === \"This\";\n\nexport const isTuple = (t: TSchema): t is TTuple => t[Kind] === \"Tuple\";\n\nexport const isUnion = (t: TSchema): t is TUnion => t[Kind] === \"Union\";\n\n/**\n * Check if a schema field is marked as sensitive.\n * Sensitive fields are encrypted when saved and masked when displayed.\n */\nexport const isSensitive = (t: TSchema): boolean =>\n isString(t) && t.sensitive === true;\n"],"mappings":";;;;;;AAKA,IAAAA,QAAA,GAAAC,OAAA;AALA;AACA;AACA;AACA;;AAmBO,MAAMC,UAAU,GAAuBC,CAAI,IAChDA,CAAC,CAACC,qBAAY,CAAC,KAAK,UAAU;AAACC,OAAA,CAAAH,UAAA,GAAAA,UAAA;AAE1B,MAAMI,QAAQ,GAAIH,CAAU,IAAmBA,CAAC,CAACI,aAAI,CAAC,KAAK,QAAQ;AAACF,OAAA,CAAAC,QAAA,GAAAA,QAAA;AAEpE,MAAME,OAAO,GAAIL,CAAU,IAAkBA,CAAC,CAACI,aAAI,CAAC,KAAK,OAAO;AAACF,OAAA,CAAAG,OAAA,GAAAA,OAAA;AAEjE,MAAMC,QAAQ,GAAIN,CAAU,IAAmBA,CAAC,CAACI,aAAI,CAAC,KAAK,QAAQ;AAACF,OAAA,CAAAI,QAAA,GAAAA,QAAA;AAEpE,MAAMC,SAAS,GAAIP,CAAU,IAAoBA,CAAC,CAACI,aAAI,CAAC,KAAK,SAAS;AAACF,OAAA,CAAAK,SAAA,GAAAA,SAAA;AAEvE,MAAMC,QAAQ,GAAIR,CAAU,IAAmBA,CAAC,CAACI,aAAI,CAAC,KAAK,QAAQ;AAACF,OAAA,CAAAM,QAAA,GAAAA,QAAA;AAEpE,MAAMC,KAAK,GAAIT,CAAU,IAAgBA,CAAC,CAACI,aAAI,CAAC,KAAK,KAAK;AAACF,OAAA,CAAAO,KAAA,GAAAA,KAAA;AAE3D,MAAMC,QAAQ,GAAIV,CAAU,IAAmBA,CAAC,CAACI,aAAI,CAAC,KAAK,QAAQ;AAACF,OAAA,CAAAQ,QAAA,GAAAA,QAAA;AAEpE,MAAMC,MAAM,GAAIX,CAAU,IAAiBA,CAAC,CAACI,aAAI,CAAC,KAAK,MAAM;AAACF,OAAA,CAAAS,MAAA,GAAAA,MAAA;AAE9D,MAAMC,OAAO,GAAIZ,CAAU,IAAkBA,CAAC,CAACI,aAAI,CAAC,KAAK,OAAO;AAACF,OAAA,CAAAU,OAAA,GAAAA,OAAA;AAEjE,MAAMC,OAAO,GAAIb,CAAU,IAAkBA,CAAC,CAACI,aAAI,CAAC,KAAK,OAAO;;AAEvE;AACA;AACA;AACA;AAHAF,OAAA,CAAAW,OAAA,GAAAA,OAAA;AAIO,MAAMC,WAAW,GAAId,CAAU,IACpCU,QAAQ,CAACV,CAAC,CAAC,IAAIA,CAAC,CAACe,SAAS,KAAK,IAAI;AAACb,OAAA,CAAAY,WAAA,GAAAA,WAAA","ignoreList":[]}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.UserCancelledError = void 0;
7
+ /**
8
+ * Utility type to extract the static type from a TypeBox schema.
9
+ */
10
+
11
+ /**
12
+ * Options for encrypting/decrypting sensitive fields in settings.
13
+ */
14
+
15
+ /**
16
+ * Options for configuring a Sprinkle instance.
17
+ */
18
+
19
+ /**
20
+ * Metadata for a profile.
21
+ */
22
+
23
+ /**
24
+ * Current profile information including ID.
25
+ */
26
+
27
+ /**
28
+ * Profile entry as returned by scanProfiles().
29
+ */
30
+
31
+ /**
32
+ * Result of the TxDialog interaction.
33
+ */
34
+
35
+ /**
36
+ * Options for TxDialog.
37
+ */
38
+
39
+ /**
40
+ * Error thrown when user cancels a prompt via Escape key.
41
+ */
42
+ class UserCancelledError extends Error {
43
+ constructor(message = "User cancelled the operation") {
44
+ super(message);
45
+ this.name = "UserCancelledError";
46
+ }
47
+ }
48
+ exports.UserCancelledError = UserCancelledError;
49
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":["UserCancelledError","Error","constructor","message","name","exports"],"sources":["../../../src/Sprinkle/types.ts"],"sourcesContent":["import { Core } from \"@blaze-cardano/sdk\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\n\n/**\n * Utility type to extract the static type from a TypeBox schema.\n */\nexport type TExact<T> = T extends TSchema ? Static<T> : T;\n\n/**\n * Options for encrypting/decrypting sensitive fields in settings.\n */\nexport interface IEncryptionOptions {\n encrypt: (plaintext: string) => string;\n decrypt: (ciphertext: string) => Promise<string>;\n}\n\n/**\n * Options for configuring a Sprinkle instance.\n */\nexport interface ISprinkleOptions {\n encryption?: IEncryptionOptions;\n}\n\n/**\n * Metadata for a profile.\n */\nexport interface IProfileMeta {\n name: string;\n description?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Current profile information including ID.\n */\nexport interface ICurrentProfile extends IProfileMeta {\n id: string;\n}\n\n/**\n * Profile entry as returned by scanProfiles().\n */\nexport interface IProfileEntry {\n id: string;\n meta: IProfileMeta;\n}\n\n/**\n * Result of the TxDialog interaction.\n */\nexport interface TxDialogResult {\n action: \"submitted\" | \"signed\" | \"cancelled\";\n txId?: string; // present only if action === 'submitted'\n tx: Core.Transaction; // the (potentially signed) transaction\n}\n\n/**\n * Options for TxDialog.\n */\nexport interface TxDialogOptions {\n beforeSign?: () => Promise<void>;\n}\n\n/**\n * Error thrown when user cancels a prompt via Escape key.\n */\nexport class UserCancelledError extends Error {\n constructor(message: string = \"User cancelled the operation\") {\n super(message);\n this.name = \"UserCancelledError\";\n }\n}\n"],"mappings":";;;;;;AAGA;AACA;AACA;;AAGA;AACA;AACA;;AAMA;AACA;AACA;;AAKA;AACA;AACA;;AAQA;AACA;AACA;;AAKA;AACA;AACA;;AAMA;AACA;AACA;;AAOA;AACA;AACA;;AAKA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,KAAK,CAAC;EAC5CC,WAAWA,CAACC,OAAe,GAAG,8BAA8B,EAAE;IAC5D,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,oBAAoB;EAClC;AACF;AAACC,OAAA,CAAAL,kBAAA,GAAAA,kBAAA","ignoreList":[]}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.GetBlaze = GetBlaze;
7
+ exports.GetProvider = GetProvider;
8
+ exports.GetWallet = GetWallet;
9
+ exports.generateWalletFromMnemonic = generateWalletFromMnemonic;
10
+ var _query = require("@blaze-cardano/query");
11
+ var _sdk = require("@blaze-cardano/sdk");
12
+ var _core = require("@blaze-cardano/core");
13
+ var _prompts = require("./prompts.js");
14
+ var _types = require("./types.js");
15
+ 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); } /**
16
+ * Wallet and provider setup utilities.
17
+ * Functions for creating providers, wallets, and Blaze instances.
18
+ */
19
+ /**
20
+ * Creates a blockchain data provider based on settings.
21
+ */
22
+ async function GetProvider(network, settings) {
23
+ switch (settings.type) {
24
+ case "blockfrost":
25
+ return new _query.Blockfrost({
26
+ network: `cardano-${network}`,
27
+ projectId: settings.projectId
28
+ });
29
+ case "maestro":
30
+ // Dynamic import - Maestro may or may not be exported depending on @blaze-cardano/query version
31
+ const queryModule = await Promise.resolve().then(() => _interopRequireWildcard(require("@blaze-cardano/query")));
32
+ if (!queryModule.Maestro) {
33
+ throw new Error("Maestro is not available in the installed version of @blaze-cardano/query. Please install a version that includes Maestro support.");
34
+ }
35
+ return new queryModule.Maestro({
36
+ network: network,
37
+ apiKey: settings.apiKey
38
+ });
39
+ default:
40
+ throw new Error("Invalid provider type");
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Creates a wallet instance based on settings.
46
+ */
47
+ async function GetWallet(settings, provider) {
48
+ switch (settings.type) {
49
+ case "hot":
50
+ return _sdk.HotWallet.fromMasterkey(_sdk.Core.Bip32PrivateKeyHex(settings.privateKey), provider, provider.network);
51
+ case "cold":
52
+ return new _sdk.ColdWallet(_sdk.Core.Address.fromBech32(settings.address), provider.network, provider);
53
+ default:
54
+ throw new Error("Invalid wallet type");
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Creates a Blaze instance with provider and wallet.
60
+ */
61
+ async function GetBlaze(network, providerSettings, walletSettings) {
62
+ const provider = await GetProvider(network, providerSettings);
63
+ const wallet = await GetWallet(walletSettings, provider);
64
+ return _sdk.Blaze.from(provider, wallet);
65
+ }
66
+
67
+ /**
68
+ * Generates a new wallet from a BIP39 mnemonic phrase.
69
+ * Displays the 24-word recovery phrase and requires user confirmation.
70
+ * @returns The Bip32PrivateKey hex string for storage
71
+ */
72
+ async function generateWalletFromMnemonic() {
73
+ const mnemonic = _sdk.Core.generateMnemonic(_core.wordlist, 256); // 24 words
74
+ const words = mnemonic.split(" ");
75
+ console.log("\n=== NEW WALLET GENERATED ===\n");
76
+ console.log("IMPORTANT: Save these 24 words in a secure location.");
77
+ console.log("This is the ONLY way to recover your wallet.\n");
78
+
79
+ // Display in 4 columns
80
+ for (let i = 0; i < 6; i++) {
81
+ 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]}`);
82
+ }
83
+ console.log("");
84
+ const confirmed = await (0, _prompts.confirmCancellable)({
85
+ message: "Have you saved your recovery phrase?",
86
+ default: false
87
+ });
88
+ if (confirmed === null) {
89
+ throw new _types.UserCancelledError("Wallet generation cancelled");
90
+ }
91
+ if (!confirmed) {
92
+ throw new Error("Wallet generation cancelled - recovery phrase not saved");
93
+ }
94
+ const entropy = _sdk.Core.mnemonicToEntropy(mnemonic, _core.wordlist);
95
+ const masterKey = _sdk.Core.Bip32PrivateKey.fromBip39Entropy(Buffer.from(entropy), "");
96
+ return masterKey.hex();
97
+ }
98
+ //# sourceMappingURL=wallet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.js","names":["_query","require","_sdk","_core","_prompts","_types","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","GetProvider","network","settings","type","Blockfrost","projectId","queryModule","Promise","resolve","then","Maestro","Error","apiKey","GetWallet","provider","HotWallet","fromMasterkey","Core","Bip32PrivateKeyHex","privateKey","ColdWallet","Address","fromBech32","address","GetBlaze","providerSettings","walletSettings","wallet","Blaze","from","generateWalletFromMnemonic","mnemonic","generateMnemonic","wordlist","words","split","console","log","toString","padStart","padEnd","confirmed","confirmCancellable","message","UserCancelledError","entropy","mnemonicToEntropy","masterKey","Bip32PrivateKey","fromBip39Entropy","Buffer","hex"],"sources":["../../../src/Sprinkle/wallet.ts"],"sourcesContent":["/**\n * Wallet and provider setup utilities.\n * Functions for creating providers, wallets, and Blaze instances.\n */\n\nimport { Blockfrost, type Provider } from \"@blaze-cardano/query\";\nimport {\n Blaze,\n ColdWallet,\n Core,\n HotWallet,\n type Wallet,\n} from \"@blaze-cardano/sdk\";\nimport { wordlist } from \"@blaze-cardano/core\";\nimport { confirmCancellable } from \"./prompts.js\";\nimport { UserCancelledError, type TExact } from \"./types.js\";\nimport {\n NetworkSchema,\n ProviderSettingsSchema,\n WalletSettingsSchema,\n} from \"./schemas.js\";\n\n/**\n * Creates a blockchain data provider based on settings.\n */\nexport async function GetProvider(\n network: TExact<typeof NetworkSchema>,\n settings: TExact<typeof ProviderSettingsSchema>,\n): Promise<Provider> {\n switch (settings.type) {\n case \"blockfrost\":\n return new Blockfrost({\n network: `cardano-${network}`,\n projectId: settings.projectId,\n });\n case \"maestro\":\n // Dynamic import - Maestro may or may not be exported depending on @blaze-cardano/query version\n const queryModule = (await import(\"@blaze-cardano/query\")) as any;\n if (!queryModule.Maestro) {\n throw new Error(\n \"Maestro is not available in the installed version of @blaze-cardano/query. Please install a version that includes Maestro support.\",\n );\n }\n return new queryModule.Maestro({\n network: network as \"mainnet\" | \"preview\" | \"preprod\",\n apiKey: settings.apiKey,\n });\n default:\n throw new Error(\"Invalid provider type\");\n }\n}\n\n/**\n * Creates a wallet instance based on settings.\n */\nexport async function GetWallet(\n settings: TExact<typeof WalletSettingsSchema>,\n provider: Provider,\n): Promise<Wallet> {\n switch (settings.type) {\n case \"hot\":\n return HotWallet.fromMasterkey(\n Core.Bip32PrivateKeyHex(settings.privateKey),\n provider,\n provider.network,\n );\n case \"cold\":\n return new ColdWallet(\n Core.Address.fromBech32(settings.address),\n provider.network,\n provider,\n );\n default:\n throw new Error(\"Invalid wallet type\");\n }\n}\n\n/**\n * Creates a Blaze instance with provider and wallet.\n */\nexport async function GetBlaze(\n network: TExact<typeof NetworkSchema>,\n providerSettings: TExact<typeof ProviderSettingsSchema>,\n walletSettings: TExact<typeof WalletSettingsSchema>,\n): Promise<Blaze<Provider, Wallet>> {\n const provider = await GetProvider(network, providerSettings);\n const wallet = await GetWallet(walletSettings, provider);\n return Blaze.from(provider, wallet);\n}\n\n/**\n * Generates a new wallet from a BIP39 mnemonic phrase.\n * Displays the 24-word recovery phrase and requires user confirmation.\n * @returns The Bip32PrivateKey hex string for storage\n */\nexport async function generateWalletFromMnemonic(): Promise<string> {\n const mnemonic = Core.generateMnemonic(wordlist, 256); // 24 words\n const words = mnemonic.split(\" \");\n\n console.log(\"\\n=== NEW WALLET GENERATED ===\\n\");\n console.log(\"IMPORTANT: Save these 24 words in a secure location.\");\n console.log(\"This is the ONLY way to recover your wallet.\\n\");\n\n // Display in 4 columns\n for (let i = 0; i < 6; i++) {\n console.log(\n `${(i + 1).toString().padStart(2)}. ${words[i]!.padEnd(12)} ` +\n `${(i + 7).toString().padStart(2)}. ${words[i + 6]!.padEnd(12)} ` +\n `${(i + 13).toString().padStart(2)}. ${words[i + 12]!.padEnd(12)} ` +\n `${(i + 19).toString().padStart(2)}. ${words[i + 18]}`,\n );\n }\n console.log(\"\");\n\n const confirmed = await confirmCancellable({\n message: \"Have you saved your recovery phrase?\",\n default: false,\n });\n\n if (confirmed === null) {\n throw new UserCancelledError(\"Wallet generation cancelled\");\n }\n if (!confirmed) {\n throw new Error(\"Wallet generation cancelled - recovery phrase not saved\");\n }\n\n const entropy = Core.mnemonicToEntropy(mnemonic, wordlist);\n const masterKey = Core.Bip32PrivateKey.fromBip39Entropy(\n Buffer.from(entropy),\n \"\",\n );\n return masterKey.hex();\n}\n"],"mappings":"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","ignoreList":[]}
@@ -7,11 +7,20 @@ import { withProfile } from "./test-helpers.js";
7
7
  const mockSelect = mock();
8
8
  const mockInput = mock();
9
9
  const mockPassword = mock();
10
+ const mockSelectCancellable = mock();
11
+ const mockInputCancellable = mock();
12
+ const mockPasswordCancellable = mock();
10
13
  mock.module("@inquirer/prompts", () => ({
11
14
  select: mockSelect,
12
15
  input: mockInput,
13
16
  password: mockPassword
14
17
  }));
18
+ mock.module("../prompts.js", () => ({
19
+ selectCancellable: mockSelectCancellable,
20
+ inputCancellable: mockInputCancellable,
21
+ passwordCancellable: mockPasswordCancellable,
22
+ confirmCancellable: mock()
23
+ }));
15
24
  describe("Encryption & Sensitive Fields", () => {
16
25
  let tmpDir;
17
26
  beforeEach(() => {
@@ -19,6 +28,9 @@ describe("Encryption & Sensitive Fields", () => {
19
28
  mockSelect.mockClear();
20
29
  mockInput.mockClear();
21
30
  mockPassword.mockClear();
31
+ mockSelectCancellable.mockClear();
32
+ mockInputCancellable.mockClear();
33
+ mockPasswordCancellable.mockClear();
22
34
  });
23
35
  afterEach(() => {
24
36
  fs.rmSync(tmpDir, {
@@ -35,14 +47,14 @@ describe("Encryption & Sensitive Fields", () => {
35
47
  })
36
48
  });
37
49
  const sprinkle = new Sprinkle(schema, tmpDir);
38
- mockPassword.mockResolvedValueOnce("my-secret");
50
+ mockPasswordCancellable.mockResolvedValueOnce("my-secret");
39
51
  const result = await sprinkle.FillInStruct(schema);
40
52
  expect(result).toEqual({
41
53
  secret: "my-secret"
42
54
  });
43
- expect(mockPassword).toHaveBeenCalledTimes(1);
44
- expect(mockPassword.mock.calls[0][0].message).toBe("Enter secret");
45
- expect(mockInput).not.toHaveBeenCalled();
55
+ expect(mockPasswordCancellable).toHaveBeenCalledTimes(1);
56
+ expect(mockPasswordCancellable.mock.calls[0][0].message).toBe("Enter secret");
57
+ expect(mockInputCancellable).not.toHaveBeenCalled();
46
58
  });
47
59
  test("uses input() for non-sensitive string fields", async () => {
48
60
  const schema = Type.Object({
@@ -51,13 +63,13 @@ describe("Encryption & Sensitive Fields", () => {
51
63
  })
52
64
  });
53
65
  const sprinkle = new Sprinkle(schema, tmpDir);
54
- mockInput.mockResolvedValueOnce("visible");
66
+ mockInputCancellable.mockResolvedValueOnce("visible");
55
67
  const result = await sprinkle.FillInStruct(schema);
56
68
  expect(result).toEqual({
57
69
  name: "visible"
58
70
  });
59
- expect(mockInput).toHaveBeenCalledTimes(1);
60
- expect(mockPassword).not.toHaveBeenCalled();
71
+ expect(mockInputCancellable).toHaveBeenCalledTimes(1);
72
+ expect(mockPasswordCancellable).not.toHaveBeenCalled();
61
73
  });
62
74
  test("does not remember sensitive field as default", async () => {
63
75
  const schema = Type.String({
@@ -66,7 +78,7 @@ describe("Encryption & Sensitive Fields", () => {
66
78
  const sprinkle = new Sprinkle(Type.Object({
67
79
  p: Type.String()
68
80
  }), tmpDir);
69
- mockPassword.mockResolvedValueOnce("secret-val");
81
+ mockPasswordCancellable.mockResolvedValueOnce("secret-val");
70
82
  await sprinkle.FillInStruct(schema);
71
83
  expect(sprinkle.defaults["string"]).toBeUndefined();
72
84
  });
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.test.js","names":["describe","expect","test","mock","beforeEach","afterEach","Sprinkle","Type","fs","path","os","withProfile","mockSelect","mockInput","mockPassword","module","select","input","password","tmpDir","mkdtempSync","join","tmpdir","mockClear","rmSync","recursive","force","schema","Object","secret","String","sensitive","title","sprinkle","mockResolvedValueOnce","result","FillInStruct","toEqual","toHaveBeenCalledTimes","calls","message","toBe","not","toHaveBeenCalled","name","p","defaults","toBeUndefined","encryption","encrypt","plain","decrypt","cipher","replace","settings","saveSettings","content","readFileSync","parsed","JSON","parse","sprinkle1","sprinkle2","loadProfile","wallet","key","address","Union","type","Literal","privateKey","outerSchema","network","count","BigInt","opts","Buffer","from","toString","s1","s2","mkdirSync","writeFileSync","stringify","New","c","options","toBeDefined","profileId"],"sources":["../../../../src/Sprinkle/__tests__/encryption.test.ts"],"sourcesContent":["import { describe, expect, test, mock, beforeEach, afterEach } from \"bun:test\";\nimport { Sprinkle, Type } from \"../index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { withProfile } from \"./test-helpers.js\";\n\nconst mockSelect = mock();\nconst mockInput = mock();\nconst mockPassword = mock();\n\nmock.module(\"@inquirer/prompts\", () => ({\n select: mockSelect,\n input: mockInput,\n password: mockPassword,\n}));\n\ndescribe(\"Encryption & Sensitive Fields\", () => {\n let tmpDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sprinkles-enc-test-\"));\n mockSelect.mockClear();\n mockInput.mockClear();\n mockPassword.mockClear();\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n describe(\"sensitive field prompts\", () => {\n test(\"uses password() for sensitive string fields\", async () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true, title: \"Enter secret\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockPassword.mockResolvedValueOnce(\"my-secret\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ secret: \"my-secret\" });\n expect(mockPassword).toHaveBeenCalledTimes(1);\n expect(mockPassword.mock.calls[0][0].message).toBe(\"Enter secret\");\n expect(mockInput).not.toHaveBeenCalled();\n });\n\n test(\"uses input() for non-sensitive string fields\", async () => {\n const schema = Type.Object({\n name: Type.String({ title: \"Enter name\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockInput.mockResolvedValueOnce(\"visible\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ name: \"visible\" });\n expect(mockInput).toHaveBeenCalledTimes(1);\n expect(mockPassword).not.toHaveBeenCalled();\n });\n\n test(\"does not remember sensitive field as default\", async () => {\n const schema = Type.String({ sensitive: true });\n const sprinkle = new Sprinkle(Type.Object({ p: Type.String() }), tmpDir);\n\n mockPassword.mockResolvedValueOnce(\"secret-val\");\n\n await sprinkle.FillInStruct(schema);\n expect(sprinkle.defaults[\"string\"]).toBeUndefined();\n });\n });\n\n describe(\"encryption on save/load\", () => {\n test(\"encrypts sensitive fields when saving with encryption configured\", () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = { name: \"visible\", secret: \"hidden\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.name).toBe(\"visible\");\n expect(parsed.settings.secret).toBe(\"ENC:hidden\");\n });\n\n test(\"decrypts sensitive fields when loading with encryption configured\", async () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n\n // First save with encryption\n const sprinkle1 = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle1.settings = { name: \"visible\", secret: \"hidden\" } as any;\n sprinkle1.saveSettings();\n\n // Then load with same encryption\n const sprinkle2 = new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n });\n await sprinkle2.loadProfile(\"test\");\n\n expect(sprinkle2.settings).toEqual({ name: \"visible\", secret: \"hidden\" });\n });\n\n test(\"does not encrypt when no encryption configured\", () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(new Sprinkle(schema, tmpDir));\n sprinkle.settings = { secret: \"plain-value\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.secret).toBe(\"plain-value\");\n });\n\n test(\"encrypts nested sensitive fields\", () => {\n const schema = Type.Object({\n wallet: Type.Object({\n key: Type.String({ sensitive: true }),\n address: Type.String(),\n }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { key: \"secret-key\", address: \"addr1...\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.key).toBe(\"ENC:secret-key\");\n expect(parsed.settings.wallet.address).toBe(\"addr1...\");\n });\n\n test(\"handles sensitive fields in union variants\", () => {\n const schema = Type.Union([\n Type.Object({\n type: Type.Literal(\"hot\"),\n privateKey: Type.String({ sensitive: true }),\n }),\n Type.Object({\n type: Type.Literal(\"cold\"),\n address: Type.String(),\n }),\n ]);\n const outerSchema = Type.Object({ wallet: schema });\n const sprinkle = withProfile(\n new Sprinkle(outerSchema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { type: \"hot\", privateKey: \"my-key\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.privateKey).toBe(\"ENC:my-key\");\n });\n\n test(\"round-trip with encryption preserves all data\", async () => {\n const schema = Type.Object({\n network: Type.String(),\n secret: Type.String({ sensitive: true }),\n count: Type.BigInt(),\n });\n const opts = {\n encryption: {\n encrypt: (plain: string) => Buffer.from(plain).toString(\"base64\"),\n decrypt: async (cipher: string) =>\n Buffer.from(cipher, \"base64\").toString(),\n },\n };\n const s1 = withProfile(new Sprinkle(schema, tmpDir, opts));\n s1.settings = {\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n } as any;\n s1.saveSettings();\n\n const s2 = new Sprinkle(schema, tmpDir, opts);\n await s2.loadProfile(\"test\");\n\n expect(s2.settings).toEqual({\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n });\n });\n });\n\n describe(\"Sprinkle.New with options\", () => {\n test(\"passes options through to instance and migrates legacy\", async () => {\n const schema = Type.Object({ name: Type.String() });\n\n // Write legacy settings file so New triggers migration\n fs.mkdirSync(tmpDir, { recursive: true });\n fs.writeFileSync(\n path.join(tmpDir, \"settings.json\"),\n JSON.stringify({ settings: { name: \"test\" }, defaults: {} }),\n );\n\n const sprinkle = await Sprinkle.New(schema, tmpDir, {\n encryption: {\n encrypt: (p) => p,\n decrypt: async (c) => c,\n },\n });\n\n expect(sprinkle.options.encryption).toBeDefined();\n expect(sprinkle.profileId).toBe(\"default\");\n expect(sprinkle.settings).toEqual({ name: \"test\" });\n });\n });\n});\n"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,IAAI,EAAEC,IAAI,EAAEC,UAAU,EAAEC,SAAS,QAAQ,UAAU;AAC9E,SAASC,QAAQ,EAAEC,IAAI,QAAQ,aAAa;AAC5C,OAAO,KAAKC,EAAE,MAAM,IAAI;AACxB,OAAO,KAAKC,IAAI,MAAM,MAAM;AAC5B,OAAO,KAAKC,EAAE,MAAM,IAAI;AACxB,SAASC,WAAW,QAAQ,mBAAmB;AAE/C,MAAMC,UAAU,GAAGT,IAAI,CAAC,CAAC;AACzB,MAAMU,SAAS,GAAGV,IAAI,CAAC,CAAC;AACxB,MAAMW,YAAY,GAAGX,IAAI,CAAC,CAAC;AAE3BA,IAAI,CAACY,MAAM,CAAC,mBAAmB,EAAE,OAAO;EACtCC,MAAM,EAAEJ,UAAU;EAClBK,KAAK,EAAEJ,SAAS;EAChBK,QAAQ,EAAEJ;AACZ,CAAC,CAAC,CAAC;AAEHd,QAAQ,CAAC,+BAA+B,EAAE,MAAM;EAC9C,IAAImB,MAAc;EAElBf,UAAU,CAAC,MAAM;IACfe,MAAM,GAAGX,EAAE,CAACY,WAAW,CAACX,IAAI,CAACY,IAAI,CAACX,EAAE,CAACY,MAAM,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACtEV,UAAU,CAACW,SAAS,CAAC,CAAC;IACtBV,SAAS,CAACU,SAAS,CAAC,CAAC;IACrBT,YAAY,CAACS,SAAS,CAAC,CAAC;EAC1B,CAAC,CAAC;EAEFlB,SAAS,CAAC,MAAM;IACdG,EAAE,CAACgB,MAAM,CAACL,MAAM,EAAE;MAAEM,SAAS,EAAE,IAAI;MAAEC,KAAK,EAAE;IAAK,CAAC,CAAC;EACrD,CAAC,CAAC;EAEF1B,QAAQ,CAAC,yBAAyB,EAAE,MAAM;IACxCE,IAAI,CAAC,6CAA6C,EAAE,YAAY;MAC9D,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBC,MAAM,EAAEtB,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE,IAAI;UAAEC,KAAK,EAAE;QAAe,CAAC;MAChE,CAAC,CAAC;MACF,MAAMC,QAAQ,GAAG,IAAI3B,QAAQ,CAACqB,MAAM,EAAER,MAAM,CAAC;MAE7CL,YAAY,CAACoB,qBAAqB,CAAC,WAAW,CAAC;MAE/C,MAAMC,MAAM,GAAG,MAAMF,QAAQ,CAACG,YAAY,CAACT,MAAM,CAAC;MAClD1B,MAAM,CAACkC,MAAM,CAAC,CAACE,OAAO,CAAC;QAAER,MAAM,EAAE;MAAY,CAAC,CAAC;MAC/C5B,MAAM,CAACa,YAAY,CAAC,CAACwB,qBAAqB,CAAC,CAAC,CAAC;MAC7CrC,MAAM,CAACa,YAAY,CAACX,IAAI,CAACoC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAACC,OAAO,CAAC,CAACC,IAAI,CAAC,cAAc,CAAC;MAClExC,MAAM,CAACY,SAAS,CAAC,CAAC6B,GAAG,CAACC,gBAAgB,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEFzC,IAAI,CAAC,8CAA8C,EAAE,YAAY;MAC/D,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBgB,IAAI,EAAErC,IAAI,CAACuB,MAAM,CAAC;UAAEE,KAAK,EAAE;QAAa,CAAC;MAC3C,CAAC,CAAC;MACF,MAAMC,QAAQ,GAAG,IAAI3B,QAAQ,CAACqB,MAAM,EAAER,MAAM,CAAC;MAE7CN,SAAS,CAACqB,qBAAqB,CAAC,SAAS,CAAC;MAE1C,MAAMC,MAAM,GAAG,MAAMF,QAAQ,CAACG,YAAY,CAACT,MAAM,CAAC;MAClD1B,MAAM,CAACkC,MAAM,CAAC,CAACE,OAAO,CAAC;QAAEO,IAAI,EAAE;MAAU,CAAC,CAAC;MAC3C3C,MAAM,CAACY,SAAS,CAAC,CAACyB,qBAAqB,CAAC,CAAC,CAAC;MAC1CrC,MAAM,CAACa,YAAY,CAAC,CAAC4B,GAAG,CAACC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEFzC,IAAI,CAAC,8CAA8C,EAAE,YAAY;MAC/D,MAAMyB,MAAM,GAAGpB,IAAI,CAACuB,MAAM,CAAC;QAAEC,SAAS,EAAE;MAAK,CAAC,CAAC;MAC/C,MAAME,QAAQ,GAAG,IAAI3B,QAAQ,CAACC,IAAI,CAACqB,MAAM,CAAC;QAAEiB,CAAC,EAAEtC,IAAI,CAACuB,MAAM,CAAC;MAAE,CAAC,CAAC,EAAEX,MAAM,CAAC;MAExEL,YAAY,CAACoB,qBAAqB,CAAC,YAAY,CAAC;MAEhD,MAAMD,QAAQ,CAACG,YAAY,CAACT,MAAM,CAAC;MACnC1B,MAAM,CAACgC,QAAQ,CAACa,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAACC,aAAa,CAAC,CAAC;IACrD,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF/C,QAAQ,CAAC,yBAAyB,EAAE,MAAM;IACxCE,IAAI,CAAC,kEAAkE,EAAE,MAAM;MAC7E,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBgB,IAAI,EAAErC,IAAI,CAACuB,MAAM,CAAC,CAAC;QACnBD,MAAM,EAAEtB,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC;MACzC,CAAC,CAAC;MACF,MAAME,QAAQ,GAAGtB,WAAW,CAC1B,IAAIL,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAE;QAC3B6B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAK,IAAK,OAAOA,KAAK,EAAE;UAClCC,OAAO,EAAE,MAAOC,MAAM,IAAKA,MAAM,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE;QACtD;MACF,CAAC,CACH,CAAC;MACDpB,QAAQ,CAACqB,QAAQ,GAAG;QAAEV,IAAI,EAAE,SAAS;QAAEf,MAAM,EAAE;MAAS,CAAQ;MAEhEI,QAAQ,CAACsB,YAAY,CAAC,CAAC;MAEvB,MAAMC,OAAO,GAAGhD,EAAE,CAACiD,YAAY,CAC7BhD,IAAI,CAACY,IAAI,CAACF,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAC1C,OACF,CAAC;MACD,MAAMuC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACJ,OAAO,CAAC;MAClCvD,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACV,IAAI,CAAC,CAACH,IAAI,CAAC,SAAS,CAAC;MAC5CxC,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACzB,MAAM,CAAC,CAACY,IAAI,CAAC,YAAY,CAAC;IACnD,CAAC,CAAC;IAEFvC,IAAI,CAAC,mEAAmE,EAAE,YAAY;MACpF,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBgB,IAAI,EAAErC,IAAI,CAACuB,MAAM,CAAC,CAAC;QACnBD,MAAM,EAAEtB,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC;MACzC,CAAC,CAAC;;MAEF;MACA,MAAM8B,SAAS,GAAGlD,WAAW,CAC3B,IAAIL,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAE;QAC3B6B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAK,IAAK,OAAOA,KAAK,EAAE;UAClCC,OAAO,EAAE,MAAOC,MAAM,IAAKA,MAAM,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE;QACtD;MACF,CAAC,CACH,CAAC;MACDQ,SAAS,CAACP,QAAQ,GAAG;QAAEV,IAAI,EAAE,SAAS;QAAEf,MAAM,EAAE;MAAS,CAAQ;MACjEgC,SAAS,CAACN,YAAY,CAAC,CAAC;;MAExB;MACA,MAAMO,SAAS,GAAG,IAAIxD,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAE;QAC7C6B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAK,IAAK,OAAOA,KAAK,EAAE;UAClCC,OAAO,EAAE,MAAOC,MAAM,IAAKA,MAAM,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE;QACtD;MACF,CAAC,CAAC;MACF,MAAMS,SAAS,CAACC,WAAW,CAAC,MAAM,CAAC;MAEnC9D,MAAM,CAAC6D,SAAS,CAACR,QAAQ,CAAC,CAACjB,OAAO,CAAC;QAAEO,IAAI,EAAE,SAAS;QAAEf,MAAM,EAAE;MAAS,CAAC,CAAC;IAC3E,CAAC,CAAC;IAEF3B,IAAI,CAAC,gDAAgD,EAAE,MAAM;MAC3D,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBC,MAAM,EAAEtB,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC;MACzC,CAAC,CAAC;MACF,MAAME,QAAQ,GAAGtB,WAAW,CAAC,IAAIL,QAAQ,CAACqB,MAAM,EAAER,MAAM,CAAC,CAAC;MAC1Dc,QAAQ,CAACqB,QAAQ,GAAG;QAAEzB,MAAM,EAAE;MAAc,CAAQ;MAEpDI,QAAQ,CAACsB,YAAY,CAAC,CAAC;MAEvB,MAAMC,OAAO,GAAGhD,EAAE,CAACiD,YAAY,CAC7BhD,IAAI,CAACY,IAAI,CAACF,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAC1C,OACF,CAAC;MACD,MAAMuC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACJ,OAAO,CAAC;MAClCvD,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACzB,MAAM,CAAC,CAACY,IAAI,CAAC,aAAa,CAAC;IACpD,CAAC,CAAC;IAEFvC,IAAI,CAAC,kCAAkC,EAAE,MAAM;MAC7C,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzBoC,MAAM,EAAEzD,IAAI,CAACqB,MAAM,CAAC;UAClBqC,GAAG,EAAE1D,IAAI,CAACuB,MAAM,CAAC;YAAEC,SAAS,EAAE;UAAK,CAAC,CAAC;UACrCmC,OAAO,EAAE3D,IAAI,CAACuB,MAAM,CAAC;QACvB,CAAC;MACH,CAAC,CAAC;MACF,MAAMG,QAAQ,GAAGtB,WAAW,CAC1B,IAAIL,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAE;QAC3B6B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAK,IAAK,OAAOA,KAAK,EAAE;UAClCC,OAAO,EAAE,MAAOC,MAAM,IAAKA,MAAM,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE;QACtD;MACF,CAAC,CACH,CAAC;MACDpB,QAAQ,CAACqB,QAAQ,GAAG;QAClBU,MAAM,EAAE;UAAEC,GAAG,EAAE,YAAY;UAAEC,OAAO,EAAE;QAAW;MACnD,CAAQ;MAERjC,QAAQ,CAACsB,YAAY,CAAC,CAAC;MAEvB,MAAMC,OAAO,GAAGhD,EAAE,CAACiD,YAAY,CAC7BhD,IAAI,CAACY,IAAI,CAACF,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAC1C,OACF,CAAC;MACD,MAAMuC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACJ,OAAO,CAAC;MAClCvD,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACU,MAAM,CAACC,GAAG,CAAC,CAACxB,IAAI,CAAC,gBAAgB,CAAC;MACzDxC,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACU,MAAM,CAACE,OAAO,CAAC,CAACzB,IAAI,CAAC,UAAU,CAAC;IACzD,CAAC,CAAC;IAEFvC,IAAI,CAAC,4CAA4C,EAAE,MAAM;MACvD,MAAMyB,MAAM,GAAGpB,IAAI,CAAC4D,KAAK,CAAC,CACxB5D,IAAI,CAACqB,MAAM,CAAC;QACVwC,IAAI,EAAE7D,IAAI,CAAC8D,OAAO,CAAC,KAAK,CAAC;QACzBC,UAAU,EAAE/D,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC;MAC7C,CAAC,CAAC,EACFxB,IAAI,CAACqB,MAAM,CAAC;QACVwC,IAAI,EAAE7D,IAAI,CAAC8D,OAAO,CAAC,MAAM,CAAC;QAC1BH,OAAO,EAAE3D,IAAI,CAACuB,MAAM,CAAC;MACvB,CAAC,CAAC,CACH,CAAC;MACF,MAAMyC,WAAW,GAAGhE,IAAI,CAACqB,MAAM,CAAC;QAAEoC,MAAM,EAAErC;MAAO,CAAC,CAAC;MACnD,MAAMM,QAAQ,GAAGtB,WAAW,CAC1B,IAAIL,QAAQ,CAACiE,WAAW,EAAEpD,MAAM,EAAE;QAChC6B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAK,IAAK,OAAOA,KAAK,EAAE;UAClCC,OAAO,EAAE,MAAOC,MAAM,IAAKA,MAAM,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE;QACtD;MACF,CAAC,CACH,CAAC;MACDpB,QAAQ,CAACqB,QAAQ,GAAG;QAClBU,MAAM,EAAE;UAAEI,IAAI,EAAE,KAAK;UAAEE,UAAU,EAAE;QAAS;MAC9C,CAAQ;MAERrC,QAAQ,CAACsB,YAAY,CAAC,CAAC;MAEvB,MAAMC,OAAO,GAAGhD,EAAE,CAACiD,YAAY,CAC7BhD,IAAI,CAACY,IAAI,CAACF,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAC1C,OACF,CAAC;MACD,MAAMuC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACJ,OAAO,CAAC;MAClCvD,MAAM,CAACyD,MAAM,CAACJ,QAAQ,CAACU,MAAM,CAACM,UAAU,CAAC,CAAC7B,IAAI,CAAC,YAAY,CAAC;IAC9D,CAAC,CAAC;IAEFvC,IAAI,CAAC,+CAA+C,EAAE,YAAY;MAChE,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QACzB4C,OAAO,EAAEjE,IAAI,CAACuB,MAAM,CAAC,CAAC;QACtBD,MAAM,EAAEtB,IAAI,CAACuB,MAAM,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC,CAAC;QACxC0C,KAAK,EAAElE,IAAI,CAACmE,MAAM,CAAC;MACrB,CAAC,CAAC;MACF,MAAMC,IAAI,GAAG;QACX3B,UAAU,EAAE;UACVC,OAAO,EAAGC,KAAa,IAAK0B,MAAM,CAACC,IAAI,CAAC3B,KAAK,CAAC,CAAC4B,QAAQ,CAAC,QAAQ,CAAC;UACjE3B,OAAO,EAAE,MAAOC,MAAc,IAC5BwB,MAAM,CAACC,IAAI,CAACzB,MAAM,EAAE,QAAQ,CAAC,CAAC0B,QAAQ,CAAC;QAC3C;MACF,CAAC;MACD,MAAMC,EAAE,GAAGpE,WAAW,CAAC,IAAIL,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAEwD,IAAI,CAAC,CAAC;MAC1DI,EAAE,CAACzB,QAAQ,GAAG;QACZkB,OAAO,EAAE,SAAS;QAClB3C,MAAM,EAAE,YAAY;QACpB4C,KAAK,EAAE;MACT,CAAQ;MACRM,EAAE,CAACxB,YAAY,CAAC,CAAC;MAEjB,MAAMyB,EAAE,GAAG,IAAI1E,QAAQ,CAACqB,MAAM,EAAER,MAAM,EAAEwD,IAAI,CAAC;MAC7C,MAAMK,EAAE,CAACjB,WAAW,CAAC,MAAM,CAAC;MAE5B9D,MAAM,CAAC+E,EAAE,CAAC1B,QAAQ,CAAC,CAACjB,OAAO,CAAC;QAC1BmC,OAAO,EAAE,SAAS;QAClB3C,MAAM,EAAE,YAAY;QACpB4C,KAAK,EAAE;MACT,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ,CAAC,CAAC;EAEFzE,QAAQ,CAAC,2BAA2B,EAAE,MAAM;IAC1CE,IAAI,CAAC,wDAAwD,EAAE,YAAY;MACzE,MAAMyB,MAAM,GAAGpB,IAAI,CAACqB,MAAM,CAAC;QAAEgB,IAAI,EAAErC,IAAI,CAACuB,MAAM,CAAC;MAAE,CAAC,CAAC;;MAEnD;MACAtB,EAAE,CAACyE,SAAS,CAAC9D,MAAM,EAAE;QAAEM,SAAS,EAAE;MAAK,CAAC,CAAC;MACzCjB,EAAE,CAAC0E,aAAa,CACdzE,IAAI,CAACY,IAAI,CAACF,MAAM,EAAE,eAAe,CAAC,EAClCwC,IAAI,CAACwB,SAAS,CAAC;QAAE7B,QAAQ,EAAE;UAAEV,IAAI,EAAE;QAAO,CAAC;QAAEE,QAAQ,EAAE,CAAC;MAAE,CAAC,CAC7D,CAAC;MAED,MAAMb,QAAQ,GAAG,MAAM3B,QAAQ,CAAC8E,GAAG,CAACzD,MAAM,EAAER,MAAM,EAAE;QAClD6B,UAAU,EAAE;UACVC,OAAO,EAAGJ,CAAC,IAAKA,CAAC;UACjBM,OAAO,EAAE,MAAOkC,CAAC,IAAKA;QACxB;MACF,CAAC,CAAC;MAEFpF,MAAM,CAACgC,QAAQ,CAACqD,OAAO,CAACtC,UAAU,CAAC,CAACuC,WAAW,CAAC,CAAC;MACjDtF,MAAM,CAACgC,QAAQ,CAACuD,SAAS,CAAC,CAAC/C,IAAI,CAAC,SAAS,CAAC;MAC1CxC,MAAM,CAACgC,QAAQ,CAACqB,QAAQ,CAAC,CAACjB,OAAO,CAAC;QAAEO,IAAI,EAAE;MAAO,CAAC,CAAC;IACrD,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"encryption.test.js","names":["describe","expect","test","mock","beforeEach","afterEach","Sprinkle","Type","fs","path","os","withProfile","mockSelect","mockInput","mockPassword","mockSelectCancellable","mockInputCancellable","mockPasswordCancellable","module","select","input","password","selectCancellable","inputCancellable","passwordCancellable","confirmCancellable","tmpDir","mkdtempSync","join","tmpdir","mockClear","rmSync","recursive","force","schema","Object","secret","String","sensitive","title","sprinkle","mockResolvedValueOnce","result","FillInStruct","toEqual","toHaveBeenCalledTimes","calls","message","toBe","not","toHaveBeenCalled","name","p","defaults","toBeUndefined","encryption","encrypt","plain","decrypt","cipher","replace","settings","saveSettings","content","readFileSync","parsed","JSON","parse","sprinkle1","sprinkle2","loadProfile","wallet","key","address","Union","type","Literal","privateKey","outerSchema","network","count","BigInt","opts","Buffer","from","toString","s1","s2","mkdirSync","writeFileSync","stringify","New","c","options","toBeDefined","profileId"],"sources":["../../../../src/Sprinkle/__tests__/encryption.test.ts"],"sourcesContent":["import { describe, expect, test, mock, beforeEach, afterEach } from \"bun:test\";\nimport { Sprinkle, Type } from \"../index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { withProfile } from \"./test-helpers.js\";\n\nconst mockSelect = mock();\nconst mockInput = mock();\nconst mockPassword = mock();\nconst mockSelectCancellable = mock();\nconst mockInputCancellable = mock();\nconst mockPasswordCancellable = mock();\n\nmock.module(\"@inquirer/prompts\", () => ({\n select: mockSelect,\n input: mockInput,\n password: mockPassword,\n}));\n\nmock.module(\"../prompts.js\", () => ({\n selectCancellable: mockSelectCancellable,\n inputCancellable: mockInputCancellable,\n passwordCancellable: mockPasswordCancellable,\n confirmCancellable: mock(),\n}));\n\ndescribe(\"Encryption & Sensitive Fields\", () => {\n let tmpDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sprinkles-enc-test-\"));\n mockSelect.mockClear();\n mockInput.mockClear();\n mockPassword.mockClear();\n mockSelectCancellable.mockClear();\n mockInputCancellable.mockClear();\n mockPasswordCancellable.mockClear();\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n describe(\"sensitive field prompts\", () => {\n test(\"uses password() for sensitive string fields\", async () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true, title: \"Enter secret\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockPasswordCancellable.mockResolvedValueOnce(\"my-secret\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ secret: \"my-secret\" });\n expect(mockPasswordCancellable).toHaveBeenCalledTimes(1);\n expect(mockPasswordCancellable.mock.calls[0][0].message).toBe(\"Enter secret\");\n expect(mockInputCancellable).not.toHaveBeenCalled();\n });\n\n test(\"uses input() for non-sensitive string fields\", async () => {\n const schema = Type.Object({\n name: Type.String({ title: \"Enter name\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockInputCancellable.mockResolvedValueOnce(\"visible\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ name: \"visible\" });\n expect(mockInputCancellable).toHaveBeenCalledTimes(1);\n expect(mockPasswordCancellable).not.toHaveBeenCalled();\n });\n\n test(\"does not remember sensitive field as default\", async () => {\n const schema = Type.String({ sensitive: true });\n const sprinkle = new Sprinkle(Type.Object({ p: Type.String() }), tmpDir);\n\n mockPasswordCancellable.mockResolvedValueOnce(\"secret-val\");\n\n await sprinkle.FillInStruct(schema);\n expect(sprinkle.defaults[\"string\"]).toBeUndefined();\n });\n });\n\n describe(\"encryption on save/load\", () => {\n test(\"encrypts sensitive fields when saving with encryption configured\", () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = { name: \"visible\", secret: \"hidden\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.name).toBe(\"visible\");\n expect(parsed.settings.secret).toBe(\"ENC:hidden\");\n });\n\n test(\"decrypts sensitive fields when loading with encryption configured\", async () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n\n // First save with encryption\n const sprinkle1 = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle1.settings = { name: \"visible\", secret: \"hidden\" } as any;\n sprinkle1.saveSettings();\n\n // Then load with same encryption\n const sprinkle2 = new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n });\n await sprinkle2.loadProfile(\"test\");\n\n expect(sprinkle2.settings).toEqual({ name: \"visible\", secret: \"hidden\" });\n });\n\n test(\"does not encrypt when no encryption configured\", () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(new Sprinkle(schema, tmpDir));\n sprinkle.settings = { secret: \"plain-value\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.secret).toBe(\"plain-value\");\n });\n\n test(\"encrypts nested sensitive fields\", () => {\n const schema = Type.Object({\n wallet: Type.Object({\n key: Type.String({ sensitive: true }),\n address: Type.String(),\n }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { key: \"secret-key\", address: \"addr1...\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.key).toBe(\"ENC:secret-key\");\n expect(parsed.settings.wallet.address).toBe(\"addr1...\");\n });\n\n test(\"handles sensitive fields in union variants\", () => {\n const schema = Type.Union([\n Type.Object({\n type: Type.Literal(\"hot\"),\n privateKey: Type.String({ sensitive: true }),\n }),\n Type.Object({\n type: Type.Literal(\"cold\"),\n address: Type.String(),\n }),\n ]);\n const outerSchema = Type.Object({ wallet: schema });\n const sprinkle = withProfile(\n new Sprinkle(outerSchema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { type: \"hot\", privateKey: \"my-key\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.privateKey).toBe(\"ENC:my-key\");\n });\n\n test(\"round-trip with encryption preserves all data\", async () => {\n const schema = Type.Object({\n network: Type.String(),\n secret: Type.String({ sensitive: true }),\n count: Type.BigInt(),\n });\n const opts = {\n encryption: {\n encrypt: (plain: string) => Buffer.from(plain).toString(\"base64\"),\n decrypt: async (cipher: string) =>\n Buffer.from(cipher, \"base64\").toString(),\n },\n };\n const s1 = withProfile(new Sprinkle(schema, tmpDir, opts));\n s1.settings = {\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n } as any;\n s1.saveSettings();\n\n const s2 = new Sprinkle(schema, tmpDir, opts);\n await s2.loadProfile(\"test\");\n\n expect(s2.settings).toEqual({\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n });\n });\n });\n\n describe(\"Sprinkle.New with options\", () => {\n test(\"passes options through to instance and migrates legacy\", async () => {\n const schema = Type.Object({ name: Type.String() });\n\n // Write legacy settings file so New triggers migration\n fs.mkdirSync(tmpDir, { recursive: true });\n fs.writeFileSync(\n path.join(tmpDir, \"settings.json\"),\n JSON.stringify({ settings: { name: \"test\" }, defaults: {} }),\n );\n\n const sprinkle = await Sprinkle.New(schema, tmpDir, {\n encryption: {\n encrypt: (p) => p,\n decrypt: async (c) => c,\n },\n });\n\n expect(sprinkle.options.encryption).toBeDefined();\n expect(sprinkle.profileId).toBe(\"default\");\n expect(sprinkle.settings).toEqual({ name: \"test\" });\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}