@sundaeswap/sprinkles 0.7.0 → 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.
- package/README.md +178 -181
- package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js +4 -4
- package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js +25 -3
- package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js +7 -9
- package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/native-script.test.js +390 -0
- package/dist/cjs/Sprinkle/__tests__/native-script.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js +367 -0
- package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js +164 -0
- package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/index.js +60 -3
- package/dist/cjs/Sprinkle/actions/builtin/index.js.map +1 -1
- package/dist/cjs/Sprinkle/actions/builtin/native-script.js +139 -0
- package/dist/cjs/Sprinkle/actions/builtin/native-script.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js +218 -0
- package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/cli-adapter.js +20 -2
- package/dist/cjs/Sprinkle/actions/cli-adapter.js.map +1 -1
- package/dist/cjs/Sprinkle/actions/index.js +12 -0
- package/dist/cjs/Sprinkle/actions/index.js.map +1 -1
- package/dist/cjs/Sprinkle/actions/mcp-adapter.js +146 -4
- package/dist/cjs/Sprinkle/actions/mcp-adapter.js.map +1 -1
- package/dist/cjs/Sprinkle/index.js +267 -5
- package/dist/cjs/Sprinkle/index.js.map +1 -1
- package/dist/cjs/Sprinkle/schemas.js +17 -1
- package/dist/cjs/Sprinkle/schemas.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js +4 -4
- package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js +25 -3
- package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js +7 -9
- package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/native-script.test.js +388 -0
- package/dist/esm/Sprinkle/__tests__/native-script.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/utility-actions.test.js +365 -0
- package/dist/esm/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js +159 -0
- package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/index.js +8 -3
- package/dist/esm/Sprinkle/actions/builtin/index.js.map +1 -1
- package/dist/esm/Sprinkle/actions/builtin/native-script.js +133 -0
- package/dist/esm/Sprinkle/actions/builtin/native-script.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/utility-actions.js +213 -0
- package/dist/esm/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/cli-adapter.js +20 -2
- package/dist/esm/Sprinkle/actions/cli-adapter.js.map +1 -1
- package/dist/esm/Sprinkle/actions/index.js +1 -1
- package/dist/esm/Sprinkle/actions/index.js.map +1 -1
- package/dist/esm/Sprinkle/actions/mcp-adapter.js +145 -5
- package/dist/esm/Sprinkle/actions/mcp-adapter.js.map +1 -1
- package/dist/esm/Sprinkle/index.js +259 -8
- package/dist/esm/Sprinkle/index.js.map +1 -1
- package/dist/esm/Sprinkle/schemas.js +16 -0
- package/dist/esm/Sprinkle/schemas.js.map +1 -1
- package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts +50 -0
- package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/index.d.ts +6 -2
- package/dist/types/Sprinkle/actions/builtin/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/actions/builtin/native-script.d.ts +27 -0
- package/dist/types/Sprinkle/actions/builtin/native-script.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts +48 -0
- package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/cli-adapter.d.ts.map +1 -1
- package/dist/types/Sprinkle/actions/index.d.ts +2 -1
- package/dist/types/Sprinkle/actions/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/actions/mcp-adapter.d.ts +24 -0
- package/dist/types/Sprinkle/actions/mcp-adapter.d.ts.map +1 -1
- package/dist/types/Sprinkle/index.d.ts +3 -1
- package/dist/types/Sprinkle/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/schemas.d.ts +72 -0
- package/dist/types/Sprinkle/schemas.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Sprinkle/__tests__/builtin-actions.test.ts +4 -4
- package/src/Sprinkle/__tests__/cli-adapter.test.ts +24 -3
- package/src/Sprinkle/__tests__/fill-in-struct.test.ts +23 -1
- package/src/Sprinkle/__tests__/mcp-adapter.test.ts +7 -5
- package/src/Sprinkle/__tests__/native-script.test.ts +341 -0
- package/src/Sprinkle/__tests__/utility-actions.test.ts +348 -0
- package/src/Sprinkle/actions/builtin/addressbook-actions.ts +168 -0
- package/src/Sprinkle/actions/builtin/index.ts +41 -2
- package/src/Sprinkle/actions/builtin/native-script.ts +165 -0
- package/src/Sprinkle/actions/builtin/utility-actions.ts +285 -0
- package/src/Sprinkle/actions/cli-adapter.ts +18 -2
- package/src/Sprinkle/actions/index.ts +2 -1
- package/src/Sprinkle/actions/mcp-adapter.ts +179 -4
- package/src/Sprinkle/index.ts +261 -3
- package/src/Sprinkle/schemas.ts +20 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Barrel export for built-in Sprinkle actions.
|
|
3
3
|
*
|
|
4
|
-
* Provides a `getBuiltinActions()` factory that returns all
|
|
4
|
+
* Provides a `getBuiltinActions()` factory that returns all 17 built-in actions
|
|
5
5
|
* ready for registration on an ActionRegistry.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -9,13 +9,18 @@ export { listProfiles, getProfile, setProfile, createProfile, deleteProfile } fr
|
|
|
9
9
|
export { getSettings, updateSettings } from "./settings-actions.js";
|
|
10
10
|
export { getWalletAddress, getWalletBalance, getWalletUtxos } from "./wallet-actions.js";
|
|
11
11
|
export { signTransaction, submitTransaction, signAndSubmit, decodeTransaction } from "./transaction-actions.js";
|
|
12
|
+
export { mintToken, simpleSend, registerStakeScript } from "./utility-actions.js";
|
|
13
|
+
export { toNativeScript, completeWithScripts } from "./native-script.js";
|
|
14
|
+
export { listAddressbook, getAddressbookEntry, setAddressbookEntry, deleteAddressbookEntry } from "./addressbook-actions.js";
|
|
12
15
|
import { listProfiles, getProfile, setProfile, createProfile, deleteProfile } from "./profile-actions.js";
|
|
13
16
|
import { getSettings, updateSettings } from "./settings-actions.js";
|
|
14
17
|
import { getWalletAddress, getWalletBalance, getWalletUtxos } from "./wallet-actions.js";
|
|
15
18
|
import { signTransaction, submitTransaction, signAndSubmit, decodeTransaction } from "./transaction-actions.js";
|
|
19
|
+
import { mintToken, simpleSend, registerStakeScript } from "./utility-actions.js";
|
|
20
|
+
import { listAddressbook, getAddressbookEntry, setAddressbookEntry, deleteAddressbookEntry } from "./addressbook-actions.js";
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
|
-
* Returns
|
|
23
|
+
* Returns all built-in Sprinkle actions.
|
|
19
24
|
* Register them on your ActionRegistry or pass them to `Sprinkle.run()`.
|
|
20
25
|
*
|
|
21
26
|
* @example
|
|
@@ -27,6 +32,6 @@ import { signTransaction, submitTransaction, signAndSubmit, decodeTransaction }
|
|
|
27
32
|
* ```
|
|
28
33
|
*/
|
|
29
34
|
export function getBuiltinActions() {
|
|
30
|
-
return [listProfiles, getProfile, setProfile, createProfile, deleteProfile, getSettings, updateSettings, getWalletAddress, getWalletBalance, getWalletUtxos, signTransaction, submitTransaction, signAndSubmit, decodeTransaction];
|
|
35
|
+
return [listProfiles, getProfile, setProfile, createProfile, deleteProfile, getSettings, updateSettings, getWalletAddress, getWalletBalance, getWalletUtxos, signTransaction, submitTransaction, signAndSubmit, decodeTransaction, mintToken, simpleSend, registerStakeScript, listAddressbook, getAddressbookEntry, setAddressbookEntry, deleteAddressbookEntry];
|
|
31
36
|
}
|
|
32
37
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["listProfiles","getProfile","setProfile","createProfile","deleteProfile","getSettings","updateSettings","getWalletAddress","getWalletBalance","getWalletUtxos","signTransaction","submitTransaction","signAndSubmit","decodeTransaction","getBuiltinActions"],"sources":["../../../../../src/Sprinkle/actions/builtin/index.ts"],"sourcesContent":["/**\n * Barrel export for built-in Sprinkle actions.\n *\n * Provides a `getBuiltinActions()` factory that returns all
|
|
1
|
+
{"version":3,"file":"index.js","names":["listProfiles","getProfile","setProfile","createProfile","deleteProfile","getSettings","updateSettings","getWalletAddress","getWalletBalance","getWalletUtxos","signTransaction","submitTransaction","signAndSubmit","decodeTransaction","mintToken","simpleSend","registerStakeScript","toNativeScript","completeWithScripts","listAddressbook","getAddressbookEntry","setAddressbookEntry","deleteAddressbookEntry","getBuiltinActions"],"sources":["../../../../../src/Sprinkle/actions/builtin/index.ts"],"sourcesContent":["/**\n * Barrel export for built-in Sprinkle actions.\n *\n * Provides a `getBuiltinActions()` factory that returns all 17 built-in actions\n * ready for registration on an ActionRegistry.\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { AnyAction } from \"../types.js\";\n\nexport {\n listProfiles,\n getProfile,\n setProfile,\n createProfile,\n deleteProfile,\n} from \"./profile-actions.js\";\n\nexport { getSettings, updateSettings } from \"./settings-actions.js\";\n\nexport {\n getWalletAddress,\n getWalletBalance,\n getWalletUtxos,\n} from \"./wallet-actions.js\";\n\nexport {\n signTransaction,\n submitTransaction,\n signAndSubmit,\n decodeTransaction,\n} from \"./transaction-actions.js\";\n\nexport {\n mintToken,\n simpleSend,\n registerStakeScript,\n} from \"./utility-actions.js\";\n\nexport {\n toNativeScript,\n completeWithScripts,\n} from \"./native-script.js\";\nexport type { NativeScriptInput } from \"./native-script.js\";\n\nexport {\n listAddressbook,\n getAddressbookEntry,\n setAddressbookEntry,\n deleteAddressbookEntry,\n} from \"./addressbook-actions.js\";\n\nimport {\n listProfiles,\n getProfile,\n setProfile,\n createProfile,\n deleteProfile,\n} from \"./profile-actions.js\";\n\nimport { getSettings, updateSettings } from \"./settings-actions.js\";\n\nimport {\n getWalletAddress,\n getWalletBalance,\n getWalletUtxos,\n} from \"./wallet-actions.js\";\n\nimport {\n signTransaction,\n submitTransaction,\n signAndSubmit,\n decodeTransaction,\n} from \"./transaction-actions.js\";\n\nimport {\n mintToken,\n simpleSend,\n registerStakeScript,\n} from \"./utility-actions.js\";\n\nimport {\n listAddressbook,\n getAddressbookEntry,\n setAddressbookEntry,\n deleteAddressbookEntry,\n} from \"./addressbook-actions.js\";\n\n/**\n * Returns all built-in Sprinkle actions.\n * Register them on your ActionRegistry or pass them to `Sprinkle.run()`.\n *\n * @example\n * ```ts\n * const sprinkle = new Sprinkle(MySchema, storagePath);\n * for (const action of getBuiltinActions()) {\n * sprinkle.registerAction(action);\n * }\n * ```\n */\nexport function getBuiltinActions<S extends TSchema>(): AnyAction<S>[] {\n return [\n listProfiles,\n getProfile,\n setProfile,\n createProfile,\n deleteProfile,\n getSettings,\n updateSettings,\n getWalletAddress,\n getWalletBalance,\n getWalletUtxos,\n signTransaction,\n submitTransaction,\n signAndSubmit,\n decodeTransaction,\n mintToken,\n simpleSend,\n registerStakeScript,\n listAddressbook,\n getAddressbookEntry,\n setAddressbookEntry,\n deleteAddressbookEntry,\n ] as unknown as AnyAction<S>[];\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;;AAKA,SACEA,YAAY,EACZC,UAAU,EACVC,UAAU,EACVC,aAAa,EACbC,aAAa,QACR,sBAAsB;AAE7B,SAASC,WAAW,EAAEC,cAAc,QAAQ,uBAAuB;AAEnE,SACEC,gBAAgB,EAChBC,gBAAgB,EAChBC,cAAc,QACT,qBAAqB;AAE5B,SACEC,eAAe,EACfC,iBAAiB,EACjBC,aAAa,EACbC,iBAAiB,QACZ,0BAA0B;AAEjC,SACEC,SAAS,EACTC,UAAU,EACVC,mBAAmB,QACd,sBAAsB;AAE7B,SACEC,cAAc,EACdC,mBAAmB,QACd,oBAAoB;AAG3B,SACEC,eAAe,EACfC,mBAAmB,EACnBC,mBAAmB,EACnBC,sBAAsB,QACjB,0BAA0B;AAEjC,SACEtB,YAAY,EACZC,UAAU,EACVC,UAAU,EACVC,aAAa,EACbC,aAAa,QACR,sBAAsB;AAE7B,SAASC,WAAW,EAAEC,cAAc,QAAQ,uBAAuB;AAEnE,SACEC,gBAAgB,EAChBC,gBAAgB,EAChBC,cAAc,QACT,qBAAqB;AAE5B,SACEC,eAAe,EACfC,iBAAiB,EACjBC,aAAa,EACbC,iBAAiB,QACZ,0BAA0B;AAEjC,SACEC,SAAS,EACTC,UAAU,EACVC,mBAAmB,QACd,sBAAsB;AAE7B,SACEG,eAAe,EACfC,mBAAmB,EACnBC,mBAAmB,EACnBC,sBAAsB,QACjB,0BAA0B;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAAA,EAAsC;EACrE,OAAO,CACLvB,YAAY,EACZC,UAAU,EACVC,UAAU,EACVC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,cAAc,EACdC,gBAAgB,EAChBC,gBAAgB,EAChBC,cAAc,EACdC,eAAe,EACfC,iBAAiB,EACjBC,aAAa,EACbC,iBAAiB,EACjBC,SAAS,EACTC,UAAU,EACVC,mBAAmB,EACnBG,eAAe,EACfC,mBAAmB,EACnBC,mBAAmB,EACnBC,sBAAsB,CACvB;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native script utilities for Sprinkle actions.
|
|
3
|
+
*
|
|
4
|
+
* Provides conversion from user-friendly input formats (CBOR hex or structured JSON)
|
|
5
|
+
* to Blaze NativeScript objects, and a helper to attach scripts during tx completion.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Core } from "@blaze-cardano/sdk";
|
|
9
|
+
import { ActionError } from "../types.js";
|
|
10
|
+
|
|
11
|
+
/** Input type: either a CBOR hex string or a MultisigScript JSON structure */
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Converts a MultisigScript JSON structure to a Blaze NativeScript.
|
|
15
|
+
* Handles the recursive structure (AllOf, AnyOf, AtLeast contain nested scripts).
|
|
16
|
+
*/
|
|
17
|
+
function multisigToNativeScript(ms) {
|
|
18
|
+
if ("Signature" in ms) {
|
|
19
|
+
const hash = Core.Ed25519KeyHashHex(ms.Signature.key_hash);
|
|
20
|
+
return Core.NativeScript.newScriptPubkey(new Core.ScriptPubkey(hash));
|
|
21
|
+
}
|
|
22
|
+
if ("AllOf" in ms) {
|
|
23
|
+
const scripts = ms.AllOf.scripts.map(multisigToNativeScript);
|
|
24
|
+
return Core.NativeScript.newScriptAll(new Core.ScriptAll(scripts));
|
|
25
|
+
}
|
|
26
|
+
if ("AnyOf" in ms) {
|
|
27
|
+
const scripts = ms.AnyOf.scripts.map(multisigToNativeScript);
|
|
28
|
+
return Core.NativeScript.newScriptAny(new Core.ScriptAny(scripts));
|
|
29
|
+
}
|
|
30
|
+
if ("AtLeast" in ms) {
|
|
31
|
+
const scripts = ms.AtLeast.scripts.map(multisigToNativeScript);
|
|
32
|
+
return Core.NativeScript.newScriptNOfK(new Core.ScriptNOfK(scripts, Number(ms.AtLeast.required)));
|
|
33
|
+
}
|
|
34
|
+
if ("Before" in ms) {
|
|
35
|
+
return Core.NativeScript.newTimelockExpiry(new Core.TimelockExpiry(Core.Slot(Number(ms.Before.time))));
|
|
36
|
+
}
|
|
37
|
+
if ("After" in ms) {
|
|
38
|
+
return Core.NativeScript.newTimelockStart(new Core.TimelockStart(Core.Slot(Number(ms.After.time))));
|
|
39
|
+
}
|
|
40
|
+
if ("Script" in ms) {
|
|
41
|
+
// Script variant references a script by hash — this is a ScriptPubkey
|
|
42
|
+
// but using the script hash directly as a key hash reference
|
|
43
|
+
const hash = Core.Ed25519KeyHashHex(ms.Script.script_hash);
|
|
44
|
+
return Core.NativeScript.newScriptPubkey(new Core.ScriptPubkey(hash));
|
|
45
|
+
}
|
|
46
|
+
throw new ActionError("Unrecognized MultisigScript variant", "INVALID_NATIVE_SCRIPT", {
|
|
47
|
+
input: ms
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Converts a native script input (CBOR hex string or MultisigScript JSON)
|
|
53
|
+
* to a Blaze Script object suitable for `provideScript()`.
|
|
54
|
+
*/
|
|
55
|
+
export function toNativeScript(input) {
|
|
56
|
+
if (typeof input === "string") {
|
|
57
|
+
try {
|
|
58
|
+
const nativeScript = Core.NativeScript.fromCbor(Core.HexBlob(input));
|
|
59
|
+
return Core.Script.newNativeScript(nativeScript);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
throw new ActionError(`Invalid native script CBOR: ${err instanceof Error ? err.message : String(err)}`, "INVALID_NATIVE_SCRIPT", {
|
|
62
|
+
error: err instanceof Error ? err.message : String(err)
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const nativeScript = multisigToNativeScript(input);
|
|
68
|
+
return Core.Script.newNativeScript(nativeScript);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
if (err instanceof ActionError) throw err;
|
|
71
|
+
throw new ActionError(`Failed to convert MultisigScript to native script: ${err instanceof Error ? err.message : String(err)}`, "INVALID_NATIVE_SCRIPT", {
|
|
72
|
+
error: err instanceof Error ? err.message : String(err)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Regex to extract a script hash from Blaze's "Could not resolve script hash" error */
|
|
78
|
+
const MISSING_SCRIPT_HASH_RE = /complete: Could not resolve script hash[: ]*([0-9a-fA-F]+)/;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Builds a hash → Script lookup from the addressbook in the sprinkle context.
|
|
82
|
+
* Returns an empty map if there's no addressbook.
|
|
83
|
+
*/
|
|
84
|
+
function buildAddressbookIndex(addressbook) {
|
|
85
|
+
const index = new Map();
|
|
86
|
+
if (!addressbook) return index;
|
|
87
|
+
for (const [, ms] of Object.entries(addressbook)) {
|
|
88
|
+
try {
|
|
89
|
+
const script = toNativeScript(ms);
|
|
90
|
+
index.set(script.hash(), script);
|
|
91
|
+
} catch {
|
|
92
|
+
// Skip invalid addressbook entries
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return index;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Attaches optional native scripts to a transaction builder and completes it.
|
|
100
|
+
*
|
|
101
|
+
* If completion fails because Blaze cannot resolve a required native script hash,
|
|
102
|
+
* and a context with an addressbook is provided, it will look up the missing script
|
|
103
|
+
* by hash in the addressbook and retry once.
|
|
104
|
+
*/
|
|
105
|
+
export async function completeWithScripts(txBuilder, nativeScripts, context) {
|
|
106
|
+
if (nativeScripts?.length) {
|
|
107
|
+
for (const input of nativeScripts) {
|
|
108
|
+
txBuilder.provideScript(toNativeScript(input));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return await txBuilder.complete();
|
|
113
|
+
} catch (err) {
|
|
114
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
115
|
+
const match = message.match(MISSING_SCRIPT_HASH_RE);
|
|
116
|
+
if (!match || !context?.sprinkle?.addressbook) {
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Build hash index from addressbook and try to resolve the missing script
|
|
121
|
+
const addressbookIndex = buildAddressbookIndex(context.sprinkle.addressbook);
|
|
122
|
+
const missingHash = match[1];
|
|
123
|
+
const script = addressbookIndex.get(missingHash);
|
|
124
|
+
if (!script) {
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Attach the found script and retry
|
|
129
|
+
txBuilder.provideScript(script);
|
|
130
|
+
return txBuilder.complete();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=native-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-script.js","names":["Core","ActionError","multisigToNativeScript","ms","hash","Ed25519KeyHashHex","Signature","key_hash","NativeScript","newScriptPubkey","ScriptPubkey","scripts","AllOf","map","newScriptAll","ScriptAll","AnyOf","newScriptAny","ScriptAny","AtLeast","newScriptNOfK","ScriptNOfK","Number","required","newTimelockExpiry","TimelockExpiry","Slot","Before","time","newTimelockStart","TimelockStart","After","Script","script_hash","input","toNativeScript","nativeScript","fromCbor","HexBlob","newNativeScript","err","Error","message","String","error","MISSING_SCRIPT_HASH_RE","buildAddressbookIndex","addressbook","index","Map","Object","entries","script","set","completeWithScripts","txBuilder","nativeScripts","context","length","provideScript","complete","match","sprinkle","addressbookIndex","missingHash","get"],"sources":["../../../../../src/Sprinkle/actions/builtin/native-script.ts"],"sourcesContent":["/**\n * Native script utilities for Sprinkle actions.\n *\n * Provides conversion from user-friendly input formats (CBOR hex or structured JSON)\n * to Blaze NativeScript objects, and a helper to attach scripts during tx completion.\n */\n\nimport { Core } from \"@blaze-cardano/sdk\";\nimport type { TxBuilder } from \"@blaze-cardano/tx\";\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { TMultisigScript } from \"../../schemas.js\";\nimport { ActionError } from \"../types.js\";\nimport type { IActionContext } from \"../types.js\";\n\n/** Input type: either a CBOR hex string or a MultisigScript JSON structure */\nexport type NativeScriptInput = string | TMultisigScript;\n\n/**\n * Converts a MultisigScript JSON structure to a Blaze NativeScript.\n * Handles the recursive structure (AllOf, AnyOf, AtLeast contain nested scripts).\n */\nfunction multisigToNativeScript(ms: TMultisigScript): Core.NativeScript {\n if (\"Signature\" in ms) {\n const hash = Core.Ed25519KeyHashHex(ms.Signature.key_hash);\n return Core.NativeScript.newScriptPubkey(new Core.ScriptPubkey(hash));\n }\n if (\"AllOf\" in ms) {\n const scripts = ms.AllOf.scripts.map(multisigToNativeScript);\n return Core.NativeScript.newScriptAll(new Core.ScriptAll(scripts));\n }\n if (\"AnyOf\" in ms) {\n const scripts = ms.AnyOf.scripts.map(multisigToNativeScript);\n return Core.NativeScript.newScriptAny(new Core.ScriptAny(scripts));\n }\n if (\"AtLeast\" in ms) {\n const scripts = ms.AtLeast.scripts.map(multisigToNativeScript);\n return Core.NativeScript.newScriptNOfK(\n new Core.ScriptNOfK(scripts, Number(ms.AtLeast.required)),\n );\n }\n if (\"Before\" in ms) {\n return Core.NativeScript.newTimelockExpiry(\n new Core.TimelockExpiry(Core.Slot(Number(ms.Before.time))),\n );\n }\n if (\"After\" in ms) {\n return Core.NativeScript.newTimelockStart(\n new Core.TimelockStart(Core.Slot(Number(ms.After.time))),\n );\n }\n if (\"Script\" in ms) {\n // Script variant references a script by hash — this is a ScriptPubkey\n // but using the script hash directly as a key hash reference\n const hash = Core.Ed25519KeyHashHex(ms.Script.script_hash);\n return Core.NativeScript.newScriptPubkey(new Core.ScriptPubkey(hash));\n }\n\n throw new ActionError(\n \"Unrecognized MultisigScript variant\",\n \"INVALID_NATIVE_SCRIPT\",\n { input: ms },\n );\n}\n\n/**\n * Converts a native script input (CBOR hex string or MultisigScript JSON)\n * to a Blaze Script object suitable for `provideScript()`.\n */\nexport function toNativeScript(input: NativeScriptInput): Core.Script {\n if (typeof input === \"string\") {\n try {\n const nativeScript = Core.NativeScript.fromCbor(\n Core.HexBlob(input),\n );\n return Core.Script.newNativeScript(nativeScript);\n } catch (err) {\n throw new ActionError(\n `Invalid native script CBOR: ${err instanceof Error ? err.message : String(err)}`,\n \"INVALID_NATIVE_SCRIPT\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n }\n\n try {\n const nativeScript = multisigToNativeScript(input);\n return Core.Script.newNativeScript(nativeScript);\n } catch (err) {\n if (err instanceof ActionError) throw err;\n throw new ActionError(\n `Failed to convert MultisigScript to native script: ${err instanceof Error ? err.message : String(err)}`,\n \"INVALID_NATIVE_SCRIPT\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n}\n\n/** Regex to extract a script hash from Blaze's \"Could not resolve script hash\" error */\nconst MISSING_SCRIPT_HASH_RE =\n /complete: Could not resolve script hash[: ]*([0-9a-fA-F]+)/;\n\n/**\n * Builds a hash → Script lookup from the addressbook in the sprinkle context.\n * Returns an empty map if there's no addressbook.\n */\nfunction buildAddressbookIndex(\n addressbook: Record<string, TMultisigScript> | undefined,\n): Map<string, Core.Script> {\n const index = new Map<string, Core.Script>();\n if (!addressbook) return index;\n for (const [, ms] of Object.entries(addressbook)) {\n try {\n const script = toNativeScript(ms);\n index.set(script.hash(), script);\n } catch {\n // Skip invalid addressbook entries\n }\n }\n return index;\n}\n\n/**\n * Attaches optional native scripts to a transaction builder and completes it.\n *\n * If completion fails because Blaze cannot resolve a required native script hash,\n * and a context with an addressbook is provided, it will look up the missing script\n * by hash in the addressbook and retry once.\n */\nexport async function completeWithScripts<S extends TSchema>(\n txBuilder: TxBuilder,\n nativeScripts?: NativeScriptInput[],\n context?: IActionContext<S>,\n): Promise<Core.Transaction> {\n if (nativeScripts?.length) {\n for (const input of nativeScripts) {\n txBuilder.provideScript(toNativeScript(input));\n }\n }\n\n try {\n return await txBuilder.complete();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const match = message.match(MISSING_SCRIPT_HASH_RE);\n\n if (!match || !context?.sprinkle?.addressbook) {\n throw err;\n }\n\n // Build hash index from addressbook and try to resolve the missing script\n const addressbookIndex = buildAddressbookIndex(\n context.sprinkle.addressbook,\n );\n const missingHash = match[1];\n const script = addressbookIndex.get(missingHash);\n\n if (!script) {\n throw err;\n }\n\n // Attach the found script and retry\n txBuilder.provideScript(script);\n return txBuilder.complete();\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in utility actions for the Sprinkle action system.
|
|
3
|
+
* These actions provide common Cardano operations: minting tokens,
|
|
4
|
+
* sending ADA/tokens, and registering stake scripts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Type } from "@sinclair/typebox";
|
|
8
|
+
import { Core, makeValue } from "@blaze-cardano/sdk";
|
|
9
|
+
import { ActionError } from "../types.js";
|
|
10
|
+
import { getBlazeFromContext, isHotWallet } from "./blaze-helper.js";
|
|
11
|
+
import { NativeScriptsParam } from "../../schemas.js";
|
|
12
|
+
import { completeWithScripts } from "./native-script.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `mint-token` -- Mint native tokens using a native script derived from the wallet's payment key.
|
|
16
|
+
* The policy is a simple ScriptPubkey requiring the wallet's payment credential to sign.
|
|
17
|
+
* Requires a hot wallet.
|
|
18
|
+
*/
|
|
19
|
+
export const mintToken = {
|
|
20
|
+
name: "mint-token",
|
|
21
|
+
description: "Mint native tokens using a native script policy derived from the wallet's payment key.",
|
|
22
|
+
category: "utility",
|
|
23
|
+
inputSchema: Type.Object({
|
|
24
|
+
tokenName: Type.String({
|
|
25
|
+
description: "Name of the token to mint"
|
|
26
|
+
}),
|
|
27
|
+
amount: Type.String({
|
|
28
|
+
description: "Amount of tokens to mint (as string for BigInt safety)"
|
|
29
|
+
}),
|
|
30
|
+
nativeScripts: NativeScriptsParam
|
|
31
|
+
}),
|
|
32
|
+
outputSchema: Type.Object({
|
|
33
|
+
policyId: Type.String({
|
|
34
|
+
description: "Policy ID of the minted token"
|
|
35
|
+
}),
|
|
36
|
+
tokenName: Type.String({
|
|
37
|
+
description: "Token name"
|
|
38
|
+
}),
|
|
39
|
+
amount: Type.String({
|
|
40
|
+
description: "Amount minted"
|
|
41
|
+
}),
|
|
42
|
+
txCbor: Type.String({
|
|
43
|
+
description: "Unsigned transaction CBOR hex ready for signing"
|
|
44
|
+
})
|
|
45
|
+
}),
|
|
46
|
+
execute: async (input, context) => {
|
|
47
|
+
const blaze = await getBlazeFromContext(context);
|
|
48
|
+
if (!isHotWallet(blaze)) {
|
|
49
|
+
throw new ActionError("Mint token requires a hot wallet to derive the native script policy.", "COLD_WALLET");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Get the wallet's payment credential hash for the native script
|
|
53
|
+
let address;
|
|
54
|
+
try {
|
|
55
|
+
address = await blaze.wallet.getChangeAddress();
|
|
56
|
+
} catch (err) {
|
|
57
|
+
throw new ActionError(`Failed to get wallet address: ${err instanceof Error ? err.message : String(err)}`, "NO_ADDRESS", {
|
|
58
|
+
error: err instanceof Error ? err.message : String(err)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const baseAddress = address.asBase();
|
|
62
|
+
if (!baseAddress) {
|
|
63
|
+
throw new ActionError("Could not derive base address from wallet. Ensure the wallet has a payment credential.", "INVALID_ADDRESS");
|
|
64
|
+
}
|
|
65
|
+
const paymentCredential = baseAddress.getPaymentCredential();
|
|
66
|
+
if (!paymentCredential?.hash) {
|
|
67
|
+
throw new ActionError("Could not extract payment credential hash from wallet address.", "NO_PAYMENT_CREDENTIAL");
|
|
68
|
+
}
|
|
69
|
+
const hash = Core.Ed25519KeyHashHex(paymentCredential.hash.toString());
|
|
70
|
+
const tokenPolicy = new Core.ScriptPubkey(hash);
|
|
71
|
+
const policy = Core.Script.newNativeScript(Core.NativeScript.newScriptPubkey(tokenPolicy));
|
|
72
|
+
const policyId = policy.hash();
|
|
73
|
+
const assetName = Core.AssetName(Core.toHex(Buffer.from(input.tokenName)));
|
|
74
|
+
const mintAmount = BigInt(input.amount);
|
|
75
|
+
const mints = new Map();
|
|
76
|
+
mints.set(assetName, mintAmount);
|
|
77
|
+
let tx;
|
|
78
|
+
try {
|
|
79
|
+
const txBuilder = blaze.newTransaction().addMint(Core.PolicyId(policyId), mints).provideScript(policy);
|
|
80
|
+
tx = await completeWithScripts(txBuilder, input.nativeScripts, context);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
if (err instanceof ActionError) throw err;
|
|
83
|
+
throw new ActionError(`Failed to build mint transaction: ${err instanceof Error ? err.message : String(err)}`, "BUILD_ERROR", {
|
|
84
|
+
error: err instanceof Error ? err.message : String(err)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
policyId: policyId.toString(),
|
|
89
|
+
tokenName: input.tokenName,
|
|
90
|
+
amount: input.amount,
|
|
91
|
+
txCbor: tx.toCbor()
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* `simple-send` -- Send ADA or a native token to a recipient address.
|
|
98
|
+
* Builds an unsigned transaction that can be signed via TxDialog or sign-transaction.
|
|
99
|
+
*/
|
|
100
|
+
export const simpleSend = {
|
|
101
|
+
name: "simple-send",
|
|
102
|
+
description: "Send ADA or a native token to a recipient address.",
|
|
103
|
+
category: "wallet",
|
|
104
|
+
inputSchema: Type.Object({
|
|
105
|
+
recipientAddress: Type.String({
|
|
106
|
+
description: "Bech32 recipient address"
|
|
107
|
+
}),
|
|
108
|
+
lovelace: Type.Optional(Type.String({
|
|
109
|
+
description: "Amount of lovelace to send (as string for BigInt safety). Required if not sending a token."
|
|
110
|
+
})),
|
|
111
|
+
policyId: Type.Optional(Type.String({
|
|
112
|
+
description: "Policy ID of the token to send"
|
|
113
|
+
})),
|
|
114
|
+
assetName: Type.Optional(Type.String({
|
|
115
|
+
description: "Asset name of the token to send (hex-encoded)"
|
|
116
|
+
})),
|
|
117
|
+
tokenAmount: Type.Optional(Type.String({
|
|
118
|
+
description: "Amount of tokens to send (as string for BigInt safety)"
|
|
119
|
+
})),
|
|
120
|
+
nativeScripts: NativeScriptsParam
|
|
121
|
+
}),
|
|
122
|
+
outputSchema: Type.Object({
|
|
123
|
+
txCbor: Type.String({
|
|
124
|
+
description: "Unsigned transaction CBOR hex ready for signing"
|
|
125
|
+
})
|
|
126
|
+
}),
|
|
127
|
+
execute: async (input, context) => {
|
|
128
|
+
const blaze = await getBlazeFromContext(context);
|
|
129
|
+
|
|
130
|
+
// Validate: must provide lovelace or token details
|
|
131
|
+
const hasToken = input.policyId && input.assetName && input.tokenAmount;
|
|
132
|
+
if (!input.lovelace && !hasToken) {
|
|
133
|
+
throw new ActionError("Must provide either lovelace amount or token details (policyId, assetName, tokenAmount).", "INVALID_INPUT");
|
|
134
|
+
}
|
|
135
|
+
let recipient;
|
|
136
|
+
try {
|
|
137
|
+
recipient = Core.Address.fromBech32(input.recipientAddress);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
throw new ActionError(`Invalid recipient address: ${err instanceof Error ? err.message : String(err)}`, "INVALID_ADDRESS", {
|
|
140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
let value;
|
|
144
|
+
if (hasToken) {
|
|
145
|
+
const assetId = `${input.policyId}${input.assetName}`;
|
|
146
|
+
value = makeValue(BigInt(input.lovelace ?? "0"), [assetId, BigInt(input.tokenAmount)]);
|
|
147
|
+
} else {
|
|
148
|
+
value = makeValue(BigInt(input.lovelace));
|
|
149
|
+
}
|
|
150
|
+
let tx;
|
|
151
|
+
try {
|
|
152
|
+
const txBuilder = blaze.newTransaction().payAssets(recipient, value);
|
|
153
|
+
tx = await completeWithScripts(txBuilder, input.nativeScripts, context);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
if (err instanceof ActionError) throw err;
|
|
156
|
+
throw new ActionError(`Failed to build send transaction: ${err instanceof Error ? err.message : String(err)}`, "BUILD_ERROR", {
|
|
157
|
+
error: err instanceof Error ? err.message : String(err)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
txCbor: tx.toCbor()
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* `register-stake-script` -- Register a stake script credential on-chain.
|
|
168
|
+
* Takes a script hash and builds a stake registration transaction.
|
|
169
|
+
*/
|
|
170
|
+
export const registerStakeScript = {
|
|
171
|
+
name: "register-stake-script",
|
|
172
|
+
description: "Register a stake script credential on-chain. Takes a script hash (hex) and builds the registration transaction.",
|
|
173
|
+
category: "utility",
|
|
174
|
+
inputSchema: Type.Object({
|
|
175
|
+
scriptHash: Type.String({
|
|
176
|
+
description: "Stake script hash in hex (28 bytes / 56 hex characters)"
|
|
177
|
+
}),
|
|
178
|
+
nativeScripts: NativeScriptsParam
|
|
179
|
+
}),
|
|
180
|
+
outputSchema: Type.Object({
|
|
181
|
+
txCbor: Type.String({
|
|
182
|
+
description: "Unsigned transaction CBOR hex ready for signing"
|
|
183
|
+
})
|
|
184
|
+
}),
|
|
185
|
+
execute: async (input, context) => {
|
|
186
|
+
const blaze = await getBlazeFromContext(context);
|
|
187
|
+
|
|
188
|
+
// Validate hex format
|
|
189
|
+
if (!/^[0-9a-fA-F]{56}$/.test(input.scriptHash)) {
|
|
190
|
+
throw new ActionError("Script hash must be exactly 56 hex characters (28 bytes).", "INVALID_SCRIPT_HASH", {
|
|
191
|
+
provided: input.scriptHash
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
const credential = Core.Credential.fromCore({
|
|
195
|
+
hash: Core.Hash28ByteBase16(input.scriptHash),
|
|
196
|
+
type: Core.CredentialType.ScriptHash
|
|
197
|
+
});
|
|
198
|
+
let tx;
|
|
199
|
+
try {
|
|
200
|
+
const txBuilder = blaze.newTransaction().addRegisterStake(credential);
|
|
201
|
+
tx = await completeWithScripts(txBuilder, input.nativeScripts, context);
|
|
202
|
+
} catch (err) {
|
|
203
|
+
if (err instanceof ActionError) throw err;
|
|
204
|
+
throw new ActionError(`Failed to build stake registration transaction: ${err instanceof Error ? err.message : String(err)}`, "BUILD_ERROR", {
|
|
205
|
+
error: err instanceof Error ? err.message : String(err)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
txCbor: tx.toCbor()
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
//# sourceMappingURL=utility-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utility-actions.js","names":["Type","Core","makeValue","ActionError","getBlazeFromContext","isHotWallet","NativeScriptsParam","completeWithScripts","mintToken","name","description","category","inputSchema","Object","tokenName","String","amount","nativeScripts","outputSchema","policyId","txCbor","execute","input","context","blaze","address","wallet","getChangeAddress","err","Error","message","error","baseAddress","asBase","paymentCredential","getPaymentCredential","hash","Ed25519KeyHashHex","toString","tokenPolicy","ScriptPubkey","policy","Script","newNativeScript","NativeScript","newScriptPubkey","assetName","AssetName","toHex","Buffer","from","mintAmount","BigInt","mints","Map","set","tx","txBuilder","newTransaction","addMint","PolicyId","provideScript","toCbor","simpleSend","recipientAddress","lovelace","Optional","tokenAmount","hasToken","recipient","Address","fromBech32","value","assetId","payAssets","registerStakeScript","scriptHash","test","provided","credential","Credential","fromCore","Hash28ByteBase16","type","CredentialType","ScriptHash","addRegisterStake"],"sources":["../../../../../src/Sprinkle/actions/builtin/utility-actions.ts"],"sourcesContent":["/**\n * Built-in utility actions for the Sprinkle action system.\n * These actions provide common Cardano operations: minting tokens,\n * sending ADA/tokens, and registering stake scripts.\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { TSchema } from \"@sinclair/typebox\";\nimport { Core, makeValue } from \"@blaze-cardano/sdk\";\nimport { ActionError } from \"../types.js\";\nimport type { IAction } from \"../types.js\";\nimport { getBlazeFromContext, isHotWallet } from \"./blaze-helper.js\";\nimport { NativeScriptsParam } from \"../../schemas.js\";\nimport type { NativeScriptInput } from \"./native-script.js\";\nimport { completeWithScripts } from \"./native-script.js\";\n\n/**\n * `mint-token` -- Mint native tokens using a native script derived from the wallet's payment key.\n * The policy is a simple ScriptPubkey requiring the wallet's payment credential to sign.\n * Requires a hot wallet.\n */\nexport const mintToken: IAction<\n { tokenName: string; amount: string; nativeScripts?: NativeScriptInput[] },\n { policyId: string; tokenName: string; amount: string; txCbor: string },\n TSchema\n> = {\n name: \"mint-token\",\n description:\n \"Mint native tokens using a native script policy derived from the wallet's payment key.\",\n category: \"utility\",\n inputSchema: Type.Object({\n tokenName: Type.String({ description: \"Name of the token to mint\" }),\n amount: Type.String({\n description: \"Amount of tokens to mint (as string for BigInt safety)\",\n }),\n nativeScripts: NativeScriptsParam,\n }),\n outputSchema: Type.Object({\n policyId: Type.String({ description: \"Policy ID of the minted token\" }),\n tokenName: Type.String({ description: \"Token name\" }),\n amount: Type.String({ description: \"Amount minted\" }),\n txCbor: Type.String({\n description: \"Unsigned transaction CBOR hex ready for signing\",\n }),\n }),\n execute: async (input, context) => {\n const blaze = await getBlazeFromContext(context);\n\n if (!isHotWallet(blaze)) {\n throw new ActionError(\n \"Mint token requires a hot wallet to derive the native script policy.\",\n \"COLD_WALLET\",\n );\n }\n\n // Get the wallet's payment credential hash for the native script\n let address: Core.Address;\n try {\n address = await blaze.wallet.getChangeAddress();\n } catch (err) {\n throw new ActionError(\n `Failed to get wallet address: ${err instanceof Error ? err.message : String(err)}`,\n \"NO_ADDRESS\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n const baseAddress = address.asBase();\n if (!baseAddress) {\n throw new ActionError(\n \"Could not derive base address from wallet. Ensure the wallet has a payment credential.\",\n \"INVALID_ADDRESS\",\n );\n }\n\n const paymentCredential = baseAddress.getPaymentCredential();\n if (!paymentCredential?.hash) {\n throw new ActionError(\n \"Could not extract payment credential hash from wallet address.\",\n \"NO_PAYMENT_CREDENTIAL\",\n );\n }\n\n const hash = Core.Ed25519KeyHashHex(paymentCredential.hash.toString());\n const tokenPolicy = new Core.ScriptPubkey(hash);\n const policy = Core.Script.newNativeScript(\n Core.NativeScript.newScriptPubkey(tokenPolicy),\n );\n\n const policyId = policy.hash();\n const assetName = Core.AssetName(\n Core.toHex(Buffer.from(input.tokenName)),\n );\n const mintAmount = BigInt(input.amount);\n\n const mints = new Map<Core.AssetName, bigint>();\n mints.set(assetName, mintAmount);\n\n let tx: Core.Transaction;\n try {\n const txBuilder = blaze\n .newTransaction()\n .addMint(Core.PolicyId(policyId), mints)\n .provideScript(policy);\n tx = await completeWithScripts(txBuilder, input.nativeScripts, context);\n } catch (err) {\n if (err instanceof ActionError) throw err;\n throw new ActionError(\n `Failed to build mint transaction: ${err instanceof Error ? err.message : String(err)}`,\n \"BUILD_ERROR\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n return {\n policyId: policyId.toString(),\n tokenName: input.tokenName,\n amount: input.amount,\n txCbor: tx.toCbor(),\n };\n },\n};\n\n/**\n * `simple-send` -- Send ADA or a native token to a recipient address.\n * Builds an unsigned transaction that can be signed via TxDialog or sign-transaction.\n */\nexport const simpleSend: IAction<\n {\n recipientAddress: string;\n lovelace?: string;\n policyId?: string;\n assetName?: string;\n tokenAmount?: string;\n nativeScripts?: NativeScriptInput[];\n },\n { txCbor: string },\n TSchema\n> = {\n name: \"simple-send\",\n description: \"Send ADA or a native token to a recipient address.\",\n category: \"wallet\",\n inputSchema: Type.Object({\n recipientAddress: Type.String({\n description: \"Bech32 recipient address\",\n }),\n lovelace: Type.Optional(\n Type.String({\n description:\n \"Amount of lovelace to send (as string for BigInt safety). Required if not sending a token.\",\n }),\n ),\n policyId: Type.Optional(\n Type.String({ description: \"Policy ID of the token to send\" }),\n ),\n assetName: Type.Optional(\n Type.String({\n description: \"Asset name of the token to send (hex-encoded)\",\n }),\n ),\n tokenAmount: Type.Optional(\n Type.String({\n description: \"Amount of tokens to send (as string for BigInt safety)\",\n }),\n ),\n nativeScripts: NativeScriptsParam,\n }),\n outputSchema: Type.Object({\n txCbor: Type.String({\n description: \"Unsigned transaction CBOR hex ready for signing\",\n }),\n }),\n execute: async (input, context) => {\n const blaze = await getBlazeFromContext(context);\n\n // Validate: must provide lovelace or token details\n const hasToken = input.policyId && input.assetName && input.tokenAmount;\n if (!input.lovelace && !hasToken) {\n throw new ActionError(\n \"Must provide either lovelace amount or token details (policyId, assetName, tokenAmount).\",\n \"INVALID_INPUT\",\n );\n }\n\n let recipient: Core.Address;\n try {\n recipient = Core.Address.fromBech32(input.recipientAddress);\n } catch (err) {\n throw new ActionError(\n `Invalid recipient address: ${err instanceof Error ? err.message : String(err)}`,\n \"INVALID_ADDRESS\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n let value: Core.Value;\n if (hasToken) {\n const assetId =\n `${input.policyId}${input.assetName}` as Core.AssetId;\n value = makeValue(\n BigInt(input.lovelace ?? \"0\"),\n [assetId, BigInt(input.tokenAmount!)],\n );\n } else {\n value = makeValue(BigInt(input.lovelace!));\n }\n\n let tx: Core.Transaction;\n try {\n const txBuilder = blaze.newTransaction().payAssets(recipient, value);\n tx = await completeWithScripts(txBuilder, input.nativeScripts, context);\n } catch (err) {\n if (err instanceof ActionError) throw err;\n throw new ActionError(\n `Failed to build send transaction: ${err instanceof Error ? err.message : String(err)}`,\n \"BUILD_ERROR\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n return {\n txCbor: tx.toCbor(),\n };\n },\n};\n\n/**\n * `register-stake-script` -- Register a stake script credential on-chain.\n * Takes a script hash and builds a stake registration transaction.\n */\nexport const registerStakeScript: IAction<\n { scriptHash: string; nativeScripts?: NativeScriptInput[] },\n { txCbor: string },\n TSchema\n> = {\n name: \"register-stake-script\",\n description:\n \"Register a stake script credential on-chain. Takes a script hash (hex) and builds the registration transaction.\",\n category: \"utility\",\n inputSchema: Type.Object({\n scriptHash: Type.String({\n description: \"Stake script hash in hex (28 bytes / 56 hex characters)\",\n }),\n nativeScripts: NativeScriptsParam,\n }),\n outputSchema: Type.Object({\n txCbor: Type.String({\n description: \"Unsigned transaction CBOR hex ready for signing\",\n }),\n }),\n execute: async (input, context) => {\n const blaze = await getBlazeFromContext(context);\n\n // Validate hex format\n if (!/^[0-9a-fA-F]{56}$/.test(input.scriptHash)) {\n throw new ActionError(\n \"Script hash must be exactly 56 hex characters (28 bytes).\",\n \"INVALID_SCRIPT_HASH\",\n { provided: input.scriptHash },\n );\n }\n\n const credential = Core.Credential.fromCore({\n hash: Core.Hash28ByteBase16(input.scriptHash),\n type: Core.CredentialType.ScriptHash,\n });\n\n let tx: Core.Transaction;\n try {\n const txBuilder = blaze.newTransaction().addRegisterStake(credential);\n tx = await completeWithScripts(txBuilder, input.nativeScripts, context);\n } catch (err) {\n if (err instanceof ActionError) throw err;\n throw new ActionError(\n `Failed to build stake registration transaction: ${err instanceof Error ? err.message : String(err)}`,\n \"BUILD_ERROR\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n return {\n txCbor: tx.toCbor(),\n };\n },\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -110,18 +110,36 @@ export function coerceValue(raw, schema) {
|
|
|
110
110
|
return [singleValue];
|
|
111
111
|
}
|
|
112
112
|
if (isObject(schema)) {
|
|
113
|
+
let obj = raw;
|
|
113
114
|
// If it's a JSON string, parse it
|
|
114
115
|
if (typeof raw === "string") {
|
|
115
116
|
const trimmed = raw.trim();
|
|
116
117
|
if (trimmed.startsWith("{")) {
|
|
117
118
|
try {
|
|
118
|
-
|
|
119
|
+
obj = JSON.parse(trimmed);
|
|
119
120
|
} catch {
|
|
120
121
|
return raw;
|
|
121
122
|
}
|
|
123
|
+
} else {
|
|
124
|
+
return raw;
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
|
-
|
|
127
|
+
// Recurse into properties to coerce nested values
|
|
128
|
+
if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
|
|
129
|
+
const props = schema.properties;
|
|
130
|
+
if (props) {
|
|
131
|
+
const result = {
|
|
132
|
+
...obj
|
|
133
|
+
};
|
|
134
|
+
for (const [key, propSchema] of Object.entries(props)) {
|
|
135
|
+
if (key in result) {
|
|
136
|
+
result[key] = coerceValue(result[key], propSchema);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return obj;
|
|
125
143
|
}
|
|
126
144
|
if (isString(schema)) {
|
|
127
145
|
if (typeof raw === "string") return raw;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-adapter.js","names":["bigIntReplacer","isArray","isBigInt","isBoolean","isInteger","isNumber","isObject","isString","isUnion","hasDefault","getDefault","executeAction","camelToKebab","str","replace","match","toLowerCase","kebabToCamel","_","char","toUpperCase","coerceValue","raw","schema","undefined","n","parseFloat","isNaN","Math","trunc","parseInt","BigInt","itemSchema","items","Array","map","item","singleValue","trimmed","trim","startsWith","JSON","parse","String","parseArgvWithSchema","rawArgs","result","properties","propName","propSchema","Object","entries","kebabName","rawValue","describeType","itemType","generateActionHelp","action","appName","app","lines","name","description","inputSchema","required","flagName","typeLabel","isReq","includes","defaultVal","requiredLabel","defaultLabel","descPart","push","join","generateAppHelp","actions","length","byCategory","Map","cat","category","bucket","get","set","categoryActions","padEnd","runCli","sprinkle","actionName","context","getAction","available","listActions","a","errorOutput","stringify","success","error","code","message","console","process","exit","log","coercedInput","data","details"],"sources":["../../../../src/Sprinkle/actions/cli-adapter.ts"],"sourcesContent":["/**\n * CLI adapter for Sprinkles actions.\n *\n * Provides:\n * - Case-conversion helpers (camelToKebab / kebabToCamel)\n * - Schema-driven type coercion (coerceValue / parseArgvWithSchema)\n * - Help text generation (generateActionHelp / generateAppHelp)\n * - CLI orchestrator (runCli)\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport { bigIntReplacer } from \"../encryption.js\";\nimport {\n isArray,\n isBigInt,\n isBoolean,\n isInteger,\n isNumber,\n isObject,\n isString,\n isUnion,\n hasDefault,\n getDefault,\n} from \"../type-guards.js\";\nimport type { AnyAction, IActionContext } from \"./types.js\";\nimport { executeAction } from \"./runner.js\";\n\n// Re-import Sprinkle as a type only to avoid circular deps\nimport type { Sprinkle } from \"../index.js\";\n\n// ---------------------------------------------------------------------------\n// Case conversion helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a camelCase string to kebab-case.\n * Examples:\n * \"myFlagName\" -> \"my-flag-name\"\n * \"getBalance\" -> \"get-balance\"\n * \"URL\" -> \"u-r-l\" (each uppercase letter gets a dash)\n */\nexport function camelToKebab(str: string): string {\n if (!str) return str;\n return str\n .replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`)\n .replace(/^-/, \"\");\n}\n\n/**\n * Convert a kebab-case string to camelCase.\n * Examples:\n * \"my-flag-name\" -> \"myFlagName\"\n * \"get-balance\" -> \"getBalance\"\n */\nexport function kebabToCamel(str: string): string {\n if (!str) return str;\n return str.replace(/-([a-z0-9])/g, (_, char: string) => char.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Schema-driven type coercion\n// ---------------------------------------------------------------------------\n\n/**\n * Coerce a raw CLI string value to the type expected by a TypeBox schema.\n *\n * Handles:\n * - Number / Integer: parseFloat / parseInt\n * - Boolean: \"true\"/\"false\" strings, or passthrough if already boolean\n * - BigInt: BigInt() constructor\n * - Array: already-array passthrough; single value wrapped in array\n * - Object: JSON string parse\n * - String: passthrough\n * - Optional: unwrap and recurse on inner schema\n * - Union: passthrough (caller should supply JSON; no schema-level heuristics)\n */\nexport function coerceValue(raw: unknown, schema: TSchema): unknown {\n // Note: TypeBox Optional<T> adds an [OptionalKind] marker but does not\n // change the schema Kind. The guards below work correctly on Optional types.\n\n // If the raw value is null or undefined, return as-is\n if (raw === null || raw === undefined) return raw;\n\n if (isNumber(schema)) {\n if (typeof raw === \"number\") return raw;\n if (typeof raw === \"string\") {\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n }\n return raw;\n }\n\n if (isInteger(schema)) {\n if (typeof raw === \"number\") return Math.trunc(raw);\n if (typeof raw === \"string\") {\n const n = parseInt(raw, 10);\n return isNaN(n) ? raw : n;\n }\n return raw;\n }\n\n if (isBoolean(schema)) {\n if (typeof raw === \"boolean\") return raw;\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n return raw;\n }\n\n if (isBigInt(schema)) {\n if (typeof raw === \"bigint\") return raw;\n if (typeof raw === \"string\" || typeof raw === \"number\") {\n try {\n return BigInt(raw);\n } catch {\n return raw;\n }\n }\n return raw;\n }\n\n if (isArray(schema)) {\n const itemSchema = (schema as { items?: TSchema }).items;\n if (Array.isArray(raw)) {\n if (itemSchema) {\n return raw.map((item) => coerceValue(item, itemSchema));\n }\n return raw;\n }\n // Single value: wrap in array\n const singleValue = itemSchema ? coerceValue(raw, itemSchema) : raw;\n return [singleValue];\n }\n\n if (isObject(schema)) {\n // If it's a JSON string, parse it\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n return JSON.parse(trimmed);\n } catch {\n return raw;\n }\n }\n }\n return raw;\n }\n\n if (isString(schema)) {\n if (typeof raw === \"string\") return raw;\n return String(raw);\n }\n\n // Union / unknown / other: return as-is (caller provides JSON)\n return raw;\n}\n\n/**\n * Walk a TypeBox object schema and coerce each property value from raw CLI args.\n *\n * - Handles kebab-case -> camelCase property name mapping\n * - Applies coerceValue for each property\n * - Applies TypeBox defaults for omitted optional fields\n *\n * @param rawArgs - Key/value record from parseCliArgs (keys may be kebab-case)\n * @param schema - A TypeBox TObject schema\n * @returns A new record with coerced values\n */\nexport function parseArgvWithSchema(\n rawArgs: Record<string, unknown>,\n schema: TSchema,\n): Record<string, unknown> {\n if (!isObject(schema)) {\n // Non-object schema: return args as-is (best-effort)\n return rawArgs;\n }\n\n const result: Record<string, unknown> = {};\n const properties = schema.properties as Record<string, TSchema>;\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n // Look up both camelCase and kebab-case versions in rawArgs\n const kebabName = camelToKebab(propName);\n\n let rawValue: unknown = undefined;\n if (propName in rawArgs) {\n rawValue = rawArgs[propName];\n } else if (kebabName !== propName && kebabName in rawArgs) {\n rawValue = rawArgs[kebabName];\n }\n\n if (rawValue === undefined) {\n // Apply default if defined on schema\n if (hasDefault(propSchema)) {\n result[propName] = getDefault(propSchema);\n }\n // Else omit: Value.Check will handle required/optional enforcement\n continue;\n }\n\n result[propName] = coerceValue(rawValue, propSchema);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Help text generation\n// ---------------------------------------------------------------------------\n\n/**\n * Describe a single TypeBox schema in a human-readable CLI type label.\n */\nfunction describeType(schema: TSchema): string {\n // Note: isOptional() only checks the OptionalKind marker; the other guards\n // still work correctly on Optional-wrapped schemas.\n if (isString(schema)) return \"<string>\";\n if (isNumber(schema)) return \"<number>\";\n if (isInteger(schema)) return \"<integer>\";\n if (isBoolean(schema)) return \"<boolean>\";\n if (isBigInt(schema)) return \"<bigint>\";\n if (isArray(schema)) {\n const itemSchema = (schema as { items?: TSchema }).items;\n const itemType = itemSchema ? describeType(itemSchema) : \"<value>\";\n return `${itemType}... (repeatable)`;\n }\n if (isObject(schema)) return \"<json>\";\n if (isUnion(schema)) return \"<json>\";\n return \"<value>\";\n}\n\n/**\n * Generate action-specific help text.\n *\n * Format:\n * ```\n * Usage: <appName> <action-name> [options]\n *\n * Description\n *\n * Options:\n * --flag-name <type> Description [default: x] (required/optional)\n * ...\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function generateActionHelp(\n action: AnyAction<any>,\n appName?: string,\n): string {\n const app = appName ?? \"app\";\n const lines: string[] = [\n `Usage: ${app} ${action.name} [options]`,\n \"\",\n action.description,\n \"\",\n \"Options:\",\n ];\n\n const schema = action.inputSchema;\n if (isObject(schema)) {\n const properties = schema.properties as Record<string, TSchema>;\n const required = (schema.required as string[] | undefined) ?? [];\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n const flagName = camelToKebab(propName);\n const typeLabel = describeType(propSchema);\n const isReq = required.includes(propName);\n const defaultVal = hasDefault(propSchema) ? getDefault(propSchema) : undefined;\n const description = (propSchema as { description?: string }).description ?? \"\";\n\n const requiredLabel = isReq ? \"(required)\" : \"(optional)\";\n const defaultLabel =\n defaultVal !== undefined ? ` [default: ${String(defaultVal)}]` : \"\";\n\n const descPart = description ? ` ${description}` : \"\";\n lines.push(\n ` --${flagName} ${typeLabel}${descPart}${defaultLabel} ${requiredLabel}`,\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\" --help Show this help message\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate application-level help listing all registered actions.\n *\n * Format:\n * ```\n * Usage: <appName> <action> [options]\n *\n * Available actions:\n *\n * category:\n * action-name Description\n *\n * Global options:\n * --help Show this help message\n * --profile <n> Use profile by name\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function generateAppHelp(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n actions: AnyAction<any>[],\n appName?: string,\n): string {\n const app = appName ?? \"app\";\n const lines: string[] = [`Usage: ${app} <action> [options]`, \"\"];\n\n if (actions.length === 0) {\n lines.push(\"No actions registered.\");\n } else {\n lines.push(\"Available actions:\");\n\n // Group by category\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const byCategory = new Map<string, AnyAction<any>[]>();\n for (const action of actions) {\n const cat = action.category ?? \"default\";\n const bucket = byCategory.get(cat);\n if (bucket) {\n bucket.push(action);\n } else {\n byCategory.set(cat, [action]);\n }\n }\n\n for (const [category, categoryActions] of byCategory) {\n if (category !== \"default\") {\n lines.push(\"\");\n lines.push(` ${category}:`);\n }\n for (const action of categoryActions) {\n lines.push(` ${action.name.padEnd(30)} ${action.description}`);\n }\n }\n }\n\n lines.push(\"\");\n lines.push(\"Global options:\");\n lines.push(\" --help Show this help message\");\n lines.push(\" --profile <n> Use profile by name\");\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// CLI orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * Run an action from CLI arguments, writing JSON output to stdout/stderr.\n *\n * Handles:\n * - Action not found: JSON error to stderr, process.exit(1)\n * - Action help (`--help` in rawArgs): prints action help to stdout\n * - Schema-driven argument coercion via parseArgvWithSchema\n * - Success: `{\"success\":true,\"data\":...}` JSON to stdout\n * - Failure: `{\"success\":false,\"error\":...}` JSON to stderr, process.exit(1)\n *\n * @param sprinkle - Fully-initialized Sprinkle instance\n * @param actionName - The action to invoke\n * @param rawArgs - Pre-parsed key/value args from parseCliArgs (profile already removed)\n * @param context - The action execution context\n * @param appName - Optional app name for help text\n */\nexport async function runCli<S extends TSchema>(\n sprinkle: Sprinkle<S>,\n actionName: string,\n rawArgs: Record<string, unknown>,\n context: IActionContext<S>,\n appName?: string,\n): Promise<void> {\n const action = sprinkle.getAction(actionName);\n\n if (!action) {\n const available = sprinkle\n .listActions()\n .map((a) => a.name)\n .join(\", \");\n const errorOutput = JSON.stringify(\n {\n success: false,\n error: {\n code: \"ACTION_NOT_FOUND\",\n message: `Action \"${actionName}\" not found. Available actions: ${available || \"(none)\"}`,\n },\n },\n bigIntReplacer,\n );\n console.error(errorOutput);\n process.exit(1);\n }\n\n // Handle --help flag for action-specific help\n if (rawArgs[\"help\"] === true) {\n console.log(generateActionHelp(action, appName));\n return;\n }\n\n // Coerce raw string args using the action's input schema\n const coercedInput = parseArgvWithSchema(rawArgs, action.inputSchema);\n\n // Execute and output result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await executeAction(action as any, coercedInput, context as any);\n\n if (result.success) {\n console.log(JSON.stringify({ success: true, data: result.data }, bigIntReplacer));\n } else {\n const errorOutput = JSON.stringify(\n {\n success: false,\n error: {\n code: result.error.code,\n message: result.error.message,\n details: result.error.details,\n },\n },\n bigIntReplacer,\n );\n console.error(errorOutput);\n process.exit(1);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"cli-adapter.js","names":["bigIntReplacer","isArray","isBigInt","isBoolean","isInteger","isNumber","isObject","isString","isUnion","hasDefault","getDefault","executeAction","camelToKebab","str","replace","match","toLowerCase","kebabToCamel","_","char","toUpperCase","coerceValue","raw","schema","undefined","n","parseFloat","isNaN","Math","trunc","parseInt","BigInt","itemSchema","items","Array","map","item","singleValue","obj","trimmed","trim","startsWith","JSON","parse","props","properties","result","key","propSchema","Object","entries","String","parseArgvWithSchema","rawArgs","propName","kebabName","rawValue","describeType","itemType","generateActionHelp","action","appName","app","lines","name","description","inputSchema","required","flagName","typeLabel","isReq","includes","defaultVal","requiredLabel","defaultLabel","descPart","push","join","generateAppHelp","actions","length","byCategory","Map","cat","category","bucket","get","set","categoryActions","padEnd","runCli","sprinkle","actionName","context","getAction","available","listActions","a","errorOutput","stringify","success","error","code","message","console","process","exit","log","coercedInput","data","details"],"sources":["../../../../src/Sprinkle/actions/cli-adapter.ts"],"sourcesContent":["/**\n * CLI adapter for Sprinkles actions.\n *\n * Provides:\n * - Case-conversion helpers (camelToKebab / kebabToCamel)\n * - Schema-driven type coercion (coerceValue / parseArgvWithSchema)\n * - Help text generation (generateActionHelp / generateAppHelp)\n * - CLI orchestrator (runCli)\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport { bigIntReplacer } from \"../encryption.js\";\nimport {\n isArray,\n isBigInt,\n isBoolean,\n isInteger,\n isNumber,\n isObject,\n isString,\n isUnion,\n hasDefault,\n getDefault,\n} from \"../type-guards.js\";\nimport type { AnyAction, IActionContext } from \"./types.js\";\nimport { executeAction } from \"./runner.js\";\n\n// Re-import Sprinkle as a type only to avoid circular deps\nimport type { Sprinkle } from \"../index.js\";\n\n// ---------------------------------------------------------------------------\n// Case conversion helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a camelCase string to kebab-case.\n * Examples:\n * \"myFlagName\" -> \"my-flag-name\"\n * \"getBalance\" -> \"get-balance\"\n * \"URL\" -> \"u-r-l\" (each uppercase letter gets a dash)\n */\nexport function camelToKebab(str: string): string {\n if (!str) return str;\n return str\n .replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`)\n .replace(/^-/, \"\");\n}\n\n/**\n * Convert a kebab-case string to camelCase.\n * Examples:\n * \"my-flag-name\" -> \"myFlagName\"\n * \"get-balance\" -> \"getBalance\"\n */\nexport function kebabToCamel(str: string): string {\n if (!str) return str;\n return str.replace(/-([a-z0-9])/g, (_, char: string) => char.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Schema-driven type coercion\n// ---------------------------------------------------------------------------\n\n/**\n * Coerce a raw CLI string value to the type expected by a TypeBox schema.\n *\n * Handles:\n * - Number / Integer: parseFloat / parseInt\n * - Boolean: \"true\"/\"false\" strings, or passthrough if already boolean\n * - BigInt: BigInt() constructor\n * - Array: already-array passthrough; single value wrapped in array\n * - Object: JSON string parse\n * - String: passthrough\n * - Optional: unwrap and recurse on inner schema\n * - Union: passthrough (caller should supply JSON; no schema-level heuristics)\n */\nexport function coerceValue(raw: unknown, schema: TSchema): unknown {\n // Note: TypeBox Optional<T> adds an [OptionalKind] marker but does not\n // change the schema Kind. The guards below work correctly on Optional types.\n\n // If the raw value is null or undefined, return as-is\n if (raw === null || raw === undefined) return raw;\n\n if (isNumber(schema)) {\n if (typeof raw === \"number\") return raw;\n if (typeof raw === \"string\") {\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n }\n return raw;\n }\n\n if (isInteger(schema)) {\n if (typeof raw === \"number\") return Math.trunc(raw);\n if (typeof raw === \"string\") {\n const n = parseInt(raw, 10);\n return isNaN(n) ? raw : n;\n }\n return raw;\n }\n\n if (isBoolean(schema)) {\n if (typeof raw === \"boolean\") return raw;\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n return raw;\n }\n\n if (isBigInt(schema)) {\n if (typeof raw === \"bigint\") return raw;\n if (typeof raw === \"string\" || typeof raw === \"number\") {\n try {\n return BigInt(raw);\n } catch {\n return raw;\n }\n }\n return raw;\n }\n\n if (isArray(schema)) {\n const itemSchema = (schema as { items?: TSchema }).items;\n if (Array.isArray(raw)) {\n if (itemSchema) {\n return raw.map((item) => coerceValue(item, itemSchema));\n }\n return raw;\n }\n // Single value: wrap in array\n const singleValue = itemSchema ? coerceValue(raw, itemSchema) : raw;\n return [singleValue];\n }\n\n if (isObject(schema)) {\n let obj = raw;\n // If it's a JSON string, parse it\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n obj = JSON.parse(trimmed);\n } catch {\n return raw;\n }\n } else {\n return raw;\n }\n }\n // Recurse into properties to coerce nested values\n if (typeof obj === \"object\" && obj !== null && !Array.isArray(obj)) {\n const props = schema.properties as Record<string, TSchema> | undefined;\n if (props) {\n const result: Record<string, unknown> = { ...(obj as Record<string, unknown>) };\n for (const [key, propSchema] of Object.entries(props)) {\n if (key in result) {\n result[key] = coerceValue(result[key], propSchema);\n }\n }\n return result;\n }\n }\n return obj;\n }\n\n if (isString(schema)) {\n if (typeof raw === \"string\") return raw;\n return String(raw);\n }\n\n // Union / unknown / other: return as-is (caller provides JSON)\n return raw;\n}\n\n/**\n * Walk a TypeBox object schema and coerce each property value from raw CLI args.\n *\n * - Handles kebab-case -> camelCase property name mapping\n * - Applies coerceValue for each property\n * - Applies TypeBox defaults for omitted optional fields\n *\n * @param rawArgs - Key/value record from parseCliArgs (keys may be kebab-case)\n * @param schema - A TypeBox TObject schema\n * @returns A new record with coerced values\n */\nexport function parseArgvWithSchema(\n rawArgs: Record<string, unknown>,\n schema: TSchema,\n): Record<string, unknown> {\n if (!isObject(schema)) {\n // Non-object schema: return args as-is (best-effort)\n return rawArgs;\n }\n\n const result: Record<string, unknown> = {};\n const properties = schema.properties as Record<string, TSchema>;\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n // Look up both camelCase and kebab-case versions in rawArgs\n const kebabName = camelToKebab(propName);\n\n let rawValue: unknown = undefined;\n if (propName in rawArgs) {\n rawValue = rawArgs[propName];\n } else if (kebabName !== propName && kebabName in rawArgs) {\n rawValue = rawArgs[kebabName];\n }\n\n if (rawValue === undefined) {\n // Apply default if defined on schema\n if (hasDefault(propSchema)) {\n result[propName] = getDefault(propSchema);\n }\n // Else omit: Value.Check will handle required/optional enforcement\n continue;\n }\n\n result[propName] = coerceValue(rawValue, propSchema);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Help text generation\n// ---------------------------------------------------------------------------\n\n/**\n * Describe a single TypeBox schema in a human-readable CLI type label.\n */\nfunction describeType(schema: TSchema): string {\n // Note: isOptional() only checks the OptionalKind marker; the other guards\n // still work correctly on Optional-wrapped schemas.\n if (isString(schema)) return \"<string>\";\n if (isNumber(schema)) return \"<number>\";\n if (isInteger(schema)) return \"<integer>\";\n if (isBoolean(schema)) return \"<boolean>\";\n if (isBigInt(schema)) return \"<bigint>\";\n if (isArray(schema)) {\n const itemSchema = (schema as { items?: TSchema }).items;\n const itemType = itemSchema ? describeType(itemSchema) : \"<value>\";\n return `${itemType}... (repeatable)`;\n }\n if (isObject(schema)) return \"<json>\";\n if (isUnion(schema)) return \"<json>\";\n return \"<value>\";\n}\n\n/**\n * Generate action-specific help text.\n *\n * Format:\n * ```\n * Usage: <appName> <action-name> [options]\n *\n * Description\n *\n * Options:\n * --flag-name <type> Description [default: x] (required/optional)\n * ...\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function generateActionHelp(\n action: AnyAction<any>,\n appName?: string,\n): string {\n const app = appName ?? \"app\";\n const lines: string[] = [\n `Usage: ${app} ${action.name} [options]`,\n \"\",\n action.description,\n \"\",\n \"Options:\",\n ];\n\n const schema = action.inputSchema;\n if (isObject(schema)) {\n const properties = schema.properties as Record<string, TSchema>;\n const required = (schema.required as string[] | undefined) ?? [];\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n const flagName = camelToKebab(propName);\n const typeLabel = describeType(propSchema);\n const isReq = required.includes(propName);\n const defaultVal = hasDefault(propSchema) ? getDefault(propSchema) : undefined;\n const description = (propSchema as { description?: string }).description ?? \"\";\n\n const requiredLabel = isReq ? \"(required)\" : \"(optional)\";\n const defaultLabel =\n defaultVal !== undefined ? ` [default: ${String(defaultVal)}]` : \"\";\n\n const descPart = description ? ` ${description}` : \"\";\n lines.push(\n ` --${flagName} ${typeLabel}${descPart}${defaultLabel} ${requiredLabel}`,\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\" --help Show this help message\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate application-level help listing all registered actions.\n *\n * Format:\n * ```\n * Usage: <appName> <action> [options]\n *\n * Available actions:\n *\n * category:\n * action-name Description\n *\n * Global options:\n * --help Show this help message\n * --profile <n> Use profile by name\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function generateAppHelp(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n actions: AnyAction<any>[],\n appName?: string,\n): string {\n const app = appName ?? \"app\";\n const lines: string[] = [`Usage: ${app} <action> [options]`, \"\"];\n\n if (actions.length === 0) {\n lines.push(\"No actions registered.\");\n } else {\n lines.push(\"Available actions:\");\n\n // Group by category\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const byCategory = new Map<string, AnyAction<any>[]>();\n for (const action of actions) {\n const cat = action.category ?? \"default\";\n const bucket = byCategory.get(cat);\n if (bucket) {\n bucket.push(action);\n } else {\n byCategory.set(cat, [action]);\n }\n }\n\n for (const [category, categoryActions] of byCategory) {\n if (category !== \"default\") {\n lines.push(\"\");\n lines.push(` ${category}:`);\n }\n for (const action of categoryActions) {\n lines.push(` ${action.name.padEnd(30)} ${action.description}`);\n }\n }\n }\n\n lines.push(\"\");\n lines.push(\"Global options:\");\n lines.push(\" --help Show this help message\");\n lines.push(\" --profile <n> Use profile by name\");\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// CLI orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * Run an action from CLI arguments, writing JSON output to stdout/stderr.\n *\n * Handles:\n * - Action not found: JSON error to stderr, process.exit(1)\n * - Action help (`--help` in rawArgs): prints action help to stdout\n * - Schema-driven argument coercion via parseArgvWithSchema\n * - Success: `{\"success\":true,\"data\":...}` JSON to stdout\n * - Failure: `{\"success\":false,\"error\":...}` JSON to stderr, process.exit(1)\n *\n * @param sprinkle - Fully-initialized Sprinkle instance\n * @param actionName - The action to invoke\n * @param rawArgs - Pre-parsed key/value args from parseCliArgs (profile already removed)\n * @param context - The action execution context\n * @param appName - Optional app name for help text\n */\nexport async function runCli<S extends TSchema>(\n sprinkle: Sprinkle<S>,\n actionName: string,\n rawArgs: Record<string, unknown>,\n context: IActionContext<S>,\n appName?: string,\n): Promise<void> {\n const action = sprinkle.getAction(actionName);\n\n if (!action) {\n const available = sprinkle\n .listActions()\n .map((a) => a.name)\n .join(\", \");\n const errorOutput = JSON.stringify(\n {\n success: false,\n error: {\n code: \"ACTION_NOT_FOUND\",\n message: `Action \"${actionName}\" not found. Available actions: ${available || \"(none)\"}`,\n },\n },\n bigIntReplacer,\n );\n console.error(errorOutput);\n process.exit(1);\n }\n\n // Handle --help flag for action-specific help\n if (rawArgs[\"help\"] === true) {\n console.log(generateActionHelp(action, appName));\n return;\n }\n\n // Coerce raw string args using the action's input schema\n const coercedInput = parseArgvWithSchema(rawArgs, action.inputSchema);\n\n // Execute and output result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await executeAction(action as any, coercedInput, context as any);\n\n if (result.success) {\n console.log(JSON.stringify({ success: true, data: result.data }, bigIntReplacer));\n } else {\n const errorOutput = JSON.stringify(\n {\n success: false,\n error: {\n code: result.error.code,\n message: result.error.message,\n details: result.error.details,\n },\n },\n bigIntReplacer,\n );\n console.error(errorOutput);\n process.exit(1);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|