@sundaeswap/sprinkles 0.6.1 → 0.8.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 (197) hide show
  1. package/README.md +178 -181
  2. package/dist/cjs/Sprinkle/__tests__/action-integration.test.js +590 -0
  3. package/dist/cjs/Sprinkle/__tests__/action-integration.test.js.map +1 -0
  4. package/dist/cjs/Sprinkle/__tests__/action-registry.test.js +193 -0
  5. package/dist/cjs/Sprinkle/__tests__/action-registry.test.js.map +1 -0
  6. package/dist/cjs/Sprinkle/__tests__/action-runner.test.js +304 -0
  7. package/dist/cjs/Sprinkle/__tests__/action-runner.test.js.map +1 -0
  8. package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js +1110 -0
  9. package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js.map +1 -0
  10. package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js +744 -0
  11. package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js.map +1 -0
  12. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
  13. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  14. package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js +711 -0
  15. package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -0
  16. package/dist/cjs/Sprinkle/__tests__/native-script.test.js +390 -0
  17. package/dist/cjs/Sprinkle/__tests__/native-script.test.js.map +1 -0
  18. package/dist/cjs/Sprinkle/__tests__/tui-helpers.test.js +334 -0
  19. package/dist/cjs/Sprinkle/__tests__/tui-helpers.test.js.map +1 -0
  20. package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js +367 -0
  21. package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
  22. package/dist/cjs/Sprinkle/__tests__/wallet-transaction-actions.test.js +749 -0
  23. package/dist/cjs/Sprinkle/__tests__/wallet-transaction-actions.test.js.map +1 -0
  24. package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js +164 -0
  25. package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
  26. package/dist/cjs/Sprinkle/actions/builtin/blaze-helper.js +61 -0
  27. package/dist/cjs/Sprinkle/actions/builtin/blaze-helper.js.map +1 -0
  28. package/dist/cjs/Sprinkle/actions/builtin/index.js +174 -0
  29. package/dist/cjs/Sprinkle/actions/builtin/index.js.map +1 -0
  30. package/dist/cjs/Sprinkle/actions/builtin/native-script.js +139 -0
  31. package/dist/cjs/Sprinkle/actions/builtin/native-script.js.map +1 -0
  32. package/dist/cjs/Sprinkle/actions/builtin/profile-actions.js +202 -0
  33. package/dist/cjs/Sprinkle/actions/builtin/profile-actions.js.map +1 -0
  34. package/dist/cjs/Sprinkle/actions/builtin/settings-actions.js +87 -0
  35. package/dist/cjs/Sprinkle/actions/builtin/settings-actions.js.map +1 -0
  36. package/dist/cjs/Sprinkle/actions/builtin/transaction-actions.js +345 -0
  37. package/dist/cjs/Sprinkle/actions/builtin/transaction-actions.js.map +1 -0
  38. package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js +218 -0
  39. package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
  40. package/dist/cjs/Sprinkle/actions/builtin/wallet-actions.js +212 -0
  41. package/dist/cjs/Sprinkle/actions/builtin/wallet-actions.js.map +1 -0
  42. package/dist/cjs/Sprinkle/actions/cli-adapter.js +390 -0
  43. package/dist/cjs/Sprinkle/actions/cli-adapter.js.map +1 -0
  44. package/dist/cjs/Sprinkle/actions/index.js +139 -0
  45. package/dist/cjs/Sprinkle/actions/index.js.map +1 -0
  46. package/dist/cjs/Sprinkle/actions/mcp-adapter.js +557 -0
  47. package/dist/cjs/Sprinkle/actions/mcp-adapter.js.map +1 -0
  48. package/dist/cjs/Sprinkle/actions/registry.js +92 -0
  49. package/dist/cjs/Sprinkle/actions/registry.js.map +1 -0
  50. package/dist/cjs/Sprinkle/actions/runner.js +190 -0
  51. package/dist/cjs/Sprinkle/actions/runner.js.map +1 -0
  52. package/dist/cjs/Sprinkle/actions/tui-helpers.js +96 -0
  53. package/dist/cjs/Sprinkle/actions/tui-helpers.js.map +1 -0
  54. package/dist/cjs/Sprinkle/actions/types.js +68 -0
  55. package/dist/cjs/Sprinkle/actions/types.js.map +1 -0
  56. package/dist/cjs/Sprinkle/index.js +678 -5
  57. package/dist/cjs/Sprinkle/index.js.map +1 -1
  58. package/dist/cjs/Sprinkle/prompts.js +12 -7
  59. package/dist/cjs/Sprinkle/prompts.js.map +1 -1
  60. package/dist/cjs/Sprinkle/schemas.js +17 -1
  61. package/dist/cjs/Sprinkle/schemas.js.map +1 -1
  62. package/dist/cjs/Sprinkle/type-guards.js +7 -1
  63. package/dist/cjs/Sprinkle/type-guards.js.map +1 -1
  64. package/dist/esm/Sprinkle/__tests__/action-integration.test.js +588 -0
  65. package/dist/esm/Sprinkle/__tests__/action-integration.test.js.map +1 -0
  66. package/dist/esm/Sprinkle/__tests__/action-registry.test.js +192 -0
  67. package/dist/esm/Sprinkle/__tests__/action-registry.test.js.map +1 -0
  68. package/dist/esm/Sprinkle/__tests__/action-runner.test.js +302 -0
  69. package/dist/esm/Sprinkle/__tests__/action-runner.test.js.map +1 -0
  70. package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js +1107 -0
  71. package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js.map +1 -0
  72. package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js +742 -0
  73. package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js.map +1 -0
  74. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
  75. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  76. package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js +710 -0
  77. package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -0
  78. package/dist/esm/Sprinkle/__tests__/native-script.test.js +388 -0
  79. package/dist/esm/Sprinkle/__tests__/native-script.test.js.map +1 -0
  80. package/dist/esm/Sprinkle/__tests__/tui-helpers.test.js +332 -0
  81. package/dist/esm/Sprinkle/__tests__/tui-helpers.test.js.map +1 -0
  82. package/dist/esm/Sprinkle/__tests__/utility-actions.test.js +365 -0
  83. package/dist/esm/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
  84. package/dist/esm/Sprinkle/__tests__/wallet-transaction-actions.test.js +747 -0
  85. package/dist/esm/Sprinkle/__tests__/wallet-transaction-actions.test.js.map +1 -0
  86. package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js +159 -0
  87. package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
  88. package/dist/esm/Sprinkle/actions/builtin/blaze-helper.js +55 -0
  89. package/dist/esm/Sprinkle/actions/builtin/blaze-helper.js.map +1 -0
  90. package/dist/esm/Sprinkle/actions/builtin/index.js +37 -0
  91. package/dist/esm/Sprinkle/actions/builtin/index.js.map +1 -0
  92. package/dist/esm/Sprinkle/actions/builtin/native-script.js +133 -0
  93. package/dist/esm/Sprinkle/actions/builtin/native-script.js.map +1 -0
  94. package/dist/esm/Sprinkle/actions/builtin/profile-actions.js +197 -0
  95. package/dist/esm/Sprinkle/actions/builtin/profile-actions.js.map +1 -0
  96. package/dist/esm/Sprinkle/actions/builtin/settings-actions.js +81 -0
  97. package/dist/esm/Sprinkle/actions/builtin/settings-actions.js.map +1 -0
  98. package/dist/esm/Sprinkle/actions/builtin/transaction-actions.js +340 -0
  99. package/dist/esm/Sprinkle/actions/builtin/transaction-actions.js.map +1 -0
  100. package/dist/esm/Sprinkle/actions/builtin/utility-actions.js +213 -0
  101. package/dist/esm/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
  102. package/dist/esm/Sprinkle/actions/builtin/wallet-actions.js +207 -0
  103. package/dist/esm/Sprinkle/actions/builtin/wallet-actions.js.map +1 -0
  104. package/dist/esm/Sprinkle/actions/cli-adapter.js +379 -0
  105. package/dist/esm/Sprinkle/actions/cli-adapter.js.map +1 -0
  106. package/dist/esm/Sprinkle/actions/index.js +12 -0
  107. package/dist/esm/Sprinkle/actions/index.js.map +1 -0
  108. package/dist/esm/Sprinkle/actions/mcp-adapter.js +547 -0
  109. package/dist/esm/Sprinkle/actions/mcp-adapter.js.map +1 -0
  110. package/dist/esm/Sprinkle/actions/registry.js +85 -0
  111. package/dist/esm/Sprinkle/actions/registry.js.map +1 -0
  112. package/dist/esm/Sprinkle/actions/runner.js +182 -0
  113. package/dist/esm/Sprinkle/actions/runner.js.map +1 -0
  114. package/dist/esm/Sprinkle/actions/tui-helpers.js +91 -0
  115. package/dist/esm/Sprinkle/actions/tui-helpers.js.map +1 -0
  116. package/dist/esm/Sprinkle/actions/types.js +61 -0
  117. package/dist/esm/Sprinkle/actions/types.js.map +1 -0
  118. package/dist/esm/Sprinkle/index.js +517 -7
  119. package/dist/esm/Sprinkle/index.js.map +1 -1
  120. package/dist/esm/Sprinkle/prompts.js +12 -7
  121. package/dist/esm/Sprinkle/prompts.js.map +1 -1
  122. package/dist/esm/Sprinkle/schemas.js +16 -0
  123. package/dist/esm/Sprinkle/schemas.js.map +1 -1
  124. package/dist/esm/Sprinkle/type-guards.js +3 -0
  125. package/dist/esm/Sprinkle/type-guards.js.map +1 -1
  126. package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts +50 -0
  127. package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts.map +1 -0
  128. package/dist/types/Sprinkle/actions/builtin/blaze-helper.d.ts +39 -0
  129. package/dist/types/Sprinkle/actions/builtin/blaze-helper.d.ts.map +1 -0
  130. package/dist/types/Sprinkle/actions/builtin/index.d.ts +30 -0
  131. package/dist/types/Sprinkle/actions/builtin/index.d.ts.map +1 -0
  132. package/dist/types/Sprinkle/actions/builtin/native-script.d.ts +27 -0
  133. package/dist/types/Sprinkle/actions/builtin/native-script.d.ts.map +1 -0
  134. package/dist/types/Sprinkle/actions/builtin/profile-actions.d.ts +55 -0
  135. package/dist/types/Sprinkle/actions/builtin/profile-actions.d.ts.map +1 -0
  136. package/dist/types/Sprinkle/actions/builtin/settings-actions.d.ts +32 -0
  137. package/dist/types/Sprinkle/actions/builtin/settings-actions.d.ts.map +1 -0
  138. package/dist/types/Sprinkle/actions/builtin/transaction-actions.d.ts +70 -0
  139. package/dist/types/Sprinkle/actions/builtin/transaction-actions.d.ts.map +1 -0
  140. package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts +48 -0
  141. package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts.map +1 -0
  142. package/dist/types/Sprinkle/actions/builtin/wallet-actions.d.ts +50 -0
  143. package/dist/types/Sprinkle/actions/builtin/wallet-actions.d.ts.map +1 -0
  144. package/dist/types/Sprinkle/actions/cli-adapter.d.ts +104 -0
  145. package/dist/types/Sprinkle/actions/cli-adapter.d.ts.map +1 -0
  146. package/dist/types/Sprinkle/actions/index.d.ts +13 -0
  147. package/dist/types/Sprinkle/actions/index.d.ts.map +1 -0
  148. package/dist/types/Sprinkle/actions/mcp-adapter.d.ts +116 -0
  149. package/dist/types/Sprinkle/actions/mcp-adapter.d.ts.map +1 -0
  150. package/dist/types/Sprinkle/actions/registry.d.ts +42 -0
  151. package/dist/types/Sprinkle/actions/registry.d.ts.map +1 -0
  152. package/dist/types/Sprinkle/actions/runner.d.ts +45 -0
  153. package/dist/types/Sprinkle/actions/runner.d.ts.map +1 -0
  154. package/dist/types/Sprinkle/actions/tui-helpers.d.ts +53 -0
  155. package/dist/types/Sprinkle/actions/tui-helpers.d.ts.map +1 -0
  156. package/dist/types/Sprinkle/actions/types.d.ts +76 -0
  157. package/dist/types/Sprinkle/actions/types.d.ts.map +1 -0
  158. package/dist/types/Sprinkle/index.d.ts +84 -2
  159. package/dist/types/Sprinkle/index.d.ts.map +1 -1
  160. package/dist/types/Sprinkle/prompts.d.ts.map +1 -1
  161. package/dist/types/Sprinkle/schemas.d.ts +72 -0
  162. package/dist/types/Sprinkle/schemas.d.ts.map +1 -1
  163. package/dist/types/Sprinkle/type-guards.d.ts +4 -1
  164. package/dist/types/Sprinkle/type-guards.d.ts.map +1 -1
  165. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  166. package/package.json +9 -2
  167. package/src/Sprinkle/__tests__/action-integration.test.ts +558 -0
  168. package/src/Sprinkle/__tests__/action-registry.test.ts +187 -0
  169. package/src/Sprinkle/__tests__/action-runner.test.ts +324 -0
  170. package/src/Sprinkle/__tests__/builtin-actions.test.ts +1022 -0
  171. package/src/Sprinkle/__tests__/cli-adapter.test.ts +736 -0
  172. package/src/Sprinkle/__tests__/fill-in-struct.test.ts +23 -1
  173. package/src/Sprinkle/__tests__/mcp-adapter.test.ts +720 -0
  174. package/src/Sprinkle/__tests__/native-script.test.ts +341 -0
  175. package/src/Sprinkle/__tests__/tui-helpers.test.ts +325 -0
  176. package/src/Sprinkle/__tests__/utility-actions.test.ts +348 -0
  177. package/src/Sprinkle/__tests__/wallet-transaction-actions.test.ts +695 -0
  178. package/src/Sprinkle/actions/builtin/addressbook-actions.ts +168 -0
  179. package/src/Sprinkle/actions/builtin/blaze-helper.ts +89 -0
  180. package/src/Sprinkle/actions/builtin/index.ts +125 -0
  181. package/src/Sprinkle/actions/builtin/native-script.ts +165 -0
  182. package/src/Sprinkle/actions/builtin/profile-actions.ts +229 -0
  183. package/src/Sprinkle/actions/builtin/settings-actions.ts +99 -0
  184. package/src/Sprinkle/actions/builtin/transaction-actions.ts +381 -0
  185. package/src/Sprinkle/actions/builtin/utility-actions.ts +285 -0
  186. package/src/Sprinkle/actions/builtin/wallet-actions.ts +233 -0
  187. package/src/Sprinkle/actions/cli-adapter.ts +446 -0
  188. package/src/Sprinkle/actions/index.ts +33 -0
  189. package/src/Sprinkle/actions/mcp-adapter.ts +638 -0
  190. package/src/Sprinkle/actions/registry.ts +97 -0
  191. package/src/Sprinkle/actions/runner.ts +200 -0
  192. package/src/Sprinkle/actions/tui-helpers.ts +114 -0
  193. package/src/Sprinkle/actions/types.ts +91 -0
  194. package/src/Sprinkle/index.ts +612 -3
  195. package/src/Sprinkle/prompts.ts +118 -72
  196. package/src/Sprinkle/schemas.ts +20 -0
  197. package/src/Sprinkle/type-guards.ts +9 -0
