@1sat/wallet-toolbox 0.0.9 → 0.0.11

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 (39) hide show
  1. package/dist/api/balance/index.d.ts +20 -8
  2. package/dist/api/balance/index.js +104 -51
  3. package/dist/api/broadcast/index.d.ts +5 -3
  4. package/dist/api/broadcast/index.js +65 -37
  5. package/dist/api/index.d.ts +16 -15
  6. package/dist/api/index.js +42 -17
  7. package/dist/api/inscriptions/index.d.ts +9 -9
  8. package/dist/api/inscriptions/index.js +79 -31
  9. package/dist/api/locks/index.d.ts +15 -12
  10. package/dist/api/locks/index.js +252 -194
  11. package/dist/api/ordinals/index.d.ts +50 -35
  12. package/dist/api/ordinals/index.js +469 -349
  13. package/dist/api/payments/index.d.ts +15 -4
  14. package/dist/api/payments/index.js +147 -92
  15. package/dist/api/signing/index.d.ts +8 -5
  16. package/dist/api/signing/index.js +70 -33
  17. package/dist/api/skills/registry.d.ts +61 -0
  18. package/dist/api/skills/registry.js +74 -0
  19. package/dist/api/skills/types.d.ts +71 -0
  20. package/dist/api/skills/types.js +14 -0
  21. package/dist/api/sweep/index.d.ts +23 -0
  22. package/dist/api/sweep/index.js +221 -0
  23. package/dist/api/sweep/types.d.ts +30 -0
  24. package/dist/api/sweep/types.js +4 -0
  25. package/dist/api/tokens/index.d.ts +37 -38
  26. package/dist/api/tokens/index.js +398 -341
  27. package/dist/index.d.ts +2 -1
  28. package/dist/index.js +2 -0
  29. package/dist/services/client/OwnerClient.js +4 -0
  30. package/dist/wallet/factory.d.ts +64 -0
  31. package/dist/wallet/factory.js +163 -0
  32. package/dist/wallet/index.d.ts +1 -0
  33. package/dist/wallet/index.js +1 -0
  34. package/package.json +13 -4
  35. package/dist/OneSatWallet.d.ts +0 -316
  36. package/dist/OneSatWallet.js +0 -956
  37. package/dist/api/OneSatApi.d.ts +0 -100
  38. package/dist/api/OneSatApi.js +0 -156
  39. package/dist/indexers/TransactionParser.d.ts +0 -53
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Balance Module
3
3
  *
4
- * Functions for querying wallet balance and payment UTXOs.
4
+ * Skills for querying wallet balance and payment UTXOs.
5
5
  */
