neutron-mcp 1.0.1 → 1.0.3
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 -17
- package/dist/index.js +113 -163
- package/dist/neutron-client.d.ts +4 -3
- package/dist/neutron-client.js +73 -44
- package/dist/types.d.ts +51 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,8 +42,8 @@ Add to your config file:
|
|
|
42
42
|
"command": "npx",
|
|
43
43
|
"args": ["-y", "neutron-mcp"],
|
|
44
44
|
"env": {
|
|
45
|
-
"
|
|
46
|
-
"
|
|
45
|
+
"NEUTRON_API_KEY": "your_api_key",
|
|
46
|
+
"NEUTRON_API_SECRET": "your_api_secret"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -63,8 +63,8 @@ Add to `~/.claude.json` or your project's `.mcp.json`:
|
|
|
63
63
|
"command": "npx",
|
|
64
64
|
"args": ["-y", "neutron-mcp"],
|
|
65
65
|
"env": {
|
|
66
|
-
"
|
|
67
|
-
"
|
|
66
|
+
"NEUTRON_API_KEY": "your_api_key",
|
|
67
|
+
"NEUTRON_API_SECRET": "your_api_secret"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -84,8 +84,8 @@ Add to `.cursor/mcp.json` in your project or global config:
|
|
|
84
84
|
"command": "npx",
|
|
85
85
|
"args": ["-y", "neutron-mcp"],
|
|
86
86
|
"env": {
|
|
87
|
-
"
|
|
88
|
-
"
|
|
87
|
+
"NEUTRON_API_KEY": "your_api_key",
|
|
88
|
+
"NEUTRON_API_SECRET": "your_api_secret"
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -105,8 +105,8 @@ Add to your Windsurf MCP configuration:
|
|
|
105
105
|
"command": "npx",
|
|
106
106
|
"args": ["-y", "neutron-mcp"],
|
|
107
107
|
"env": {
|
|
108
|
-
"
|
|
109
|
-
"
|
|
108
|
+
"NEUTRON_API_KEY": "your_api_key",
|
|
109
|
+
"NEUTRON_API_SECRET": "your_api_secret"
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -126,8 +126,8 @@ Add to your Cline MCP settings:
|
|
|
126
126
|
"command": "npx",
|
|
127
127
|
"args": ["-y", "neutron-mcp"],
|
|
128
128
|
"env": {
|
|
129
|
-
"
|
|
130
|
-
"
|
|
129
|
+
"NEUTRON_API_KEY": "your_api_key",
|
|
130
|
+
"NEUTRON_API_SECRET": "your_api_secret"
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -164,7 +164,7 @@ Once configured, just ask your AI assistant naturally:
|
|
|
164
164
|
|
|
165
165
|
> "Set up a webhook for transaction notifications"
|
|
166
166
|
|
|
167
|
-
> "What banks are supported for payouts in
|
|
167
|
+
> "What banks are supported for payouts in Vietnam?"
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
@@ -189,7 +189,7 @@ Once configured, just ask your AI assistant naturally:
|
|
|
189
189
|
| `neutron_create_transaction` | Create payment (Lightning, on-chain, USDT, fiat) |
|
|
190
190
|
| `neutron_list_transactions` | List transactions with filters |
|
|
191
191
|
| `neutron_get_transaction` | Get transaction status |
|
|
192
|
-
| `neutron_confirm_transaction` | Confirm
|
|
192
|
+
| `neutron_confirm_transaction` | Confirm quoted transaction |
|
|
193
193
|
| `neutron_cancel_transaction` | Cancel pending transaction |
|
|
194
194
|
|
|
195
195
|
### Webhooks
|
|
@@ -214,7 +214,7 @@ Once configured, just ask your AI assistant naturally:
|
|
|
214
214
|
| **Bitcoin Lightning** | Bolt11 invoices, LNURL, Lightning Address |
|
|
215
215
|
| **Bitcoin On-chain** | Standard BTC transactions |
|
|
216
216
|
| **Stablecoins** | USDT on Ethereum (ERC20) and Tron (TRC20) |
|
|
217
|
-
| **Fiat Payouts** | Bank transfers, Mobile money |
|
|
217
|
+
| **Fiat Payouts** | Bank transfers, Mobile money (VN, NG, KE, GH, etc.) |
|
|
218
218
|
|
|
219
219
|
---
|
|
220
220
|
|
|
@@ -227,7 +227,7 @@ Once configured, just ask your AI assistant naturally:
|
|
|
227
227
|
> "Create a payment flow where users can pay $10/month in Bitcoin. Generate a Lightning invoice and set up a webhook to activate their account when paid."
|
|
228
228
|
|
|
229
229
|
### Payout System
|
|
230
|
-
> "Build a function to pay out earnings to users
|
|
230
|
+
> "Build a function to pay out earnings to users in Vietnam. Send VND to their bank account from our BTC balance."
|
|
231
231
|
|
|
232
232
|
### Treasury Management
|
|
233
233
|
> "Show me all my wallet balances and recent transactions. Then help me consolidate funds by transferring USDT to my main wallet."
|
|
@@ -238,9 +238,9 @@ Once configured, just ask your AI assistant naturally:
|
|
|
238
238
|
|
|
239
239
|
| Variable | Required | Description |
|
|
240
240
|
|----------|----------|-------------|
|
|
241
|
-
| `
|
|
242
|
-
| `
|
|
243
|
-
| `NEUTRON_API_URL` | No | API URL (defaults to `https://
|
|
241
|
+
| `NEUTRON_API_KEY` | Yes | Your Neutron API key |
|
|
242
|
+
| `NEUTRON_API_SECRET` | Yes | Your Neutron API secret |
|
|
243
|
+
| `NEUTRON_API_URL` | No | API URL (defaults to `https://enapi.npay.dev`) |
|
|
244
244
|
|
|
245
245
|
---
|
|
246
246
|
|
package/dist/index.js
CHANGED
|
@@ -6,63 +6,26 @@ import { z } from "zod";
|
|
|
6
6
|
import { NeutronClient } from "./neutron-client.js";
|
|
7
7
|
// Validation schemas
|
|
8
8
|
const CreateTransactionSchema = z.object({
|
|
9
|
-
|
|
10
|
-
"lightning",
|
|
11
|
-
"lightning_address",
|
|
12
|
-
"lnurl",
|
|
13
|
-
"bolt11",
|
|
14
|
-
"on_chain",
|
|
15
|
-
"eth",
|
|
16
|
-
"tron",
|
|
17
|
-
"bank",
|
|
18
|
-
"mobile_money",
|
|
19
|
-
"internal",
|
|
20
|
-
]),
|
|
9
|
+
extRefId: z.string().optional(),
|
|
21
10
|
sourceCurrency: z.string(),
|
|
22
|
-
sourceAmount: z.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"lightning",
|
|
26
|
-
"lightning_address",
|
|
27
|
-
"lnurl",
|
|
28
|
-
"bolt11",
|
|
29
|
-
"on_chain",
|
|
30
|
-
"eth",
|
|
31
|
-
"tron",
|
|
32
|
-
"bank",
|
|
33
|
-
"mobile_money",
|
|
34
|
-
"internal",
|
|
35
|
-
]),
|
|
11
|
+
sourceAmount: z.number().optional(),
|
|
12
|
+
sourceMethod: z.string(),
|
|
13
|
+
sourceNotes: z.string().optional(),
|
|
36
14
|
destCurrency: z.string(),
|
|
37
|
-
destAmount: z.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
destAccountNumber: z.string().optional(),
|
|
42
|
-
destBankCode: z.string().optional(),
|
|
43
|
-
destPhoneNumber: z.string().optional(),
|
|
15
|
+
destAmount: z.number().optional(),
|
|
16
|
+
destMethod: z.string(),
|
|
17
|
+
destBankAcctNum: z.string().optional(),
|
|
18
|
+
destInstitutionCode: z.string().optional(),
|
|
44
19
|
destRecipientName: z.string().optional(),
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
destCountryCode: z.string().optional(),
|
|
21
|
+
destAddress: z.string().optional(),
|
|
22
|
+
kycType: z.enum(["individual", "business"]).optional(),
|
|
47
23
|
});
|
|
48
24
|
const ListTransactionsSchema = z.object({
|
|
49
25
|
status: z
|
|
50
|
-
.enum(["pending", "processing", "completed", "failed", "cancelled"])
|
|
51
|
-
.optional(),
|
|
52
|
-
method: z
|
|
53
|
-
.enum([
|
|
54
|
-
"lightning",
|
|
55
|
-
"lightning_address",
|
|
56
|
-
"lnurl",
|
|
57
|
-
"bolt11",
|
|
58
|
-
"on_chain",
|
|
59
|
-
"eth",
|
|
60
|
-
"tron",
|
|
61
|
-
"bank",
|
|
62
|
-
"mobile_money",
|
|
63
|
-
"internal",
|
|
64
|
-
])
|
|
26
|
+
.enum(["quoted", "pending", "processing", "completed", "failed", "cancelled"])
|
|
65
27
|
.optional(),
|
|
28
|
+
method: z.string().optional(),
|
|
66
29
|
currency: z.string().optional(),
|
|
67
30
|
fromDate: z.string().optional(),
|
|
68
31
|
toDate: z.string().optional(),
|
|
@@ -97,18 +60,18 @@ const UpdateWebhookSchema = z.object({
|
|
|
97
60
|
});
|
|
98
61
|
// Initialize Neutron client
|
|
99
62
|
function createClient() {
|
|
100
|
-
const apiUrl = process.env.NEUTRON_API_URL || "https://
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
if (!
|
|
104
|
-
throw new Error("
|
|
63
|
+
const apiUrl = process.env.NEUTRON_API_URL || "https://enapi.npay.dev";
|
|
64
|
+
const apiKey = process.env.NEUTRON_API_KEY;
|
|
65
|
+
const apiSecret = process.env.NEUTRON_API_SECRET;
|
|
66
|
+
if (!apiKey || !apiSecret) {
|
|
67
|
+
throw new Error("NEUTRON_API_KEY and NEUTRON_API_SECRET environment variables are required");
|
|
105
68
|
}
|
|
106
|
-
return new NeutronClient({ apiUrl,
|
|
69
|
+
return new NeutronClient({ apiUrl, apiKey, apiSecret });
|
|
107
70
|
}
|
|
108
71
|
// Create MCP server
|
|
109
72
|
const server = new Server({
|
|
110
73
|
name: "neutron-mcp-server",
|
|
111
|
-
version: "1.0.
|
|
74
|
+
version: "1.0.3",
|
|
112
75
|
}, {
|
|
113
76
|
capabilities: {
|
|
114
77
|
tools: {},
|
|
@@ -118,7 +81,7 @@ const server = new Server({
|
|
|
118
81
|
const tools = [
|
|
119
82
|
{
|
|
120
83
|
name: "neutron_get_account",
|
|
121
|
-
description: "Get Neutron account information including name,
|
|
84
|
+
description: "Get Neutron account information including display name, status, country, and timezone",
|
|
122
85
|
inputSchema: {
|
|
123
86
|
type: "object",
|
|
124
87
|
properties: {},
|
|
@@ -167,7 +130,6 @@ const tools = [
|
|
|
167
130
|
type: "string",
|
|
168
131
|
enum: ["eth", "tron"],
|
|
169
132
|
description: "Network for USDT address (eth for ERC20, tron for TRC20)",
|
|
170
|
-
default: "tron",
|
|
171
133
|
},
|
|
172
134
|
},
|
|
173
135
|
required: [],
|
|
@@ -175,106 +137,75 @@ const tools = [
|
|
|
175
137
|
},
|
|
176
138
|
{
|
|
177
139
|
name: "neutron_create_transaction",
|
|
178
|
-
description: `Create a new transaction. Supports Lightning payments
|
|
140
|
+
description: `Create a new transaction. Supports Lightning payments, Bitcoin on-chain, USDT, and fiat payouts.
|
|
179
141
|
|
|
180
|
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
142
|
+
Example for VND bank payout:
|
|
143
|
+
- sourceCurrency: "BTC", sourceMethod: "lightning", sourceAmount: 0.001
|
|
144
|
+
- destCurrency: "VND", destMethod: "vnd-instant", destAmount: 300000
|
|
145
|
+
- destBankAcctNum: "0123456789", destInstitutionCode: "970422"
|
|
146
|
+
- destRecipientName: "NGUYEN VAN A", destCountryCode: "VN"`,
|
|
185
147
|
inputSchema: {
|
|
186
148
|
type: "object",
|
|
187
149
|
properties: {
|
|
188
|
-
|
|
150
|
+
extRefId: {
|
|
189
151
|
type: "string",
|
|
190
|
-
|
|
191
|
-
"lightning",
|
|
192
|
-
"lightning_address",
|
|
193
|
-
"lnurl",
|
|
194
|
-
"bolt11",
|
|
195
|
-
"on_chain",
|
|
196
|
-
"eth",
|
|
197
|
-
"tron",
|
|
198
|
-
"bank",
|
|
199
|
-
"mobile_money",
|
|
200
|
-
"internal",
|
|
201
|
-
],
|
|
202
|
-
description: "Source funding method",
|
|
152
|
+
description: "Your external reference ID for tracking",
|
|
203
153
|
},
|
|
204
154
|
sourceCurrency: {
|
|
205
155
|
type: "string",
|
|
206
|
-
description: "Source currency (BTC, USDT,
|
|
156
|
+
description: "Source currency (BTC, USDT, etc.)",
|
|
207
157
|
},
|
|
208
158
|
sourceAmount: {
|
|
209
|
-
type: "
|
|
210
|
-
description: "Amount
|
|
159
|
+
type: "number",
|
|
160
|
+
description: "Amount from source",
|
|
211
161
|
},
|
|
212
|
-
|
|
162
|
+
sourceMethod: {
|
|
213
163
|
type: "string",
|
|
214
|
-
description: "
|
|
164
|
+
description: "Source method (lightning, on_chain, internal, etc.)",
|
|
215
165
|
},
|
|
216
|
-
|
|
166
|
+
sourceNotes: {
|
|
217
167
|
type: "string",
|
|
218
|
-
|
|
219
|
-
"lightning",
|
|
220
|
-
"lightning_address",
|
|
221
|
-
"lnurl",
|
|
222
|
-
"bolt11",
|
|
223
|
-
"on_chain",
|
|
224
|
-
"eth",
|
|
225
|
-
"tron",
|
|
226
|
-
"bank",
|
|
227
|
-
"mobile_money",
|
|
228
|
-
"internal",
|
|
229
|
-
],
|
|
230
|
-
description: "Destination payout method",
|
|
168
|
+
description: "Notes for the source transaction",
|
|
231
169
|
},
|
|
232
170
|
destCurrency: {
|
|
233
171
|
type: "string",
|
|
234
|
-
description: "Destination currency",
|
|
172
|
+
description: "Destination currency (VND, USD, BTC, etc.)",
|
|
235
173
|
},
|
|
236
174
|
destAmount: {
|
|
237
|
-
type: "
|
|
238
|
-
description: "Amount to
|
|
239
|
-
},
|
|
240
|
-
destAddress: {
|
|
241
|
-
type: "string",
|
|
242
|
-
description: "Destination address (for on_chain, eth, tron)",
|
|
243
|
-
},
|
|
244
|
-
destLightningAddress: {
|
|
245
|
-
type: "string",
|
|
246
|
-
description: "Lightning address (e.g., user@wallet.me)",
|
|
175
|
+
type: "number",
|
|
176
|
+
description: "Amount to destination",
|
|
247
177
|
},
|
|
248
|
-
|
|
178
|
+
destMethod: {
|
|
249
179
|
type: "string",
|
|
250
|
-
description: "
|
|
180
|
+
description: "Destination method (vnd-instant, lightning, on_chain, tron, etc.)",
|
|
251
181
|
},
|
|
252
|
-
|
|
182
|
+
destBankAcctNum: {
|
|
253
183
|
type: "string",
|
|
254
184
|
description: "Bank account number (for bank payouts)",
|
|
255
185
|
},
|
|
256
|
-
|
|
186
|
+
destInstitutionCode: {
|
|
257
187
|
type: "string",
|
|
258
|
-
description: "Bank code
|
|
188
|
+
description: "Bank/institution code",
|
|
259
189
|
},
|
|
260
|
-
|
|
190
|
+
destRecipientName: {
|
|
261
191
|
type: "string",
|
|
262
|
-
description: "
|
|
192
|
+
description: "Recipient full legal name (for fiat payouts)",
|
|
263
193
|
},
|
|
264
|
-
|
|
194
|
+
destCountryCode: {
|
|
265
195
|
type: "string",
|
|
266
|
-
description: "
|
|
196
|
+
description: "Destination country code (VN, NG, etc.)",
|
|
267
197
|
},
|
|
268
|
-
|
|
198
|
+
destAddress: {
|
|
269
199
|
type: "string",
|
|
270
|
-
description: "
|
|
200
|
+
description: "Crypto address (for on_chain, tron, eth)",
|
|
271
201
|
},
|
|
272
|
-
|
|
202
|
+
kycType: {
|
|
273
203
|
type: "string",
|
|
274
|
-
|
|
204
|
+
enum: ["individual", "business"],
|
|
205
|
+
description: "KYC type for recipient",
|
|
275
206
|
},
|
|
276
207
|
},
|
|
277
|
-
required: ["
|
|
208
|
+
required: ["sourceCurrency", "sourceMethod", "destCurrency", "destMethod"],
|
|
278
209
|
},
|
|
279
210
|
},
|
|
280
211
|
{
|
|
@@ -285,23 +216,18 @@ Examples:
|
|
|
285
216
|
properties: {
|
|
286
217
|
status: {
|
|
287
218
|
type: "string",
|
|
288
|
-
enum: [
|
|
219
|
+
enum: [
|
|
220
|
+
"quoted",
|
|
221
|
+
"pending",
|
|
222
|
+
"processing",
|
|
223
|
+
"completed",
|
|
224
|
+
"failed",
|
|
225
|
+
"cancelled",
|
|
226
|
+
],
|
|
289
227
|
description: "Filter by transaction status",
|
|
290
228
|
},
|
|
291
229
|
method: {
|
|
292
230
|
type: "string",
|
|
293
|
-
enum: [
|
|
294
|
-
"lightning",
|
|
295
|
-
"lightning_address",
|
|
296
|
-
"lnurl",
|
|
297
|
-
"bolt11",
|
|
298
|
-
"on_chain",
|
|
299
|
-
"eth",
|
|
300
|
-
"tron",
|
|
301
|
-
"bank",
|
|
302
|
-
"mobile_money",
|
|
303
|
-
"internal",
|
|
304
|
-
],
|
|
305
231
|
description: "Filter by transaction method",
|
|
306
232
|
},
|
|
307
233
|
currency: {
|
|
@@ -318,7 +244,7 @@ Examples:
|
|
|
318
244
|
},
|
|
319
245
|
limit: {
|
|
320
246
|
type: "number",
|
|
321
|
-
description: "Number of results to return
|
|
247
|
+
description: "Number of results to return",
|
|
322
248
|
},
|
|
323
249
|
offset: {
|
|
324
250
|
type: "number",
|
|
@@ -336,7 +262,7 @@ Examples:
|
|
|
336
262
|
properties: {
|
|
337
263
|
transactionId: {
|
|
338
264
|
type: "string",
|
|
339
|
-
description: "The transaction ID to check",
|
|
265
|
+
description: "The transaction ID (txnId) to check",
|
|
340
266
|
},
|
|
341
267
|
},
|
|
342
268
|
required: ["transactionId"],
|
|
@@ -344,7 +270,7 @@ Examples:
|
|
|
344
270
|
},
|
|
345
271
|
{
|
|
346
272
|
name: "neutron_confirm_transaction",
|
|
347
|
-
description: "Confirm a
|
|
273
|
+
description: "Confirm a quoted transaction to proceed with execution",
|
|
348
274
|
inputSchema: {
|
|
349
275
|
type: "object",
|
|
350
276
|
properties: {
|
|
@@ -358,7 +284,7 @@ Examples:
|
|
|
358
284
|
},
|
|
359
285
|
{
|
|
360
286
|
name: "neutron_cancel_transaction",
|
|
361
|
-
description: "Cancel a pending transaction",
|
|
287
|
+
description: "Cancel a pending or quoted transaction",
|
|
362
288
|
inputSchema: {
|
|
363
289
|
type: "object",
|
|
364
290
|
properties: {
|
|
@@ -468,7 +394,7 @@ Examples:
|
|
|
468
394
|
properties: {
|
|
469
395
|
country: {
|
|
470
396
|
type: "string",
|
|
471
|
-
description: "Country code (ISO 3166-1 alpha-2, e.g., NG, KE, GH)",
|
|
397
|
+
description: "Country code (ISO 3166-1 alpha-2, e.g., VN, NG, KE, GH)",
|
|
472
398
|
},
|
|
473
399
|
},
|
|
474
400
|
required: ["country"],
|
|
@@ -519,30 +445,42 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
519
445
|
}
|
|
520
446
|
case "neutron_create_transaction": {
|
|
521
447
|
const validated = CreateTransactionSchema.parse(args);
|
|
448
|
+
const reqDetails = {};
|
|
449
|
+
if (validated.destBankAcctNum)
|
|
450
|
+
reqDetails.bankAcctNum = validated.destBankAcctNum;
|
|
451
|
+
if (validated.destInstitutionCode)
|
|
452
|
+
reqDetails.institutionCode = validated.destInstitutionCode;
|
|
453
|
+
if (validated.destAddress)
|
|
454
|
+
reqDetails.address = validated.destAddress;
|
|
522
455
|
const transaction = await client.createTransaction({
|
|
456
|
+
extRefId: validated.extRefId,
|
|
523
457
|
sourceReq: {
|
|
458
|
+
ccy: validated.sourceCurrency,
|
|
459
|
+
amtRequested: validated.sourceAmount,
|
|
524
460
|
method: validated.sourceMethod,
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
walletId: validated.sourceWalletId,
|
|
461
|
+
notes: validated.sourceNotes,
|
|
462
|
+
reqDetails: {},
|
|
528
463
|
},
|
|
529
464
|
destReq: {
|
|
465
|
+
ccy: validated.destCurrency,
|
|
466
|
+
amtRequested: validated.destAmount,
|
|
530
467
|
method: validated.destMethod,
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
468
|
+
reqDetails,
|
|
469
|
+
kyc: validated.kycType
|
|
470
|
+
? {
|
|
471
|
+
type: validated.kycType,
|
|
472
|
+
details: {
|
|
473
|
+
legalFullName: validated.destRecipientName,
|
|
474
|
+
countryCode: validated.destCountryCode,
|
|
475
|
+
},
|
|
476
|
+
}
|
|
477
|
+
: undefined,
|
|
541
478
|
},
|
|
542
|
-
reference: validated.reference,
|
|
543
479
|
});
|
|
544
480
|
return {
|
|
545
|
-
content: [
|
|
481
|
+
content: [
|
|
482
|
+
{ type: "text", text: JSON.stringify(transaction, null, 2) },
|
|
483
|
+
],
|
|
546
484
|
};
|
|
547
485
|
}
|
|
548
486
|
case "neutron_list_transactions": {
|
|
@@ -557,28 +495,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
557
495
|
offset: validated.offset,
|
|
558
496
|
});
|
|
559
497
|
return {
|
|
560
|
-
content: [
|
|
498
|
+
content: [
|
|
499
|
+
{ type: "text", text: JSON.stringify(transactions, null, 2) },
|
|
500
|
+
],
|
|
561
501
|
};
|
|
562
502
|
}
|
|
563
503
|
case "neutron_get_transaction": {
|
|
564
504
|
const { transactionId } = args;
|
|
565
|
-
const transaction = await client.
|
|
505
|
+
const transaction = await client.getTransaction(transactionId);
|
|
566
506
|
return {
|
|
567
|
-
content: [
|
|
507
|
+
content: [
|
|
508
|
+
{ type: "text", text: JSON.stringify(transaction, null, 2) },
|
|
509
|
+
],
|
|
568
510
|
};
|
|
569
511
|
}
|
|
570
512
|
case "neutron_confirm_transaction": {
|
|
571
513
|
const { transactionId } = args;
|
|
572
514
|
const transaction = await client.confirmTransaction(transactionId);
|
|
573
515
|
return {
|
|
574
|
-
content: [
|
|
516
|
+
content: [
|
|
517
|
+
{ type: "text", text: JSON.stringify(transaction, null, 2) },
|
|
518
|
+
],
|
|
575
519
|
};
|
|
576
520
|
}
|
|
577
521
|
case "neutron_cancel_transaction": {
|
|
578
522
|
const { transactionId } = args;
|
|
579
523
|
const transaction = await client.cancelTransaction(transactionId);
|
|
580
524
|
return {
|
|
581
|
-
content: [
|
|
525
|
+
content: [
|
|
526
|
+
{ type: "text", text: JSON.stringify(transaction, null, 2) },
|
|
527
|
+
],
|
|
582
528
|
};
|
|
583
529
|
}
|
|
584
530
|
case "neutron_create_webhook": {
|
|
@@ -612,14 +558,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
612
558
|
const { webhookId } = args;
|
|
613
559
|
await client.deleteWebhook(webhookId);
|
|
614
560
|
return {
|
|
615
|
-
content: [
|
|
561
|
+
content: [
|
|
562
|
+
{ type: "text", text: `Webhook ${webhookId} deleted successfully` },
|
|
563
|
+
],
|
|
616
564
|
};
|
|
617
565
|
}
|
|
618
566
|
case "neutron_get_fiat_institutions": {
|
|
619
567
|
const { country } = args;
|
|
620
568
|
const institutions = await client.getFiatInstitutions(country);
|
|
621
569
|
return {
|
|
622
|
-
content: [
|
|
570
|
+
content: [
|
|
571
|
+
{ type: "text", text: JSON.stringify(institutions, null, 2) },
|
|
572
|
+
],
|
|
623
573
|
};
|
|
624
574
|
}
|
|
625
575
|
default:
|
package/dist/neutron-client.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { NeutronConfig, Account, Wallet, ReceiveAddress, Transaction, CreateTransactionRequest, TransactionListParams, TransactionListResponse, Webhook, CreateWebhookRequest, UpdateWebhookRequest, FiatInstitution } from "./types.js";
|
|
2
2
|
export declare class NeutronClient {
|
|
3
3
|
private config;
|
|
4
|
-
private
|
|
4
|
+
private accountId;
|
|
5
|
+
private accessToken;
|
|
5
6
|
private tokenExpiry;
|
|
6
7
|
constructor(config: NeutronConfig);
|
|
7
8
|
private generateSignature;
|
|
9
|
+
private ensureAuthenticated;
|
|
8
10
|
private request;
|
|
9
|
-
authenticate(): Promise<void>;
|
|
10
11
|
getAccount(): Promise<Account>;
|
|
11
12
|
getWallets(): Promise<Wallet[]>;
|
|
12
13
|
getWallet(walletId: string): Promise<Wallet>;
|
|
@@ -14,7 +15,7 @@ export declare class NeutronClient {
|
|
|
14
15
|
getUsdtAddress(network?: "eth" | "tron"): Promise<ReceiveAddress>;
|
|
15
16
|
createTransaction(request: CreateTransactionRequest): Promise<Transaction>;
|
|
16
17
|
getTransactions(params?: TransactionListParams): Promise<TransactionListResponse>;
|
|
17
|
-
|
|
18
|
+
getTransaction(transactionId: string): Promise<Transaction>;
|
|
18
19
|
confirmTransaction(transactionId: string): Promise<Transaction>;
|
|
19
20
|
cancelTransaction(transactionId: string): Promise<Transaction>;
|
|
20
21
|
createWebhook(request: CreateWebhookRequest): Promise<Webhook>;
|
package/dist/neutron-client.js
CHANGED
|
@@ -1,75 +1,96 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
2
|
export class NeutronClient {
|
|
3
3
|
config;
|
|
4
|
-
|
|
4
|
+
accountId = null;
|
|
5
|
+
accessToken = null;
|
|
5
6
|
tokenExpiry = 0;
|
|
6
7
|
constructor(config) {
|
|
7
8
|
this.config = config;
|
|
8
9
|
}
|
|
9
|
-
generateSignature(
|
|
10
|
-
|
|
10
|
+
generateSignature(payload) {
|
|
11
|
+
// HMAC-SHA256 signature: {apiKey}&payload={payload}
|
|
12
|
+
const stringToSign = `${this.config.apiKey}&payload=${payload}`;
|
|
11
13
|
return crypto
|
|
12
|
-
.createHmac("sha256", this.config.
|
|
13
|
-
.update(
|
|
14
|
+
.createHmac("sha256", this.config.apiSecret)
|
|
15
|
+
.update(stringToSign)
|
|
14
16
|
.digest("hex");
|
|
15
17
|
}
|
|
18
|
+
async ensureAuthenticated() {
|
|
19
|
+
// Check if we have a valid token
|
|
20
|
+
if (this.accessToken && this.accountId && Date.now() < this.tokenExpiry) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Authenticate to get accountId and accessToken
|
|
24
|
+
const payload = JSON.stringify({ test: "auth" });
|
|
25
|
+
const signature = this.generateSignature(payload);
|
|
26
|
+
const response = await fetch(`${this.config.apiUrl}/api/v2/authentication/token-signature`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"X-Api-Key": this.config.apiKey,
|
|
31
|
+
"X-Api-Signature": signature,
|
|
32
|
+
},
|
|
33
|
+
body: payload,
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const error = await response.json().catch(() => ({}));
|
|
37
|
+
throw new Error(`Authentication failed: ${response.status} - ${error.message || response.statusText}`);
|
|
38
|
+
}
|
|
39
|
+
const authResult = (await response.json());
|
|
40
|
+
this.accountId = authResult.accountId;
|
|
41
|
+
this.accessToken = authResult.accessToken;
|
|
42
|
+
// Set expiry (parse the expiredAt or default to 1 hour)
|
|
43
|
+
this.tokenExpiry = authResult.expiredAt
|
|
44
|
+
? new Date(authResult.expiredAt).getTime()
|
|
45
|
+
: Date.now() + 3600000;
|
|
46
|
+
}
|
|
16
47
|
async request(method, path, body) {
|
|
17
|
-
|
|
18
|
-
const bodyString = body ? JSON.stringify(body) : undefined;
|
|
19
|
-
const signature = this.generateSignature(method, path, timestamp, bodyString);
|
|
48
|
+
await this.ensureAuthenticated();
|
|
20
49
|
const headers = {
|
|
21
50
|
"Content-Type": "application/json",
|
|
22
|
-
|
|
23
|
-
"X-Timestamp": timestamp,
|
|
24
|
-
"X-Signature": signature,
|
|
51
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
25
52
|
};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
headers["Authorization"] = `Bearer ${this.token}`;
|
|
29
|
-
}
|
|
30
|
-
const response = await fetch(`${this.config.apiUrl}${path}`, {
|
|
53
|
+
const url = `${this.config.apiUrl}${path}`;
|
|
54
|
+
const response = await fetch(url, {
|
|
31
55
|
method,
|
|
32
56
|
headers,
|
|
33
|
-
body:
|
|
57
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
34
58
|
});
|
|
35
59
|
if (!response.ok) {
|
|
36
60
|
const error = await response.json().catch(() => ({}));
|
|
37
61
|
throw new Error(`API Error: ${response.status} - ${error.message || response.statusText}`);
|
|
38
62
|
}
|
|
39
|
-
|
|
40
|
-
if (!result.success && result.error) {
|
|
41
|
-
throw new Error(`${result.error.code}: ${result.error.message}`);
|
|
42
|
-
}
|
|
43
|
-
return result.data;
|
|
44
|
-
}
|
|
45
|
-
// Authentication
|
|
46
|
-
async authenticate() {
|
|
47
|
-
const result = await this.request("POST", "/authenticate");
|
|
48
|
-
this.token = result.token;
|
|
49
|
-
this.tokenExpiry = Date.now() + result.expiresIn * 1000;
|
|
63
|
+
return (await response.json());
|
|
50
64
|
}
|
|
51
65
|
// Account Management
|
|
52
66
|
async getAccount() {
|
|
53
|
-
|
|
67
|
+
await this.ensureAuthenticated();
|
|
68
|
+
return this.request("GET", `/api/v2/account/${this.accountId}`);
|
|
54
69
|
}
|
|
55
70
|
async getWallets() {
|
|
56
|
-
|
|
71
|
+
await this.ensureAuthenticated();
|
|
72
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/wallets`);
|
|
57
73
|
}
|
|
58
74
|
async getWallet(walletId) {
|
|
59
|
-
|
|
75
|
+
await this.ensureAuthenticated();
|
|
76
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/wallet/${walletId}`);
|
|
60
77
|
}
|
|
61
78
|
// Receive Addresses
|
|
62
79
|
async getBitcoinAddress() {
|
|
63
|
-
|
|
80
|
+
await this.ensureAuthenticated();
|
|
81
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/bitcoin/receive-address`);
|
|
64
82
|
}
|
|
65
83
|
async getUsdtAddress(network = "tron") {
|
|
66
|
-
|
|
84
|
+
await this.ensureAuthenticated();
|
|
85
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/usdt/receive-address?network=${network}`);
|
|
67
86
|
}
|
|
68
87
|
// Transactions
|
|
69
88
|
async createTransaction(request) {
|
|
70
|
-
|
|
89
|
+
await this.ensureAuthenticated();
|
|
90
|
+
return this.request("POST", `/api/v2/account/${this.accountId}/transaction`, request);
|
|
71
91
|
}
|
|
72
92
|
async getTransactions(params) {
|
|
93
|
+
await this.ensureAuthenticated();
|
|
73
94
|
const queryParams = new URLSearchParams();
|
|
74
95
|
if (params) {
|
|
75
96
|
Object.entries(params).forEach(([key, value]) => {
|
|
@@ -79,32 +100,40 @@ export class NeutronClient {
|
|
|
79
100
|
});
|
|
80
101
|
}
|
|
81
102
|
const query = queryParams.toString();
|
|
82
|
-
return this.request("GET", `/transactions${query ? `?${query}` : ""}`);
|
|
103
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/transactions${query ? `?${query}` : ""}`);
|
|
83
104
|
}
|
|
84
|
-
async
|
|
85
|
-
|
|
105
|
+
async getTransaction(transactionId) {
|
|
106
|
+
await this.ensureAuthenticated();
|
|
107
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/transaction/${transactionId}`);
|
|
86
108
|
}
|
|
87
109
|
async confirmTransaction(transactionId) {
|
|
88
|
-
|
|
110
|
+
await this.ensureAuthenticated();
|
|
111
|
+
return this.request("PUT", `/api/v2/account/${this.accountId}/transaction/${transactionId}/confirm`);
|
|
89
112
|
}
|
|
90
113
|
async cancelTransaction(transactionId) {
|
|
91
|
-
|
|
114
|
+
await this.ensureAuthenticated();
|
|
115
|
+
return this.request("DELETE", `/api/v2/account/${this.accountId}/transaction/${transactionId}`);
|
|
92
116
|
}
|
|
93
117
|
// Webhooks
|
|
94
118
|
async createWebhook(request) {
|
|
95
|
-
|
|
119
|
+
await this.ensureAuthenticated();
|
|
120
|
+
return this.request("POST", `/api/v2/account/${this.accountId}/webhook`, request);
|
|
96
121
|
}
|
|
97
122
|
async getWebhooks() {
|
|
98
|
-
|
|
123
|
+
await this.ensureAuthenticated();
|
|
124
|
+
return this.request("GET", `/api/v2/account/${this.accountId}/webhooks`);
|
|
99
125
|
}
|
|
100
126
|
async updateWebhook(webhookId, request) {
|
|
101
|
-
|
|
127
|
+
await this.ensureAuthenticated();
|
|
128
|
+
return this.request("PUT", `/api/v2/account/${this.accountId}/webhook/${webhookId}`, request);
|
|
102
129
|
}
|
|
103
130
|
async deleteWebhook(webhookId) {
|
|
104
|
-
await this.
|
|
131
|
+
await this.ensureAuthenticated();
|
|
132
|
+
await this.request("DELETE", `/api/v2/account/${this.accountId}/webhook/${webhookId}`);
|
|
105
133
|
}
|
|
106
134
|
// Reference Data
|
|
107
135
|
async getFiatInstitutions(country) {
|
|
108
|
-
|
|
136
|
+
await this.ensureAuthenticated();
|
|
137
|
+
return this.request("GET", `/api/v2/reference/fiat-institutions/${country}`);
|
|
109
138
|
}
|
|
110
139
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
export interface NeutronConfig {
|
|
2
2
|
apiUrl: string;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiSecret: string;
|
|
5
|
+
}
|
|
6
|
+
export interface AuthResponse {
|
|
7
|
+
accountId: string;
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken: string;
|
|
10
|
+
expiredAt: string;
|
|
11
|
+
scope: string;
|
|
5
12
|
}
|
|
6
13
|
export interface Account {
|
|
7
14
|
id: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
parentId?: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
accountStatus: string;
|
|
18
|
+
countryCode: string;
|
|
19
|
+
timezone: string;
|
|
11
20
|
createdAt: string;
|
|
21
|
+
updatedAt: string;
|
|
12
22
|
}
|
|
13
23
|
export interface Wallet {
|
|
14
24
|
id: string;
|
|
@@ -23,62 +33,49 @@ export interface ReceiveAddress {
|
|
|
23
33
|
network?: string;
|
|
24
34
|
expiresAt?: string;
|
|
25
35
|
}
|
|
26
|
-
export type TransactionMethod = "lightning" | "lightning_address" | "lnurl" | "bolt11" | "on_chain" | "eth" | "tron" | "bank" | "mobile_money" | "internal";
|
|
27
|
-
export type
|
|
28
|
-
export interface
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
export type TransactionMethod = "lightning" | "lightning_address" | "lnurl" | "bolt11" | "on_chain" | "eth" | "tron" | "bank" | "mobile_money" | "vnd-instant" | "internal";
|
|
37
|
+
export type TransactionState = "quoted" | "pending" | "processing" | "completed" | "failed" | "cancelled";
|
|
38
|
+
export interface TransactionSourceReq {
|
|
39
|
+
ccy: string;
|
|
40
|
+
amtRequested?: number;
|
|
41
|
+
method: string;
|
|
42
|
+
notes?: string;
|
|
43
|
+
reqDetails?: Record<string, unknown>;
|
|
33
44
|
}
|
|
34
|
-
export interface
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
phoneNumber?: string;
|
|
44
|
-
recipientName?: string;
|
|
45
|
-
country?: string;
|
|
45
|
+
export interface TransactionDestReq {
|
|
46
|
+
ccy: string;
|
|
47
|
+
amtRequested?: number;
|
|
48
|
+
method: string;
|
|
49
|
+
reqDetails?: Record<string, unknown>;
|
|
50
|
+
kyc?: {
|
|
51
|
+
type: "individual" | "business";
|
|
52
|
+
details: Record<string, unknown>;
|
|
53
|
+
};
|
|
46
54
|
}
|
|
47
55
|
export interface CreateTransactionRequest {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
extRefId?: string;
|
|
57
|
+
sourceReq: TransactionSourceReq;
|
|
58
|
+
destReq: TransactionDestReq;
|
|
59
|
+
sourceOfFunds?: {
|
|
60
|
+
purpose?: number;
|
|
61
|
+
source?: number;
|
|
62
|
+
relationship?: number;
|
|
63
|
+
};
|
|
52
64
|
}
|
|
53
65
|
export interface Transaction {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
destination: {
|
|
63
|
-
method: TransactionMethod;
|
|
64
|
-
currency: string;
|
|
65
|
-
amount: string;
|
|
66
|
-
address?: string;
|
|
67
|
-
};
|
|
68
|
-
fees: {
|
|
69
|
-
amount: string;
|
|
70
|
-
currency: string;
|
|
71
|
-
};
|
|
72
|
-
exchangeRate?: string;
|
|
73
|
-
paymentRequest?: string;
|
|
74
|
-
createdAt: string;
|
|
75
|
-
updatedAt: string;
|
|
66
|
+
txnId: string;
|
|
67
|
+
extRefId?: string;
|
|
68
|
+
txnState: TransactionState;
|
|
69
|
+
fxRate?: number;
|
|
70
|
+
sourceReq: TransactionSourceReq;
|
|
71
|
+
destReq: TransactionDestReq;
|
|
72
|
+
createdAt?: string;
|
|
73
|
+
updatedAt?: string;
|
|
76
74
|
completedAt?: string;
|
|
77
|
-
metadata?: Record<string, unknown>;
|
|
78
75
|
}
|
|
79
76
|
export interface TransactionListParams {
|
|
80
|
-
status?:
|
|
81
|
-
method?:
|
|
77
|
+
status?: TransactionState;
|
|
78
|
+
method?: string;
|
|
82
79
|
currency?: string;
|
|
83
80
|
fromDate?: string;
|
|
84
81
|
toDate?: string;
|
|
@@ -96,7 +93,7 @@ export interface Webhook {
|
|
|
96
93
|
id: string;
|
|
97
94
|
url: string;
|
|
98
95
|
events: WebhookEvent[];
|
|
99
|
-
secret
|
|
96
|
+
secret?: string;
|
|
100
97
|
status: "active" | "inactive";
|
|
101
98
|
createdAt: string;
|
|
102
99
|
}
|
|
@@ -116,11 +113,3 @@ export interface FiatInstitution {
|
|
|
116
113
|
type: "bank" | "mobile_money";
|
|
117
114
|
supportedCurrencies: string[];
|
|
118
115
|
}
|
|
119
|
-
export interface ApiResponse<T> {
|
|
120
|
-
success: boolean;
|
|
121
|
-
data?: T;
|
|
122
|
-
error?: {
|
|
123
|
-
code: string;
|
|
124
|
-
message: string;
|
|
125
|
-
};
|
|
126
|
-
}
|