bsv-mcp 0.2.9 → 0.2.11

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +26 -2
  3. package/dist/index.js +6777 -126216
  4. package/index.ts +287 -265
  5. package/package.json +4 -3
  6. package/tools/bap/generate.test.ts +17 -16
  7. package/tools/index.ts +8 -3
  8. package/tools/ordinals/getInscription.ts +15 -65
  9. package/tools/ordinals/getTokenByIdOrTicker.ts +14 -80
  10. package/tools/ordinals/index.ts +8 -7
  11. package/tools/ordinals/marketListings.ts +21 -188
  12. package/tools/ordinals/marketSales.ts +21 -127
  13. package/tools/ordinals/searchInscriptions.ts +21 -108
  14. package/tools/wallet/brc100.ts +572 -0
  15. package/tools/wallet/cancelListing.ts +80 -0
  16. package/tools/wallet/createOrdinals.ts +62 -143
  17. package/tools/wallet/getAddress.ts +19 -13
  18. package/tools/wallet/getBalance.ts +29 -25
  19. package/tools/wallet/getBsv21Balances.ts +28 -0
  20. package/tools/wallet/getLockData.ts +25 -0
  21. package/tools/wallet/getOrdinals.ts +35 -0
  22. package/tools/wallet/listOrdinal.ts +86 -0
  23. package/tools/wallet/listTokens.ts +28 -0
  24. package/tools/wallet/lockBsv.ts +69 -0
  25. package/tools/wallet/opnsDeregister.ts +80 -0
  26. package/tools/wallet/opnsRegister.ts +80 -0
  27. package/tools/wallet/purchaseListing.ts +89 -290
  28. package/tools/wallet/refreshUtxos.ts +21 -32
  29. package/tools/wallet/schemas.ts +7 -11
  30. package/tools/wallet/sendAllBsv.ts +64 -0
  31. package/tools/wallet/sendToAddress.ts +46 -47
  32. package/tools/wallet/signBsm.ts +29 -0
  33. package/tools/wallet/sweepBsv.ts +70 -0
  34. package/tools/wallet/sweepBsv21.ts +71 -0
  35. package/tools/wallet/sweepOrdinals.ts +69 -0
  36. package/tools/wallet/tools.ts +50 -88
  37. package/tools/wallet/transferOrdToken.ts +137 -129
  38. package/tools/wallet/unlockBsv.ts +57 -0
  39. package/tools/wallet/a2bPublishAgent.ts +0 -307
  40. package/tools/wallet/sendOrdinals.ts +0 -160
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "bsv-mcp",
3
3
  "module": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.2.9",
5
+ "version": "0.2.11",
6
6
  "license": "MIT",
7
7
  "author": "satchmo",
8
8
  "description": "A collection of Bitcoin SV (BSV) tools for the Model Context Protocol (MCP) framework",
@@ -79,6 +79,8 @@
79
79
  "typescript": "^5.9.3"
80
80
  },
81
81
  "dependencies": {
82
+ "@1sat/actions": "0.0.27",
83
+ "@1sat/wallet-remote": "0.0.7",
82
84
  "@bsv/sdk": "^2.0.6",
83
85
  "@modelcontextprotocol/ext-apps": "^1.2.0",
84
86
  "@modelcontextprotocol/sdk": "^1.27.1",
@@ -104,7 +106,6 @@
104
106
  "start:next": "next start",
105
107
  "lint": "biome check .",
106
108
  "lint:fix": "biome check . --write",
107
- "deploy": "vercel --prod",
108
- "deploy:preview": "vercel"
109
+ "prepack": "bun run build:all"
109
110
  }
110
111
  }
@@ -23,7 +23,7 @@ import * as utxoUtils from "../wallet/fetchPaymentUtxos";
23
23
  import { type BapGenerateArgs, registerBapGenerateTool } from "./generate";
24
24
 
25
25
  type GenericToolHandler = (
26
- params: { args: BapGenerateArgs },
26
+ params: BapGenerateArgs,
27
27
  extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
28
28
  ) => CallToolResult | Promise<CallToolResult>;
29
29
 
