bsv-mcp 0.0.21 → 0.0.23
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 +17 -40
- package/index.ts +28 -28
- package/package.json +4 -4
- package/tools/bsv/explore.ts +331 -261
- package/tools/bsv/getPrice.ts +19 -10
- package/tools/bsv/index.ts +1 -1
- package/tools/index.ts +10 -10
- package/tools/mnee/getBalance.ts +53 -43
- package/tools/mnee/index.ts +7 -7
- package/tools/mnee/parseTx.ts +31 -27
- package/tools/mnee/sendMnee.ts +70 -66
- package/tools/ordinals/getTokenByIdOrTicker.ts +14 -7
- package/tools/ordinals/marketListings.ts +26 -13
- package/tools/ordinals/marketSales.ts +11 -17
- package/tools/utils/index.ts +19 -15
- package/tools/wallet/createOrdinals.ts +27 -13
- package/tools/wallet/getAddress.ts +6 -1
- package/tools/wallet/purchaseListing.ts +18 -16
- package/tools/wallet/schemas.ts +55 -32
- package/tools/wallet/sendOrdinals.ts +106 -92
- package/tools/wallet/sendToAddress.ts +1 -1
- package/tools/wallet/tools.test.ts +3 -3
- package/tools/wallet/tools.ts +51 -38
- package/tools/wallet/transferOrdToken.ts +138 -0
- package/tools/wallet/wallet.ts +3 -9
- package/tools/wallet/transferOrdToken/index.ts +0 -103
package/tools/wallet/tools.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
CallToolResult,
|
|
6
|
+
ServerNotification,
|
|
7
|
+
ServerRequest,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
5
9
|
import type { z } from "zod";
|
|
6
10
|
import type {
|
|
7
11
|
abortActionArgsSchema,
|
|
@@ -34,6 +38,7 @@ import {
|
|
|
34
38
|
walletEncryptionArgsSchema,
|
|
35
39
|
} from "./schemas";
|
|
36
40
|
|
|
41
|
+
import { Utils, type WalletProtocol } from "@bsv/sdk";
|
|
37
42
|
import { registerCreateOrdinalsTool } from "./createOrdinals";
|
|
38
43
|
import type { createOrdinalsArgsSchema } from "./createOrdinals";
|
|
39
44
|
import { registerGetAddressTool } from "./getAddress";
|
|
@@ -41,7 +46,6 @@ import { registerPurchaseListingTool } from "./purchaseListing";
|
|
|
41
46
|
import { registerSendToAddressTool } from "./sendToAddress";
|
|
42
47
|
import { registerTransferOrdTokenTool } from "./transferOrdToken";
|
|
43
48
|
import type { transferOrdTokenArgsSchema } from "./transferOrdToken";
|
|
44
|
-
import { Utils, type WalletProtocol } from "@bsv/sdk";
|
|
45
49
|
|
|
46
50
|
// Define mapping from tool names to argument schemas
|
|
47
51
|
type ToolArgSchemas = {
|
|
@@ -79,7 +83,7 @@ type ToolArgSchemas = {
|
|
|
79
83
|
// Define a type for the handler function with proper argument types
|
|
80
84
|
type ToolHandler = (
|
|
81
85
|
params: { args: unknown },
|
|
82
|
-
extra: RequestHandlerExtra,
|
|
86
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
83
87
|
) => Promise<CallToolResult>;
|
|
84
88
|
|
|
85
89
|
// Define a map type for tool name to handler functions
|
|
@@ -127,7 +131,7 @@ export function registerWalletTools(
|
|
|
127
131
|
{ args: getPublicKeyArgsSchema },
|
|
128
132
|
async (
|
|
129
133
|
{ args }: { args: z.infer<typeof getPublicKeyArgsSchema> },
|
|
130
|
-
extra: RequestHandlerExtra,
|
|
134
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
131
135
|
) => {
|
|
132
136
|
try {
|
|
133
137
|
const result = await wallet.getPublicKey(args);
|
|
@@ -146,7 +150,7 @@ export function registerWalletTools(
|
|
|
146
150
|
{ args: createSignatureArgsSchema },
|
|
147
151
|
async (
|
|
148
152
|
{ args }: { args: z.infer<typeof createSignatureArgsSchema> },
|
|
149
|
-
extra: RequestHandlerExtra,
|
|
153
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
150
154
|
) => {
|
|
151
155
|
try {
|
|
152
156
|
const result = await wallet.createSignature(args);
|
|
@@ -165,7 +169,7 @@ export function registerWalletTools(
|
|
|
165
169
|
{ args: verifySignatureArgsSchema },
|
|
166
170
|
async (
|
|
167
171
|
{ args }: { args: z.infer<typeof verifySignatureArgsSchema> },
|
|
168
|
-
extra: RequestHandlerExtra,
|
|
172
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
169
173
|
) => {
|
|
170
174
|
try {
|
|
171
175
|
const result = await wallet.verifySignature(args);
|
|
@@ -181,33 +185,33 @@ export function registerWalletTools(
|
|
|
181
185
|
registerTool(
|
|
182
186
|
"wallet_encryption",
|
|
183
187
|
"Combined tool for encrypting and decrypting data using the wallet's cryptographic keys.\n\n" +
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
188
|
+
"PARAMETERS:\n" +
|
|
189
|
+
'- mode: (required) Either "encrypt" to encrypt plaintext or "decrypt" to decrypt ciphertext\n' +
|
|
190
|
+
"- data: (required) Text string or array of numbers to process\n" +
|
|
191
|
+
"- encoding: (optional) For text input, the encoding format (utf8, hex, base64) - default is utf8\n\n" +
|
|
192
|
+
"EXAMPLES:\n" +
|
|
193
|
+
"1. Encrypt text data:\n" +
|
|
194
|
+
" {\n" +
|
|
195
|
+
' "mode": "encrypt",\n' +
|
|
196
|
+
' "data": "Hello World"\n' +
|
|
197
|
+
" }\n\n" +
|
|
198
|
+
"2. Decrypt previously encrypted data:\n" +
|
|
199
|
+
" {\n" +
|
|
200
|
+
' "mode": "decrypt",\n' +
|
|
201
|
+
' "data": [encrypted bytes from previous response]\n' +
|
|
202
|
+
" }",
|
|
199
203
|
{ args: walletEncryptionArgsSchema },
|
|
200
204
|
async (
|
|
201
205
|
{ args }: { args: z.infer<typeof walletEncryptionArgsSchema> },
|
|
202
|
-
extra: RequestHandlerExtra,
|
|
206
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
203
207
|
) => {
|
|
204
208
|
try {
|
|
205
209
|
const { mode, data, encoding } = args;
|
|
206
|
-
|
|
210
|
+
|
|
207
211
|
// Set default values for required parameters
|
|
208
212
|
const protocolID: WalletProtocol = [1, "aes256"];
|
|
209
213
|
const keyID = "default";
|
|
210
|
-
|
|
214
|
+
|
|
211
215
|
// Convert string data to binary if needed
|
|
212
216
|
let binaryData: number[];
|
|
213
217
|
if (Array.isArray(data)) {
|
|
@@ -217,8 +221,9 @@ export function registerWalletTools(
|
|
|
217
221
|
const { toArray } = Utils;
|
|
218
222
|
binaryData = toArray(data, encoding || "utf8");
|
|
219
223
|
}
|
|
220
|
-
|
|
221
|
-
let result: { ciphertext?: number[]; plaintext?: number[] | string } =
|
|
224
|
+
|
|
225
|
+
let result: { ciphertext?: number[]; plaintext?: number[] | string } =
|
|
226
|
+
{};
|
|
222
227
|
if (mode === "encrypt") {
|
|
223
228
|
result = await wallet.encrypt({
|
|
224
229
|
plaintext: binaryData,
|
|
@@ -231,7 +236,7 @@ export function registerWalletTools(
|
|
|
231
236
|
protocolID,
|
|
232
237
|
keyID,
|
|
233
238
|
});
|
|
234
|
-
|
|
239
|
+
|
|
235
240
|
// For decryption, convert plaintext back to string if it's likely UTF-8 text
|
|
236
241
|
if (result.plaintext as number[]) {
|
|
237
242
|
try {
|
|
@@ -239,11 +244,13 @@ export function registerWalletTools(
|
|
|
239
244
|
const textResult = toUTF8(result.plaintext as number[]);
|
|
240
245
|
// If conversion succeeds and seems like valid text, return as string
|
|
241
246
|
if (textResult && textResult.length > 0) {
|
|
242
|
-
return {
|
|
243
|
-
content: [
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
return {
|
|
248
|
+
content: [
|
|
249
|
+
{
|
|
250
|
+
type: "text",
|
|
251
|
+
text: JSON.stringify({ plaintext: textResult }),
|
|
252
|
+
},
|
|
253
|
+
],
|
|
247
254
|
};
|
|
248
255
|
}
|
|
249
256
|
} catch (e) {
|
|
@@ -251,13 +258,19 @@ export function registerWalletTools(
|
|
|
251
258
|
}
|
|
252
259
|
}
|
|
253
260
|
}
|
|
254
|
-
|
|
261
|
+
|
|
255
262
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
256
263
|
} catch (error) {
|
|
257
|
-
const errorMessage =
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
const errorMessage =
|
|
265
|
+
error instanceof Error ? error.message : String(error);
|
|
266
|
+
return {
|
|
267
|
+
content: [
|
|
268
|
+
{
|
|
269
|
+
type: "text",
|
|
270
|
+
text: `Error during ${args.mode}: ${errorMessage}`,
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
isError: true,
|
|
261
274
|
};
|
|
262
275
|
}
|
|
263
276
|
},
|
|
@@ -265,6 +278,6 @@ export function registerWalletTools(
|
|
|
265
278
|
|
|
266
279
|
// Register createOrdinals tool
|
|
267
280
|
registerCreateOrdinalsTool(server, wallet);
|
|
268
|
-
|
|
281
|
+
|
|
269
282
|
return handlers;
|
|
270
283
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
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 {
|
|
8
|
+
type Distribution,
|
|
9
|
+
type Payment,
|
|
10
|
+
type TokenChangeResult,
|
|
11
|
+
TokenInputMode,
|
|
12
|
+
TokenSelectionStrategy,
|
|
13
|
+
TokenType,
|
|
14
|
+
type TokenUtxo,
|
|
15
|
+
type TransferOrdTokensConfig,
|
|
16
|
+
type Utxo,
|
|
17
|
+
selectTokenUtxos,
|
|
18
|
+
transferOrdTokens,
|
|
19
|
+
} from "js-1sat-ord";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import type { Wallet } from "./wallet";
|
|
22
|
+
|
|
23
|
+
// Schema for BSV-20/BSV-21 token transfer arguments
|
|
24
|
+
export const transferOrdTokenArgsSchema = z.object({
|
|
25
|
+
protocol: z.enum(["bsv-20", "bsv-21"]),
|
|
26
|
+
tokenID: z.string(),
|
|
27
|
+
sendAmount: z.number(),
|
|
28
|
+
paymentUtxos: z.array(
|
|
29
|
+
z.object({
|
|
30
|
+
txid: z.string(),
|
|
31
|
+
vout: z.number(),
|
|
32
|
+
satoshis: z.number(),
|
|
33
|
+
script: z.string(),
|
|
34
|
+
}),
|
|
35
|
+
),
|
|
36
|
+
tokenUtxos: z.array(
|
|
37
|
+
z.object({
|
|
38
|
+
txid: z.string(),
|
|
39
|
+
vout: z.number(),
|
|
40
|
+
satoshis: z.literal(1),
|
|
41
|
+
script: z.string(),
|
|
42
|
+
amt: z.string(),
|
|
43
|
+
id: z.string(),
|
|
44
|
+
}),
|
|
45
|
+
),
|
|
46
|
+
distributions: z.array(z.object({ address: z.string(), tokens: z.number() })),
|
|
47
|
+
decimals: z.number(),
|
|
48
|
+
additionalPayments: z
|
|
49
|
+
.array(z.object({ to: z.string(), amount: z.number() }))
|
|
50
|
+
.optional(),
|
|
51
|
+
});
|
|
52
|
+
export type TransferOrdTokenArgs = z.infer<typeof transferOrdTokenArgsSchema>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Register the wallet_transferOrdToken tool for transferring BSV tokens.
|
|
56
|
+
*/
|
|
57
|
+
export function registerTransferOrdTokenTool(
|
|
58
|
+
server: McpServer,
|
|
59
|
+
wallet: Wallet,
|
|
60
|
+
) {
|
|
61
|
+
server.tool(
|
|
62
|
+
"wallet_transferOrdToken",
|
|
63
|
+
"Transfers BSV-20 or BSV-21 tokens from your wallet via js-1sat-ord transferOrdTokens.",
|
|
64
|
+
{ args: transferOrdTokenArgsSchema },
|
|
65
|
+
async (
|
|
66
|
+
{ args }: { args: TransferOrdTokenArgs },
|
|
67
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
68
|
+
) => {
|
|
69
|
+
try {
|
|
70
|
+
// fetch keys
|
|
71
|
+
const paymentPk = wallet.getPrivateKey();
|
|
72
|
+
if (!paymentPk) throw new Error("No private key available");
|
|
73
|
+
const ordPk = paymentPk;
|
|
74
|
+
const changeAddress = paymentPk.toAddress().toString();
|
|
75
|
+
const ordAddress = changeAddress;
|
|
76
|
+
|
|
77
|
+
// select token UTXOs
|
|
78
|
+
const { selectedUtxos: inputTokens } = selectTokenUtxos(
|
|
79
|
+
args.tokenUtxos as TokenUtxo[],
|
|
80
|
+
args.sendAmount,
|
|
81
|
+
args.decimals,
|
|
82
|
+
{
|
|
83
|
+
inputStrategy: TokenSelectionStrategy.SmallestFirst,
|
|
84
|
+
outputStrategy: TokenSelectionStrategy.LargestFirst,
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// build config
|
|
89
|
+
const config: TransferOrdTokensConfig = {
|
|
90
|
+
protocol:
|
|
91
|
+
args.protocol === "bsv-20" ? TokenType.BSV20 : TokenType.BSV21,
|
|
92
|
+
tokenID: args.tokenID,
|
|
93
|
+
utxos: args.paymentUtxos as Utxo[],
|
|
94
|
+
inputTokens,
|
|
95
|
+
distributions: args.distributions as Distribution[],
|
|
96
|
+
tokenChangeAddress: ordAddress,
|
|
97
|
+
changeAddress,
|
|
98
|
+
paymentPk,
|
|
99
|
+
ordPk,
|
|
100
|
+
additionalPayments: (args.additionalPayments as Payment[]) || [],
|
|
101
|
+
decimals: args.decimals,
|
|
102
|
+
inputMode: TokenInputMode.Needed,
|
|
103
|
+
splitConfig: {
|
|
104
|
+
outputs: inputTokens.length === 1 ? 2 : 1,
|
|
105
|
+
threshold: args.sendAmount,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// execute transfer
|
|
110
|
+
const result: TokenChangeResult = await transferOrdTokens(config);
|
|
111
|
+
await result.tx.broadcast();
|
|
112
|
+
|
|
113
|
+
// refresh UTXOs
|
|
114
|
+
try {
|
|
115
|
+
await wallet.refreshUtxos();
|
|
116
|
+
} catch {}
|
|
117
|
+
|
|
118
|
+
// respond
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: JSON.stringify({
|
|
124
|
+
txid: result.tx.id("hex"),
|
|
125
|
+
spentOutpoints: result.spentOutpoints,
|
|
126
|
+
payChange: result.payChange,
|
|
127
|
+
tokenChange: result.tokenChange,
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
} catch (err: unknown) {
|
|
133
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
134
|
+
return { content: [{ type: "text", text: msg }], isError: true };
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
}
|
package/tools/wallet/wallet.ts
CHANGED
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* See: https://github.com/bitcoin-sv/ts-sdk/blob/main/src/wallet/Wallet.interfaces.ts
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
9
|
-
LockingScript,
|
|
10
|
-
PrivateKey,
|
|
11
|
-
ProtoWallet,
|
|
12
|
-
Transaction,
|
|
13
|
-
} from "@bsv/sdk";
|
|
8
|
+
import { LockingScript, PrivateKey, ProtoWallet, Transaction } from "@bsv/sdk";
|
|
14
9
|
import type {
|
|
15
10
|
AbortActionArgs,
|
|
16
11
|
AbortActionResult,
|
|
@@ -87,13 +82,12 @@ export class Wallet extends ProtoWallet implements WalletInterface {
|
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
const address = privateKey.toAddress();
|
|
90
|
-
|
|
85
|
+
|
|
91
86
|
const utxos = await fetchPayUtxos(address);
|
|
92
87
|
const nftUtxos = await fetchNftUtxos(address);
|
|
93
88
|
this.paymentUtxos = utxos;
|
|
94
89
|
this.nftUtxos = nftUtxos;
|
|
95
90
|
this.lastUtxoFetch = Date.now();
|
|
96
|
-
|
|
97
91
|
} catch (error) {
|
|
98
92
|
console.error("Error refreshing UTXOs:", error);
|
|
99
93
|
throw error;
|
|
@@ -130,7 +124,7 @@ export class Wallet extends ProtoWallet implements WalletInterface {
|
|
|
130
124
|
if (!privateKey) {
|
|
131
125
|
throw new Error("No private key available");
|
|
132
126
|
}
|
|
133
|
-
|
|
127
|
+
|
|
134
128
|
const publicKey = privateKey.toPublicKey();
|
|
135
129
|
return {
|
|
136
130
|
publicKey: publicKey.toDER("hex") as PubKeyHex,
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
import {
|
|
5
|
-
transferOrdTokens,
|
|
6
|
-
TokenType,
|
|
7
|
-
TokenInputMode,
|
|
8
|
-
TokenSelectionStrategy,
|
|
9
|
-
selectTokenUtxos,
|
|
10
|
-
type TransferOrdTokensConfig,
|
|
11
|
-
type Utxo,
|
|
12
|
-
type TokenUtxo,
|
|
13
|
-
type Payment,
|
|
14
|
-
type Distribution,
|
|
15
|
-
type TokenChangeResult,
|
|
16
|
-
} from "js-1sat-ord";
|
|
17
|
-
import type { Wallet } from "../wallet";
|
|
18
|
-
|
|
19
|
-
// Schema for BSV-20/BSV-21 token transfer arguments
|
|
20
|
-
export const transferOrdTokenArgsSchema = z.object({
|
|
21
|
-
protocol: z.enum(["bsv-20", "bsv-21"]),
|
|
22
|
-
tokenID: z.string(),
|
|
23
|
-
sendAmount: z.number(),
|
|
24
|
-
paymentUtxos: z.array(
|
|
25
|
-
z.object({ txid: z.string(), vout: z.number(), satoshis: z.number(), script: z.string() })
|
|
26
|
-
),
|
|
27
|
-
tokenUtxos: z.array(
|
|
28
|
-
z.object({ txid: z.string(), vout: z.number(), satoshis: z.literal(1), script: z.string(), amt: z.string(), id: z.string() })
|
|
29
|
-
),
|
|
30
|
-
distributions: z.array(z.object({ address: z.string(), tokens: z.number() })),
|
|
31
|
-
decimals: z.number(),
|
|
32
|
-
additionalPayments: z.array(z.object({ to: z.string(), amount: z.number() })).optional(),
|
|
33
|
-
});
|
|
34
|
-
export type TransferOrdTokenArgs = z.infer<typeof transferOrdTokenArgsSchema>;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Register the wallet_transferOrdToken tool for transferring BSV tokens.
|
|
38
|
-
*/
|
|
39
|
-
export function registerTransferOrdTokenTool(server: McpServer, wallet: Wallet) {
|
|
40
|
-
server.tool(
|
|
41
|
-
"wallet_transferOrdToken",
|
|
42
|
-
"Transfers BSV-20 or BSV-21 tokens from your wallet via js-1sat-ord transferOrdTokens.",
|
|
43
|
-
{ args: transferOrdTokenArgsSchema },
|
|
44
|
-
async (
|
|
45
|
-
{ args }: { args: TransferOrdTokenArgs },
|
|
46
|
-
extra: RequestHandlerExtra
|
|
47
|
-
) => {
|
|
48
|
-
try {
|
|
49
|
-
// fetch keys
|
|
50
|
-
const paymentPk = wallet.getPrivateKey();
|
|
51
|
-
if (!paymentPk) throw new Error("No private key available");
|
|
52
|
-
const ordPk = paymentPk;
|
|
53
|
-
const changeAddress = paymentPk.toAddress().toString();
|
|
54
|
-
const ordAddress = changeAddress;
|
|
55
|
-
|
|
56
|
-
// select token UTXOs
|
|
57
|
-
const { selectedUtxos: inputTokens } = selectTokenUtxos(
|
|
58
|
-
args.tokenUtxos as TokenUtxo[],
|
|
59
|
-
args.sendAmount,
|
|
60
|
-
args.decimals,
|
|
61
|
-
{ inputStrategy: TokenSelectionStrategy.SmallestFirst, outputStrategy: TokenSelectionStrategy.LargestFirst }
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
// build config
|
|
65
|
-
const config: TransferOrdTokensConfig = {
|
|
66
|
-
protocol: args.protocol === "bsv-20" ? TokenType.BSV20 : TokenType.BSV21,
|
|
67
|
-
tokenID: args.tokenID,
|
|
68
|
-
utxos: args.paymentUtxos as Utxo[],
|
|
69
|
-
inputTokens,
|
|
70
|
-
distributions: args.distributions as Distribution[],
|
|
71
|
-
tokenChangeAddress: ordAddress,
|
|
72
|
-
changeAddress,
|
|
73
|
-
paymentPk,
|
|
74
|
-
ordPk,
|
|
75
|
-
additionalPayments: args.additionalPayments as Payment[] || [],
|
|
76
|
-
decimals: args.decimals,
|
|
77
|
-
inputMode: TokenInputMode.Needed,
|
|
78
|
-
splitConfig: { outputs: inputTokens.length === 1 ? 2 : 1, threshold: args.sendAmount },
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// execute transfer
|
|
82
|
-
const result: TokenChangeResult = await transferOrdTokens(config);
|
|
83
|
-
await result.tx.broadcast();
|
|
84
|
-
|
|
85
|
-
// refresh UTXOs
|
|
86
|
-
try { await wallet.refreshUtxos(); } catch {}
|
|
87
|
-
|
|
88
|
-
// respond
|
|
89
|
-
return {
|
|
90
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
91
|
-
txid: result.tx.id("hex"),
|
|
92
|
-
spentOutpoints: result.spentOutpoints,
|
|
93
|
-
payChange: result.payChange,
|
|
94
|
-
tokenChange: result.tokenChange,
|
|
95
|
-
}) }]
|
|
96
|
-
};
|
|
97
|
-
} catch (err: unknown) {
|
|
98
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
99
|
-
return { content: [{ type: "text", text: msg }], isError: true };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
}
|