@@ -0,0 +1,348 @@
1
+ import { describe, expect, test, mock, beforeEach } from "bun:test";
2
+ import { ActionError } from "../actions/types.js";
3
+
4
+ // ---------------------------------------------------------------------------
5
+ // Mocks
6
+ // ---------------------------------------------------------------------------
7
+
8
+ // Controllable mock state
9
+ let mockBlaze: any = {};
10
+ let mockIsHot = true;
11
+ let mockBlazeError: Error | null = null;
12
+
13
+ mock.module("../actions/builtin/blaze-helper.js", () => ({
14
+ getBlazeFromContext: async () => {
15
+ if (mockBlazeError) throw mockBlazeError;
16
+ return mockBlaze;
17
+ },
18
+ isHotWallet: () => mockIsHot,
19
+ }));
20
+
21
+ // Track calls to blaze transaction builder
22
+ let mintCalls: Array<{ policyId: string; mints: Map<string, bigint> }> = [];
23
+ let provideScriptCalls: any[] = [];
24
+ let payAssetsCalls: Array<{ address: any; value: any }> = [];
25
+ let registerStakeCalls: any[] = [];
26
+
27
+ // Mock transaction returned by complete()
28
+ const mockCompletedTx = {
29
+ toCbor: () => "mock-tx-cbor-hex",
30
+ };
31
+
32
+ // Mock transaction builder chain
33
+ function makeTxBuilder() {
34
+ return {
35
+ addMint: (policyId: string, mints: Map<string, bigint>) => {
36
+ mintCalls.push({ policyId, mints });
37
+ return makeTxBuilder();
38
+ },
39
+ provideScript: (script: any) => {
40
+ provideScriptCalls.push(script);
41
+ return makeTxBuilder();
42
+ },
43
+ payAssets: (address: any, value: any) => {
44
+ payAssetsCalls.push({ address, value });
45
+ return makeTxBuilder();
46
+ },
47
+ addRegisterStake: (credential: any) => {
48
+ registerStakeCalls.push(credential);
49
+ return makeTxBuilder();
50
+ },
51
+ complete: async () => mockCompletedTx,
52
+ };
53
+ }
54
+
55
+ // Mock address with payment credential
56
+ function makeMockAddress(hash = "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234") {
57
+ return {
58
+ toBech32: () => "addr_test1qzmock",
59
+ asBase: () => ({
60
+ getPaymentCredential: () => ({
61
+ hash: { toString: () => hash },
62
+ }),
63
+ }),
64
+ };
65
+ }
66
+
67
+ mock.module("@blaze-cardano/sdk", () => ({
68
+ Core: {
69
+ Ed25519KeyHashHex: (h: string) => h,
70
+ ScriptPubkey: class {
71
+ hash: string;
72
+ constructor(h: string) { this.hash = h; }
73
+ },
74
+ Script: {
75
+ newNativeScript: (ns: any) => ({
76
+ hash: () => "mock-policy-id-hash",
77
+ }),
78
+ },
79
+ NativeScript: {
80
+ newScriptPubkey: (sp: any) => sp,
81
+ },
82
+ PolicyId: (s: string) => s,
83
+ AssetName: (s: string) => s,
84
+ toHex: (buf: Buffer) => buf.toString("hex"),
85
+ Address: {
86
+ fromBech32: (addr: string) => {
87
+ if (addr === "invalid-address") throw new Error("Invalid bech32");
88
+ return { toBech32: () => addr };
89
+ },
90
+ },
91
+ TxCBOR: (s: string) => s,
92
+ Hash28ByteBase16: (s: string) => s,
93
+ Credential: {
94
+ fromCore: (c: any) => c,
95
+ },
96
+ CredentialType: {
97
+ ScriptHash: 1,
98
+ },
99
+ },
100
+ makeValue: (...args: any[]) => ({ __makeValueArgs: args }),
101
+ Blaze: class {},
102
+ HotWallet: class {},
103
+ }));
104
+
105
+ // Import actions after mocks are set up
106
+ const { mintToken, simpleSend, registerStakeScript } = await import(
107
+ "../actions/builtin/utility-actions.js"
108
+ );
109
+
110
+ // Minimal context factory
111
+ function makeContext(settingsOverrides: Record<string, unknown> = {}) {
112
+ return {
113
+ sprinkle: {} as any,
114
+ settings: {
115
+ network: "preview",
116
+ provider: { type: "blockfrost", apiKey: "test" },
117
+ wallet: { type: "hot", mnemonic: "test words" },
118
+ ...settingsOverrides,
119
+ } as any,
120
+ };
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // mint-token
125
+ // ---------------------------------------------------------------------------
126
+
127
+ describe("mint-token", () => {
128
+ beforeEach(() => {
129
+ mockBlazeError = null;
130
+ mockIsHot = true;
131
+ mintCalls = [];
132
+ provideScriptCalls = [];
133
+ mockBlaze = {
134
+ wallet: {
135
+ getChangeAddress: async () => makeMockAddress(),
136
+ },
137
+ newTransaction: () => makeTxBuilder(),
138
+ };
139
+ });
140
+
141
+ test("has correct metadata", () => {
142
+ expect(mintToken.name).toBe("mint-token");
143
+ expect(mintToken.category).toBe("utility");
144
+ });
145
+
146
+ test("builds a mint transaction and returns policy info", async () => {
147
+ const ctx = makeContext();
148
+ const result = await mintToken.execute(
149
+ { tokenName: "MyToken", amount: "1000" },
150
+ ctx,
151
+ );
152
+ expect(result.policyId).toBe("mock-policy-id-hash");
153
+ expect(result.tokenName).toBe("MyToken");
154
+ expect(result.amount).toBe("1000");
155
+ expect(result.txCbor).toBe("mock-tx-cbor-hex");
156
+ expect(mintCalls).toHaveLength(1);
157
+ expect(provideScriptCalls).toHaveLength(1);
158
+ });
159
+
160
+ test("throws COLD_WALLET when wallet is not hot", async () => {
161
+ mockIsHot = false;
162
+ const ctx = makeContext();
163
+ await expect(
164
+ mintToken.execute({ tokenName: "T", amount: "1" }, ctx),
165
+ ).rejects.toMatchObject({ code: "COLD_WALLET" });
166
+ });
167
+
168
+ test("throws WALLET_NOT_CONFIGURED when blaze init fails", async () => {
169
+ mockBlazeError = new ActionError(
170
+ "Missing settings",
171
+ "WALLET_NOT_CONFIGURED",
172
+ { missingFields: ["wallet"] },
173
+ );
174
+ const ctx = makeContext();
175
+ await expect(
176
+ mintToken.execute({ tokenName: "T", amount: "1" }, ctx),
177
+ ).rejects.toMatchObject({ code: "WALLET_NOT_CONFIGURED" });
178
+ });
179
+
180
+ test("throws NO_ADDRESS when getChangeAddress fails", async () => {
181
+ mockBlaze = {
182
+ wallet: {
183
+ getChangeAddress: async () => {
184
+ throw new Error("no address");
185
+ },
186
+ },
187
+ newTransaction: () => makeTxBuilder(),
188
+ };
189
+ const ctx = makeContext();
190
+ await expect(
191
+ mintToken.execute({ tokenName: "T", amount: "1" }, ctx),
192
+ ).rejects.toMatchObject({ code: "NO_ADDRESS" });
193
+ });
194
+
195
+ test("throws INVALID_ADDRESS when base address is null", async () => {
196
+ mockBlaze = {
197
+ wallet: {
198
+ getChangeAddress: async () => ({
199
+ toBech32: () => "addr_test1...",
200
+ asBase: () => null,
201
+ }),
202
+ },
203
+ newTransaction: () => makeTxBuilder(),
204
+ };
205
+ const ctx = makeContext();
206
+ await expect(
207
+ mintToken.execute({ tokenName: "T", amount: "1" }, ctx),
208
+ ).rejects.toMatchObject({ code: "INVALID_ADDRESS" });
209
+ });
210
+ });
211
+
212
+ // ---------------------------------------------------------------------------
213
+ // simple-send
214
+ // ---------------------------------------------------------------------------
215
+
216
+ describe("simple-send", () => {
217
+ beforeEach(() => {
218
+ mockBlazeError = null;
219
+ mockIsHot = true;
220
+ payAssetsCalls = [];
221
+ mockBlaze = {
222
+ newTransaction: () => makeTxBuilder(),
223
+ };
224
+ });
225
+
226
+ test("has correct metadata", () => {
227
+ expect(simpleSend.name).toBe("simple-send");
228
+ expect(simpleSend.category).toBe("wallet");
229
+ });
230
+
231
+ test("builds a lovelace-only send transaction", async () => {
232
+ const ctx = makeContext();
233
+ const result = await simpleSend.execute(
234
+ { recipientAddress: "addr_test1qzrecipient", lovelace: "5000000" },
235
+ ctx,
236
+ );
237
+ expect(result.txCbor).toBe("mock-tx-cbor-hex");
238
+ expect(payAssetsCalls).toHaveLength(1);
239
+ });
240
+
241
+ test("builds a token send transaction", async () => {
242
+ const ctx = makeContext();
243
+ const result = await simpleSend.execute(
244
+ {
245
+ recipientAddress: "addr_test1qzrecipient",
246
+ policyId: "a".repeat(56),
247
+ assetName: "4d79546f6b656e",
248
+ tokenAmount: "100",
249
+ },
250
+ ctx,
251
+ );
252
+ expect(result.txCbor).toBe("mock-tx-cbor-hex");
253
+ expect(payAssetsCalls).toHaveLength(1);
254
+ });
255
+
256
+ test("throws INVALID_INPUT when neither lovelace nor token provided", async () => {
257
+ const ctx = makeContext();
258
+ await expect(
259
+ simpleSend.execute({ recipientAddress: "addr_test1qzrecipient" }, ctx),
260
+ ).rejects.toMatchObject({ code: "INVALID_INPUT" });
261
+ });
262
+
263
+ test("throws INVALID_ADDRESS for bad recipient", async () => {
264
+ const ctx = makeContext();
265
+ await expect(
266
+ simpleSend.execute(
267
+ { recipientAddress: "invalid-address", lovelace: "1000000" },
268
+ ctx,
269
+ ),
270
+ ).rejects.toMatchObject({ code: "INVALID_ADDRESS" });
271
+ });
272
+
273
+ test("throws WALLET_NOT_CONFIGURED when blaze init fails", async () => {
274
+ mockBlazeError = new ActionError(
275
+ "Missing settings",
276
+ "WALLET_NOT_CONFIGURED",
277
+ { missingFields: ["wallet"] },
278
+ );
279
+ const ctx = makeContext();
280
+ await expect(
281
+ simpleSend.execute(
282
+ { recipientAddress: "addr_test1qz", lovelace: "1000000" },
283
+ ctx,
284
+ ),
285
+ ).rejects.toMatchObject({ code: "WALLET_NOT_CONFIGURED" });
286
+ });
287
+ });
288
+
289
+ // ---------------------------------------------------------------------------
290
+ // register-stake-script
291
+ // ---------------------------------------------------------------------------
292
+
293
+ describe("register-stake-script", () => {
294
+ beforeEach(() => {
295
+ mockBlazeError = null;
296
+ mockIsHot = true;
297
+ registerStakeCalls = [];
298
+ mockBlaze = {
299
+ newTransaction: () => makeTxBuilder(),
300
+ };
301
+ });
302
+
303
+ test("has correct metadata", () => {
304
+ expect(registerStakeScript.name).toBe("register-stake-script");
305
+ expect(registerStakeScript.category).toBe("utility");
306
+ });
307
+
308
+ test("builds a stake registration transaction", async () => {
309
+ const validHash = "a".repeat(56);
310
+ const ctx = makeContext();
311
+ const result = await registerStakeScript.execute(
312
+ { scriptHash: validHash },
313
+ ctx,
314
+ );
315
+ expect(result.txCbor).toBe("mock-tx-cbor-hex");
316
+ expect(registerStakeCalls).toHaveLength(1);
317
+ expect(registerStakeCalls[0]).toMatchObject({
318
+ hash: validHash,
319
+ type: 1, // ScriptHash
320
+ });
321
+ });
322
+
323
+ test("throws INVALID_SCRIPT_HASH for wrong length", async () => {
324
+ const ctx = makeContext();
325
+ await expect(
326
+ registerStakeScript.execute({ scriptHash: "tooshort" }, ctx),
327
+ ).rejects.toMatchObject({ code: "INVALID_SCRIPT_HASH" });
328
+ });
329
+
330
+ test("throws INVALID_SCRIPT_HASH for non-hex characters", async () => {
331
+ const ctx = makeContext();
332
+ await expect(
333
+ registerStakeScript.execute({ scriptHash: "g".repeat(56) }, ctx),
334
+ ).rejects.toMatchObject({ code: "INVALID_SCRIPT_HASH" });
335
+ });
336
+
337
+ test("throws WALLET_NOT_CONFIGURED when blaze init fails", async () => {
338
+ mockBlazeError = new ActionError(
339
+ "Missing settings",
340
+ "WALLET_NOT_CONFIGURED",
341
+ { missingFields: ["provider"] },
342
+ );
343
+ const ctx = makeContext();
344
+ await expect(
345
+ registerStakeScript.execute({ scriptHash: "a".repeat(56) }, ctx),
346
+ ).rejects.toMatchObject({ code: "WALLET_NOT_CONFIGURED" });
347
+ });
348
+ });