@@ -115,12 +115,13 @@ describe("BAP Generate Tool", () => {
115
115
  it("should register bap_generate tool with the MCP server", () => {
116
116
  registerBapGenerateTool(mockMcpServerInstance as unknown as McpServer);
117
117
  expect(mockServerToolSpy).toHaveBeenCalledTimes(1);
118
- expect(mockServerToolSpy).toHaveBeenCalledWith(
119
- "bap_generate",
120
- expect.any(String),
121
- { args: expect.any(Object) },
122
- expect.any(Function),
123
- );
118
+ const [name, description, schema, handler] =
119
+ mockServerToolSpy.mock.calls[0];
120
+ expect(name).toBe("bap_generate");
121
+ expect(typeof description).toBe("string");
122
+ expect(schema).toHaveProperty("alternateName");
123
+ expect(schema).toHaveProperty("description");
124
+ expect(typeof handler).toBe("function");
124
125
  });
125
126
 
126
127
  const getRegisteredHandler = (): GenericToolHandler => {
@@ -141,7 +142,7 @@ describe("BAP Generate Tool", () => {
141
142
  ServerRequest,
142
143
  ServerNotification
143
144
  >;
144
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
145
+ const result = (await handler({}, mockExtra)) as CallToolResult;
145
146
 
146
147
  expect(result.isError).toBe(false);
147
148
  expect(mkdirSyncSpy).toHaveBeenCalledWith(KEY_DIR, {
@@ -174,7 +175,7 @@ describe("BAP Generate Tool", () => {
174
175
  ServerRequest,
175
176
  ServerNotification
176
177
  >;
177
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
178
+ const result = (await handler({}, mockExtra)) as CallToolResult;
178
179
 
179
180
  expect(result.isError).toBe(true);
180
181
  expect(result.content?.[0]?.text).toContain(
@@ -192,7 +193,7 @@ describe("BAP Generate Tool", () => {
192
193
  ServerRequest,
193
194
  ServerNotification
194
195
  >;
195
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
196
+ const result = (await handler({}, mockExtra)) as CallToolResult;
196
197
 
197
198
  expect(result.isError).toBe(true);
198
199
  expect(result.content?.[0]?.text).toContain(
@@ -214,7 +215,7 @@ describe("BAP Generate Tool", () => {
214
215
  ServerRequest,
215
216
  ServerNotification
216
217
  >;
217
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
218
+ const result = (await handler({}, mockExtra)) as CallToolResult;
218
219
 
219
220
  expect(result.isError).toBe(true);
220
221
  expect(result.content?.[0]?.text).toContain(
@@ -236,7 +237,7 @@ describe("BAP Generate Tool", () => {
236
237
  ServerRequest,
237
238
  ServerNotification
238
239
  >;
239
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
240
+ const result = (await handler({}, mockExtra)) as CallToolResult;
240
241
 
241
242
  expect(result.isError).toBe(true);
242
243
  expect(result.content?.[0]?.text).toContain(
@@ -260,7 +261,7 @@ describe("BAP Generate Tool", () => {
260
261
  try {
261
262
  registerBapGenerateTool(mockMcpServerInstance as unknown as McpServer);
262
263
  const handler = getRegisteredHandler();
263
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
264
+ const result = (await handler({}, mockExtra)) as CallToolResult;
264
265
 
265
266
  expect(result.isError).toBe(true);
266
267
  expect(result.content?.[0]?.text).toContain(
@@ -283,7 +284,7 @@ describe("BAP Generate Tool", () => {
283
284
  ServerRequest,
284
285
  ServerNotification
285
286
  >;
286
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
287
+ const result = (await handler({}, mockExtra)) as CallToolResult;
287
288
 
288
289
  expect(result.isError).toBe(true);
289
290
  expect(result.content?.[0]?.text).toContain(
@@ -302,7 +303,7 @@ describe("BAP Generate Tool", () => {
302
303
  ServerRequest,
303
304
  ServerNotification
304
305
  >;
305
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
306
+ const result = (await handler({}, mockExtra)) as CallToolResult;
306
307
 
307
308
  expect(result.isError).toBe(false);
308
309
  expect(result.content?.[0]?.text).toContain(
@@ -333,7 +334,7 @@ describe("BAP Generate Tool", () => {
333
334
  ServerRequest,
334
335
  ServerNotification
335
336
  >;
336
- const result = (await handler({ args: {} }, mockExtra)) as CallToolResult;
337
+ const result = (await handler({}, mockExtra)) as CallToolResult;
337
338
 
338
339
  expect(result.isError).toBe(false);
339
340
  expect(result.content?.[0]?.text).toContain(
package/tools/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { OneSatContext } from "@1sat/actions";
2
+ import type { OneSatServices } from "@1sat/wallet-remote";
1
3
  import type { PrivateKey } from "@bsv/sdk";
2
4
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
5
  import { registerA2bDiscoverTool } from "./a2b/discover";
@@ -41,6 +43,8 @@ export interface ToolsConfig {
41
43
  wallet?: Wallet;
42
44
  integratedWallet?: IntegratedWallet;
43
45
  disableBroadcasting?: boolean; // For wallet tools
46
+ ctx?: OneSatContext;
47
+ services?: OneSatServices;
44
48
  }
45
49
 
46
50
  /**
@@ -81,7 +85,7 @@ export function registerAllTools(
81
85
 
82
86
  // Register Ordinals-related tools
83
87
  if (enableOrdinalsTools) {
84
- registerOrdinalsTools(server);
88
+ registerOrdinalsTools(server, config.ctx);
85
89
  }
86
90
 
87
91
  // Register utility tools
@@ -126,9 +130,10 @@ export function registerAllTools(
126
130
  } else if (config.wallet) {
127
131
  // Register normal wallet tools
128
132
  const walletToolOptions = {
129
- disableBroadcasting: config.disableBroadcasting === true, // Default to false if undefined
130
- enableA2bTools: enableA2bTools, // Use the already determined enableA2bTools value
133
+ disableBroadcasting: config.disableBroadcasting === true,
134
+ enableA2bTools: enableA2bTools,
131
135
  identityPk: config.identityPk,
136
+ ctx: config.ctx,
132
137
  };
133
138
  registerWalletTools(server, config.wallet, walletToolOptions);
134
139
  }
@@ -1,83 +1,33 @@
1
+ import type { OneSatContext } from "@1sat/actions";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
3
  import { z } from "zod";
4
4
 
5
- // Schema for get inscription arguments
6
- export const getInscriptionArgsSchema = z.object({
7
- outpoint: z.string().describe("Outpoint in format 'txid_vout'"),
8
- });
9
-
10
- export type GetInscriptionArgs = z.infer<typeof getInscriptionArgsSchema>;
11
-
12
- // Inscription API response type
13
- interface InscriptionResponse {
14
- outpoint: string;
15
- origin: {
16
- outpoint: string;
17
- data?: {
18
- insc?: {
19
- text?: string;
20
- json?: unknown;
21
- file?: {
22
- hash?: string;
23
- size?: number;
24
- type?: string;
25
- };
26
- };
27
- };
28
- };
29
- height?: number;
30
- idx?: number;
31
- satoshis?: number;
32
- script?: string;
33
- spend?: string;
34
- [key: string]: unknown;
35
- }
36
-
37
5
  /**
38
- * Register the Ordinals inscription lookup tool
6
+ * Register the inscription metadata lookup tool
39
7
  */
40
- export function registerGetInscriptionTool(server: McpServer): void {
8
+ export function registerGetInscriptionTool(
9
+ server: McpServer,
10
+ ctx?: OneSatContext,
11
+ ): void {
41
12
  server.tool(
42
13
  "ordinals_getInscription",
43
- "Retrieves detailed information about a specific ordinal inscription by its outpoint. Returns complete inscription data including content type, file information, inscription origin, and current status. Useful for verifying NFT authenticity or retrieving metadata about digital artifacts.",
14
+ "Retrieves metadata for an inscription by its outpoint. Returns content type, file info, origin, MAP data, and sequence info.",
44
15
  {
45
- ...getInscriptionArgsSchema.shape,
16
+ outpoint: z
17
+ .string()
18
+ .describe("Outpoint in format 'txid_vout'"),
46
19
  },
47
- async (
48
- { outpoint },
49
- extra: RequestHandlerExtra,
50
- ) => {
20
+ async ({ outpoint }) => {
51
21
  try {
22
+ if (!ctx?.services) {
23
+ throw new Error("OneSat services not available");
24
+ }
52
25
 
53
- // Validate outpoint format
54
26
  if (!/^[0-9a-f]{64}_\d+$/i.test(outpoint)) {
55
27
  throw new Error("Invalid outpoint format. Expected 'txid_vout'");
56
28
  }
57
29
 
58
- // Fetch inscription data from GorillaPool API
59
- const response = await fetch(
60
- `https://ordinals.gorillapool.io/api/inscriptions/${outpoint}`,
61
- );
62
-
63
- if (response.status === 404) {
64
- return {
65
- content: [
66
- {
67
- type: "text",
68
- text: JSON.stringify({ error: "Inscription not found" }),
69
- },
70
- ],
71
- };
72
- }
73
-
74
- if (!response.ok) {
75
- throw new Error(
76
- `API error: ${response.status} ${response.statusText}`,
77
- );
78
- }
79
-
80
- const data = (await response.json()) as InscriptionResponse;
30
+ const data = await ctx.services.ordfs.getMetadata(outpoint);
81
31
 
82
32
  return {
83
33
  content: [
@@ -1,99 +1,33 @@
1
+ import type { OneSatContext } from "@1sat/actions";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
3
  import { z } from "zod";
4
4
 
5
- // Schema for get token by ID or ticker arguments
6
- export const getTokenByIdOrTickerArgsSchema = z
7
- .object({
8
- id: z
9
- .string()
10
- .optional()
11
- .describe("BSV20 token ID in outpoint format (txid_vout)"),
12
- tick: z.string().optional().describe("BSV20 token ticker symbol"),
13
- })
14
- .refine((data) => data.id || data.tick, {
15
- message: "Either id or tick must be provided",
16
- });
17
-
18
- export type GetTokenByIdOrTickerArgs = z.infer<
19
- typeof getTokenByIdOrTickerArgsSchema
20
- >;
21
-
22
- // BSV20 token response type
23
- interface TokenResponse {
24
- id: string;
25
- tick?: string;
26
- sym?: string;
27
- max?: string;
28
- lim?: string;
29
- dec?: number;
30
- supply?: string;
31
- amt?: string;
32
- status?: number;
33
- icon?: string;
34
- height?: number;
35
- [key: string]: unknown;
36
- }
37
-
38
5
  /**
39
- * Register the BSV20 token lookup tool
6
+ * Register the BSV21 token lookup tool
40
7
  */
41
- export function registerGetTokenByIdOrTickerTool(server: McpServer): void {
8
+ export function registerGetTokenByIdOrTickerTool(
9
+ server: McpServer,
10
+ ctx?: OneSatContext,
11
+ ): void {
42
12
  server.tool(
43
13
  "ordinals_getTokenByIdOrTicker",
44
- "Retrieves detailed information about a specific BSV-20 token by its ID or ticker symbol. Returns complete token data including ticker symbol, supply information, decimals, and current status. This tool is useful for verifying token authenticity or checking supply metrics.",
14
+ "Retrieves detailed information about a BSV21 token by its ID (txid_vout format). Returns token data including symbol, supply, decimals, funding status, and current state.",
45
15
  {
46
16
  id: z
47
17
  .string()
48
- .optional()
49
- .describe("BSV20 token ID in outpoint format (txid_vout)"),
50
- tick: z.string().optional().describe("BSV20 token ticker symbol"),
18
+ .describe("BSV21 token ID in outpoint format (txid_vout)"),
51
19
  },
52
- async (
53
- { id, tick },
54
- extra: RequestHandlerExtra,
55
- ) => {
20
+ async ({ id }) => {
56
21
  try {
57
-
58
- // Validate that at least one of id or tick is provided
59
- if (!id && !tick) {
60
- throw new Error("Either token ID or ticker symbol must be provided");
61
- }
62
-
63
- // Validate ID format if provided
64
- if (id && !/^[0-9a-f]{64}_\d+$/i.test(id)) {
65
- throw new Error("Invalid BSV20 ID format. Expected 'txid_vout'");
66
- }
67
-
68
- // Determine which endpoint to use based on provided parameters
69
- let endpoint: string;
70
- if (id) {
71
- endpoint = `https://ordinals.gorillapool.io/api/bsv20/id/${id}`;
72
- } else {
73
- endpoint = `https://ordinals.gorillapool.io/api/bsv20/tick/${tick}`;
74
- }
75
-
76
- // Fetch BSV20 token data from GorillaPool API
77
- const response = await fetch(endpoint);
78
-
79
- if (response.status === 404) {
80
- return {
81
- content: [
82
- {
83
- type: "text",
84
- text: JSON.stringify({ error: "BSV20 token not found" }),
85
- },
86
- ],
87
- };
22
+ if (!ctx?.services) {
23
+ throw new Error("OneSat services not available");
88
24
  }
89
25
 
90
- if (!response.ok) {
91
- throw new Error(
92
- `API error: ${response.status} ${response.statusText}`,
93
- );
26
+ if (!/^[0-9a-f]{64}_\d+$/i.test(id)) {
27
+ throw new Error("Invalid token ID format. Expected 'txid_vout'");
94
28
  }
95
29
 
96
- const data = (await response.json()) as TokenResponse;
30
+ const data = await ctx.services.bsv21.getTokenDetails(id);
97
31
 
98
32
  return {
99
33
  content: [
@@ -1,3 +1,4 @@
1
+ import type { OneSatContext } from "@1sat/actions";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
3
  import { registerGetInscriptionTool } from "./getInscription";
3
4
  import { registerGetTokenByIdOrTickerTool } from "./getTokenByIdOrTicker";
@@ -8,12 +9,12 @@ import { registerSearchInscriptionsTool } from "./searchInscriptions";
8
9
  /**
9
10
  * Register all Ordinals tools with the MCP server
10
11
  * @param server The MCP server instance
12
+ * @param ctx OneSat context for SDK service access
11
13
  */
12
- export function registerOrdinalsTools(server: McpServer): void {
13
- // Register Ordinals-related tools
14
- registerGetInscriptionTool(server);
15
- registerSearchInscriptionsTool(server);
16
- registerMarketListingsTool(server);
17
- registerMarketSalesTool(server);
18
- registerGetTokenByIdOrTickerTool(server);
14
+ export function registerOrdinalsTools(server: McpServer, ctx?: OneSatContext): void {
15
+ registerGetInscriptionTool(server, ctx);
16
+ registerSearchInscriptionsTool(server, ctx);
17
+ registerMarketListingsTool(server, ctx);
18
+ registerMarketSalesTool(server, ctx);
19
+ registerGetTokenByIdOrTickerTool(server, ctx);
19
20
  }
@@ -1,197 +1,30 @@
1
+ import type { OneSatContext } from "@1sat/actions";
1
2
  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
-
5
- // Enhanced schema for unified market listings arguments
6
- export const marketListingsArgsSchema = z.object({
7
- // Common parameters
8
- limit: z
9
- .number()
10
- .int()
11
- .min(1)
12
- .max(100)
13
- .default(20)
14
- .describe("Number of results (1-100, default 20)"),
15
- offset: z.number().int().min(0).default(0).describe("Pagination offset"),
16
- dir: z
17
- .enum(["asc", "desc"])
18
- .default("desc")
19
- .describe("Sort direction (asc or desc)"),
20
- address: z.string().optional().describe("Bitcoin address"),
21
-
22
- // NFT-specific parameters
23
- origin: z.string().optional().describe("Origin outpoint"),
24
- mime: z.string().optional().describe("MIME type filter"),
25
- num: z.string().optional().describe("Inscription number"),
26
-
27
- // General market parameters
28
- minPrice: z.number().optional().describe("Minimum price in satoshis"),
29
- maxPrice: z.number().optional().describe("Maximum price in satoshis"),
30
-
31
- // Token-specific parameters
32
- tokenType: z
33
- .enum(["nft", "bsv20", "bsv21", "all"])
34
- .default("all")
35
- .describe("Type of token to search for (nft, bsv20, bsv21, or all)"),
36
- sort: z
37
- .enum(["recent", "price", "num", "height", "price_per_token"])
38
- .default("recent")
39
- .describe("Sort method (recent, price, num, height, price_per_token)"),
40
- id: z.string().optional().describe("Token ID in outpoint format"),
41
- tick: z.string().optional().describe("Token ticker symbol"),
42
- pending: z
43
- .boolean()
44
- .default(false)
45
- .optional()
46
- .describe("Include pending sales"),
47
- });
48
-
49
- export type MarketListingsArgs = z.infer<typeof marketListingsArgsSchema>;
50
-
51
- // Unified response type that covers all token types
52
- interface MarketListingResponse {
53
- results: Array<{
54
- outpoint: string;
55
- origin?: {
56
- outpoint: string;
57
- data?: {
58
- insc?: {
59
- text?: string;
60
- file?: {
61
- type?: string;
62
- size?: number;
63
- };
64
- };
65
- };
66
- };
67
- data?: {
68
- list?: {
69
- price?: number;
70
- payout?: string;
71
- sale?: boolean;
72
- price_per_token?: number;
73
- };
74
- bsv20?: {
75
- id?: string;
76
- tick?: string;
77
- sym?: string;
78
- amt?: string;
79
- op?: string;
80
- };
81
- };
82
- satoshis?: number;
83
- height?: number;
84
- [key: string]: unknown;
85
- }>;
86
- total: number;
87
- }
88
3
 
89
4
  /**
90
- * Register the unified Ordinals market listings tool
91
- * Handles NFTs, BSV20, and BSV21 tokens
5
+ * Register the market listings tool (stub — awaiting 1sat-stack implementation)
92
6
  */
93
- export function registerMarketListingsTool(server: McpServer): void {
7
+ export function registerMarketListingsTool(
8
+ server: McpServer,
9
+ ctx?: OneSatContext,
10
+ ): void {
94
11
  server.tool(
95
12
  "ordinals_marketListings",
96
- "Retrieves current marketplace listings for Bitcoin SV ordinals with flexible filtering. Supports multiple asset types (NFTs, BSV-20 tokens, BSV-21 tokens) through a unified interface. Results include listing prices, details about the assets, and seller information.",
97
- {
98
- ...marketListingsArgsSchema.shape,
99
- },
100
- async (
101
- { limit, offset, sort, dir, address, origin, mime, num, minPrice, maxPrice, tokenType, id, tick, pending },
102
- extra: RequestHandlerExtra,
103
- ) => {
104
- try {
105
-
106
- // Determine the API endpoint based on tokenType
107
- let baseUrl = "https://ordinals.gorillapool.io/api";
108
- let useTokenParams = false;
109
-
110
- if (tokenType === "bsv20" || tokenType === "bsv21") {
111
- baseUrl += "/bsv20/market";
112
- useTokenParams = true;
113
- } else if (tokenType === "nft" || tokenType === "all") {
114
- baseUrl += "/market";
115
- }
116
-
117
- // Build the URL with query parameters
118
- const url = new URL(baseUrl);
119
- url.searchParams.append("limit", limit.toString());
120
- url.searchParams.append("offset", offset.toString());
121
- url.searchParams.append("dir", dir);
122
-
123
- // Add sort parameter based on token type
124
- if (useTokenParams) {
125
- // BSV20/BSV21 specific sort options
126
- if (
127
- sort === "height" ||
128
- sort === "price" ||
129
- sort === "price_per_token"
130
- ) {
131
- url.searchParams.append("sort", sort);
132
- }
133
- // Add token-specific parameters
134
- if (tokenType === "bsv21") {
135
- url.searchParams.append("type", "v2");
136
- }
137
- if (id) url.searchParams.append("id", id);
138
- if (tick) url.searchParams.append("tick", tick);
139
- if (pending !== undefined)
140
- url.searchParams.append("pending", pending.toString());
141
- // For BSV20/21, min/max price parameters have slightly different names
142
- if (minPrice !== undefined)
143
- url.searchParams.append("min_price", minPrice.toString());
144
- if (maxPrice !== undefined)
145
- url.searchParams.append("max_price", maxPrice.toString());
146
- } else {
147
- // NFT specific sort options
148
- if (sort === "recent" || sort === "price" || sort === "num") {
149
- url.searchParams.append("sort", sort);
150
- }
151
- // Add NFT-specific parameters
152
- if (origin) url.searchParams.append("origin", origin);
153
- if (mime) url.searchParams.append("mime", mime);
154
- if (num) url.searchParams.append("num", num);
155
- // For NFTs, min/max price parameters use short names
156
- if (minPrice !== undefined)
157
- url.searchParams.append("min", minPrice.toString());
158
- if (maxPrice !== undefined)
159
- url.searchParams.append("max", maxPrice.toString());
160
- }
161
-
162
- // Add common parameters
163
- if (address) url.searchParams.append("address", address);
164
-
165
- // Make the fetch request
166
- const response = await fetch(url.toString());
167
-
168
- if (!response.ok) {
169
- throw new Error(
170
- `API error: ${response.status} ${response.statusText}`,
171
- );
172
- }
173
-
174
- const data = (await response.json()) as MarketListingResponse;
175
-
176
- return {
177
- content: [
178
- {
179
- type: "text",
180
- text: JSON.stringify(data, null, 2),
181
- },
182
- ],
183
- };
184
- } catch (error) {
185
- return {
186
- content: [
187
- {
188
- type: "text",
189
- text: error instanceof Error ? error.message : String(error),
190
- },
191
- ],
192
- isError: true,
193
- };
194
- }
13
+ "Query marketplace listings for ordinals and tokens. Currently awaiting 1sat-stack marketplace API implementation.",
14
+ {},
15
+ async () => {
16
+ return {
17
+ content: [
18
+ {
19
+ type: "text",
20
+ text: JSON.stringify({
21
+ error: "Marketplace listings API not yet available on 1sat-stack",
22
+ status: "not_implemented",
23
+ }),
24
+ },
25
+ ],
26
+ isError: true,
27
+ };
195
28
  },
196
29
  );
197
30
  }