bsv-mcp 0.0.35 → 0.2.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/CHANGELOG.md +112 -1
- package/README.md +233 -4
- package/dist/index.js +111762 -0
- package/index.ts +804 -86
- package/next-env.d.ts +6 -0
- package/package.json +57 -15
- package/prompts/bsvSdk/index.ts +5 -5
- package/prompts/bsvSdk/transaction.ts +2 -2
- package/prompts/bsvSdk/wallet.ts +1 -1
- package/prompts/index.ts +1 -1
- package/resources/bitcom.ts +132 -0
- package/resources/resources.ts +7 -3
- package/smithery.yaml +3 -0
- package/test-mcp-server.ts +157 -0
- package/tools/bap/friend.ts +267 -0
- package/tools/bap/generate.test.ts +350 -0
- package/tools/bap/generate.ts +433 -0
- package/tools/bap/getCurrentAddress.ts +76 -0
- package/tools/bap/getId.test.ts +121 -0
- package/tools/bap/getId.ts +169 -0
- package/tools/bap/index.ts +111 -0
- package/tools/bap/types.ts +66 -0
- package/tools/bap/utils.ts +33 -0
- package/tools/bigblocks/components.ts +304 -0
- package/tools/bigblocks/docs.ts +488 -0
- package/tools/bigblocks/examples.ts +527 -0
- package/tools/bigblocks/generator.ts +485 -0
- package/tools/bigblocks/index.ts +23 -0
- package/tools/bsocial/bigblocksApiClient.ts +189 -0
- package/tools/bsocial/bmapFollow.ts +125 -0
- package/tools/bsocial/bmapLikes.ts +111 -0
- package/tools/bsocial/bmapReadPosts.ts +148 -0
- package/tools/bsocial/createPost.ts +136 -0
- package/tools/bsocial/index.ts +45 -0
- package/tools/bsocial/readPosts.ts +255 -0
- package/tools/bsv/decodeTransaction.ts +5 -1
- package/tools/constants.ts +21 -0
- package/tools/index.ts +103 -17
- package/tools/mnee/index.ts +8 -0
- package/tools/mnee/parseTx.ts +1 -1
- package/tools/mnee/sendMnee.ts +1 -1
- package/tools/utils/aip.ts +46 -0
- package/tools/utils/conversion.ts +1 -0
- package/tools/utils/errorHandler.ts +76 -0
- package/tools/utils/index.ts +45 -1
- package/tools/utils/installAgentMaster.ts +84 -0
- package/tools/utils/logger.ts +20 -0
- package/tools/utils/toolConfig.ts +80 -0
- package/tools/utils/toolRegistration.ts +66 -0
- package/tools/utils/transactionBuilder.ts +196 -0
- package/tools/wallet/a2bPublishAgent.ts +8 -4
- package/tools/wallet/a2bPublishMcp.ts +28 -24
- package/tools/wallet/createOrdinals.ts +4 -2
- package/tools/wallet/fetchPaymentUtxos.ts +44 -43
- package/tools/wallet/gatherCollectionInfo.ts +374 -0
- package/tools/wallet/getAddress.ts +13 -21
- package/tools/wallet/getBalance.ts +66 -0
- package/tools/wallet/getBalanceDroplet.ts +59 -0
- package/tools/wallet/integratedWallet.ts +120 -0
- package/tools/wallet/mintCollection.ts +378 -0
- package/tools/wallet/purchaseListing.ts +4 -4
- package/tools/wallet/schemas.ts +18 -249
- package/tools/wallet/sendOrdinals.ts +4 -2
- package/tools/wallet/sendToAddress.ts +5 -1
- package/tools/wallet/setupDroplet.ts +172 -0
- package/tools/wallet/tools.ts +71 -156
- package/tools/wallet/transactionHelper.ts +121 -0
- package/tools/wallet/transferOrdToken.ts +7 -4
- package/tools/wallet/utxo.ts +62 -0
- package/tools/wallet/wallet.ts +237 -234
- package/tools/a2b/call.ts +0 -32
package/tools/wallet/tools.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
1
|
+
import { type PrivateKey, Utils } from "@bsv/sdk";
|
|
2
|
+
import type {
|
|
3
|
+
McpServer,
|
|
4
|
+
ToolCallback,
|
|
5
|
+
} from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
6
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
7
|
import type {
|
|
5
8
|
CallToolResult,
|
|
@@ -7,84 +10,48 @@ import type {
|
|
|
7
10
|
ServerRequest,
|
|
8
11
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
12
|
import type { z } from "zod";
|
|
10
|
-
import type {
|
|
11
|
-
abortActionArgsSchema,
|
|
12
|
-
acquireCertificateArgsSchema,
|
|
13
|
-
createHmacArgsSchema,
|
|
14
|
-
discoverByAttributesArgsSchema,
|
|
15
|
-
discoverByIdentityKeyArgsSchema,
|
|
16
|
-
getHeaderArgsSchema,
|
|
17
|
-
internalizeActionArgsSchema,
|
|
18
|
-
listActionsArgsSchema,
|
|
19
|
-
listCertificatesArgsSchema,
|
|
20
|
-
listOutputsArgsSchema,
|
|
21
|
-
proveCertificateArgsSchema,
|
|
22
|
-
relinquishCertificateArgsSchema,
|
|
23
|
-
relinquishOutputArgsSchema,
|
|
24
|
-
revealCounterpartyKeyLinkageArgsSchema,
|
|
25
|
-
revealSpecificKeyLinkageArgsSchema,
|
|
26
|
-
verifyHmacArgsSchema,
|
|
27
|
-
} from "./schemas";
|
|
28
|
-
import type { Wallet } from "./wallet";
|
|
29
|
-
|
|
30
13
|
import {
|
|
31
|
-
|
|
14
|
+
type a2bPublishMcpArgsSchema,
|
|
15
|
+
registerA2bPublishMcpTool,
|
|
16
|
+
} from "./a2bPublishMcp";
|
|
17
|
+
import {
|
|
18
|
+
type createOrdinalsArgsSchema,
|
|
19
|
+
registerCreateOrdinalsTool,
|
|
20
|
+
} from "./createOrdinals";
|
|
21
|
+
import { registerGatherCollectionInfoTool } from "./gatherCollectionInfo";
|
|
22
|
+
import { registerGetAddressTool } from "./getAddress";
|
|
23
|
+
import { registerWalletGetBalanceTool } from "./getBalance";
|
|
24
|
+
import { registerGetPublicKeyTool } from "./getPublicKey";
|
|
25
|
+
import { registerMintCollectionTool } from "./mintCollection";
|
|
26
|
+
import { registerPurchaseListingTool } from "./purchaseListing";
|
|
27
|
+
import { registerRefreshUtxosTool } from "./refreshUtxos";
|
|
28
|
+
import {
|
|
32
29
|
type emptyArgsSchema,
|
|
33
30
|
type getAddressArgsSchema,
|
|
34
31
|
type getPublicKeyArgsSchema,
|
|
35
32
|
type purchaseListingArgsSchema,
|
|
36
33
|
type sendToAddressArgsSchema,
|
|
37
|
-
verifySignatureArgsSchema,
|
|
38
34
|
walletEncryptionArgsSchema,
|
|
39
35
|
} from "./schemas";
|
|
40
|
-
|
|
41
|
-
import { Utils, type WalletProtocol } from "@bsv/sdk";
|
|
42
|
-
import { registerCreateOrdinalsTool } from "./createOrdinals";
|
|
43
|
-
import type { createOrdinalsArgsSchema } from "./createOrdinals";
|
|
44
|
-
import { registerGetAddressTool } from "./getAddress";
|
|
45
|
-
import { registerGetPublicKeyTool } from "./getPublicKey";
|
|
46
|
-
import { registerPurchaseListingTool } from "./purchaseListing";
|
|
47
|
-
import { registerRefreshUtxosTool } from "./refreshUtxos";
|
|
48
36
|
import { registerSendToAddressTool } from "./sendToAddress";
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
import type {
|
|
37
|
+
import {
|
|
38
|
+
registerTransferOrdTokenTool,
|
|
39
|
+
type transferOrdTokenArgsSchema,
|
|
40
|
+
} from "./transferOrdToken";
|
|
41
|
+
import type { Wallet } from "./wallet";
|
|
54
42
|
|
|
55
43
|
// Define mapping from tool names to argument schemas
|
|
56
44
|
type ToolArgSchemas = {
|
|
57
45
|
wallet_getPublicKey: typeof getPublicKeyArgsSchema;
|
|
58
|
-
wallet_createSignature: typeof createSignatureArgsSchema;
|
|
59
|
-
wallet_verifySignature: typeof verifySignatureArgsSchema;
|
|
60
46
|
wallet_encryption: typeof walletEncryptionArgsSchema;
|
|
61
|
-
wallet_listActions: typeof listActionsArgsSchema;
|
|
62
|
-
wallet_listOutputs: typeof listOutputsArgsSchema;
|
|
63
|
-
wallet_getNetwork: typeof emptyArgsSchema;
|
|
64
|
-
wallet_getVersion: typeof emptyArgsSchema;
|
|
65
|
-
wallet_revealCounterpartyKeyLinkage: typeof revealCounterpartyKeyLinkageArgsSchema;
|
|
66
|
-
wallet_revealSpecificKeyLinkage: typeof revealSpecificKeyLinkageArgsSchema;
|
|
67
|
-
wallet_createHmac: typeof createHmacArgsSchema;
|
|
68
|
-
wallet_verifyHmac: typeof verifyHmacArgsSchema;
|
|
69
|
-
wallet_abortAction: typeof abortActionArgsSchema;
|
|
70
|
-
wallet_internalizeAction: typeof internalizeActionArgsSchema;
|
|
71
|
-
wallet_relinquishOutput: typeof relinquishOutputArgsSchema;
|
|
72
|
-
wallet_acquireCertificate: typeof acquireCertificateArgsSchema;
|
|
73
|
-
wallet_listCertificates: typeof listCertificatesArgsSchema;
|
|
74
|
-
wallet_proveCertificate: typeof proveCertificateArgsSchema;
|
|
75
|
-
wallet_relinquishCertificate: typeof relinquishCertificateArgsSchema;
|
|
76
|
-
wallet_discoverByIdentityKey: typeof discoverByIdentityKeyArgsSchema;
|
|
77
|
-
wallet_discoverByAttributes: typeof discoverByAttributesArgsSchema;
|
|
78
|
-
wallet_isAuthenticated: typeof emptyArgsSchema;
|
|
79
|
-
wallet_waitForAuthentication: typeof emptyArgsSchema;
|
|
80
|
-
wallet_getHeaderForHeight: typeof getHeaderArgsSchema;
|
|
81
47
|
wallet_getAddress: typeof getAddressArgsSchema;
|
|
82
48
|
wallet_sendToAddress: typeof sendToAddressArgsSchema;
|
|
83
49
|
wallet_purchaseListing: typeof purchaseListingArgsSchema;
|
|
84
50
|
wallet_transferOrdToken: typeof transferOrdTokenArgsSchema;
|
|
85
|
-
wallet_a2bPublish: typeof
|
|
51
|
+
wallet_a2bPublish: typeof a2bPublishMcpArgsSchema;
|
|
86
52
|
wallet_createOrdinals: typeof createOrdinalsArgsSchema;
|
|
87
53
|
wallet_refreshUtxos: typeof emptyArgsSchema;
|
|
54
|
+
wallet_getBalance: typeof emptyArgsSchema;
|
|
88
55
|
};
|
|
89
56
|
|
|
90
57
|
// Define a type for the handler function with proper argument types
|
|
@@ -104,6 +71,7 @@ export function registerWalletTools(
|
|
|
104
71
|
config: {
|
|
105
72
|
disableBroadcasting: boolean;
|
|
106
73
|
enableA2bTools: boolean;
|
|
74
|
+
identityPk?: PrivateKey;
|
|
107
75
|
},
|
|
108
76
|
): ToolHandlerMap {
|
|
109
77
|
const handlers = {} as ToolHandlerMap;
|
|
@@ -124,7 +92,7 @@ export function registerWalletTools(
|
|
|
124
92
|
registerSendToAddressTool(server, wallet);
|
|
125
93
|
|
|
126
94
|
// Register the wallet_getAddress tool
|
|
127
|
-
registerGetAddressTool(server);
|
|
95
|
+
registerGetAddressTool(server, wallet);
|
|
128
96
|
|
|
129
97
|
// Register the wallet_getPublicKey tool
|
|
130
98
|
registerGetPublicKeyTool(server, wallet);
|
|
@@ -138,58 +106,17 @@ export function registerWalletTools(
|
|
|
138
106
|
// Register the wallet_refreshUtxos tool
|
|
139
107
|
registerRefreshUtxosTool(server, wallet);
|
|
140
108
|
|
|
109
|
+
// Register the wallet_getBalance tool
|
|
110
|
+
registerWalletGetBalanceTool(server, wallet);
|
|
111
|
+
|
|
141
112
|
// A2B tools have to be explicitly enabled
|
|
142
113
|
if (config.enableA2bTools) {
|
|
143
|
-
// Register the wallet_a2bPublishAgent tool
|
|
144
|
-
// registerA2bPublishAgentTool(server, wallet);
|
|
145
|
-
|
|
146
114
|
// Register the wallet_a2bPublishMcp tool
|
|
147
|
-
registerA2bPublishMcpTool(server, wallet, {
|
|
115
|
+
registerA2bPublishMcpTool(server, wallet, config.identityPk, {
|
|
148
116
|
disableBroadcasting: config.disableBroadcasting,
|
|
149
117
|
});
|
|
150
118
|
}
|
|
151
119
|
|
|
152
|
-
// Register only the minimal public-facing tools
|
|
153
|
-
// wallet_createAction, wallet_signAction and wallet_getHeight have been removed
|
|
154
|
-
|
|
155
|
-
// Register wallet_createSignature
|
|
156
|
-
registerTool(
|
|
157
|
-
"wallet_createSignature",
|
|
158
|
-
"Creates a cryptographic signature using the wallet's private key. This tool enables secure message signing and transaction authorization, supporting various signature protocols.",
|
|
159
|
-
{ args: createSignatureArgsSchema },
|
|
160
|
-
async (
|
|
161
|
-
{ args }: { args: z.infer<typeof createSignatureArgsSchema> },
|
|
162
|
-
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
163
|
-
) => {
|
|
164
|
-
try {
|
|
165
|
-
const result = await wallet.createSignature(args);
|
|
166
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
167
|
-
} catch (err: unknown) {
|
|
168
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
169
|
-
return { content: [{ type: "text", text: msg }], isError: true };
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
// Register wallet_verifySignature
|
|
175
|
-
registerTool(
|
|
176
|
-
"wallet_verifySignature",
|
|
177
|
-
"Verifies a cryptographic signature against a message or data. This tool supports various verification protocols and can validate signatures from both the wallet's own keys and external public keys.",
|
|
178
|
-
{ args: verifySignatureArgsSchema },
|
|
179
|
-
async (
|
|
180
|
-
{ args }: { args: z.infer<typeof verifySignatureArgsSchema> },
|
|
181
|
-
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
182
|
-
) => {
|
|
183
|
-
try {
|
|
184
|
-
const result = await wallet.verifySignature(args);
|
|
185
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
186
|
-
} catch (err: unknown) {
|
|
187
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
188
|
-
return { content: [{ type: "text", text: msg }], isError: true };
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
);
|
|
192
|
-
|
|
193
120
|
// Register combined wallet_encryption tool
|
|
194
121
|
registerTool(
|
|
195
122
|
"wallet_encryption",
|
|
@@ -197,12 +124,15 @@ export function registerWalletTools(
|
|
|
197
124
|
"PARAMETERS:\n" +
|
|
198
125
|
'- mode: (required) Either "encrypt" to encrypt plaintext or "decrypt" to decrypt ciphertext\n' +
|
|
199
126
|
"- data: (required) Text string or array of numbers to process\n" +
|
|
200
|
-
"- encoding: (optional) For text input, the encoding format (utf8, hex, base64) - default is utf8\n
|
|
127
|
+
"- encoding: (optional) For text input, the encoding format (utf8, hex, base64) - default is utf8\n" +
|
|
128
|
+
"- recipientPublicKeyHex: (optional) Hexadecimal representation of the recipient's public key (required for encrypt mode)\n\n" +
|
|
201
129
|
"EXAMPLES:\n" +
|
|
202
130
|
"1. Encrypt text data:\n" +
|
|
203
131
|
" {\n" +
|
|
204
132
|
' "mode": "encrypt",\n' +
|
|
205
|
-
' "data": "Hello World"
|
|
133
|
+
' "data": "Hello World",\n' +
|
|
134
|
+
' "encoding": "utf8",\n' +
|
|
135
|
+
' "recipientPublicKeyHex": "020202020202020202020202020202020202020202020202020202020202020202"\n' +
|
|
206
136
|
" }\n\n" +
|
|
207
137
|
"2. Decrypt previously encrypted data:\n" +
|
|
208
138
|
" {\n" +
|
|
@@ -215,60 +145,41 @@ export function registerWalletTools(
|
|
|
215
145
|
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
216
146
|
) => {
|
|
217
147
|
try {
|
|
218
|
-
const { mode, data, encoding } = args;
|
|
148
|
+
const { mode, data, encoding, recipientPublicKeyHex } = args;
|
|
219
149
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// Convert string data to binary if needed
|
|
225
|
-
let binaryData: number[];
|
|
226
|
-
if (Array.isArray(data)) {
|
|
227
|
-
binaryData = data;
|
|
150
|
+
let inputData: number[];
|
|
151
|
+
if (typeof data === "string") {
|
|
152
|
+
inputData = Utils.toArray(data, encoding || "utf8");
|
|
228
153
|
} else {
|
|
229
|
-
|
|
230
|
-
const { toArray } = Utils;
|
|
231
|
-
binaryData = toArray(data, encoding || "utf8");
|
|
154
|
+
inputData = Array.from(data);
|
|
232
155
|
}
|
|
233
156
|
|
|
234
|
-
let
|
|
235
|
-
|
|
236
|
-
if (mode === "encrypt") {
|
|
237
|
-
result = await wallet.encrypt({
|
|
238
|
-
plaintext: binaryData,
|
|
239
|
-
protocolID,
|
|
240
|
-
keyID,
|
|
241
|
-
});
|
|
242
|
-
} else if (mode === "decrypt") {
|
|
243
|
-
result = await wallet.decrypt({
|
|
244
|
-
ciphertext: binaryData,
|
|
245
|
-
protocolID,
|
|
246
|
-
keyID,
|
|
247
|
-
});
|
|
157
|
+
// let resultBuffer: Buffer;
|
|
158
|
+
// let resultOutput: string | number[];
|
|
248
159
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
],
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
} catch (e) {
|
|
266
|
-
// If UTF-8 conversion fails, continue with binary result
|
|
267
|
-
}
|
|
268
|
-
}
|
|
160
|
+
if (mode === "encrypt") {
|
|
161
|
+
// recipientPublicKeyHex is validated by Zod schema to be present for encrypt mode
|
|
162
|
+
// The schema ensures recipientPublicKeyHex is defined here.
|
|
163
|
+
// resultBuffer = await wallet.encrypt({
|
|
164
|
+
// data: inputBuffer,
|
|
165
|
+
// recipientPublicKeyHex: recipientPublicKeyHex as string, // Still needs type assertion if Zod optional isn't fully narrowed
|
|
166
|
+
// });
|
|
167
|
+
throw new Error("Encrypt method not yet implemented in wallet");
|
|
168
|
+
// if (encoding === "utf8") {
|
|
169
|
+
// resultOutput = Array.from(resultBuffer);
|
|
170
|
+
// } else {
|
|
171
|
+
// resultOutput = resultBuffer.toString(encoding || "base64");
|
|
172
|
+
// }
|
|
269
173
|
}
|
|
270
|
-
|
|
271
|
-
|
|
174
|
+
// mode === "decrypt"
|
|
175
|
+
// resultBuffer = await wallet.decrypt({ data: inputBuffer });
|
|
176
|
+
throw new Error("Decrypt method not yet implemented in wallet");
|
|
177
|
+
|
|
178
|
+
// return {
|
|
179
|
+
// content: [
|
|
180
|
+
// { type: "text", text: JSON.stringify({ data: resultOutput }) },
|
|
181
|
+
// ],
|
|
182
|
+
// };
|
|
272
183
|
} catch (error) {
|
|
273
184
|
const errorMessage =
|
|
274
185
|
error instanceof Error ? error.message : String(error);
|
|
@@ -288,5 +199,9 @@ export function registerWalletTools(
|
|
|
288
199
|
// Register createOrdinals tool
|
|
289
200
|
registerCreateOrdinalsTool(server, wallet);
|
|
290
201
|
|
|
202
|
+
// Register collection tools
|
|
203
|
+
registerGatherCollectionInfoTool(server, wallet);
|
|
204
|
+
registerMintCollectionTool(server, wallet);
|
|
205
|
+
|
|
291
206
|
return handlers;
|
|
292
207
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { PrivateKey } from "@bsv/sdk";
|
|
2
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import {
|
|
4
|
+
createErrorResponse,
|
|
5
|
+
createResponse,
|
|
6
|
+
formatError,
|
|
7
|
+
} from "../utils/errorHandler";
|
|
8
|
+
import type { Wallet } from "./wallet";
|
|
9
|
+
|
|
10
|
+
interface TransactionContext {
|
|
11
|
+
wallet: Wallet;
|
|
12
|
+
identityKey?: string; // WIF from environment
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface TransactionResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
txid?: string;
|
|
18
|
+
rawTx?: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Common transaction workflow wrapper
|
|
24
|
+
*/
|
|
25
|
+
export async function executeTransaction<TArgs>(
|
|
26
|
+
args: TArgs,
|
|
27
|
+
context: TransactionContext,
|
|
28
|
+
handler: (
|
|
29
|
+
args: TArgs,
|
|
30
|
+
keys: {
|
|
31
|
+
paymentKey: PrivateKey;
|
|
32
|
+
identityKey?: PrivateKey;
|
|
33
|
+
address: string;
|
|
34
|
+
},
|
|
35
|
+
wallet: Wallet,
|
|
36
|
+
) => Promise<TransactionResult>,
|
|
37
|
+
): Promise<CallToolResult> {
|
|
38
|
+
try {
|
|
39
|
+
const { wallet, identityKey: identityKeyWif } = context;
|
|
40
|
+
|
|
41
|
+
// Get payment key
|
|
42
|
+
const paymentKey = wallet.getPaymentKey();
|
|
43
|
+
if (!paymentKey) {
|
|
44
|
+
throw new Error("Payment key not available");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Get address
|
|
48
|
+
const address = await wallet.getAddress();
|
|
49
|
+
if (!address) {
|
|
50
|
+
throw new Error("Could not get wallet address");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Parse identity key if provided
|
|
54
|
+
let identityKey: PrivateKey | undefined;
|
|
55
|
+
if (identityKeyWif) {
|
|
56
|
+
try {
|
|
57
|
+
identityKey = PrivateKey.fromWif(identityKeyWif);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.warn(
|
|
60
|
+
"Invalid IDENTITY_KEY_WIF provided, skipping identity features",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Execute the transaction handler
|
|
66
|
+
const result = await handler(
|
|
67
|
+
args,
|
|
68
|
+
{ paymentKey, identityKey, address: address.toString() },
|
|
69
|
+
wallet,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Refresh UTXOs after successful transaction
|
|
73
|
+
if (
|
|
74
|
+
result.success &&
|
|
75
|
+
result.txid &&
|
|
76
|
+
process.env.DISABLE_BROADCASTING !== "true"
|
|
77
|
+
) {
|
|
78
|
+
wallet.refreshUtxos().catch((err) => {
|
|
79
|
+
console.warn("Failed to refresh UTXOs after transaction:", err);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return createResponse(result);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
return createErrorResponse(error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get identity key from environment
|
|
91
|
+
*/
|
|
92
|
+
export function getIdentityKeyFromEnv(): PrivateKey | undefined {
|
|
93
|
+
const identityKeyWif = process.env.IDENTITY_KEY_WIF;
|
|
94
|
+
if (!identityKeyWif) return undefined;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
return PrivateKey.fromWif(identityKeyWif);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.warn("Invalid IDENTITY_KEY_WIF in environment:", formatError(e));
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Standard response for disabled broadcasting
|
|
106
|
+
*/
|
|
107
|
+
export function createDisabledBroadcastResponse(
|
|
108
|
+
txid: string,
|
|
109
|
+
rawTx: string,
|
|
110
|
+
extra?: Record<string, unknown>,
|
|
111
|
+
): TransactionResult {
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
txid,
|
|
115
|
+
rawTx,
|
|
116
|
+
broadcastDisabled: true,
|
|
117
|
+
message:
|
|
118
|
+
"Broadcasting disabled. Use the raw transaction hex to broadcast manually.",
|
|
119
|
+
...extra,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -8,18 +8,20 @@ import type {
|
|
|
8
8
|
import {
|
|
9
9
|
type Distribution,
|
|
10
10
|
type LocalSigner,
|
|
11
|
+
OneSatBroadcaster,
|
|
11
12
|
type Payment,
|
|
13
|
+
selectTokenUtxos,
|
|
12
14
|
type TokenChangeResult,
|
|
13
15
|
TokenInputMode,
|
|
14
16
|
TokenSelectionStrategy,
|
|
15
17
|
TokenType,
|
|
16
18
|
type TokenUtxo,
|
|
17
19
|
type TransferOrdTokensConfig,
|
|
18
|
-
type Utxo,
|
|
19
|
-
selectTokenUtxos,
|
|
20
20
|
transferOrdTokens,
|
|
21
|
+
type Utxo,
|
|
21
22
|
} from "js-1sat-ord";
|
|
22
23
|
import { z } from "zod";
|
|
24
|
+
import { V5Broadcaster } from "../../utils/broadcaster";
|
|
23
25
|
import type { Wallet } from "./wallet";
|
|
24
26
|
|
|
25
27
|
// Schema for BSV-20/BSV-21 token transfer arguments
|
|
@@ -70,7 +72,7 @@ export function registerTransferOrdTokenTool(
|
|
|
70
72
|
) => {
|
|
71
73
|
try {
|
|
72
74
|
// fetch keys
|
|
73
|
-
const paymentPk = wallet.
|
|
75
|
+
const paymentPk = wallet.getPaymentKey();
|
|
74
76
|
if (!paymentPk) throw new Error("No private key available");
|
|
75
77
|
const ordPk = paymentPk;
|
|
76
78
|
const changeAddress = paymentPk.toAddress().toString();
|
|
@@ -122,7 +124,8 @@ export function registerTransferOrdTokenTool(
|
|
|
122
124
|
const result: TokenChangeResult = await transferOrdTokens(config);
|
|
123
125
|
const disableBroadcasting = process.env.DISABLE_BROADCASTING === "true";
|
|
124
126
|
if (!disableBroadcasting) {
|
|
125
|
-
|
|
127
|
+
const broadcaster = new V5Broadcaster();
|
|
128
|
+
await result.tx.broadcast(broadcaster);
|
|
126
129
|
|
|
127
130
|
// refresh UTXOs
|
|
128
131
|
try {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Transaction } from "@bsv/sdk";
|
|
2
|
+
|
|
3
|
+
export async function getTransactionById(
|
|
4
|
+
txid: string,
|
|
5
|
+
): Promise<Transaction | null> {
|
|
6
|
+
const url = `https://junglebus.gorillapool.io/v1/transaction/${txid}`;
|
|
7
|
+
try {
|
|
8
|
+
const response = await fetch(url);
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
console.error(
|
|
11
|
+
`Failed to fetch transaction ${txid} from Junglebus: ${response.status} ${response.statusText}`,
|
|
12
|
+
);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const rawTxBuffer = await response.arrayBuffer();
|
|
16
|
+
if (!rawTxBuffer) {
|
|
17
|
+
console.error(`Empty raw transaction buffer for ${txid} from Junglebus`);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const uint8Array = arrayBufferToUint8Array(rawTxBuffer);
|
|
22
|
+
const tx = Transaction.fromBinary(uint8Array);
|
|
23
|
+
|
|
24
|
+
return tx;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error(
|
|
27
|
+
`Error fetching or parsing transaction ${txid}: ${error instanceof Error ? error.message : String(error)}`,
|
|
28
|
+
);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function getBeefTransactionById(
|
|
34
|
+
txid: string,
|
|
35
|
+
): Promise<Transaction | null> {
|
|
36
|
+
const url = `https://junglebus.gorillapool.io/v1/transaction/beef/${txid}`;
|
|
37
|
+
try {
|
|
38
|
+
// console.error("URL:", url);
|
|
39
|
+
const response = await fetch(url);
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
console.warn(
|
|
42
|
+
`Failed to fetch transaction ${txid} from Junglebus: ${response.status} ${response.statusText}`,
|
|
43
|
+
);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const rawTxBuffer = await response.arrayBuffer();
|
|
47
|
+
if (!rawTxBuffer) {
|
|
48
|
+
console.warn(`Empty raw transaction buffer for ${txid} from Junglebus`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const uint8Array = arrayBufferToUint8Array(rawTxBuffer);
|
|
53
|
+
const tx = Transaction.fromBEEF(uint8Array, txid);
|
|
54
|
+
|
|
55
|
+
return tx;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(
|
|
58
|
+
`Error fetching or parsing transaction ${txid}: ${error instanceof Error ? error.message : String(error)}`,
|
|
59
|
+
);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|