@secondlayer/stacks 5.1.3 → 6.0.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 CHANGED
@@ -64,14 +64,7 @@ multi-broadcast gap, which is why it lives here rather than being deferred to
64
64
  | `@secondlayer/stacks/pox` | PoX stacking — solo and delegated |
65
65
  | `@secondlayer/stacks/stackingdao` | StackingDAO liquid staking (STX/stSTX) |
66
66
 
67
- ### Deprecated: `/tools` and `/tools/btc`
68
-
69
- Give your agent Stacks reads through [`@secondlayer/mcp`](https://www.npmjs.com/package/@secondlayer/mcp) instead. The two AI SDK tool entries below still import, and stay until the next major, but they get no new tools. The tradeoff of keeping them: `ai` and `zod` are now optional peer dependencies, so a project that imports either entry installs both itself; a project that only reads contracts installs neither.
70
-
71
- | Module | Description |
72
- |---|---|
73
- | `@secondlayer/stacks/tools` | **Deprecated.** AI SDK `tool()` set for Stacks reads. Bare exports read `STACKS_NETWORK` (or `STACKS_CHAIN`) and `STACKS_NODE_RPC_URL`, `SL_API_URL` or `STACKS_RPC_URL`; `createStacksTools(client)` binds your own client |
74
- | `@secondlayer/stacks/tools/btc` | **Deprecated.** AI SDK `tool()` set for Bitcoin reads via mempool.space (`BTC_MEMPOOL_URL` overrides the host) |
67
+ Agent Stacks reads go through [`@secondlayer/mcp`](https://www.npmjs.com/package/@secondlayer/mcp).
75
68
 
76
69
  ## Guides
77
70
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/stacks",
3
- "version": "5.1.3",
3
+ "version": "6.0.0",
4
4
  "description": "Typed Stacks client for TypeScript: read contracts, decode Clarity, build and send transactions.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -99,16 +99,6 @@
99
99
  "import": "./dist/src/connect/walletconnect/index.js",
100
100
  "require": "./dist/src/connect/walletconnect/index.cjs"
101
101
  },
102
- "./tools": {
103
- "types": "./dist/src/tools/index.d.ts",
104
- "import": "./dist/src/tools/index.js",
105
- "require": "./dist/src/tools/index.cjs"
106
- },
107
- "./tools/btc": {
108
- "types": "./dist/src/tools/btc/index.d.ts",
109
- "import": "./dist/src/tools/btc/index.js",
110
- "require": "./dist/src/tools/btc/index.cjs"
111
- },
112
102
  "./filters": {
113
103
  "types": "./dist/src/filters/index.d.ts",
114
104
  "import": "./dist/src/filters/index.js",
@@ -133,16 +123,12 @@
133
123
  "devDependencies": {
134
124
  "@stacks/clarinet-sdk": "3.21.1",
135
125
  "@stacks/transactions": "7.0.6",
136
- "@types/bun": "latest",
137
- "ai": "6.0.167",
138
- "zod": "^4.3.6"
126
+ "@types/bun": "latest"
139
127
  },
140
128
  "peerDependencies": {
141
129
  "@stacks/clarinet-sdk": "^3",
142
130
  "@stacks/transactions": "^7",
143
- "ai": "^6",
144
- "typescript": "^5",
145
- "zod": "^4"
131
+ "typescript": "^5"
146
132
  },
147
133
  "peerDependenciesMeta": {
148
134
  "@stacks/clarinet-sdk": {
@@ -150,12 +136,6 @@
150
136
  },
151
137
  "@stacks/transactions": {
152
138
  "optional": true
153
- },
154
- "ai": {
155
- "optional": true
156
- },
157
- "zod": {
158
- "optional": true
159
139
  }
160
140
  },
161
141
  "dependencies": {
@@ -1,131 +0,0 @@
1
- var import_node_module = require("node:module");
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- function __accessProp(key) {
7
- return this[key];
8
- }
9
- var __toCommonJS = (from) => {
10
- var entry = (__moduleCache ??= new WeakMap).get(from), desc;
11
- if (entry)
12
- return entry;
13
- entry = __defProp({}, "__esModule", { value: true });
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (var key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(entry, key))
17
- __defProp(entry, key, {
18
- get: __accessProp.bind(from, key),
19
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
- });
21
- }
22
- __moduleCache.set(from, entry);
23
- return entry;
24
- };
25
- var __moduleCache;
26
- var __returnValue = (v) => v;
27
- function __exportSetter(name, newValue) {
28
- this[name] = __returnValue.bind(null, newValue);
29
- }
30
- var __export = (target, all) => {
31
- for (var name in all)
32
- __defProp(target, name, {
33
- get: all[name],
34
- enumerable: true,
35
- configurable: true,
36
- set: __exportSetter.bind(all, name)
37
- });
38
- };
39
-
40
- // src/tools/btc/index.ts
41
- var exports_btc = {};
42
- __export(exports_btc, {
43
- btcUtxos: () => btcUtxos,
44
- btcFeeEstimate: () => btcFeeEstimate,
45
- btcConfirmations: () => btcConfirmations,
46
- btcBlockHeight: () => btcBlockHeight,
47
- btcBalance: () => btcBalance,
48
- BTC_ADDRESS: () => BTC_ADDRESS
49
- });
50
- module.exports = __toCommonJS(exports_btc);
51
- var import_ai = require("ai");
52
- var import_zod = require("zod");
53
- function baseUrl() {
54
- return (process.env.BTC_MEMPOOL_URL ?? "https://mempool.space").replace(/\/$/, "");
55
- }
56
- async function get(path) {
57
- const res = await fetch(`${baseUrl()}${path}`, {
58
- headers: { Accept: "application/json" }
59
- });
60
- if (!res.ok) {
61
- throw new Error(`BTC mempool.space ${path} → ${res.status} ${res.statusText}`);
62
- }
63
- const contentType = res.headers.get("content-type") ?? "";
64
- if (contentType.includes("application/json"))
65
- return res.json();
66
- return res.text();
67
- }
68
- var BTC_TXID = import_zod.z.string().regex(/^[0-9a-fA-F]{64}$/, "64-character hex BTC txid");
69
- var BTC_ADDRESS = import_zod.z.string().regex(/^(1[a-zA-HJ-NP-Z0-9]{25,34}|3[a-zA-HJ-NP-Z0-9]{25,34}|bc1[a-zA-HJ-NP-Z0-9]{11,71}|tb1[a-zA-HJ-NP-Z0-9]{11,71})$/, { message: "Invalid Bitcoin address" });
70
- var btcConfirmations = import_ai.tool({
71
- description: "Number of confirmations for a Bitcoin transaction. Returns { confirmations, confirmed }.",
72
- inputSchema: import_zod.z.object({ txid: BTC_TXID }),
73
- execute: async ({ txid }) => {
74
- const tx = await get(`/api/tx/${txid}`);
75
- if (!tx.status.confirmed || tx.status.block_height == null) {
76
- return { confirmed: false, confirmations: 0 };
77
- }
78
- const tip = await get("/api/blocks/tip/height");
79
- return {
80
- confirmed: true,
81
- confirmations: Math.max(0, tip - tx.status.block_height + 1),
82
- blockHeight: tx.status.block_height
83
- };
84
- }
85
- });
86
- var btcBalance = import_ai.tool({
87
- description: "Bitcoin balance for an address, in satoshis. Returns { confirmedSat, unconfirmedSat }.",
88
- inputSchema: import_zod.z.object({ address: BTC_ADDRESS }),
89
- execute: async ({ address }) => {
90
- const info = await get(`/api/address/${encodeURIComponent(address)}`);
91
- return {
92
- confirmedSat: info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum,
93
- unconfirmedSat: info.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum
94
- };
95
- }
96
- });
97
- var btcUtxos = import_ai.tool({
98
- description: "List of unspent outputs for a Bitcoin address (truncated to `limit`).",
99
- inputSchema: import_zod.z.object({
100
- address: BTC_ADDRESS,
101
- limit: import_zod.z.number().int().min(1).max(50).default(25)
102
- }),
103
- execute: async ({ address, limit }) => {
104
- const utxos = await get(`/api/address/${encodeURIComponent(address)}/utxo`);
105
- return { utxos: utxos.slice(0, limit) };
106
- }
107
- });
108
- var btcFeeEstimate = import_ai.tool({
109
- description: "Current Bitcoin fee estimates in sat/vB across priority tiers (fastest, 30-min, hour, economy).",
110
- inputSchema: import_zod.z.object({}),
111
- execute: async () => {
112
- const fees = await get("/api/v1/fees/recommended");
113
- return {
114
- fastestSatVb: fees.fastestFee ?? 0,
115
- halfHourSatVb: fees.halfHourFee ?? 0,
116
- hourSatVb: fees.hourFee ?? 0,
117
- economySatVb: fees.economyFee ?? 0,
118
- minimumSatVb: fees.minimumFee ?? 0
119
- };
120
- }
121
- });
122
- var btcBlockHeight = import_ai.tool({
123
- description: "Current Bitcoin chain tip height.",
124
- inputSchema: import_zod.z.object({}),
125
- execute: async () => ({
126
- height: await get("/api/blocks/tip/height")
127
- })
128
- });
129
-
130
- //# debugId=A9918581E436E21F64756E2164756E21
131
- //# sourceMappingURL=index.cjs.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/tools/btc/index.ts"],
4
- "sourcesContent": [
5
- "/**\n * Bitcoin read tools for AI SDK tool calls. Useful for sBTC peg-in/peg-out\n * flows, BTC-collateralized lending, and anywhere a Stacks contract's\n * behaviour depends on BTC state.\n *\n * @deprecated Point your agent at `@secondlayer/mcp` instead; this entry\n * stays importable until the next major but gets no new tools. Installing\n * it means installing `ai` and `zod` yourself: both are optional peers of\n * the package, not dependencies.\n *\n * Backed by mempool.space by default. Swap endpoints by setting\n * `BTC_MEMPOOL_URL` in the caller's env. Reads only, no BTC writes.\n *\n * import { generateText } from \"ai\"\n * import { btcConfirmations, btcBalance } from \"@secondlayer/stacks/tools/btc\"\n * await generateText({\n * model: anthropic(\"claude-sonnet-4-6\"),\n * tools: { btcConfirmations, btcBalance },\n * prompt: \"…\",\n * })\n */\n\nimport { type Tool, tool } from \"ai\";\nimport { z } from \"zod\";\n\n// biome-ignore lint/suspicious/noExplicitAny: Tool's input-schema generic too precise for isolated-declarations; AI SDK validates at runtime\ntype LooseTool = Tool<any, any>;\n\nfunction baseUrl(): string {\n\treturn (process.env.BTC_MEMPOOL_URL ?? \"https://mempool.space\").replace(\n\t\t/\\/$/,\n\t\t\"\",\n\t);\n}\n\nasync function get<T>(path: string): Promise<T> {\n\tconst res = await fetch(`${baseUrl()}${path}`, {\n\t\theaders: { Accept: \"application/json\" },\n\t});\n\tif (!res.ok) {\n\t\tthrow new Error(\n\t\t\t`BTC mempool.space ${path} → ${res.status} ${res.statusText}`,\n\t\t);\n\t}\n\tconst contentType = res.headers.get(\"content-type\") ?? \"\";\n\tif (contentType.includes(\"application/json\")) return res.json() as Promise<T>;\n\treturn res.text() as unknown as Promise<T>;\n}\n\nconst BTC_TXID = z\n\t.string()\n\t.regex(/^[0-9a-fA-F]{64}$/, \"64-character hex BTC txid\");\nexport const BTC_ADDRESS: z.ZodString = z\n\t.string()\n\t.regex(\n\t\t/^(1[a-zA-HJ-NP-Z0-9]{25,34}|3[a-zA-HJ-NP-Z0-9]{25,34}|bc1[a-zA-HJ-NP-Z0-9]{11,71}|tb1[a-zA-HJ-NP-Z0-9]{11,71})$/,\n\t\t{ message: \"Invalid Bitcoin address\" },\n\t);\n\nexport const btcConfirmations: LooseTool = tool({\n\tdescription:\n\t\t\"Number of confirmations for a Bitcoin transaction. Returns { confirmations, confirmed }.\",\n\tinputSchema: z.object({ txid: BTC_TXID }),\n\texecute: async ({ txid }) => {\n\t\tconst tx = await get<{\n\t\t\tstatus: { confirmed: boolean; block_height?: number };\n\t\t}>(`/api/tx/${txid}`);\n\t\tif (!tx.status.confirmed || tx.status.block_height == null) {\n\t\t\treturn { confirmed: false, confirmations: 0 };\n\t\t}\n\t\tconst tip = await get<number>(\"/api/blocks/tip/height\");\n\t\treturn {\n\t\t\tconfirmed: true,\n\t\t\tconfirmations: Math.max(0, tip - tx.status.block_height + 1),\n\t\t\tblockHeight: tx.status.block_height,\n\t\t};\n\t},\n});\n\nexport const btcBalance: LooseTool = tool({\n\tdescription:\n\t\t\"Bitcoin balance for an address, in satoshis. Returns { confirmedSat, unconfirmedSat }.\",\n\tinputSchema: z.object({ address: BTC_ADDRESS }),\n\texecute: async ({ address }) => {\n\t\tconst info = await get<{\n\t\t\tchain_stats: { funded_txo_sum: number; spent_txo_sum: number };\n\t\t\tmempool_stats: { funded_txo_sum: number; spent_txo_sum: number };\n\t\t}>(`/api/address/${encodeURIComponent(address)}`);\n\t\treturn {\n\t\t\tconfirmedSat:\n\t\t\t\tinfo.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum,\n\t\t\tunconfirmedSat:\n\t\t\t\tinfo.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum,\n\t\t};\n\t},\n});\n\nexport const btcUtxos: LooseTool = tool({\n\tdescription:\n\t\t\"List of unspent outputs for a Bitcoin address (truncated to `limit`).\",\n\tinputSchema: z.object({\n\t\taddress: BTC_ADDRESS,\n\t\tlimit: z.number().int().min(1).max(50).default(25),\n\t}),\n\texecute: async ({ address, limit }) => {\n\t\tconst utxos = await get<\n\t\t\tArray<{\n\t\t\t\ttxid: string;\n\t\t\t\tvout: number;\n\t\t\t\tvalue: number;\n\t\t\t\tstatus: { confirmed: boolean; block_height?: number };\n\t\t\t}>\n\t\t>(`/api/address/${encodeURIComponent(address)}/utxo`);\n\t\treturn { utxos: utxos.slice(0, limit) };\n\t},\n});\n\nexport const btcFeeEstimate: LooseTool = tool({\n\tdescription:\n\t\t\"Current Bitcoin fee estimates in sat/vB across priority tiers (fastest, 30-min, hour, economy).\",\n\tinputSchema: z.object({}),\n\texecute: async () => {\n\t\tconst fees = await get<Record<string, number>>(\"/api/v1/fees/recommended\");\n\t\treturn {\n\t\t\tfastestSatVb: fees.fastestFee ?? 0,\n\t\t\thalfHourSatVb: fees.halfHourFee ?? 0,\n\t\t\thourSatVb: fees.hourFee ?? 0,\n\t\t\teconomySatVb: fees.economyFee ?? 0,\n\t\t\tminimumSatVb: fees.minimumFee ?? 0,\n\t\t};\n\t},\n});\n\nexport const btcBlockHeight: LooseTool = tool({\n\tdescription: \"Current Bitcoin chain tip height.\",\n\tinputSchema: z.object({}),\n\texecute: async () => ({\n\t\theight: await get<number>(\"/api/blocks/tip/height\"),\n\t}),\n});\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "A9918581E436E21F64756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- import { Tool } from "ai";
2
- import { z } from "zod";
3
- type LooseTool = Tool<any, any>;
4
- declare const BTC_ADDRESS: z.ZodString;
5
- declare const btcConfirmations: LooseTool;
6
- declare const btcBalance: LooseTool;
7
- declare const btcUtxos: LooseTool;
8
- declare const btcFeeEstimate: LooseTool;
9
- declare const btcBlockHeight: LooseTool;
10
- export { btcUtxos, btcFeeEstimate, btcConfirmations, btcBlockHeight, btcBalance, BTC_ADDRESS };
@@ -1,10 +0,0 @@
1
- import { Tool } from "ai";
2
- import { z } from "zod";
3
- type LooseTool = Tool<any, any>;
4
- declare const BTC_ADDRESS: z.ZodString;
5
- declare const btcConfirmations: LooseTool;
6
- declare const btcBalance: LooseTool;
7
- declare const btcUtxos: LooseTool;
8
- declare const btcFeeEstimate: LooseTool;
9
- declare const btcBlockHeight: LooseTool;
10
- export { btcUtxos, btcFeeEstimate, btcConfirmations, btcBlockHeight, btcBalance, BTC_ADDRESS };
@@ -1,90 +0,0 @@
1
- // src/tools/btc/index.ts
2
- import { tool } from "ai";
3
- import { z } from "zod";
4
- function baseUrl() {
5
- return (process.env.BTC_MEMPOOL_URL ?? "https://mempool.space").replace(/\/$/, "");
6
- }
7
- async function get(path) {
8
- const res = await fetch(`${baseUrl()}${path}`, {
9
- headers: { Accept: "application/json" }
10
- });
11
- if (!res.ok) {
12
- throw new Error(`BTC mempool.space ${path} → ${res.status} ${res.statusText}`);
13
- }
14
- const contentType = res.headers.get("content-type") ?? "";
15
- if (contentType.includes("application/json"))
16
- return res.json();
17
- return res.text();
18
- }
19
- var BTC_TXID = z.string().regex(/^[0-9a-fA-F]{64}$/, "64-character hex BTC txid");
20
- var BTC_ADDRESS = z.string().regex(/^(1[a-zA-HJ-NP-Z0-9]{25,34}|3[a-zA-HJ-NP-Z0-9]{25,34}|bc1[a-zA-HJ-NP-Z0-9]{11,71}|tb1[a-zA-HJ-NP-Z0-9]{11,71})$/, { message: "Invalid Bitcoin address" });
21
- var btcConfirmations = tool({
22
- description: "Number of confirmations for a Bitcoin transaction. Returns { confirmations, confirmed }.",
23
- inputSchema: z.object({ txid: BTC_TXID }),
24
- execute: async ({ txid }) => {
25
- const tx = await get(`/api/tx/${txid}`);
26
- if (!tx.status.confirmed || tx.status.block_height == null) {
27
- return { confirmed: false, confirmations: 0 };
28
- }
29
- const tip = await get("/api/blocks/tip/height");
30
- return {
31
- confirmed: true,
32
- confirmations: Math.max(0, tip - tx.status.block_height + 1),
33
- blockHeight: tx.status.block_height
34
- };
35
- }
36
- });
37
- var btcBalance = tool({
38
- description: "Bitcoin balance for an address, in satoshis. Returns { confirmedSat, unconfirmedSat }.",
39
- inputSchema: z.object({ address: BTC_ADDRESS }),
40
- execute: async ({ address }) => {
41
- const info = await get(`/api/address/${encodeURIComponent(address)}`);
42
- return {
43
- confirmedSat: info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum,
44
- unconfirmedSat: info.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum
45
- };
46
- }
47
- });
48
- var btcUtxos = tool({
49
- description: "List of unspent outputs for a Bitcoin address (truncated to `limit`).",
50
- inputSchema: z.object({
51
- address: BTC_ADDRESS,
52
- limit: z.number().int().min(1).max(50).default(25)
53
- }),
54
- execute: async ({ address, limit }) => {
55
- const utxos = await get(`/api/address/${encodeURIComponent(address)}/utxo`);
56
- return { utxos: utxos.slice(0, limit) };
57
- }
58
- });
59
- var btcFeeEstimate = tool({
60
- description: "Current Bitcoin fee estimates in sat/vB across priority tiers (fastest, 30-min, hour, economy).",
61
- inputSchema: z.object({}),
62
- execute: async () => {
63
- const fees = await get("/api/v1/fees/recommended");
64
- return {
65
- fastestSatVb: fees.fastestFee ?? 0,
66
- halfHourSatVb: fees.halfHourFee ?? 0,
67
- hourSatVb: fees.hourFee ?? 0,
68
- economySatVb: fees.economyFee ?? 0,
69
- minimumSatVb: fees.minimumFee ?? 0
70
- };
71
- }
72
- });
73
- var btcBlockHeight = tool({
74
- description: "Current Bitcoin chain tip height.",
75
- inputSchema: z.object({}),
76
- execute: async () => ({
77
- height: await get("/api/blocks/tip/height")
78
- })
79
- });
80
- export {
81
- btcUtxos,
82
- btcFeeEstimate,
83
- btcConfirmations,
84
- btcBlockHeight,
85
- btcBalance,
86
- BTC_ADDRESS
87
- };
88
-
89
- //# debugId=E811F99F534F2FE364756E2164756E21
90
- //# sourceMappingURL=index.js.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/tools/btc/index.ts"],
4
- "sourcesContent": [
5
- "/**\n * Bitcoin read tools for AI SDK tool calls. Useful for sBTC peg-in/peg-out\n * flows, BTC-collateralized lending, and anywhere a Stacks contract's\n * behaviour depends on BTC state.\n *\n * @deprecated Point your agent at `@secondlayer/mcp` instead; this entry\n * stays importable until the next major but gets no new tools. Installing\n * it means installing `ai` and `zod` yourself: both are optional peers of\n * the package, not dependencies.\n *\n * Backed by mempool.space by default. Swap endpoints by setting\n * `BTC_MEMPOOL_URL` in the caller's env. Reads only, no BTC writes.\n *\n * import { generateText } from \"ai\"\n * import { btcConfirmations, btcBalance } from \"@secondlayer/stacks/tools/btc\"\n * await generateText({\n * model: anthropic(\"claude-sonnet-4-6\"),\n * tools: { btcConfirmations, btcBalance },\n * prompt: \"…\",\n * })\n */\n\nimport { type Tool, tool } from \"ai\";\nimport { z } from \"zod\";\n\n// biome-ignore lint/suspicious/noExplicitAny: Tool's input-schema generic too precise for isolated-declarations; AI SDK validates at runtime\ntype LooseTool = Tool<any, any>;\n\nfunction baseUrl(): string {\n\treturn (process.env.BTC_MEMPOOL_URL ?? \"https://mempool.space\").replace(\n\t\t/\\/$/,\n\t\t\"\",\n\t);\n}\n\nasync function get<T>(path: string): Promise<T> {\n\tconst res = await fetch(`${baseUrl()}${path}`, {\n\t\theaders: { Accept: \"application/json\" },\n\t});\n\tif (!res.ok) {\n\t\tthrow new Error(\n\t\t\t`BTC mempool.space ${path} → ${res.status} ${res.statusText}`,\n\t\t);\n\t}\n\tconst contentType = res.headers.get(\"content-type\") ?? \"\";\n\tif (contentType.includes(\"application/json\")) return res.json() as Promise<T>;\n\treturn res.text() as unknown as Promise<T>;\n}\n\nconst BTC_TXID = z\n\t.string()\n\t.regex(/^[0-9a-fA-F]{64}$/, \"64-character hex BTC txid\");\nexport const BTC_ADDRESS: z.ZodString = z\n\t.string()\n\t.regex(\n\t\t/^(1[a-zA-HJ-NP-Z0-9]{25,34}|3[a-zA-HJ-NP-Z0-9]{25,34}|bc1[a-zA-HJ-NP-Z0-9]{11,71}|tb1[a-zA-HJ-NP-Z0-9]{11,71})$/,\n\t\t{ message: \"Invalid Bitcoin address\" },\n\t);\n\nexport const btcConfirmations: LooseTool = tool({\n\tdescription:\n\t\t\"Number of confirmations for a Bitcoin transaction. Returns { confirmations, confirmed }.\",\n\tinputSchema: z.object({ txid: BTC_TXID }),\n\texecute: async ({ txid }) => {\n\t\tconst tx = await get<{\n\t\t\tstatus: { confirmed: boolean; block_height?: number };\n\t\t}>(`/api/tx/${txid}`);\n\t\tif (!tx.status.confirmed || tx.status.block_height == null) {\n\t\t\treturn { confirmed: false, confirmations: 0 };\n\t\t}\n\t\tconst tip = await get<number>(\"/api/blocks/tip/height\");\n\t\treturn {\n\t\t\tconfirmed: true,\n\t\t\tconfirmations: Math.max(0, tip - tx.status.block_height + 1),\n\t\t\tblockHeight: tx.status.block_height,\n\t\t};\n\t},\n});\n\nexport const btcBalance: LooseTool = tool({\n\tdescription:\n\t\t\"Bitcoin balance for an address, in satoshis. Returns { confirmedSat, unconfirmedSat }.\",\n\tinputSchema: z.object({ address: BTC_ADDRESS }),\n\texecute: async ({ address }) => {\n\t\tconst info = await get<{\n\t\t\tchain_stats: { funded_txo_sum: number; spent_txo_sum: number };\n\t\t\tmempool_stats: { funded_txo_sum: number; spent_txo_sum: number };\n\t\t}>(`/api/address/${encodeURIComponent(address)}`);\n\t\treturn {\n\t\t\tconfirmedSat:\n\t\t\t\tinfo.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum,\n\t\t\tunconfirmedSat:\n\t\t\t\tinfo.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum,\n\t\t};\n\t},\n});\n\nexport const btcUtxos: LooseTool = tool({\n\tdescription:\n\t\t\"List of unspent outputs for a Bitcoin address (truncated to `limit`).\",\n\tinputSchema: z.object({\n\t\taddress: BTC_ADDRESS,\n\t\tlimit: z.number().int().min(1).max(50).default(25),\n\t}),\n\texecute: async ({ address, limit }) => {\n\t\tconst utxos = await get<\n\t\t\tArray<{\n\t\t\t\ttxid: string;\n\t\t\t\tvout: number;\n\t\t\t\tvalue: number;\n\t\t\t\tstatus: { confirmed: boolean; block_height?: number };\n\t\t\t}>\n\t\t>(`/api/address/${encodeURIComponent(address)}/utxo`);\n\t\treturn { utxos: utxos.slice(0, limit) };\n\t},\n});\n\nexport const btcFeeEstimate: LooseTool = tool({\n\tdescription:\n\t\t\"Current Bitcoin fee estimates in sat/vB across priority tiers (fastest, 30-min, hour, economy).\",\n\tinputSchema: z.object({}),\n\texecute: async () => {\n\t\tconst fees = await get<Record<string, number>>(\"/api/v1/fees/recommended\");\n\t\treturn {\n\t\t\tfastestSatVb: fees.fastestFee ?? 0,\n\t\t\thalfHourSatVb: fees.halfHourFee ?? 0,\n\t\t\thourSatVb: fees.hourFee ?? 0,\n\t\t\teconomySatVb: fees.economyFee ?? 0,\n\t\t\tminimumSatVb: fees.minimumFee ?? 0,\n\t\t};\n\t},\n});\n\nexport const btcBlockHeight: LooseTool = tool({\n\tdescription: \"Current Bitcoin chain tip height.\",\n\tinputSchema: z.object({}),\n\texecute: async () => ({\n\t\theight: await get<number>(\"/api/blocks/tip/height\"),\n\t}),\n});\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "E811F99F534F2FE364756E2164756E21",
9
- "names": []
10
- }