@aibtc/mcp-server 1.30.0 → 1.30.2
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 +13 -0
- package/dist/config/contracts.d.ts +4 -0
- package/dist/config/contracts.d.ts.map +1 -1
- package/dist/config/contracts.js +2 -0
- package/dist/config/contracts.js.map +1 -1
- package/dist/services/sbtc.service.d.ts +27 -0
- package/dist/services/sbtc.service.d.ts.map +1 -1
- package/dist/services/sbtc.service.js +87 -1
- package/dist/services/sbtc.service.js.map +1 -1
- package/dist/services/x402.service.d.ts +1 -1
- package/dist/services/x402.service.d.ts.map +1 -1
- package/dist/services/x402.service.js +26 -19
- package/dist/services/x402.service.js.map +1 -1
- package/dist/tools/endpoint.tools.js +1 -1
- package/dist/tools/endpoint.tools.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/psbt.helpers.d.ts +12 -0
- package/dist/tools/psbt.helpers.d.ts.map +1 -0
- package/dist/tools/psbt.helpers.js +34 -0
- package/dist/tools/psbt.helpers.js.map +1 -0
- package/dist/tools/psbt.tools.d.ts +3 -0
- package/dist/tools/psbt.tools.d.ts.map +1 -0
- package/dist/tools/psbt.tools.js +384 -0
- package/dist/tools/psbt.tools.js.map +1 -0
- package/dist/tools/sbtc.tools.d.ts.map +1 -1
- package/dist/tools/sbtc.tools.js +187 -0
- package/dist/tools/sbtc.tools.js.map +1 -1
- package/dist/tools/signing.tools.d.ts.map +1 -1
- package/dist/tools/signing.tools.js +5 -4
- package/dist/tools/signing.tools.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psbt.tools.d.ts","sourceRoot":"","sources":["../../src/tools/psbt.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuFpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgYzD"}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import * as btc from "@scure/btc-signer";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { NETWORK } from "../config/networks.js";
|
|
4
|
+
import { DUST_THRESHOLD, P2TR_INPUT_BASE_VBYTES, P2WPKH_INPUT_VBYTES, } from "../config/bitcoin-constants.js";
|
|
5
|
+
import { MempoolApi, getMempoolTxUrl } from "../services/mempool-api.js";
|
|
6
|
+
import { getWalletManager } from "../services/wallet-manager.js";
|
|
7
|
+
import { getBtcNetwork } from "../transactions/bitcoin-builder.js";
|
|
8
|
+
import { createErrorResponse, createJsonResponse } from "../utils/index.js";
|
|
9
|
+
import { estimateBuyPsbtFeeSats, parseOutpoint } from "./psbt.helpers.js";
|
|
10
|
+
function decodePsbtBase64(psbtBase64) {
|
|
11
|
+
const bytes = Buffer.from(psbtBase64, "base64");
|
|
12
|
+
if (bytes.length === 0) {
|
|
13
|
+
throw new Error("Invalid PSBT: empty base64 payload");
|
|
14
|
+
}
|
|
15
|
+
return btc.Transaction.fromPSBT(bytes, {
|
|
16
|
+
allowUnknownInputs: true,
|
|
17
|
+
allowUnknownOutputs: true,
|
|
18
|
+
disableScriptCheck: true,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function encodePsbtBase64(tx) {
|
|
22
|
+
return Buffer.from(tx.toPSBT()).toString("base64");
|
|
23
|
+
}
|
|
24
|
+
function decodeScriptType(script) {
|
|
25
|
+
try {
|
|
26
|
+
return btc.OutScript.decode(script).type;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return "unknown";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function detectInputScriptType(input) {
|
|
33
|
+
if (!input.witnessUtxo?.script) {
|
|
34
|
+
return "unknown";
|
|
35
|
+
}
|
|
36
|
+
return decodeScriptType(input.witnessUtxo.script);
|
|
37
|
+
}
|
|
38
|
+
function getInputSigningStatus(input) {
|
|
39
|
+
if (input.finalScriptSig || input.finalScriptWitness) {
|
|
40
|
+
return "finalized";
|
|
41
|
+
}
|
|
42
|
+
if (input.partialSig?.length || input.tapKeySig) {
|
|
43
|
+
return "partially_signed";
|
|
44
|
+
}
|
|
45
|
+
return "unsigned";
|
|
46
|
+
}
|
|
47
|
+
function chooseSellerInputVbytes(scriptType) {
|
|
48
|
+
if (scriptType === "tr" || scriptType === "tr_ms" || scriptType === "tr_ns") {
|
|
49
|
+
return Math.ceil(P2TR_INPUT_BASE_VBYTES + 16);
|
|
50
|
+
}
|
|
51
|
+
if (scriptType === "wpkh") {
|
|
52
|
+
return P2WPKH_INPUT_VBYTES;
|
|
53
|
+
}
|
|
54
|
+
return 90;
|
|
55
|
+
}
|
|
56
|
+
function resolveFeeRateWithTiers(feeRate, tiers) {
|
|
57
|
+
if (typeof feeRate === "number") {
|
|
58
|
+
return feeRate;
|
|
59
|
+
}
|
|
60
|
+
switch (feeRate) {
|
|
61
|
+
case "fast":
|
|
62
|
+
return tiers.fast;
|
|
63
|
+
case "slow":
|
|
64
|
+
return tiers.slow;
|
|
65
|
+
case "medium":
|
|
66
|
+
default:
|
|
67
|
+
return tiers.medium;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function registerPsbtTools(server) {
|
|
71
|
+
server.registerTool("psbt_create_ordinal_buy", {
|
|
72
|
+
description: "Create a PSBT for buying an ordinal: buyer pays seller in BTC, seller's inscription UTXO is transferred to buyer. " +
|
|
73
|
+
"This prepares the PSBT for both parties to sign.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
inscriptionUtxo: z
|
|
76
|
+
.string()
|
|
77
|
+
.describe("Seller inscription outpoint in txid:vout format"),
|
|
78
|
+
sellerAddress: z.string().describe("Seller BTC address to receive payment"),
|
|
79
|
+
priceSats: z
|
|
80
|
+
.number()
|
|
81
|
+
.int()
|
|
82
|
+
.positive()
|
|
83
|
+
.describe("Purchase price in satoshis paid to seller"),
|
|
84
|
+
buyerReceiveAddress: z
|
|
85
|
+
.string()
|
|
86
|
+
.describe("Buyer BTC address that will receive the inscription UTXO"),
|
|
87
|
+
feeRate: z
|
|
88
|
+
.union([z.enum(["fast", "medium", "slow"]), z.number().positive()])
|
|
89
|
+
.optional()
|
|
90
|
+
.default("medium")
|
|
91
|
+
.describe("Fee rate: 'fast' (~10 min), 'medium' (~30 min), 'slow' (~1 hr), or explicit sat/vB"),
|
|
92
|
+
},
|
|
93
|
+
}, async ({ inscriptionUtxo, sellerAddress, priceSats, buyerReceiveAddress, feeRate }) => {
|
|
94
|
+
try {
|
|
95
|
+
const walletManager = getWalletManager();
|
|
96
|
+
const account = walletManager.getActiveAccount();
|
|
97
|
+
if (!account?.btcAddress || !account.btcPublicKey) {
|
|
98
|
+
throw new Error("Wallet must be unlocked with Bitcoin keys. Use wallet_unlock first.");
|
|
99
|
+
}
|
|
100
|
+
const outpoint = parseOutpoint(inscriptionUtxo);
|
|
101
|
+
const mempool = new MempoolApi(NETWORK);
|
|
102
|
+
const btcNetwork = getBtcNetwork(NETWORK);
|
|
103
|
+
const sellerTxHex = await mempool.getTxHex(outpoint.txid);
|
|
104
|
+
const sellerTx = btc.Transaction.fromRaw(Buffer.from(sellerTxHex, "hex"), {
|
|
105
|
+
allowUnknownInputs: true,
|
|
106
|
+
allowUnknownOutputs: true,
|
|
107
|
+
disableScriptCheck: true,
|
|
108
|
+
});
|
|
109
|
+
if (outpoint.vout >= sellerTx.outputsLength) {
|
|
110
|
+
throw new Error(`Invalid outpoint: vout ${outpoint.vout} out of range (outputs=${sellerTx.outputsLength})`);
|
|
111
|
+
}
|
|
112
|
+
const inscriptionOutput = sellerTx.getOutput(outpoint.vout);
|
|
113
|
+
if (inscriptionOutput.amount === undefined || inscriptionOutput.script === undefined) {
|
|
114
|
+
throw new Error("Inscription outpoint is missing amount/script in source transaction.");
|
|
115
|
+
}
|
|
116
|
+
const inscriptionAmount = inscriptionOutput.amount;
|
|
117
|
+
const inscriptionScript = inscriptionOutput.script;
|
|
118
|
+
const inscriptionValueSats = Number(inscriptionAmount);
|
|
119
|
+
if (!Number.isSafeInteger(inscriptionValueSats) || inscriptionValueSats <= 0) {
|
|
120
|
+
throw new Error("Inscription output amount is invalid or too large.");
|
|
121
|
+
}
|
|
122
|
+
const sellerScriptType = decodeScriptType(inscriptionScript);
|
|
123
|
+
const sellerInputVbytes = chooseSellerInputVbytes(sellerScriptType);
|
|
124
|
+
const feeTiers = await mempool.getFeeTiers();
|
|
125
|
+
const resolvedFeeRate = resolveFeeRateWithTiers(feeRate, feeTiers);
|
|
126
|
+
const utxos = (await mempool.getUtxos(account.btcAddress))
|
|
127
|
+
.filter((u) => u.status.confirmed)
|
|
128
|
+
.filter((u) => !(u.txid.toLowerCase() === outpoint.txid && u.vout === outpoint.vout))
|
|
129
|
+
.sort((a, b) => b.value - a.value);
|
|
130
|
+
if (utxos.length === 0) {
|
|
131
|
+
throw new Error(`No confirmed buyer UTXOs available at ${account.btcAddress}. Fund the wallet first.`);
|
|
132
|
+
}
|
|
133
|
+
const selectedUtxos = [];
|
|
134
|
+
let selectedTotal = 0;
|
|
135
|
+
let estimatedFee = 0;
|
|
136
|
+
for (const utxo of utxos) {
|
|
137
|
+
selectedUtxos.push(utxo);
|
|
138
|
+
selectedTotal += utxo.value;
|
|
139
|
+
estimatedFee = estimateBuyPsbtFeeSats({
|
|
140
|
+
feeRate: resolvedFeeRate,
|
|
141
|
+
buyerInputCount: selectedUtxos.length,
|
|
142
|
+
sellerInputVbytes,
|
|
143
|
+
outputCount: 3,
|
|
144
|
+
});
|
|
145
|
+
if (selectedTotal >= priceSats + estimatedFee) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (selectedTotal < priceSats + estimatedFee) {
|
|
150
|
+
throw new Error(`Insufficient buyer funds: have ${selectedTotal} sats, need at least ${priceSats + estimatedFee} sats.`);
|
|
151
|
+
}
|
|
152
|
+
const changeSats = selectedTotal - priceSats - estimatedFee;
|
|
153
|
+
const includeChange = changeSats >= DUST_THRESHOLD;
|
|
154
|
+
const tx = new btc.Transaction({
|
|
155
|
+
allowUnknownInputs: true,
|
|
156
|
+
allowUnknownOutputs: true,
|
|
157
|
+
disableScriptCheck: true,
|
|
158
|
+
});
|
|
159
|
+
tx.addInput({
|
|
160
|
+
txid: outpoint.txid,
|
|
161
|
+
index: outpoint.vout,
|
|
162
|
+
witnessUtxo: {
|
|
163
|
+
amount: inscriptionAmount,
|
|
164
|
+
script: inscriptionScript,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const buyerP2wpkh = btc.p2wpkh(account.btcPublicKey, btcNetwork);
|
|
168
|
+
for (const utxo of selectedUtxos) {
|
|
169
|
+
tx.addInput({
|
|
170
|
+
txid: utxo.txid,
|
|
171
|
+
index: utxo.vout,
|
|
172
|
+
witnessUtxo: {
|
|
173
|
+
amount: BigInt(utxo.value),
|
|
174
|
+
script: buyerP2wpkh.script,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
tx.addOutputAddress(buyerReceiveAddress, inscriptionAmount, btcNetwork);
|
|
179
|
+
tx.addOutputAddress(sellerAddress, BigInt(priceSats), btcNetwork);
|
|
180
|
+
if (includeChange) {
|
|
181
|
+
tx.addOutputAddress(account.btcAddress, BigInt(changeSats), btcNetwork);
|
|
182
|
+
}
|
|
183
|
+
const psbtBase64 = encodePsbtBase64(tx);
|
|
184
|
+
return createJsonResponse({
|
|
185
|
+
success: true,
|
|
186
|
+
network: NETWORK,
|
|
187
|
+
psbtBase64,
|
|
188
|
+
summary: {
|
|
189
|
+
inscriptionUtxo: `${outpoint.txid}:${outpoint.vout}`,
|
|
190
|
+
inscriptionValueSats,
|
|
191
|
+
sellerAddress,
|
|
192
|
+
buyerFundingAddress: account.btcAddress,
|
|
193
|
+
buyerReceiveAddress,
|
|
194
|
+
priceSats,
|
|
195
|
+
feeRate: resolvedFeeRate,
|
|
196
|
+
estimatedFeeSats: estimatedFee,
|
|
197
|
+
buyerInputCount: selectedUtxos.length,
|
|
198
|
+
includesChange: includeChange,
|
|
199
|
+
changeSats: includeChange ? changeSats : 0,
|
|
200
|
+
sellerInputScriptType: sellerScriptType,
|
|
201
|
+
sellerInputIndex: 0,
|
|
202
|
+
buyerInputIndexes: selectedUtxos.map((_, idx) => idx + 1),
|
|
203
|
+
},
|
|
204
|
+
nextSteps: [
|
|
205
|
+
"1. Share PSBT with seller to sign seller input (index 0)",
|
|
206
|
+
"2. Sign buyer inputs with psbt_sign",
|
|
207
|
+
"3. Finalize and broadcast with psbt_broadcast",
|
|
208
|
+
],
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
return createErrorResponse(error);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
server.registerTool("psbt_sign", {
|
|
216
|
+
description: "Sign one or more PSBT inputs with the active wallet. Supports buyer (P2WPKH) and taproot keys.",
|
|
217
|
+
inputSchema: {
|
|
218
|
+
psbtBase64: z.string().describe("PSBT in base64 format"),
|
|
219
|
+
signInputs: z
|
|
220
|
+
.array(z.number().int().nonnegative())
|
|
221
|
+
.optional()
|
|
222
|
+
.describe("Optional input indexes to sign. Signs all signable inputs if omitted."),
|
|
223
|
+
finalizeSignedInputs: z
|
|
224
|
+
.boolean()
|
|
225
|
+
.optional()
|
|
226
|
+
.default(false)
|
|
227
|
+
.describe("Finalize only the inputs signed in this call"),
|
|
228
|
+
},
|
|
229
|
+
}, async ({ psbtBase64, signInputs, finalizeSignedInputs }) => {
|
|
230
|
+
try {
|
|
231
|
+
const walletManager = getWalletManager();
|
|
232
|
+
const account = walletManager.getActiveAccount();
|
|
233
|
+
if (!account?.btcPrivateKey && !account?.taprootPrivateKey) {
|
|
234
|
+
throw new Error("No BTC signing keys available. Unlock wallet first with wallet_unlock.");
|
|
235
|
+
}
|
|
236
|
+
const tx = decodePsbtBase64(psbtBase64);
|
|
237
|
+
const indexes = signInputs && signInputs.length > 0
|
|
238
|
+
? Array.from(new Set(signInputs))
|
|
239
|
+
: Array.from({ length: tx.inputsLength }, (_, i) => i);
|
|
240
|
+
const signedInputs = [];
|
|
241
|
+
const skippedInputs = [];
|
|
242
|
+
const finalizedInputs = [];
|
|
243
|
+
for (const idx of indexes) {
|
|
244
|
+
if (idx < 0 || idx >= tx.inputsLength) {
|
|
245
|
+
skippedInputs.push({ index: idx, reason: "input index out of range" });
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
let signed = false;
|
|
249
|
+
const errors = [];
|
|
250
|
+
if (account.btcPrivateKey) {
|
|
251
|
+
try {
|
|
252
|
+
signed = tx.signIdx(account.btcPrivateKey, idx) || signed;
|
|
253
|
+
}
|
|
254
|
+
catch (e) {
|
|
255
|
+
errors.push(`btc key: ${String(e)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (!signed && account.taprootPrivateKey) {
|
|
259
|
+
try {
|
|
260
|
+
signed = tx.signIdx(account.taprootPrivateKey, idx) || signed;
|
|
261
|
+
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
errors.push(`taproot key: ${String(e)}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (!signed) {
|
|
267
|
+
skippedInputs.push({
|
|
268
|
+
index: idx,
|
|
269
|
+
reason: errors.length > 0 ? errors.join(" | ") : "no matching key for this input",
|
|
270
|
+
});
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
signedInputs.push(idx);
|
|
274
|
+
if (finalizeSignedInputs) {
|
|
275
|
+
try {
|
|
276
|
+
tx.finalizeIdx(idx);
|
|
277
|
+
finalizedInputs.push(idx);
|
|
278
|
+
}
|
|
279
|
+
catch (e) {
|
|
280
|
+
skippedInputs.push({
|
|
281
|
+
index: idx,
|
|
282
|
+
reason: `signed but not finalizable yet: ${String(e)}`,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return createJsonResponse({
|
|
288
|
+
success: signedInputs.length > 0,
|
|
289
|
+
network: NETWORK,
|
|
290
|
+
signedInputs,
|
|
291
|
+
finalizedInputs,
|
|
292
|
+
skippedInputs,
|
|
293
|
+
psbtBase64: encodePsbtBase64(tx),
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
return createErrorResponse(error);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
server.registerTool("psbt_broadcast", {
|
|
301
|
+
description: "Finalize a fully signed PSBT and broadcast it to the Bitcoin network via mempool.space.",
|
|
302
|
+
inputSchema: {
|
|
303
|
+
psbtBase64: z.string().describe("Fully signed PSBT in base64 format"),
|
|
304
|
+
},
|
|
305
|
+
}, async ({ psbtBase64 }) => {
|
|
306
|
+
try {
|
|
307
|
+
const tx = decodePsbtBase64(psbtBase64);
|
|
308
|
+
tx.finalize();
|
|
309
|
+
const rawTx = tx.extract();
|
|
310
|
+
const txHex = Buffer.from(rawTx).toString("hex");
|
|
311
|
+
const mempool = new MempoolApi(NETWORK);
|
|
312
|
+
const txid = await mempool.broadcastTransaction(txHex);
|
|
313
|
+
return createJsonResponse({
|
|
314
|
+
success: true,
|
|
315
|
+
network: NETWORK,
|
|
316
|
+
txid,
|
|
317
|
+
explorerUrl: getMempoolTxUrl(txid, NETWORK),
|
|
318
|
+
txHex,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
return createErrorResponse(error);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
server.registerTool("psbt_decode", {
|
|
326
|
+
description: "Decode a PSBT to inspect inputs, outputs, signatures, and signing status before broadcast.",
|
|
327
|
+
inputSchema: {
|
|
328
|
+
psbtBase64: z.string().describe("PSBT in base64 format"),
|
|
329
|
+
},
|
|
330
|
+
}, async ({ psbtBase64 }) => {
|
|
331
|
+
try {
|
|
332
|
+
const tx = decodePsbtBase64(psbtBase64);
|
|
333
|
+
const btcNetwork = getBtcNetwork(NETWORK);
|
|
334
|
+
const inputs = Array.from({ length: tx.inputsLength }, (_, idx) => {
|
|
335
|
+
const input = tx.getInput(idx);
|
|
336
|
+
const txidHex = input.txid
|
|
337
|
+
? Buffer.from(input.txid).toString("hex")
|
|
338
|
+
: undefined;
|
|
339
|
+
return {
|
|
340
|
+
index: idx,
|
|
341
|
+
outpoint: txidHex !== undefined ? `${txidHex}:${input.index}` : undefined,
|
|
342
|
+
scriptType: detectInputScriptType(input),
|
|
343
|
+
amountSats: input.witnessUtxo?.amount?.toString(),
|
|
344
|
+
hasWitnessUtxo: !!input.witnessUtxo,
|
|
345
|
+
hasNonWitnessUtxo: !!input.nonWitnessUtxo,
|
|
346
|
+
partialSigCount: input.partialSig?.length ?? 0,
|
|
347
|
+
hasTapKeySig: !!input.tapKeySig,
|
|
348
|
+
status: getInputSigningStatus(input),
|
|
349
|
+
};
|
|
350
|
+
});
|
|
351
|
+
const outputs = Array.from({ length: tx.outputsLength }, (_, idx) => {
|
|
352
|
+
const output = tx.getOutput(idx);
|
|
353
|
+
return {
|
|
354
|
+
index: idx,
|
|
355
|
+
amountSats: output.amount?.toString(),
|
|
356
|
+
address: tx.getOutputAddress(idx, btcNetwork),
|
|
357
|
+
scriptHex: output.script ? Buffer.from(output.script).toString("hex") : undefined,
|
|
358
|
+
};
|
|
359
|
+
});
|
|
360
|
+
let feeSats;
|
|
361
|
+
try {
|
|
362
|
+
feeSats = tx.fee.toString();
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
feeSats = undefined;
|
|
366
|
+
}
|
|
367
|
+
return createJsonResponse({
|
|
368
|
+
network: NETWORK,
|
|
369
|
+
txidIfFinalized: tx.isFinal ? tx.id : undefined,
|
|
370
|
+
isFinal: tx.isFinal,
|
|
371
|
+
inputsLength: tx.inputsLength,
|
|
372
|
+
outputsLength: tx.outputsLength,
|
|
373
|
+
vsize: tx.vsize,
|
|
374
|
+
feeSats,
|
|
375
|
+
inputs,
|
|
376
|
+
outputs,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
return createErrorResponse(error);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=psbt.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psbt.tools.js","sourceRoot":"","sources":["../../src/tools/psbt.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sbtc.tools.d.ts","sourceRoot":"","sources":["../../src/tools/sbtc.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"sbtc.tools.d.ts","sourceRoot":"","sources":["../../src/tools/sbtc.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6CpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyjBzD"}
|
package/dist/tools/sbtc.tools.js
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
|
+
import * as btc from "@scure/btc-signer";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { getAccount, getWalletAddress, NETWORK } from "../services/x402.service.js";
|
|
3
4
|
import { getSbtcService } from "../services/sbtc.service.js";
|
|
4
5
|
import { getSbtcDepositService } from "../services/sbtc-deposit.service.js";
|
|
5
6
|
import { getExplorerTxUrl } from "../config/networks.js";
|
|
7
|
+
import { getContracts, parseContractId } from "../config/contracts.js";
|
|
6
8
|
import { createJsonResponse, createErrorResponse, resolveFee } from "../utils/index.js";
|
|
7
9
|
import { getWalletManager } from "../services/wallet-manager.js";
|
|
8
10
|
import { MempoolApi, getMempoolTxUrl } from "../services/mempool-api.js";
|
|
11
|
+
import { getBtcNetwork } from "../transactions/bitcoin-builder.js";
|
|
9
12
|
import { sponsoredSchema } from "./schemas.js";
|
|
13
|
+
function parseBtcRecipientTuple(btcRecipientAddress) {
|
|
14
|
+
const decoded = btc.Address(getBtcNetwork(NETWORK)).decode(btcRecipientAddress);
|
|
15
|
+
if (decoded.type === "tr" && decoded.pubkey) {
|
|
16
|
+
return { version: 0x06, hashbytesHex: Buffer.from(decoded.pubkey).toString("hex") };
|
|
17
|
+
}
|
|
18
|
+
switch (decoded.type) {
|
|
19
|
+
case "pkh":
|
|
20
|
+
return { version: 0x00, hashbytesHex: Buffer.from(decoded.hash).toString("hex") };
|
|
21
|
+
case "sh":
|
|
22
|
+
return { version: 0x01, hashbytesHex: Buffer.from(decoded.hash).toString("hex") };
|
|
23
|
+
case "wpkh":
|
|
24
|
+
return { version: 0x04, hashbytesHex: Buffer.from(decoded.hash).toString("hex") };
|
|
25
|
+
case "wsh":
|
|
26
|
+
return { version: 0x05, hashbytesHex: Buffer.from(decoded.hash).toString("hex") };
|
|
27
|
+
default:
|
|
28
|
+
throw new Error("Unsupported BTC recipient address type. Supported: P2PKH, P2SH, P2WPKH, P2WSH, P2TR.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getReadonlySenderAddress() {
|
|
32
|
+
const contracts = getContracts(NETWORK);
|
|
33
|
+
return parseContractId(contracts.SBTC_REGISTRY).address;
|
|
34
|
+
}
|
|
10
35
|
export function registerSbtcTools(server) {
|
|
11
36
|
// Get sBTC balance
|
|
12
37
|
server.registerTool("sbtc_get_balance", {
|
|
@@ -73,6 +98,168 @@ Example: To send 0.001 sBTC, use amount "100000" (satoshis).`,
|
|
|
73
98
|
return createErrorResponse(error);
|
|
74
99
|
}
|
|
75
100
|
});
|
|
101
|
+
// Shared withdrawal logic used by both sbtc_initiate_withdrawal and sbtc_withdraw
|
|
102
|
+
async function executeWithdrawal(params) {
|
|
103
|
+
const { amount, btcRecipientAddress, maxFee, fee, sponsored } = params;
|
|
104
|
+
if (amount <= maxFee) {
|
|
105
|
+
throw new Error(`Withdrawal amount must exceed maxFee. amount=${amount}, maxFee=${maxFee}`);
|
|
106
|
+
}
|
|
107
|
+
const sbtcService = getSbtcService(NETWORK);
|
|
108
|
+
const account = await getAccount();
|
|
109
|
+
const resolvedFee = await resolveFee(fee, NETWORK, "contract_call");
|
|
110
|
+
const recipientTuple = parseBtcRecipientTuple(btcRecipientAddress);
|
|
111
|
+
const result = await sbtcService.initiateWithdrawal(account, BigInt(amount), BigInt(maxFee), recipientTuple, resolvedFee, sponsored);
|
|
112
|
+
let requestId = null;
|
|
113
|
+
try {
|
|
114
|
+
requestId = await sbtcService.getWithdrawalRequestIdFromTx(result.txid);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
requestId = null;
|
|
118
|
+
}
|
|
119
|
+
return { result, recipientTuple, requestId };
|
|
120
|
+
}
|
|
121
|
+
const withdrawalInputSchema = {
|
|
122
|
+
amount: z
|
|
123
|
+
.number()
|
|
124
|
+
.int()
|
|
125
|
+
.positive()
|
|
126
|
+
.describe("Amount to withdraw in satoshis"),
|
|
127
|
+
btcRecipientAddress: z
|
|
128
|
+
.string()
|
|
129
|
+
.describe("Bitcoin recipient address (P2PKH/P2SH/P2WPKH/P2WSH/P2TR)"),
|
|
130
|
+
maxFee: z
|
|
131
|
+
.number()
|
|
132
|
+
.int()
|
|
133
|
+
.nonnegative()
|
|
134
|
+
.optional()
|
|
135
|
+
.default(2000)
|
|
136
|
+
.describe("Maximum signer fee in satoshis"),
|
|
137
|
+
fee: z
|
|
138
|
+
.string()
|
|
139
|
+
.optional()
|
|
140
|
+
.describe("Optional fee: 'low' | 'medium' | 'high' preset or micro-STX amount."),
|
|
141
|
+
sponsored: sponsoredSchema,
|
|
142
|
+
};
|
|
143
|
+
// Initiate sBTC withdrawal (peg-out to BTC L1)
|
|
144
|
+
server.registerTool("sbtc_initiate_withdrawal", {
|
|
145
|
+
description: `Initiate an sBTC peg-out to a Bitcoin L1 address.
|
|
146
|
+
|
|
147
|
+
Locks (amount + maxFee) of sBTC in the sBTC protocol and creates a withdrawal request.
|
|
148
|
+
Signers later process the request and send BTC on L1.`,
|
|
149
|
+
inputSchema: withdrawalInputSchema,
|
|
150
|
+
}, async ({ amount, btcRecipientAddress, maxFee, fee, sponsored }) => {
|
|
151
|
+
try {
|
|
152
|
+
const { result, recipientTuple, requestId } = await executeWithdrawal({
|
|
153
|
+
amount, btcRecipientAddress, maxFee, fee, sponsored,
|
|
154
|
+
});
|
|
155
|
+
return createJsonResponse({
|
|
156
|
+
success: true,
|
|
157
|
+
txid: result.txid,
|
|
158
|
+
requestId,
|
|
159
|
+
network: NETWORK,
|
|
160
|
+
recipient: {
|
|
161
|
+
address: btcRecipientAddress,
|
|
162
|
+
version: recipientTuple.version,
|
|
163
|
+
hashbytesHex: recipientTuple.hashbytesHex,
|
|
164
|
+
},
|
|
165
|
+
withdrawal: {
|
|
166
|
+
amountSats: amount,
|
|
167
|
+
maxFeeSats: maxFee,
|
|
168
|
+
lockedSats: amount + maxFee,
|
|
169
|
+
},
|
|
170
|
+
explorerUrl: getExplorerTxUrl(result.txid, NETWORK),
|
|
171
|
+
nextStep: requestId !== null
|
|
172
|
+
? `Track with sbtc_withdrawal_status using requestId=${requestId}`
|
|
173
|
+
: "Track with sbtc_withdrawal_status using this txid once it confirms.",
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
return createErrorResponse(error);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// Compatibility alias for sbtc_initiate_withdrawal
|
|
181
|
+
server.registerTool("sbtc_withdraw", {
|
|
182
|
+
description: "Alias for sbtc_initiate_withdrawal. Initiates an sBTC peg-out request to BTC L1.",
|
|
183
|
+
inputSchema: withdrawalInputSchema,
|
|
184
|
+
}, async ({ amount, btcRecipientAddress, maxFee, fee, sponsored }) => {
|
|
185
|
+
try {
|
|
186
|
+
const { result } = await executeWithdrawal({
|
|
187
|
+
amount, btcRecipientAddress, maxFee, fee, sponsored,
|
|
188
|
+
});
|
|
189
|
+
return createJsonResponse({
|
|
190
|
+
success: true,
|
|
191
|
+
txid: result.txid,
|
|
192
|
+
network: NETWORK,
|
|
193
|
+
explorerUrl: getExplorerTxUrl(result.txid, NETWORK),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
return createErrorResponse(error);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// Check withdrawal request status
|
|
201
|
+
server.registerTool("sbtc_withdrawal_status", {
|
|
202
|
+
description: "Check status of an sBTC withdrawal request by requestId or initiating txid.",
|
|
203
|
+
inputSchema: {
|
|
204
|
+
requestId: z
|
|
205
|
+
.number()
|
|
206
|
+
.int()
|
|
207
|
+
.positive()
|
|
208
|
+
.optional()
|
|
209
|
+
.describe("Withdrawal request ID"),
|
|
210
|
+
txid: z
|
|
211
|
+
.string()
|
|
212
|
+
.optional()
|
|
213
|
+
.describe("Initiate-withdrawal transaction ID (used to resolve requestId)"),
|
|
214
|
+
},
|
|
215
|
+
}, async ({ requestId, txid }) => {
|
|
216
|
+
try {
|
|
217
|
+
if (requestId === undefined && !txid) {
|
|
218
|
+
throw new Error("Provide either requestId or txid.");
|
|
219
|
+
}
|
|
220
|
+
const sbtcService = getSbtcService(NETWORK);
|
|
221
|
+
let resolvedRequestId = requestId;
|
|
222
|
+
if (resolvedRequestId === undefined && txid) {
|
|
223
|
+
resolvedRequestId = await sbtcService.getWithdrawalRequestIdFromTx(txid);
|
|
224
|
+
if (resolvedRequestId === null) {
|
|
225
|
+
return createJsonResponse({
|
|
226
|
+
txid,
|
|
227
|
+
requestId: null,
|
|
228
|
+
status: "pending_tx",
|
|
229
|
+
message: "Could not resolve requestId from tx yet. The transaction may still be pending or unindexed.",
|
|
230
|
+
network: NETWORK,
|
|
231
|
+
explorerUrl: getExplorerTxUrl(txid, NETWORK),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (resolvedRequestId == null) {
|
|
236
|
+
throw new Error("Unable to resolve withdrawal request ID.");
|
|
237
|
+
}
|
|
238
|
+
const request = await sbtcService.getWithdrawalRequest(resolvedRequestId, getReadonlySenderAddress());
|
|
239
|
+
if (!request) {
|
|
240
|
+
return createJsonResponse({
|
|
241
|
+
requestId: resolvedRequestId,
|
|
242
|
+
status: "not_found",
|
|
243
|
+
network: NETWORK,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return createJsonResponse({
|
|
247
|
+
requestId: request.id,
|
|
248
|
+
status: request.status,
|
|
249
|
+
network: NETWORK,
|
|
250
|
+
amountSats: request.amountSats,
|
|
251
|
+
maxFeeSats: request.maxFeeSats,
|
|
252
|
+
sender: request.sender,
|
|
253
|
+
blockHeight: request.blockHeight,
|
|
254
|
+
recipient: request.recipient,
|
|
255
|
+
txid,
|
|
256
|
+
...(txid ? { explorerUrl: getExplorerTxUrl(txid, NETWORK) } : {}),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
return createErrorResponse(error);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
76
263
|
// Get sBTC deposit info
|
|
77
264
|
server.registerTool("sbtc_get_deposit_info", {
|
|
78
265
|
description: "Get information about how to deposit BTC to receive sBTC.",
|