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