6
- import type { WalletInterface } from "@bsv/sdk";
6
+ import type { Skill } from "../skills/types";
7
7
  export interface Balance {
8
8
  /** Balance in satoshis */
9
9
  satoshis: number;
@@ -18,21 +18,33 @@ export interface PaymentUtxo {
18
18
  satoshis: number;
19
19
  script: string;
20
20
  }
21
+ /** Input for getBalance skill (no required params) */
22
+ export type GetBalanceInput = Record<string, never>;
21
23
  /**
22
24
  * Get wallet balance with USD conversion.
23
25
  */
24
- export declare function getBalance(cwi: WalletInterface, chain?: "main" | "test", wocApiKey?: string): Promise<Balance>;
26
+ export declare const getBalance: Skill<GetBalanceInput, Balance>;
27
+ /** Input for getPaymentUtxos skill (no required params) */
28
+ export type GetPaymentUtxosInput = Record<string, never>;
25
29
  /**
26
30
  * Get payment UTXOs for external use.
27
31
  */
28
- export declare function getPaymentUtxos(cwi: WalletInterface): Promise<PaymentUtxo[]>;
32
+ export declare const getPaymentUtxos: Skill<GetPaymentUtxosInput, PaymentUtxo[]>;
33
+ /** Input for getExchangeRate skill (no required params) */
34
+ export type GetExchangeRateInput = Record<string, never>;
29
35
  /**
30
36
  * Get current BSV/USD exchange rate.
31
37
  */
32
- export declare function getExchangeRate(chain?: "main" | "test", wocApiKey?: string): Promise<number>;
38
+ export declare const getExchangeRate: Skill<GetExchangeRateInput, number>;
39
+ /** Input for getChainInfo skill (no required params) */
40
+ export type GetChainInfoInput = Record<string, never>;
41
+ /** Output for getChainInfo skill */
42
+ export interface ChainInfo {
43
+ blocks: number;
44
+ }
33
45
  /**
34
46
  * Get chain info from WhatsOnChain.
35
47
  */
36
- export declare function getChainInfo(chain?: "main" | "test", wocApiKey?: string): Promise<{
37
- blocks: number;
38
- } | null>;
48
+ export declare const getChainInfo: Skill<GetChainInfoInput, ChainInfo | null>;
49
+ /** All balance skills for registry */
50
+ export declare const balanceSkills: (Skill<GetBalanceInput, Balance> | Skill<GetPaymentUtxosInput, PaymentUtxo[]> | Skill<GetExchangeRateInput, number> | Skill<GetChainInfoInput, ChainInfo | null>)[];
@@ -1,47 +1,15 @@
1
1
  /**
2
2
  * Balance Module
3
3
  *
4
- * Functions for querying wallet balance and payment UTXOs.
4
+ * Skills for querying wallet balance and payment UTXOs.
5
5
  */
6
6
  import { FUNDING_BASKET, WOC_MAINNET_URL, WOC_TESTNET_URL, EXCHANGE_RATE_CACHE_TTL } from "../constants";
7
7
  // Module-level cache for exchange rate
8
8
  let exchangeRateCache = null;
9
- /**
10
- * Get wallet balance with USD conversion.
11
- */
12
- export async function getBalance(cwi, chain = "main", wocApiKey) {
13
- const exchangeRate = await getExchangeRate(chain, wocApiKey);
14
- const result = await cwi.listOutputs({ basket: FUNDING_BASKET, limit: 10000 });
15
- console.log(`[getBalance] Found ${result.outputs.length} outputs in "${FUNDING_BASKET}" basket, total: ${result.totalOutputs}`);
16
- const satoshis = result.outputs.reduce((sum, o) => sum + o.satoshis, 0);
17
- console.log(`[getBalance] Total satoshis: ${satoshis}`);
18
- const bsv = satoshis / 100_000_000;
19
- const usdInCents = Math.round(bsv * exchangeRate * 100);
20
- return { satoshis, bsv, usdInCents };
21
- }
22
- /**
23
- * Get payment UTXOs for external use.
24
- */
25
- export async function getPaymentUtxos(cwi) {
26
- const result = await cwi.listOutputs({
27
- basket: FUNDING_BASKET,
28
- include: "locking scripts",
29
- limit: 10000,
30
- });
31
- return result.outputs.map((o) => {
32
- const [txid, voutStr] = o.outpoint.split(".");
33
- return {
34
- txid,
35
- vout: parseInt(voutStr, 10),
36
- satoshis: o.satoshis,
37
- script: o.lockingScript || "",
38
- };
39
- });
40
- }
41
- /**
42
- * Get current BSV/USD exchange rate.
43
- */
44
- export async function getExchangeRate(chain = "main", wocApiKey) {
9
+ // ============================================================================
10
+ // Internal helpers
11
+ // ============================================================================
12
+ async function fetchExchangeRate(chain, wocApiKey) {
45
13
  if (exchangeRateCache && Date.now() - exchangeRateCache.timestamp < EXCHANGE_RATE_CACHE_TTL) {
46
14
  return exchangeRateCache.rate;
47
15
  }
@@ -62,21 +30,106 @@ export async function getExchangeRate(chain = "main", wocApiKey) {
62
30
  return exchangeRateCache?.rate ?? 0;
63
31
  }
64
32
  }
33
+ /**
34
+ * Get wallet balance with USD conversion.
35
+ */
36
+ export const getBalance = {
37
+ meta: {
38
+ name: "getBalance",
39
+ description: "Get wallet balance in satoshis, BSV, and USD cents",
40
+ category: "balance",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {},
44
+ },
45
+ },
46
+ async execute(ctx) {
47
+ const exchangeRate = await fetchExchangeRate(ctx.chain, ctx.wocApiKey);
48
+ const result = await ctx.wallet.listOutputs({ basket: FUNDING_BASKET, limit: 10000 });
49
+ const satoshis = result.outputs.reduce((sum, o) => sum + o.satoshis, 0);
50
+ const bsv = satoshis / 100_000_000;
51
+ const usdInCents = Math.round(bsv * exchangeRate * 100);
52
+ return { satoshis, bsv, usdInCents };
53
+ },
54
+ };
55
+ /**
56
+ * Get payment UTXOs for external use.
57
+ */
58
+ export const getPaymentUtxos = {
59
+ meta: {
60
+ name: "getPaymentUtxos",
61
+ description: "Get payment UTXOs from the wallet for external use",
62
+ category: "balance",
63
+ inputSchema: {
64
+ type: "object",
65
+ properties: {},
66
+ },
67
+ },
68
+ async execute(ctx) {
69
+ const result = await ctx.wallet.listOutputs({
70
+ basket: FUNDING_BASKET,
71
+ include: "locking scripts",
72
+ limit: 10000,
73
+ });
74
+ return result.outputs.map((o) => {
75
+ const [txid, voutStr] = o.outpoint.split(".");
76
+ return {
77
+ txid,
78
+ vout: Number.parseInt(voutStr, 10),
79
+ satoshis: o.satoshis,
80
+ script: o.lockingScript || "",
81
+ };
82
+ });
83
+ },
84
+ };
85
+ /**
86
+ * Get current BSV/USD exchange rate.
87
+ */
88
+ export const getExchangeRate = {
89
+ meta: {
90
+ name: "getExchangeRate",
91
+ description: "Get current BSV/USD exchange rate from WhatsOnChain",
92
+ category: "balance",
93
+ inputSchema: {
94
+ type: "object",
95
+ properties: {},
96
+ },
97
+ },
98
+ async execute(ctx) {
99
+ return fetchExchangeRate(ctx.chain, ctx.wocApiKey);
100
+ },
101
+ };
65
102
  /**
66
103
  * Get chain info from WhatsOnChain.
67
104
  */
68
- export async function getChainInfo(chain = "main", wocApiKey) {
69
- const baseUrl = chain === "main" ? WOC_MAINNET_URL : WOC_TESTNET_URL;
70
- const headers = {};
71
- if (wocApiKey)
72
- headers["woc-api-key"] = wocApiKey;
73
- try {
74
- const response = await fetch(`${baseUrl}/chain/info`, { headers });
75
- if (!response.ok)
105
+ export const getChainInfo = {
106
+ meta: {
107
+ name: "getChainInfo",
108
+ description: "Get current chain info (block height) from WhatsOnChain",
109
+ category: "balance",
110
+ inputSchema: {
111
+ type: "object",
112
+ properties: {},
113
+ },
114
+ },
115
+ async execute(ctx) {
116
+ const baseUrl = ctx.chain === "main" ? WOC_MAINNET_URL : WOC_TESTNET_URL;
117
+ const headers = {};
118
+ if (ctx.wocApiKey)
119
+ headers["woc-api-key"] = ctx.wocApiKey;
120
+ try {
121
+ const response = await fetch(`${baseUrl}/chain/info`, { headers });
122
+ if (!response.ok)
123
+ return null;
124
+ return await response.json();
125
+ }
126
+ catch {
76
127
  return null;
77
- return await response.json();
78
- }
79
- catch {
80
- return null;
81
- }
82
- }
128
+ }
129
+ },
130
+ };
131
+ // ============================================================================
132
+ // Module exports
133
+ // ============================================================================
134
+ /** All balance skills for registry */
135
+ export const balanceSkills = [getBalance, getPaymentUtxos, getExchangeRate, getChainInfo];
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Broadcast Module
3
3
  *
4
- * Functions for broadcasting transactions.
4
+ * Skills for broadcasting transactions.
5
5
  */
6
- import { type WalletInterface } from "@bsv/sdk";
6
+ import type { Skill } from "../skills/types";
7
7
  export interface BroadcastRequest {
8
8
  /** Raw transaction hex */
9
9
  rawtx: string;
@@ -19,4 +19,6 @@ export interface BroadcastResponse {
19
19
  /**
20
20
  * Broadcast a transaction and internalize it into the wallet.
21
21
  */
22
- export declare function broadcast(cwi: WalletInterface, request: BroadcastRequest): Promise<BroadcastResponse>;
22
+ export declare const broadcast: Skill<BroadcastRequest, BroadcastResponse>;
23
+ /** All broadcast skills for registry */
24
+ export declare const broadcastSkills: Skill<BroadcastRequest, BroadcastResponse>[];
@@ -1,45 +1,73 @@
1
1
  /**
2
2
  * Broadcast Module
3
3
  *
4
- * Functions for broadcasting transactions.
4
+ * Skills for broadcasting transactions.
5
5
  */
6
- import { Beef, Transaction, } from "@bsv/sdk";
6
+ import { Beef, Transaction } from "@bsv/sdk";
7
+ // ============================================================================
8
+ // Skills
9
+ // ============================================================================
7
10
  /**
8
11
  * Broadcast a transaction and internalize it into the wallet.
9
12
  */
10
- export async function broadcast(cwi, request) {
11
- try {
12
- let tx;
13
- switch (request.format) {
14
- case "beef":
15
- tx = Transaction.fromHexBEEF(request.rawtx);
16
- break;
17
- case "ef":
18
- tx = Transaction.fromHexEF(request.rawtx);
19
- break;
20
- default:
21
- tx = Transaction.fromHex(request.rawtx);
22
- }
23
- const txid = tx.id("hex");
24
- const beef = new Beef();
25
- beef.mergeTransaction(tx);
26
- const outputs = tx.outputs.map((_, index) => ({
27
- outputIndex: index,
28
- protocol: "wallet payment",
29
- paymentRemittance: {
30
- derivationPrefix: "default",
31
- derivationSuffix: `${txid}.${index}`,
32
- senderIdentityKey: "",
13
+ export const broadcast = {
14
+ meta: {
15
+ name: "broadcast",
16
+ description: "Broadcast a transaction and internalize it into the wallet",
17
+ category: "broadcast",
18
+ inputSchema: {
19
+ type: "object",
20
+ properties: {
21
+ rawtx: { type: "string", description: "Raw transaction hex" },
22
+ format: {
23
+ type: "string",
24
+ description: "Transaction format (tx, beef, ef)",
25
+ enum: ["tx", "beef", "ef"],
26
+ },
27
+ description: { type: "string", description: "Description for wallet records" },
33
28
  },
34
- }));
35
- await cwi.internalizeAction({
36
- tx: Array.from(beef.toBinary()),
37
- outputs,
38
- description: request.description || "Broadcast transaction",
39
- });
40
- return { txid };
41
- }
42
- catch (error) {
43
- return { error: error instanceof Error ? error.message : "Unknown error" };
44
- }
45
- }
29
+ required: ["rawtx"],
30
+ },
31
+ },
32
+ async execute(ctx, input) {
33
+ try {
34
+ let tx;
35
+ switch (input.format) {
36
+ case "beef":
37
+ tx = Transaction.fromHexBEEF(input.rawtx);
38
+ break;
39
+ case "ef":
40
+ tx = Transaction.fromHexEF(input.rawtx);
41
+ break;
42
+ default:
43
+ tx = Transaction.fromHex(input.rawtx);
44
+ }
45
+ const txid = tx.id("hex");
46
+ const beef = new Beef();
47
+ beef.mergeTransaction(tx);
48
+ const outputs = tx.outputs.map((_, index) => ({
49
+ outputIndex: index,
50
+ protocol: "wallet payment",
51
+ paymentRemittance: {
52
+ derivationPrefix: "default",
53
+ derivationSuffix: `${txid}.${index}`,
54
+ senderIdentityKey: "",
55
+ },
56
+ }));
57
+ await ctx.wallet.internalizeAction({
58
+ tx: Array.from(beef.toBinary()),
59
+ outputs,
60
+ description: input.description || "Broadcast transaction",
61
+ });
62
+ return { txid };
63
+ }
64
+ catch (error) {
65
+ return { error: error instanceof Error ? error.message : "Unknown error" };
66
+ }
67
+ },
68
+ };
69
+ // ============================================================================
70
+ // Module exports
71
+ // ============================================================================
72
+ /** All broadcast skills for registry */
73
+ export const broadcastSkills = [broadcast];
@@ -1,29 +1,29 @@
1
1
  /**
2
2
  * 1Sat Wallet Toolbox API Layer
3
3
  *
4
- * This module provides the OneSatApi class for interacting with the 1Sat ecosystem.
5
- * All methods work with any BRC-100 compatible wallet interface (CWI).
4
+ * This module provides skills (self-describing actions) for interacting with the 1Sat ecosystem.
5
+ * All skills work with any BRC-100 compatible wallet interface via OneSatContext.
6
6
  *
7
7
  * Usage:
8
8
  * ```typescript
9
- * import { OneSatApi } from '@1sat/wallet-toolbox';
9
+ * import { createContext, transferOrdinal, skillRegistry } from '@1sat/wallet-toolbox/api';
10
10
  *
11
- * // Create API instance with a CWI-compatible wallet
12
- * const api = new OneSatApi(cwi);
11
+ * // Create context with a BRC-100 compatible wallet
12
+ * const ctx = createContext(wallet, { services, chain: 'main' });
13
13
  *
14
- * // Use the API
15
- * const balance = await api.getBalance();
16
- * const ordinals = await api.listOrdinals();
17
- * const result = await api.sendBsv([{ address: '...', satoshis: 1000 }]);
18
- * ```
14
+ * // Execute skills directly
15
+ * const result = await transferOrdinal.execute(ctx, { outpoint: '...', address: '...' });
19
16
  *
20
- * You can also import functions directly from modules:
21
- * ```typescript
22
- * import { listOrdinals } from '@1sat/wallet-toolbox/api/ordinals';
23
- * import { sendBsv } from '@1sat/wallet-toolbox/api/payments';
17
+ * // Or via registry (useful for AI agents)
18
+ * const skill = skillRegistry.get('transferOrdinal');
19
+ * const result = await skill.execute(ctx, { outpoint: '...', address: '...' });
20
+ *
21
+ * // Get MCP-compatible tool list
22
+ * const tools = skillRegistry.toMcpTools();
24
23
  * ```
25
24
  */
26
- export { OneSatApi } from "./OneSatApi";
25
+ export { type OneSatContext, type Skill, type SkillMetadata, type SkillCategory, type JsonSchemaProperty, createContext, } from "./skills/types";
26
+ export { SkillRegistry, skillRegistry, type McpTool } from "./skills/registry";
27
27
  export * from "./constants";
28
28
  export * from "./balance";
29
29
  export * from "./payments";
@@ -33,4 +33,5 @@ export * from "./inscriptions";
33
33
  export * from "./locks";
34
34
  export * from "./signing";
35
35
  export * from "./broadcast";
36
+ export * from "./sweep";
36
37
  export type { WalletInterface, WalletOutput, CreateActionArgs, CreateActionResult, CreateActionOutput, CreateActionInput, ListOutputsResult, ListOutputsArgs, } from "@bsv/sdk";
package/dist/api/index.js CHANGED
@@ -1,33 +1,34 @@
1
1
  /**
2
2
  * 1Sat Wallet Toolbox API Layer
3
3
  *
4
- * This module provides the OneSatApi class for interacting with the 1Sat ecosystem.
5
- * All methods work with any BRC-100 compatible wallet interface (CWI).
4
+ * This module provides skills (self-describing actions) for interacting with the 1Sat ecosystem.
5
+ * All skills work with any BRC-100 compatible wallet interface via OneSatContext.
6
6
  *
7
7
  * Usage:
8
8
  * ```typescript
9
- * import { OneSatApi } from '@1sat/wallet-toolbox';
9
+ * import { createContext, transferOrdinal, skillRegistry } from '@1sat/wallet-toolbox/api';
10
10
  *
11
- * // Create API instance with a CWI-compatible wallet
12
- * const api = new OneSatApi(cwi);
11
+ * // Create context with a BRC-100 compatible wallet
12
+ * const ctx = createContext(wallet, { services, chain: 'main' });
13
13
  *
14
- * // Use the API
15
- * const balance = await api.getBalance();
16
- * const ordinals = await api.listOrdinals();
17
- * const result = await api.sendBsv([{ address: '...', satoshis: 1000 }]);
18
- * ```
14
+ * // Execute skills directly
15
+ * const result = await transferOrdinal.execute(ctx, { outpoint: '...', address: '...' });
19
16
  *
20
- * You can also import functions directly from modules:
21
- * ```typescript
22
- * import { listOrdinals } from '@1sat/wallet-toolbox/api/ordinals';
23
- * import { sendBsv } from '@1sat/wallet-toolbox/api/payments';
17
+ * // Or via registry (useful for AI agents)
18
+ * const skill = skillRegistry.get('transferOrdinal');
19
+ * const result = await skill.execute(ctx, { outpoint: '...', address: '...' });
20
+ *
21
+ * // Get MCP-compatible tool list
22
+ * const tools = skillRegistry.toMcpTools();
24
23
  * ```
25
24
  */
26
- // Export the main API class
27
- export { OneSatApi } from "./OneSatApi";
25
+ // Export skill types and helpers
26
+ export { createContext, } from "./skills/types";
27
+ // Export skill registry
28
+ export { SkillRegistry, skillRegistry } from "./skills/registry";
28
29
  // Export constants
29
30
  export * from "./constants";
30
- // Export module functions and types
31
+ // Export module skills and types
31
32
  export * from "./balance";
32
33
  export * from "./payments";
33
34
  export * from "./ordinals";
@@ -36,3 +37,27 @@ export * from "./inscriptions";
36
37
  export * from "./locks";
37
38
  export * from "./signing";
38
39
  export * from "./broadcast";
40
+ // Export sweep module (uses external signing, not skill-based)
41
+ export * from "./sweep";
42
+ // Register all skills with the global registry
43
+ import { skillRegistry } from "./skills/registry";
44
+ import { balanceSkills } from "./balance";
45
+ import { paymentsSkills } from "./payments";
46
+ import { ordinalsSkills } from "./ordinals";
47
+ import { tokensSkills } from "./tokens";
48
+ import { inscriptionsSkills } from "./inscriptions";
49
+ import { locksSkills } from "./locks";
50
+ import { signingSkills } from "./signing";
51
+ import { broadcastSkills } from "./broadcast";
52
+ import { sweepSkills } from "./sweep";
53
+ skillRegistry.registerAll([
54
+ ...balanceSkills,
55
+ ...paymentsSkills,
56
+ ...ordinalsSkills,
57
+ ...tokensSkills,
58
+ ...inscriptionsSkills,
59
+ ...locksSkills,
60
+ ...signingSkills,
61
+ ...broadcastSkills,
62
+ ...sweepSkills,
63
+ ]);
@@ -1,18 +1,16 @@
1
1
  /**
2
2
  * Inscriptions Module
3
3
  *
4
- * Functions for creating inscriptions.
4
+ * Skills for creating inscriptions.
5
5
  */
6
- import { type WalletInterface } from "@bsv/sdk";
6
+ import type { Skill } from "../skills/types";
7
7
  export interface InscribeRequest {
8
- /** Base64 encoded data */
9
- base64Data: string;
10
- /** MIME type of the content */
11
- mimeType: string;
8
+ /** Base64 encoded content */
9
+ base64Content: string;
10
+ /** Content type (MIME type) */
11
+ contentType: string;
12
12
  /** Optional MAP metadata */
13
13
  map?: Record<string, string>;
14
- /** Destination address for the inscription (required - use a derived address) */
15
- destination: string;
16
14
  }
17
15
  export interface InscribeResponse {
18
16
  txid?: string;
@@ -22,4 +20,6 @@ export interface InscribeResponse {
22
20
  /**
23
21
  * Create an inscription.
24
22
  */
25
- export declare function inscribe(cwi: WalletInterface, request: InscribeRequest): Promise<InscribeResponse>;
23
+ export declare const inscribe: Skill<InscribeRequest, InscribeResponse>;
24
+ /** All inscription skills for registry */
25
+ export declare const inscriptionsSkills: Skill<InscribeRequest, InscribeResponse>[];
@@ -1,17 +1,21 @@
1
1
  /**
2
2
  * Inscriptions Module
3
3
  *
4
- * Functions for creating inscriptions.
4
+ * Skills for creating inscriptions.
5
5
  */
6
- import { P2PKH, Script, Utils, } from "@bsv/sdk";
6
+ import { P2PKH, PublicKey, Script, Utils } from "@bsv/sdk";
7
7
  import { Inscription } from "@bopen-io/templates";
8
- import { MAX_INSCRIPTION_BYTES } from "../constants";
9
- /**
10
- * Build an inscription locking script.
11
- */
12
- function buildInscriptionScript(address, base64Data, mimeType) {
13
- const content = Utils.toArray(base64Data, "base64");
14
- const inscription = Inscription.create(new Uint8Array(content), mimeType);
8
+ import { MAX_INSCRIPTION_BYTES, ORDINALS_BASKET } from "../constants";
9
+ // ============================================================================
10
+ // Constants
11
+ // ============================================================================
12
+ const ORDINAL_PROTOCOL = [1, "ordinal"];
13
+ // ============================================================================
14
+ // Internal helpers
15
+ // ============================================================================
16
+ function buildInscriptionScript(address, base64Content, contentType) {
17
+ const content = Utils.toArray(base64Content, "base64");
18
+ const inscription = Inscription.create(new Uint8Array(content), contentType);
15
19
  const inscriptionScript = inscription.lock();
16
20
  const p2pkhScript = new P2PKH().lock(address);
17
21
  const combined = new Script();
@@ -21,30 +25,74 @@ function buildInscriptionScript(address, base64Data, mimeType) {
21
25
  combined.chunks.push(chunk);
22
26
  return combined;
23
27
  }
28
+ // ============================================================================
29
+ // Skills
30
+ // ============================================================================
24
31
  /**
25
32
  * Create an inscription.
26
33
  */
27
- export async function inscribe(cwi, request) {
28
- try {
29
- const decoded = Buffer.from(request.base64Data, "base64");
30
- if (decoded.length > MAX_INSCRIPTION_BYTES) {
31
- return { error: `Inscription data too large: ${decoded.length} bytes (max ${MAX_INSCRIPTION_BYTES})` };
34
+ export const inscribe = {
35
+ meta: {
36
+ name: "inscribe",
37
+ description: "Create a new inscription with the given content and type",
38
+ category: "inscriptions",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ base64Content: { type: "string", description: "Base64 encoded content" },
43
+ contentType: { type: "string", description: "Content type (MIME type)" },
44
+ map: {
45
+ type: "object",
46
+ description: "Optional MAP metadata",
47
+ properties: {},
48
+ },
49
+ },
50
+ required: ["base64Content", "contentType"],
51
+ },
52
+ },
53
+ async execute(ctx, input) {
54
+ try {
55
+ const decoded = Utils.toArray(input.base64Content, "base64");
56
+ if (decoded.length > MAX_INSCRIPTION_BYTES) {
57
+ return { error: `Inscription data too large: ${decoded.length} bytes (max ${MAX_INSCRIPTION_BYTES})` };
58
+ }
59
+ const keyID = Date.now().toString();
60
+ const { publicKey } = await ctx.wallet.getPublicKey({
61
+ protocolID: ORDINAL_PROTOCOL,
62
+ keyID,
63
+ counterparty: "self",
64
+ forSelf: true,
65
+ });
66
+ const address = PublicKey.fromString(publicKey).toAddress();
67
+ const lockingScript = buildInscriptionScript(address, input.base64Content, input.contentType);
68
+ const result = await ctx.wallet.createAction({
69
+ description: "Create inscription",
70
+ outputs: [
71
+ {
72
+ lockingScript: lockingScript.toHex(),
73
+ satoshis: 1,
74
+ outputDescription: "Inscription",
75
+ basket: ORDINALS_BASKET,
76
+ tags: [`type:${input.contentType}`],
77
+ customInstructions: JSON.stringify({
78
+ protocolID: ORDINAL_PROTOCOL,
79
+ keyID,
80
+ }),
81
+ },
82
+ ],
83
+ });
84
+ if (!result.txid) {
85
+ return { error: "no-txid-returned" };
86
+ }
87
+ return { txid: result.txid, rawtx: result.tx ? Utils.toHex(result.tx) : undefined };
32
88
  }
33
- const lockingScript = buildInscriptionScript(request.destination, request.base64Data, request.mimeType);
34
- const result = await cwi.createAction({
35
- description: "Create inscription",
36
- outputs: [{
37
- lockingScript: lockingScript.toHex(),
38
- satoshis: 1,
39
- outputDescription: "Inscription",
40
- }],
41
- });
42
- if (!result.txid) {
43
- return { error: "no-txid-returned" };
89
+ catch (error) {
90
+ return { error: error instanceof Error ? error.message : "unknown-error" };
44
91
  }
45
- return { txid: result.txid, rawtx: result.tx ? Utils.toHex(result.tx) : undefined };
46
- }
47
- catch (error) {
48
- return { error: error instanceof Error ? error.message : "unknown-error" };
49
- }
50
- }
92
+ },
93
+ };
94
+ // ============================================================================
95
+ // Module exports
96
+ // ============================================================================
97
+ /** All inscription skills for registry */
98
+ export const inscriptionsSkills = [inscribe];