cryptoiz-mcp 4.16.8 → 4.16.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +132 -22
  2. package/package.json +15 -5
  3. package/setup.js +0 -0
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
- var VERSION = 'v4.16.8';
2
+ var VERSION = 'v4.16.10';
3
3
  var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
4
4
  var TOOL_ENDPOINTS = {
5
5
  get_whale_alpha: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-alpha-scanner',
@@ -18,6 +18,7 @@ var SOL_RPC = 'https://api.mainnet-beta.solana.com';
18
18
  var TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
19
19
  var ATA_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
20
20
  var MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
21
+ var COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';
21
22
 
22
23
  var _updateNotified = false;
23
24
  function notifyUpdate(data, headers) {
@@ -29,11 +30,16 @@ function notifyUpdate(data, headers) {
29
30
  console.error('[cryptoiz-mcp] UPDATE: ' + VERSION + ' -> ' + latest + ' | Run: ' + cmd);
30
31
  }
31
32
 
32
- var Connection = require('@solana/web3.js').Connection;
33
- var PublicKey = require('@solana/web3.js').PublicKey;
34
- var Transaction = require('@solana/web3.js').Transaction;
35
- var Keypair = require('@solana/web3.js').Keypair;
36
- var _bs58mod = require('bs58'); var bs58 = _bs58mod.default || _bs58mod;
33
+ var solana = require('@solana/web3.js');
34
+ var Connection = solana.Connection;
35
+ var PublicKey = solana.PublicKey;
36
+ var Transaction = solana.Transaction;
37
+ var TransactionMessage = solana.TransactionMessage;
38
+ var VersionedTransaction = solana.VersionedTransaction;
39
+ var Keypair = solana.Keypair;
40
+ // Fix bs58 v6 ESM-only issue: support both CJS (v5) and ESM-compiled (v6)
41
+ var _bs58mod = require('bs58');
42
+ var bs58 = _bs58mod.default || _bs58mod;
37
43
  var Server = require('@modelcontextprotocol/sdk/server/index.js').Server;
38
44
  var StdioServerTransport = require('@modelcontextprotocol/sdk/server/stdio.js').StdioServerTransport;
39
45
  var CallToolRequestSchema = require('@modelcontextprotocol/sdk/types.js').CallToolRequestSchema;
@@ -53,27 +59,75 @@ function findATA(wallet, mint) {
53
59
  return PublicKey.findProgramAddressSync([walletPk.toBuffer(), tokPk.toBuffer(), mintPk.toBuffer()], ataPk)[0];
54
60
  }
55
61
 
56
- // V1: direct on-chain USDC transfer + x402 memo for indexer
62
+ // V2: Dexter gas-sponsored. 4-ix tx: Limit + Price + TransferChecked + Memo(nonce)
63
+ // Dexter pays SOL gas — user only needs USDC
64
+ async function buildV2PaymentPayload(amount, feePayerAddr) {
65
+ var kp = getKeypair();
66
+ var conn = new Connection(SOL_RPC, 'confirmed');
67
+ var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
68
+ var recipientATA = findATA(RECIPIENT, USDC_MINT);
69
+ var feePayerPk = new PublicKey(feePayerAddr);
70
+ var computeBudgetPk = new PublicKey(COMPUTE_BUDGET_PROGRAM);
71
+ var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
72
+ var usdcMintPk = new PublicKey(USDC_MINT);
73
+ // ComputeUnitLimit(20000)
74
+ var setLimitData = Buffer.alloc(5);
75
+ setLimitData[0] = 0x02;
76
+ setLimitData.writeUInt32LE(20000, 1);
77
+ var setLimitIx = { programId: computeBudgetPk, keys: [], data: setLimitData };
78
+ // ComputeUnitPrice(1)
79
+ var setPriceData = Buffer.alloc(9);
80
+ setPriceData[0] = 0x03;
81
+ setPriceData.writeBigUInt64LE(BigInt(1), 1);
82
+ var setPriceIx = { programId: computeBudgetPk, keys: [], data: setPriceData };
83
+ // TransferChecked
84
+ var transferKeys = [
85
+ { pubkey: userATA, isSigner: false, isWritable: true },
86
+ { pubkey: usdcMintPk, isSigner: false, isWritable: false },
87
+ { pubkey: recipientATA, isSigner: false, isWritable: true },
88
+ { pubkey: kp.publicKey, isSigner: true, isWritable: false },
89
+ ];
90
+ var transferData = Buffer.alloc(10);
91
+ transferData[0] = 0x0c;
92
+ transferData.writeUInt32LE(amount & 0xFFFFFFFF, 1);
93
+ transferData.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
94
+ transferData[9] = 6;
95
+ var transferIx = { programId: tokenProgramPk, keys: transferKeys, data: transferData };
96
+ // FIX v4.16.10: NO Memo instruction in V2 — Dexter scheme_exact_svm whitelist
97
+ // only allows ComputeBudget + SPL Token + Lighthouse. Memo would be rejected.
98
+ var bh = await conn.getLatestBlockhash('confirmed');
99
+ var message = new TransactionMessage({
100
+ payerKey: feePayerPk,
101
+ recentBlockhash: bh.blockhash,
102
+ instructions: [setLimitIx, setPriceIx, transferIx],
103
+ }).compileToV0Message();
104
+ var vtx = new VersionedTransaction(message);
105
+ vtx.sign([kp]);
106
+ var txB64 = Buffer.from(vtx.serialize()).toString('base64');
107
+ console.error('[cryptoiz-mcp] V2 tx built (Dexter gas-sponsored), 3 ix: limit+price+transferChecked');
108
+ return txB64;
109
+ }
110
+
111
+ // V1: direct on-chain, user pays SOL gas (fallback only)
57
112
  async function sendUSDC(amount, toolName) {
58
113
  var kp = getKeypair();
59
114
  var conn = new Connection(SOL_RPC, 'confirmed');
60
115
  var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
61
116
  var recipientATA = findATA(RECIPIENT, USDC_MINT);
62
- // TransferChecked ix
63
117
  var keys = [
64
118
  { pubkey: userATA, isSigner: false, isWritable: true },
65
119
  { pubkey: new PublicKey(USDC_MINT), isSigner: false, isWritable: false },
66
120
  { pubkey: recipientATA, isSigner: false, isWritable: true },
67
121
  { pubkey: kp.publicKey, isSigner: true, isWritable: false },
68
122
  ];
69
- var data = Buffer.alloc(9);
123
+ // FIX v4.16.10: TransferChecked needs 10 bytes (1 disc + 8 amount + 1 decimals)
124
+ var data = Buffer.alloc(10);
70
125
  data[0] = 0x0c;
71
126
  data.writeUInt32LE(amount & 0xFFFFFFFF, 1);
72
127
  data.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
73
- data[8] = 6;
128
+ data[9] = 6;
74
129
  var transferIx = { programId: new PublicKey(TOKEN_PROGRAM), keys: keys, data: data };
75
- // Memo ix for x402scan indexer
76
- var nonce = Date.now().toString(16) + Math.floor(Math.random() * 0xffff).toString(16);
130
+ var nonce = Date.now().toString(16) + Math.floor(Math.random()*0xffff).toString(16);
77
131
  var memoIx = {
78
132
  programId: new PublicKey(MEMO_PROGRAM),
79
133
  keys: [],
@@ -86,7 +140,7 @@ async function sendUSDC(amount, toolName) {
86
140
  tx.sign(kp);
87
141
  var sig = await conn.sendRawTransaction(tx.serialize(), { skipPreflight: false });
88
142
  await conn.confirmTransaction({ signature: sig, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight }, 'confirmed');
89
- console.error('[cryptoiz-mcp] TX: ' + sig);
143
+ console.error('[cryptoiz-mcp] V1 TX: ' + sig);
90
144
  return sig;
91
145
  }
92
146
 
@@ -101,22 +155,78 @@ async function callTool(toolName, args) {
101
155
  if (toolName === 'get_whale_divergence' && args && args.timeframe) queryParts.push('tf=' + args.timeframe);
102
156
  if (toolName === 'get_token_ca' && args && args.name) queryParts.push('name=' + encodeURIComponent(args.name));
103
157
  var url = (TOOL_ENDPOINTS[toolName] || GATEWAY) + '?' + queryParts.join('&');
158
+
104
159
  // Step 1: discovery
105
160
  var resp1 = await fetch(url, { headers: clientHeaders() });
106
161
  if (resp1.status === 200) { var d = await resp1.json(); notifyUpdate(d, resp1.headers); return d; }
107
162
  if (resp1.status !== 402) throw new Error('Server error ' + resp1.status + ': ' + (await resp1.text()).substring(0, 200));
163
+
108
164
  // Step 2: parse payment requirements
109
165
  var payReq = null;
166
+ var useV2 = false;
110
167
  var prHeader = resp1.headers.get('payment-required');
111
- if (prHeader) { try { var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8')); if (arr && arr[0]) payReq = arr[0]; } catch(_e) {} }
112
- if (!payReq) { var b402 = await resp1.json(); if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0]; }
168
+ if (prHeader) {
169
+ try {
170
+ var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8'));
171
+ if (arr && arr[0]) { payReq = arr[0]; useV2 = true; }
172
+ } catch(_e) {}
173
+ }
174
+ if (!payReq) {
175
+ var b402 = await resp1.json();
176
+ if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0];
177
+ }
113
178
  if (!payReq) throw new Error('No payment requirements in 402');
179
+
114
180
  var amount = parseInt(payReq.maxAmountRequired || payReq.amount || '10000');
115
- console.error('[cryptoiz-mcp] Paying ' + (amount/1000000).toFixed(4) + ' USDC for ' + toolName);
116
- // Step 3: V1 direct transfer
117
- var sig = await sendUSDC(amount, toolName);
118
- // Step 4: submit
119
- var resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': Buffer.from(JSON.stringify({ signature: sig })).toString('base64') }) });
181
+ var hasFeePayer = payReq.extra && payReq.extra.feePayer;
182
+ var paymentHeader = '';
183
+ var headerName = '';
184
+
185
+ // Step 3: Try V2 Dexter (gas-sponsored by Dexter user only needs USDC)
186
+ if (useV2 && hasFeePayer) {
187
+ console.error('[cryptoiz-mcp] V2 mode: Dexter gas-sponsored, paying ' + (amount/1000000).toFixed(4) + ' USDC');
188
+ try {
189
+ var txB64 = await buildV2PaymentPayload(amount, payReq.extra.feePayer);
190
+ // FIX v4.16.10: x402Version:2 (was 1), add 'accepted' (chosen PaymentRequirements
191
+ // verbatim — Dexter /verify needs this to match amount/asset/payTo). Removed bogus
192
+ // signature field — V2 schema only has payload.transaction.
193
+ var v2Payload = {
194
+ x402Version: 2,
195
+ scheme: 'exact',
196
+ network: payReq.network || 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
197
+ accepted: payReq,
198
+ payload: { transaction: txB64 },
199
+ extensions: {}
200
+ };
201
+ paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
202
+ headerName = 'payment-signature';
203
+ } catch(v2Err) {
204
+ console.error('[cryptoiz-mcp] V2 build failed: ' + v2Err.message + ' -> fallback V1');
205
+ useV2 = false;
206
+ }
207
+ }
208
+
209
+ // Step 4: V1 fallback (user pays gas — only if V2 failed)
210
+ if (!paymentHeader) {
211
+ console.error('[cryptoiz-mcp] V1 fallback: direct on-chain transfer');
212
+ var sig = await sendUSDC(amount, toolName);
213
+ paymentHeader = Buffer.from(JSON.stringify({ signature: sig })).toString('base64');
214
+ headerName = 'x-payment';
215
+ }
216
+
217
+ // Step 5: submit payment
218
+ var headers2 = {};
219
+ headers2[headerName] = paymentHeader;
220
+ var resp2 = await fetch(url, { headers: clientHeaders(headers2) });
221
+
222
+ // Step 6: if V2 failed at server, retry with V1
223
+ if (resp2.status !== 200 && useV2) {
224
+ console.error('[cryptoiz-mcp] V2 settle failed, trying V1 fallback...');
225
+ var fallbackSig = await sendUSDC(amount, toolName);
226
+ var v1Header = Buffer.from(JSON.stringify({ signature: fallbackSig })).toString('base64');
227
+ resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': v1Header }) });
228
+ }
229
+
120
230
  if (resp2.status !== 200) throw new Error('Payment failed ' + resp2.status + ': ' + (await resp2.text()).substring(0, 300));
121
231
  var data = await resp2.json();
122
232
  notifyUpdate(data, resp2.headers);
@@ -131,7 +241,7 @@ var TOOLS = [
131
241
  { name: 'get_whale_distribution', description: 'Distribution phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
132
242
  { name: 'get_btc_regime', description: 'BTC macro regime. Cost: $0.01 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
133
243
  { name: 'get_btc_futures_signal', description: 'BTC futures signal. Cost: $0.03 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
134
- { name: 'get_token_ca', description: 'Token contract address by name. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
244
+ { name: 'get_token_ca', description: 'Token contract address. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
135
245
  { name: 'get_status', description: 'CryptoIZ MCP status. FREE', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
136
246
  ];
137
247
 
@@ -149,6 +259,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
149
259
  async function main() {
150
260
  var transport = new StdioServerTransport();
151
261
  await server.connect(transport);
152
- console.error('[cryptoiz-mcp] ' + VERSION + ' running (V1 direct)');
262
+ console.error('[cryptoiz-mcp] ' + VERSION + ' running (V2 Dexter gas-sponsored + V1 fallback)');
153
263
  }
154
264
  main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptoiz-mcp",
3
- "version": "4.16.8",
3
+ "version": "4.16.10",
4
4
  "description": "CryptoIZ MCP Server - Solana DEX whale intelligence via Claude Desktop with x402 USDC micropayments",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -8,14 +8,24 @@
8
8
  "cryptoiz-mcp": "./index.js",
9
9
  "cryptoiz-mcp-setup": "./setup.js"
10
10
  },
11
- "files": ["index.js", "setup.js", "package.json", "README.md"],
11
+ "files": [
12
+ "index.js",
13
+ "setup.js",
14
+ "package.json",
15
+ "README.md"
16
+ ],
12
17
  "dependencies": {
13
18
  "@modelcontextprotocol/sdk": "^1.0.4",
14
19
  "@solana/web3.js": "^1.95.8",
15
20
  "bs58": "^6.0.0"
16
21
  },
17
- "engines": { "node": ">=18.0.0" },
22
+ "engines": {
23
+ "node": ">=18.0.0"
24
+ },
18
25
  "author": "CryptoIZ",
19
26
  "license": "MIT",
20
- "repository": { "type": "git", "url": "git+https://github.com/dadang11/cryptoiz-mcp.git" }
21
- }
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/dadang11/cryptoiz-mcp.git"
30
+ }
31
+ }
package/setup.js CHANGED
File without changes