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/schemas.ts
CHANGED
|
@@ -1,77 +1,11 @@
|
|
|
1
|
-
import type { SecurityLevel } from "@bsv/sdk";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
|
-
// Define SecurityLevel to match the BSV SDK exactly
|
|
5
|
-
const SecurityLevelEnum = z.union([z.literal(0), z.literal(1), z.literal(2)]);
|
|
6
|
-
|
|
7
|
-
// Create a custom validator without tuples
|
|
8
|
-
export const walletProtocolSchema = z.custom<[SecurityLevel, string]>((val) => {
|
|
9
|
-
return (
|
|
10
|
-
Array.isArray(val) &&
|
|
11
|
-
val.length === 2 &&
|
|
12
|
-
(val[0] === 0 || val[0] === 1 || val[0] === 2) &&
|
|
13
|
-
typeof val[1] === "string"
|
|
14
|
-
);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
3
|
// Empty args schema for functions that don't take arguments
|
|
18
4
|
export const emptyArgsSchema = z.object({});
|
|
19
5
|
|
|
20
6
|
// Get public key arguments
|
|
21
7
|
export const getPublicKeyArgsSchema = z.object({});
|
|
22
8
|
|
|
23
|
-
// Create signature arguments
|
|
24
|
-
export const createSignatureArgsSchema = z.object({
|
|
25
|
-
data: z.array(z.number()).optional(),
|
|
26
|
-
hashToDirectlySign: z.array(z.number()).optional(),
|
|
27
|
-
protocolID: walletProtocolSchema,
|
|
28
|
-
keyID: z.string(),
|
|
29
|
-
privilegedReason: z.string().optional(),
|
|
30
|
-
counterparty: z
|
|
31
|
-
.union([z.string(), z.literal("self"), z.literal("anyone")])
|
|
32
|
-
.optional(),
|
|
33
|
-
privileged: z.boolean().optional(),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Verify signature arguments
|
|
37
|
-
export const verifySignatureArgsSchema = z.object({
|
|
38
|
-
data: z.array(z.number()).optional(),
|
|
39
|
-
hashToDirectlyVerify: z.array(z.number()).optional(),
|
|
40
|
-
signature: z.array(z.number()),
|
|
41
|
-
protocolID: walletProtocolSchema,
|
|
42
|
-
keyID: z.string(),
|
|
43
|
-
privilegedReason: z.string().optional(),
|
|
44
|
-
counterparty: z
|
|
45
|
-
.union([z.string(), z.literal("self"), z.literal("anyone")])
|
|
46
|
-
.optional(),
|
|
47
|
-
forSelf: z.boolean().optional(),
|
|
48
|
-
privileged: z.boolean().optional(),
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Wallet encryption args
|
|
52
|
-
export const walletEncryptArgsSchema = z.object({
|
|
53
|
-
plaintext: z.array(z.number()),
|
|
54
|
-
protocolID: walletProtocolSchema,
|
|
55
|
-
keyID: z.string(),
|
|
56
|
-
privilegedReason: z.string().optional(),
|
|
57
|
-
counterparty: z
|
|
58
|
-
.union([z.string(), z.literal("self"), z.literal("anyone")])
|
|
59
|
-
.optional(),
|
|
60
|
-
privileged: z.boolean().optional(),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Wallet decryption args
|
|
64
|
-
export const walletDecryptArgsSchema = z.object({
|
|
65
|
-
ciphertext: z.array(z.number()),
|
|
66
|
-
protocolID: walletProtocolSchema,
|
|
67
|
-
keyID: z.string(),
|
|
68
|
-
privilegedReason: z.string().optional(),
|
|
69
|
-
counterparty: z
|
|
70
|
-
.union([z.string(), z.literal("self"), z.literal("anyone")])
|
|
71
|
-
.optional(),
|
|
72
|
-
privileged: z.boolean().optional(),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
9
|
// Combined wallet encryption/decryption args
|
|
76
10
|
export const walletEncryptionArgsSchema = z
|
|
77
11
|
.object({
|
|
@@ -91,190 +25,25 @@ export const walletEncryptionArgsSchema = z
|
|
|
91
25
|
.optional()
|
|
92
26
|
.default("utf8")
|
|
93
27
|
.describe("Encoding of text data (default: utf8)"),
|
|
28
|
+
recipientPublicKeyHex: z
|
|
29
|
+
.string()
|
|
30
|
+
.length(66)
|
|
31
|
+
.regex(/^(02|03)[0-9a-fA-F]{64}$/)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe(
|
|
34
|
+
"Recipient's public key in hex format (required for encryption mode)",
|
|
35
|
+
),
|
|
94
36
|
})
|
|
95
|
-
.describe("Schema for encryption and decryption operations")
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
message: z.string(),
|
|
106
|
-
hmac: z.string(),
|
|
107
|
-
publicKey: z.string(),
|
|
108
|
-
encoding: z.enum(["utf8", "hex", "base64"]).optional(),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Transaction input schema
|
|
112
|
-
export const transactionInputSchema = z.object({
|
|
113
|
-
outpoint: z.string(),
|
|
114
|
-
inputDescription: z.string(), // Required field
|
|
115
|
-
sequence: z.number().optional(),
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Transaction output schema
|
|
119
|
-
export const transactionOutputSchema = z.object({
|
|
120
|
-
lockingScript: z.string(),
|
|
121
|
-
satoshis: z.number(),
|
|
122
|
-
outputDescription: z.string(), // Required field
|
|
123
|
-
change: z.boolean().optional(),
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Create action args
|
|
127
|
-
export const createActionArgsSchema = z.object({
|
|
128
|
-
description: z.string(),
|
|
129
|
-
labels: z.array(z.string()).optional(),
|
|
130
|
-
lockTime: z.number().optional(),
|
|
131
|
-
version: z.number().optional(),
|
|
132
|
-
inputBEEF: z.array(z.number()).optional(),
|
|
133
|
-
inputs: z.array(transactionInputSchema).optional(),
|
|
134
|
-
outputs: z.array(transactionOutputSchema).optional(),
|
|
135
|
-
options: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// Sign action args
|
|
139
|
-
export const signActionArgsSchema = z.object({
|
|
140
|
-
reference: z.string(),
|
|
141
|
-
spends: z.record(z.any()).optional(),
|
|
142
|
-
options: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// List actions args
|
|
146
|
-
export const listActionsArgsSchema = z.object({
|
|
147
|
-
labels: z.array(z.string()),
|
|
148
|
-
labelQueryMode: z.enum(["any", "all"]).optional(),
|
|
149
|
-
limit: z.number().optional(),
|
|
150
|
-
offset: z.number().optional(),
|
|
151
|
-
includeInputs: z.boolean().optional(),
|
|
152
|
-
includeOutputs: z.boolean().optional(),
|
|
153
|
-
includeLabels: z.boolean().optional(),
|
|
154
|
-
includeInputSourceLockingScripts: z.boolean().optional(),
|
|
155
|
-
includeInputUnlockingScripts: z.boolean().optional(),
|
|
156
|
-
seekPermission: z.boolean().optional(),
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// List outputs args
|
|
160
|
-
export const listOutputsArgsSchema = z.object({
|
|
161
|
-
basket: z.string(),
|
|
162
|
-
tags: z.array(z.string()).optional(),
|
|
163
|
-
tagQueryMode: z.enum(["all", "any"]).optional(),
|
|
164
|
-
limit: z.number().optional(),
|
|
165
|
-
offset: z.number().optional(),
|
|
166
|
-
include: z.enum(["locking scripts", "entire transactions"]).optional(),
|
|
167
|
-
includeLabels: z.boolean().optional(),
|
|
168
|
-
includeTags: z.boolean().optional(),
|
|
169
|
-
includeCustomInstructions: z.boolean().optional(),
|
|
170
|
-
seekPermission: z.boolean().optional(),
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// Reveal counterparty key linkage args
|
|
174
|
-
export const revealCounterpartyKeyLinkageArgsSchema = z.object({
|
|
175
|
-
counterparty: z.string(),
|
|
176
|
-
verifier: z.string(),
|
|
177
|
-
privileged: z.boolean().optional(),
|
|
178
|
-
privilegedReason: z.string().optional(),
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Reveal specific key linkage args
|
|
182
|
-
export const revealSpecificKeyLinkageArgsSchema = z.object({
|
|
183
|
-
keyID: z.number(),
|
|
184
|
-
verifier: z.string(),
|
|
185
|
-
privileged: z.boolean().optional(),
|
|
186
|
-
privilegedReason: z.string().optional(),
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
// Abort action args
|
|
190
|
-
export const abortActionArgsSchema = z.object({
|
|
191
|
-
reference: z.string(),
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Internalize action args
|
|
195
|
-
export const internalizeActionArgsSchema = z.object({
|
|
196
|
-
tx: z.array(z.number()),
|
|
197
|
-
outputs: z.array(
|
|
198
|
-
z.object({
|
|
199
|
-
outputIndex: z.number(),
|
|
200
|
-
protocol: z.enum(["wallet payment", "basket insertion"]),
|
|
201
|
-
lockingScript: z.string(),
|
|
202
|
-
satoshis: z.number(),
|
|
203
|
-
}),
|
|
204
|
-
),
|
|
205
|
-
description: z.string(),
|
|
206
|
-
labels: z.array(z.string()).optional(),
|
|
207
|
-
seekPermission: z.boolean().optional(),
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Relinquish output args
|
|
211
|
-
export const relinquishOutputArgsSchema = z.object({
|
|
212
|
-
basket: z.string(),
|
|
213
|
-
output: z.string(),
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Acquire certificate args
|
|
217
|
-
export const acquireCertificateArgsSchema = z.object({
|
|
218
|
-
type: z.string(),
|
|
219
|
-
certifier: z.string(),
|
|
220
|
-
acquisitionProtocol: z.enum(["direct", "issuance"]),
|
|
221
|
-
fields: z.record(z.string()),
|
|
222
|
-
certifierUrl: z.string().optional(),
|
|
223
|
-
serialNumber: z.string().optional(),
|
|
224
|
-
signature: z.string().optional(),
|
|
225
|
-
revocationOutpoint: z.string().optional(),
|
|
226
|
-
keyringForSubject: z.record(z.string()).optional(),
|
|
227
|
-
keyringRevealer: z.string().optional(),
|
|
228
|
-
privileged: z.boolean().optional(),
|
|
229
|
-
privilegedReason: z.string().optional(),
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
// List certificates args
|
|
233
|
-
export const listCertificatesArgsSchema = z.object({
|
|
234
|
-
certifiers: z.array(z.string()),
|
|
235
|
-
types: z.array(z.string()),
|
|
236
|
-
limit: z.number().optional(),
|
|
237
|
-
offset: z.number().optional(),
|
|
238
|
-
privileged: z.boolean().optional(),
|
|
239
|
-
privilegedReason: z.string().optional(),
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// Prove certificate args
|
|
243
|
-
export const proveCertificateArgsSchema = z.object({
|
|
244
|
-
certificate: z.object({}),
|
|
245
|
-
fieldsToReveal: z.array(z.string()),
|
|
246
|
-
verifier: z.string(),
|
|
247
|
-
privileged: z.boolean().optional(),
|
|
248
|
-
privilegedReason: z.string().optional(),
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// Relinquish certificate args
|
|
252
|
-
export const relinquishCertificateArgsSchema = z.object({
|
|
253
|
-
type: z.string(),
|
|
254
|
-
serialNumber: z.string(),
|
|
255
|
-
certifier: z.string(),
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Discover by identity key args
|
|
259
|
-
export const discoverByIdentityKeyArgsSchema = z.object({
|
|
260
|
-
identityKey: z.string(),
|
|
261
|
-
limit: z.number().optional(),
|
|
262
|
-
offset: z.number().optional(),
|
|
263
|
-
seekPermission: z.boolean().optional(),
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
// Discover by attributes args
|
|
267
|
-
export const discoverByAttributesArgsSchema = z.object({
|
|
268
|
-
attributes: z.record(z.string()),
|
|
269
|
-
limit: z.number().optional(),
|
|
270
|
-
offset: z.number().optional(),
|
|
271
|
-
seekPermission: z.boolean().optional(),
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
// Get header for height args
|
|
275
|
-
export const getHeaderArgsSchema = z.object({
|
|
276
|
-
height: z.number(),
|
|
277
|
-
});
|
|
37
|
+
.describe("Schema for encryption and decryption operations")
|
|
38
|
+
.superRefine((val, ctx) => {
|
|
39
|
+
if (val.mode === "encrypt" && !val.recipientPublicKeyHex) {
|
|
40
|
+
ctx.addIssue({
|
|
41
|
+
code: z.ZodIssueCode.custom,
|
|
42
|
+
message: "recipientPublicKeyHex is required when mode is 'encrypt'",
|
|
43
|
+
path: ["recipientPublicKeyHex"],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
278
47
|
|
|
279
48
|
// Get address args
|
|
280
49
|
export const getAddressArgsSchema = z.object({});
|
|
@@ -6,14 +6,15 @@ import type {
|
|
|
6
6
|
ServerNotification,
|
|
7
7
|
ServerRequest,
|
|
8
8
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
-
import { sendOrdinals } from "js-1sat-ord";
|
|
10
9
|
import type {
|
|
11
10
|
ChangeResult,
|
|
12
11
|
LocalSigner,
|
|
13
12
|
SendOrdinalsConfig,
|
|
14
13
|
} from "js-1sat-ord";
|
|
14
|
+
import { OneSatBroadcaster, sendOrdinals } from "js-1sat-ord";
|
|
15
15
|
import { Sigma } from "sigma-protocol";
|
|
16
16
|
import { z } from "zod";
|
|
17
|
+
import { V5Broadcaster } from "../../utils/broadcaster";
|
|
17
18
|
import type { Wallet } from "./wallet";
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -121,7 +122,8 @@ export function registerSendOrdinalsTool(server: McpServer, wallet: Wallet) {
|
|
|
121
122
|
// 7. Broadcast the transaction
|
|
122
123
|
const disableBroadcasting = process.env.DISABLE_BROADCASTING === "true";
|
|
123
124
|
if (!disableBroadcasting) {
|
|
124
|
-
|
|
125
|
+
const broadcaster = new V5Broadcaster();
|
|
126
|
+
await changeResult.tx.broadcast(broadcaster);
|
|
125
127
|
|
|
126
128
|
// 8. Refresh the wallet's UTXOs after spending
|
|
127
129
|
try {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { P2PKH } from "@bsv/sdk";
|
|
2
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
|
+
import type {
|
|
5
|
+
ServerNotification,
|
|
6
|
+
ServerRequest,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
4
8
|
import { toSatoshi } from "satoshi-token";
|
|
5
9
|
import type { z } from "zod";
|
|
6
10
|
import { getBsvPriceWithCache } from "../bsv/getPrice";
|
|
@@ -22,7 +26,7 @@ export function registerSendToAddressTool(server: McpServer, wallet: Wallet) {
|
|
|
22
26
|
},
|
|
23
27
|
async (
|
|
24
28
|
{ args }: { args: SendToAddressArgs },
|
|
25
|
-
extra: RequestHandlerExtra,
|
|
29
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
26
30
|
) => {
|
|
27
31
|
try {
|
|
28
32
|
const {
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
3
|
+
import type {
|
|
4
|
+
ServerNotification,
|
|
5
|
+
ServerRequest,
|
|
6
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { DropletClient } from "../../utils/droplet";
|
|
9
|
+
import type { IntegratedWallet } from "./integratedWallet";
|
|
10
|
+
|
|
11
|
+
const setupDropletArgsSchema = z.object({
|
|
12
|
+
action: z.enum(["register_key", "create_faucet", "check_status"]),
|
|
13
|
+
faucetName: z.string().optional(),
|
|
14
|
+
fixedDropSats: z.number().optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export type SetupDropletArgs = z.infer<typeof setupDropletArgsSchema>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Register the setupDroplet tool for Droplet API initialization
|
|
21
|
+
*/
|
|
22
|
+
export function registerSetupDropletTool(
|
|
23
|
+
server: McpServer,
|
|
24
|
+
integratedWallet: IntegratedWallet,
|
|
25
|
+
) {
|
|
26
|
+
server.tool(
|
|
27
|
+
"wallet_setupDroplet",
|
|
28
|
+
"Setup and manage Droplet API integration. Actions: register_key (registers your public key), create_faucet (creates a new faucet), check_status (checks faucet status)",
|
|
29
|
+
{
|
|
30
|
+
args: setupDropletArgsSchema,
|
|
31
|
+
},
|
|
32
|
+
async (
|
|
33
|
+
{ args }: { args: SetupDropletArgs },
|
|
34
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
35
|
+
) => {
|
|
36
|
+
try {
|
|
37
|
+
const dropletClient = integratedWallet.getDropletClient();
|
|
38
|
+
if (!dropletClient) {
|
|
39
|
+
throw new Error("Droplet client not configured");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const config = dropletClient.getConfig();
|
|
43
|
+
const apiUrl = config.apiUrl;
|
|
44
|
+
const authKey = config.authKey;
|
|
45
|
+
|
|
46
|
+
switch (args.action) {
|
|
47
|
+
case "register_key": {
|
|
48
|
+
if (!authKey) {
|
|
49
|
+
throw new Error("No auth key configured");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const pubkey = authKey.toPublicKey().toString();
|
|
53
|
+
|
|
54
|
+
// Register the key with the Droplet API
|
|
55
|
+
const response = await fetch(`${apiUrl}/auth/register`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify({ publicKey: pubkey }),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const error = await response.text();
|
|
65
|
+
throw new Error(`Failed to register key: ${error}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
text: JSON.stringify({
|
|
73
|
+
status: "success",
|
|
74
|
+
message: "Key registered successfully",
|
|
75
|
+
publicKey: pubkey,
|
|
76
|
+
}),
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case "create_faucet": {
|
|
83
|
+
if (!args.faucetName) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
"faucetName is required for create_faucet action",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// First, ensure the key is registered
|
|
90
|
+
if (authKey) {
|
|
91
|
+
const pubkey = authKey.toPublicKey().toString();
|
|
92
|
+
await fetch(`${apiUrl}/auth/register`, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: {
|
|
95
|
+
"Content-Type": "application/json",
|
|
96
|
+
},
|
|
97
|
+
body: JSON.stringify({ publicKey: pubkey }),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Create the faucet
|
|
102
|
+
const body = {
|
|
103
|
+
name: args.faucetName,
|
|
104
|
+
fixed_drop_sats: args.fixedDropSats || 1000,
|
|
105
|
+
max_consolidation_inputs: 20,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const headers = authKey
|
|
109
|
+
? await dropletClient.getAuthHeaders("POST", "/faucets", body)
|
|
110
|
+
: {};
|
|
111
|
+
|
|
112
|
+
const response = await fetch(`${apiUrl}/faucets`, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: {
|
|
115
|
+
"Content-Type": "application/json",
|
|
116
|
+
...headers,
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify(body),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
const error = await response.text();
|
|
123
|
+
throw new Error(`Failed to create faucet: ${error}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const result = await response.json();
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "text",
|
|
131
|
+
text: JSON.stringify({
|
|
132
|
+
status: "success",
|
|
133
|
+
message: "Faucet created successfully",
|
|
134
|
+
faucet: result,
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
case "check_status": {
|
|
142
|
+
const status = await dropletClient.getFaucetStatus();
|
|
143
|
+
return {
|
|
144
|
+
content: [
|
|
145
|
+
{
|
|
146
|
+
type: "text",
|
|
147
|
+
text: JSON.stringify({
|
|
148
|
+
status: "success",
|
|
149
|
+
faucetStatus: status,
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
default:
|
|
157
|
+
throw new Error(`Unknown action: ${args.action}`);
|
|
158
|
+
}
|
|
159
|
+
} catch (error) {
|
|
160
|
+
return {
|
|
161
|
+
content: [
|
|
162
|
+
{
|
|
163
|
+
type: "text",
|
|
164
|
+
text: error instanceof Error ? error.message : String(error),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
isError: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
}
|