cryptoiz-mcp 4.16.8 → 4.16.9

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 (2) hide show
  1. package/index.js +128 -20
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
- var VERSION = 'v4.16.8';
2
+ var VERSION = 'v4.16.9';
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,13 +59,65 @@ 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 memoProgramPk = new PublicKey(MEMO_PROGRAM);
72
+ var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
73
+ var usdcMintPk = new PublicKey(USDC_MINT);
74
+ // ComputeUnitLimit(20000)
75
+ var setLimitData = Buffer.alloc(5);
76
+ setLimitData[0] = 0x02;
77
+ setLimitData.writeUInt32LE(20000, 1);
78
+ var setLimitIx = { programId: computeBudgetPk, keys: [], data: setLimitData };
79
+ // ComputeUnitPrice(1)
80
+ var setPriceData = Buffer.alloc(9);
81
+ setPriceData[0] = 0x03;
82
+ setPriceData.writeBigUInt64LE(BigInt(1), 1);
83
+ var setPriceIx = { programId: computeBudgetPk, keys: [], data: setPriceData };
84
+ // TransferChecked
85
+ var transferKeys = [
86
+ { pubkey: userATA, isSigner: false, isWritable: true },
87
+ { pubkey: usdcMintPk, isSigner: false, isWritable: false },
88
+ { pubkey: recipientATA, isSigner: false, isWritable: true },
89
+ { pubkey: kp.publicKey, isSigner: true, isWritable: false },
90
+ ];
91
+ var transferData = Buffer.alloc(10);
92
+ transferData[0] = 0x0c;
93
+ transferData.writeUInt32LE(amount & 0xFFFFFFFF, 1);
94
+ transferData.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
95
+ transferData[9] = 6;
96
+ var transferIx = { programId: tokenProgramPk, keys: transferKeys, data: transferData };
97
+ // Memo with nonce
98
+ var nonceBytes = new Uint8Array(16);
99
+ for (var i = 0; i < 16; i++) nonceBytes[i] = Math.floor(Math.random() * 256);
100
+ var nonceHex = Array.from(nonceBytes).map(function(b) { return b.toString(16).padStart(2,'0'); }).join('');
101
+ var memoIx = { programId: memoProgramPk, keys: [], data: Buffer.from(nonceHex, 'utf8') };
102
+ var bh = await conn.getLatestBlockhash('confirmed');
103
+ var message = new TransactionMessage({
104
+ payerKey: feePayerPk,
105
+ recentBlockhash: bh.blockhash,
106
+ instructions: [setLimitIx, setPriceIx, transferIx, memoIx],
107
+ }).compileToV0Message();
108
+ var vtx = new VersionedTransaction(message);
109
+ vtx.sign([kp]);
110
+ var txB64 = Buffer.from(vtx.serialize()).toString('base64');
111
+ console.error('[cryptoiz-mcp] V2 tx built (Dexter gas-sponsored), nonce=' + nonceHex.substring(0,8) + '...');
112
+ return txB64;
113
+ }
114
+
115
+ // V1: direct on-chain, user pays SOL gas (fallback only)
57
116
  async function sendUSDC(amount, toolName) {
58
117
  var kp = getKeypair();
59
118
  var conn = new Connection(SOL_RPC, 'confirmed');
60
119
  var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
61
120
  var recipientATA = findATA(RECIPIENT, USDC_MINT);
62
- // TransferChecked ix
63
121
  var keys = [
64
122
  { pubkey: userATA, isSigner: false, isWritable: true },
65
123
  { pubkey: new PublicKey(USDC_MINT), isSigner: false, isWritable: false },
@@ -72,8 +130,7 @@ async function sendUSDC(amount, toolName) {
72
130
  data.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
73
131
  data[8] = 6;
74
132
  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);
133
+ var nonce = Date.now().toString(16) + Math.floor(Math.random()*0xffff).toString(16);
77
134
  var memoIx = {
78
135
  programId: new PublicKey(MEMO_PROGRAM),
79
136
  keys: [],
@@ -86,7 +143,7 @@ async function sendUSDC(amount, toolName) {
86
143
  tx.sign(kp);
87
144
  var sig = await conn.sendRawTransaction(tx.serialize(), { skipPreflight: false });
88
145
  await conn.confirmTransaction({ signature: sig, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight }, 'confirmed');
89
- console.error('[cryptoiz-mcp] TX: ' + sig);
146
+ console.error('[cryptoiz-mcp] V1 TX: ' + sig);
90
147
  return sig;
91
148
  }
92
149
 
@@ -101,22 +158,73 @@ async function callTool(toolName, args) {
101
158
  if (toolName === 'get_whale_divergence' && args && args.timeframe) queryParts.push('tf=' + args.timeframe);
102
159
  if (toolName === 'get_token_ca' && args && args.name) queryParts.push('name=' + encodeURIComponent(args.name));
103
160
  var url = (TOOL_ENDPOINTS[toolName] || GATEWAY) + '?' + queryParts.join('&');
161
+
104
162
  // Step 1: discovery
105
163
  var resp1 = await fetch(url, { headers: clientHeaders() });
106
164
  if (resp1.status === 200) { var d = await resp1.json(); notifyUpdate(d, resp1.headers); return d; }
107
165
  if (resp1.status !== 402) throw new Error('Server error ' + resp1.status + ': ' + (await resp1.text()).substring(0, 200));
166
+
108
167
  // Step 2: parse payment requirements
109
168
  var payReq = null;
169
+ var useV2 = false;
110
170
  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]; }
171
+ if (prHeader) {
172
+ try {
173
+ var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8'));
174
+ if (arr && arr[0]) { payReq = arr[0]; useV2 = true; }
175
+ } catch(_e) {}
176
+ }
177
+ if (!payReq) {
178
+ var b402 = await resp1.json();
179
+ if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0];
180
+ }
113
181
  if (!payReq) throw new Error('No payment requirements in 402');
182
+
114
183
  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') }) });
184
+ var hasFeePayer = payReq.extra && payReq.extra.feePayer;
185
+ var paymentHeader = '';
186
+ var headerName = '';
187
+
188
+ // Step 3: Try V2 Dexter (gas-sponsored by Dexter user only needs USDC)
189
+ if (useV2 && hasFeePayer) {
190
+ console.error('[cryptoiz-mcp] V2 mode: Dexter gas-sponsored, paying ' + (amount/1000000).toFixed(4) + ' USDC');
191
+ try {
192
+ var txB64 = await buildV2PaymentPayload(amount, payReq.extra.feePayer);
193
+ var v2Payload = {
194
+ x402Version: 1,
195
+ scheme: 'exact',
196
+ network: payReq.network || 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
197
+ payload: { transaction: txB64, signature: '' }
198
+ };
199
+ paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
200
+ headerName = 'payment-signature';
201
+ } catch(v2Err) {
202
+ console.error('[cryptoiz-mcp] V2 build failed: ' + v2Err.message + ' -> fallback V1');
203
+ useV2 = false;
204
+ }
205
+ }
206
+
207
+ // Step 4: V1 fallback (user pays gas — only if V2 failed)
208
+ if (!paymentHeader) {
209
+ console.error('[cryptoiz-mcp] V1 fallback: direct on-chain transfer');
210
+ var sig = await sendUSDC(amount, toolName);
211
+ paymentHeader = Buffer.from(JSON.stringify({ signature: sig })).toString('base64');
212
+ headerName = 'x-payment';
213
+ }
214
+
215
+ // Step 5: submit payment
216
+ var headers2 = {};
217
+ headers2[headerName] = paymentHeader;
218
+ var resp2 = await fetch(url, { headers: clientHeaders(headers2) });
219
+
220
+ // Step 6: if V2 failed at server, retry with V1
221
+ if (resp2.status !== 200 && useV2) {
222
+ console.error('[cryptoiz-mcp] V2 settle failed, trying V1 fallback...');
223
+ var fallbackSig = await sendUSDC(amount, toolName);
224
+ var v1Header = Buffer.from(JSON.stringify({ signature: fallbackSig })).toString('base64');
225
+ resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': v1Header }) });
226
+ }
227
+
120
228
  if (resp2.status !== 200) throw new Error('Payment failed ' + resp2.status + ': ' + (await resp2.text()).substring(0, 300));
121
229
  var data = await resp2.json();
122
230
  notifyUpdate(data, resp2.headers);
@@ -131,7 +239,7 @@ var TOOLS = [
131
239
  { name: 'get_whale_distribution', description: 'Distribution phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
132
240
  { name: 'get_btc_regime', description: 'BTC macro regime. Cost: $0.01 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
133
241
  { 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 } },
242
+ { name: 'get_token_ca', description: 'Token contract address. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
135
243
  { name: 'get_status', description: 'CryptoIZ MCP status. FREE', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
136
244
  ];
137
245
 
@@ -149,6 +257,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
149
257
  async function main() {
150
258
  var transport = new StdioServerTransport();
151
259
  await server.connect(transport);
152
- console.error('[cryptoiz-mcp] ' + VERSION + ' running (V1 direct)');
260
+ console.error('[cryptoiz-mcp] ' + VERSION + ' running (V2 Dexter gas-sponsored + V1 fallback)');
153
261
  }
154
262
  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.9",
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",