bsv-mcp 0.2.8 → 0.2.10
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/dist/app.html +733 -0
- package/dist/index.js +93177 -29402
- package/index.ts +32 -1
- package/package.json +4 -1
- package/tools/index.ts +7 -2
- package/tools/wallet/brc100.ts +572 -0
- package/tools/wallet/createOrdinals.ts +62 -143
- package/tools/wallet/getBalance.ts +29 -25
- package/tools/wallet/purchaseListing.ts +89 -290
- package/tools/wallet/schemas.ts +7 -11
- package/tools/wallet/sendToAddress.ts +46 -47
- package/tools/wallet/tools.ts +12 -86
- package/tools/wallet/transferOrdToken.ts +137 -129
|
@@ -1,168 +1,87 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
CreateOrdinalsCollectionItemMetadata,
|
|
7
|
-
CreateOrdinalsCollectionMetadata,
|
|
8
|
-
CreateOrdinalsConfig,
|
|
9
|
-
Destination,
|
|
10
|
-
Inscription,
|
|
11
|
-
LocalSigner,
|
|
12
|
-
PreMAP,
|
|
13
|
-
} from "js-1sat-ord";
|
|
14
|
-
import { createOrdinals } from "js-1sat-ord";
|
|
15
|
-
import { z } from "zod";
|
|
16
|
-
import { V5Broadcaster } from "../../utils/broadcaster";
|
|
17
|
-
import type { Wallet } from "./wallet";
|
|
1
|
+
import type { OneSatContext } from '@1sat/actions'
|
|
2
|
+
import { inscribe } from '@1sat/actions'
|
|
3
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
4
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
|
|
5
|
+
import { z } from 'zod'
|
|
18
6
|
|
|
19
|
-
/**
|
|
20
|
-
* Schema for the createOrdinals tool arguments.
|
|
21
|
-
* This is a simplified interface compared to the full CreateOrdinalsConfig
|
|
22
|
-
* in js-1sat-ord. The wallet will provide UTXOs, private key, etc.
|
|
23
|
-
*/
|
|
24
7
|
export const createOrdinalsArgsSchema = z.object({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Content type (e.g., "image/jpeg", "text/plain", etc.)
|
|
28
|
-
contentType: z.string().describe("MIME type of the content"),
|
|
29
|
-
// Optional destination address (if not provided, uses the wallet's address)
|
|
8
|
+
dataB64: z.string().describe('Base64-encoded content to inscribe'),
|
|
9
|
+
contentType: z.string().describe('MIME type of the content'),
|
|
30
10
|
destinationAddress: z
|
|
31
11
|
.string()
|
|
32
12
|
.optional()
|
|
33
|
-
.describe(
|
|
34
|
-
// Optional metadata for the inscription
|
|
13
|
+
.describe('Optional destination address for the ordinal'),
|
|
35
14
|
metadata: z
|
|
36
|
-
.
|
|
15
|
+
.record(z.string(), z.string())
|
|
37
16
|
.optional()
|
|
38
|
-
.describe(
|
|
39
|
-
|
|
17
|
+
.describe('Optional MAP metadata for the inscription'),
|
|
18
|
+
signWithBAP: z
|
|
19
|
+
.boolean()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Sign with BAP identity (Sigma protocol). Uses anchor+inscription two-step flow.'),
|
|
22
|
+
})
|
|
40
23
|
|
|
41
|
-
export type CreateOrdinalsArgs = z.infer<typeof createOrdinalsArgsSchema
|
|
24
|
+
export type CreateOrdinalsArgs = z.infer<typeof createOrdinalsArgsSchema>
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
export function registerCreateOrdinalsTool(
|
|
27
|
+
server: McpServer,
|
|
28
|
+
ctx: OneSatContext | undefined,
|
|
29
|
+
) {
|
|
47
30
|
server.tool(
|
|
48
|
-
|
|
49
|
-
|
|
31
|
+
'wallet_createOrdinals',
|
|
32
|
+
'Creates and inscribes ordinals (NFTs) on the Bitcoin SV blockchain. This tool lets you mint new digital artifacts by encoding data directly into the blockchain. Supports various content types including images, text, JSON, and HTML. The tool handles transaction creation, fee calculation, and broadcasting.',
|
|
50
33
|
{ ...createOrdinalsArgsSchema.shape },
|
|
51
|
-
async ({ dataB64, contentType, destinationAddress, metadata }): Promise<CallToolResult> => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
|
|
62
|
-
e,
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 1. Get private key from wallet
|
|
68
|
-
const paymentPk = wallet.getPrivateKey();
|
|
69
|
-
if (!paymentPk) {
|
|
70
|
-
throw new Error("No private key available in wallet");
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 2. Get payment UTXOs from wallet
|
|
74
|
-
const { paymentUtxos } = await wallet.getUtxos();
|
|
75
|
-
if (!paymentUtxos || paymentUtxos.length === 0) {
|
|
76
|
-
throw new Error(
|
|
77
|
-
"No payment UTXOs available to fund this inscription",
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// 3. Get the wallet address for change/destination if not provided
|
|
82
|
-
const walletAddress = paymentPk.toAddress().toString();
|
|
83
|
-
|
|
84
|
-
// 4. Create the inscription object
|
|
85
|
-
const inscription: Inscription = {
|
|
86
|
-
dataB64: dataB64,
|
|
87
|
-
contentType: contentType,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// 5. Create the destination
|
|
91
|
-
const destinations: Destination[] = [
|
|
92
|
-
{
|
|
93
|
-
address: destinationAddress || walletAddress,
|
|
94
|
-
inscription,
|
|
95
|
-
},
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
const createOrdinalsConfig: CreateOrdinalsConfig = {
|
|
99
|
-
utxos: paymentUtxos,
|
|
100
|
-
destinations,
|
|
101
|
-
paymentPk,
|
|
102
|
-
changeAddress: walletAddress,
|
|
103
|
-
metaData: metadata as
|
|
104
|
-
| PreMAP
|
|
105
|
-
| CreateOrdinalsCollectionMetadata
|
|
106
|
-
| CreateOrdinalsCollectionItemMetadata,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
if (identityPk) {
|
|
110
|
-
createOrdinalsConfig.signer = {
|
|
111
|
-
idKey: identityPk,
|
|
112
|
-
} as LocalSigner;
|
|
34
|
+
async ({ dataB64, contentType, destinationAddress, metadata, signWithBAP }): Promise<CallToolResult> => {
|
|
35
|
+
if (!ctx) {
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: 'Wallet not initialized. Please configure a wallet before creating ordinals.',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
isError: true,
|
|
113
44
|
}
|
|
45
|
+
}
|
|
114
46
|
|
|
115
|
-
|
|
116
|
-
const result = await
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
const broadcaster = new V5Broadcaster();
|
|
125
|
-
await changeResult.tx.broadcast(broadcaster);
|
|
126
|
-
|
|
127
|
-
// 8. Refresh the wallet's UTXOs after spending
|
|
128
|
-
try {
|
|
129
|
-
await wallet.refreshUtxos();
|
|
130
|
-
} catch (refreshError) {
|
|
131
|
-
console.warn(
|
|
132
|
-
"Failed to refresh UTXOs after transaction:",
|
|
133
|
-
refreshError,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 9. Return transaction details
|
|
47
|
+
try {
|
|
48
|
+
const result = await inscribe.execute(ctx, {
|
|
49
|
+
base64Content: dataB64,
|
|
50
|
+
contentType,
|
|
51
|
+
map: metadata,
|
|
52
|
+
signWithBAP,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
if (result.error) {
|
|
138
56
|
return {
|
|
139
|
-
content: [
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
text: JSON.stringify({
|
|
143
|
-
txid: changeResult.tx.id("hex"),
|
|
144
|
-
spentOutpoints: changeResult.spentOutpoints,
|
|
145
|
-
payChange: changeResult.payChange,
|
|
146
|
-
inscriptionAddress: destinationAddress || walletAddress,
|
|
147
|
-
contentType: contentType,
|
|
148
|
-
}),
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
};
|
|
57
|
+
content: [{ type: 'text', text: result.error }],
|
|
58
|
+
isError: true,
|
|
59
|
+
}
|
|
152
60
|
}
|
|
153
61
|
|
|
154
62
|
return {
|
|
155
63
|
content: [
|
|
156
64
|
{
|
|
157
|
-
type:
|
|
158
|
-
text:
|
|
65
|
+
type: 'text',
|
|
66
|
+
text: JSON.stringify({
|
|
67
|
+
txid: result.txid,
|
|
68
|
+
rawtx: result.rawtx,
|
|
69
|
+
contentType,
|
|
70
|
+
}),
|
|
159
71
|
},
|
|
160
72
|
],
|
|
161
|
-
}
|
|
73
|
+
}
|
|
162
74
|
} catch (err: unknown) {
|
|
163
|
-
|
|
164
|
-
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: err instanceof Error ? err.message : String(err),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
isError: true,
|
|
83
|
+
}
|
|
165
84
|
}
|
|
166
85
|
},
|
|
167
|
-
)
|
|
86
|
+
)
|
|
168
87
|
}
|
|
@@ -1,54 +1,58 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import type { OneSatContext } from '@1sat/actions'
|
|
2
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
3
|
+
import { toBitcoin } from 'satoshi-token'
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Registers the wallet_getBalance tool
|
|
7
|
-
*/
|
|
8
5
|
export function registerWalletGetBalanceTool(
|
|
9
6
|
server: McpServer,
|
|
10
|
-
|
|
7
|
+
ctx: OneSatContext | undefined,
|
|
11
8
|
) {
|
|
12
9
|
server.tool(
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
'wallet_getBalance',
|
|
11
|
+
'Retrieves the current BSV balance for the wallet.',
|
|
15
12
|
{},
|
|
16
13
|
async () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
if (!ctx) {
|
|
15
|
+
return {
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: 'text',
|
|
19
|
+
text: 'Wallet not initialized. Please configure a wallet before checking balance.',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
isError: true,
|
|
25
23
|
}
|
|
24
|
+
}
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
try {
|
|
27
|
+
const result = await ctx.wallet.listOutputs({ basket: 'default' })
|
|
28
|
+
const totalSatoshis = result.outputs.reduce(
|
|
29
|
+
(sum, output) => sum + output.satoshis,
|
|
30
|
+
0,
|
|
31
|
+
)
|
|
28
32
|
|
|
29
33
|
return {
|
|
30
34
|
content: [
|
|
31
35
|
{
|
|
32
|
-
type:
|
|
36
|
+
type: 'text',
|
|
33
37
|
text: JSON.stringify({
|
|
34
38
|
satoshis: totalSatoshis,
|
|
35
|
-
bsv:
|
|
36
|
-
utxoCount:
|
|
39
|
+
bsv: toBitcoin(totalSatoshis),
|
|
40
|
+
utxoCount: result.totalOutputs,
|
|
37
41
|
}),
|
|
38
42
|
},
|
|
39
43
|
],
|
|
40
|
-
}
|
|
44
|
+
}
|
|
41
45
|
} catch (error) {
|
|
42
46
|
return {
|
|
43
47
|
content: [
|
|
44
48
|
{
|
|
45
|
-
type:
|
|
49
|
+
type: 'text',
|
|
46
50
|
text: error instanceof Error ? error.message : String(error),
|
|
47
51
|
},
|
|
48
52
|
],
|
|
49
53
|
isError: true,
|
|
50
|
-
}
|
|
54
|
+
}
|
|
51
55
|
}
|
|
52
56
|
},
|
|
53
|
-
)
|
|
57
|
+
)
|
|
54
58
|
}
|