cryptoiz-mcp 4.15.1 → 4.15.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.
Files changed (2) hide show
  1. package/index.js +64 -21
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -9,7 +9,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
9
9
  import { Connection, Keypair, PublicKey, Transaction, SystemProgram, VersionedTransaction, TransactionMessage } from '@solana/web3.js';
10
10
  import bs58 from 'bs58';
11
11
 
12
- var VERSION = 'v4.15.1';
12
+ var VERSION = 'v4.15.3';
13
13
  var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
14
14
  var RECIPIENT = 'DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX';
15
15
  var USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
@@ -42,45 +42,66 @@ function findATA(wallet, mint) {
42
42
 
43
43
  // ===== V2: Build partially-signed tx for Dexter facilitator =====
44
44
  // Dexter pays gas (feePayer), user only signs the transfer
45
- async function buildV2PaymentPayload(amount) {
45
+ // Tx MUST contain 3 instructions in order: SetComputeUnitLimit, SetComputeUnitPrice, SPL Transfer
46
+ var COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';
47
+
48
+ async function buildV2PaymentPayload(amount, feePayerAddr) {
46
49
  var kp = getKeypair();
47
50
  var conn = new Connection(SOL_RPC, 'confirmed');
48
51
 
49
52
  var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
50
53
  var recipientATA = findATA(RECIPIENT, USDC_MINT);
51
- var feePayerPk = new PublicKey(DEXTER_FEE_PAYER);
54
+ var feePayerPk = new PublicKey(feePayerAddr);
55
+ var computeBudgetPk = new PublicKey(COMPUTE_BUDGET_PROGRAM);
56
+
57
+ // Instruction 1: SetComputeUnitLimit (instruction index 2, u32 units)
58
+ var setLimitData = Buffer.alloc(5);
59
+ setLimitData.writeUInt8(2, 0);
60
+ setLimitData.writeUInt32LE(200000, 1);
61
+ var setLimitIx = {
62
+ programId: computeBudgetPk,
63
+ keys: [],
64
+ data: setLimitData,
65
+ };
66
+
67
+ // Instruction 2: SetComputeUnitPrice (instruction index 3, u64 microLamports)
68
+ var setPriceData = Buffer.alloc(9);
69
+ setPriceData.writeUInt8(3, 0);
70
+ setPriceData.writeUInt32LE(50000, 1); // 50000 microLamports
71
+ setPriceData.writeUInt32LE(0, 5);
72
+ var setPriceIx = {
73
+ programId: computeBudgetPk,
74
+ keys: [],
75
+ data: setPriceData,
76
+ };
52
77
 
53
- // Build SPL Token transfer instruction
78
+ // Instruction 3: SPL Token Transfer
54
79
  var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
55
- var keys = [
80
+ var transferKeys = [
56
81
  { pubkey: userATA, isSigner: false, isWritable: true },
57
82
  { pubkey: recipientATA, isSigner: false, isWritable: true },
58
83
  { pubkey: kp.publicKey, isSigner: true, isWritable: false },
59
84
  ];
60
-
61
- // SPL Token Transfer instruction data: instruction index 3 + u64 amount (LE)
62
- var data = Buffer.alloc(9);
63
- data.writeUInt8(3, 0); // Transfer instruction index
64
- // Write amount as u64 LE
85
+ var transferData = Buffer.alloc(9);
86
+ transferData.writeUInt8(3, 0);
65
87
  var lo = amount & 0xFFFFFFFF;
66
88
  var hi = Math.floor(amount / 0x100000000) & 0xFFFFFFFF;
67
- data.writeUInt32LE(lo, 1);
68
- data.writeUInt32LE(hi, 5);
69
-
89
+ transferData.writeUInt32LE(lo, 1);
90
+ transferData.writeUInt32LE(hi, 5);
70
91
  var transferIx = {
71
92
  programId: tokenProgramPk,
72
- keys: keys,
73
- data: data,
93
+ keys: transferKeys,
94
+ data: transferData,
74
95
  };
75
96
 
76
97
  // Get recent blockhash
77
98
  var bhResult = await conn.getLatestBlockhash('confirmed');
78
99
 
79
- // Build V0 message with Dexter as feePayer
100
+ // Build V0 message: feePayer = Dexter, 3 instructions in required order
80
101
  var message = new TransactionMessage({
81
102
  payerKey: feePayerPk,
82
103
  recentBlockhash: bhResult.blockhash,
83
- instructions: [transferIx],
104
+ instructions: [setLimitIx, setPriceIx, transferIx],
84
105
  }).compileToV0Message();
85
106
 
86
107
  var vtx = new VersionedTransaction(message);
@@ -88,10 +109,10 @@ async function buildV2PaymentPayload(amount) {
88
109
  // Partially sign with user keypair only (Dexter signs as feePayer later)
89
110
  vtx.sign([kp]);
90
111
 
91
- // Serialize and base64 encode
92
112
  var serialized = vtx.serialize();
93
113
  var txB64 = Buffer.from(serialized).toString('base64');
94
114
 
115
+ console.error('[cryptoiz-mcp] V2 tx built: 3 instructions (ComputeLimit + ComputePrice + Transfer), feePayer=' + feePayerAddr.substring(0, 8) + '...');
95
116
  return txB64;
96
117
  }
97
118
 
@@ -210,9 +231,10 @@ async function callTool(toolName, args) {
210
231
 
211
232
  if (useV2 && paymentRequirements.extra && paymentRequirements.extra.feePayer) {
212
233
  // V2: Build partially-signed tx, Dexter pays gas
213
- console.error('[cryptoiz-mcp] V2 mode: building partial tx for Dexter gas sponsorship...');
234
+ var v2FeePayer = paymentRequirements.extra.feePayer;
235
+ console.error('[cryptoiz-mcp] V2 mode: building 3-instruction tx for Dexter, feePayer=' + v2FeePayer.substring(0, 8) + '...');
214
236
  try {
215
- var txB64 = await buildV2PaymentPayload(amount);
237
+ var txB64 = await buildV2PaymentPayload(amount, v2FeePayer);
216
238
 
217
239
  // Build V2 payment payload per x402 spec
218
240
  var v2Payload = {
@@ -226,7 +248,7 @@ async function callTool(toolName, args) {
226
248
 
227
249
  paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
228
250
  headerName = 'payment-signature';
229
- console.error('[cryptoiz-mcp] V2 partial tx built, sending via PAYMENT-SIGNATURE header');
251
+ console.error('[cryptoiz-mcp] V2 tx ready, sending via payment-signature header');
230
252
  } catch(e) {
231
253
  console.error('[cryptoiz-mcp] V2 build failed: ' + e.message + ', falling back to V1');
232
254
  useV2 = false;
@@ -253,6 +275,27 @@ async function callTool(toolName, args) {
253
275
 
254
276
  var resp2 = await fetch(url, { headers: headers2 });
255
277
 
278
+ // V2 settle failed? Auto-fallback to V1
279
+ if (resp2.status !== 200 && useV2) {
280
+ var v2ErrBody = await resp2.text();
281
+ console.error('[cryptoiz-mcp] V2 settle failed (' + resp2.status + '): ' + v2ErrBody.substring(0, 200));
282
+ console.error('[cryptoiz-mcp] Auto-fallback to V1 (sendUSDC on-chain)...');
283
+
284
+ try {
285
+ // V1: send USDC on-chain, retry with x-payment
286
+ var fallbackSig = await sendUSDC(amount);
287
+ console.error('[cryptoiz-mcp] V1 fallback TX confirmed: ' + fallbackSig);
288
+
289
+ var v1FallbackPayload = { signature: fallbackSig };
290
+ var v1FallbackHeader = Buffer.from(JSON.stringify(v1FallbackPayload)).toString('base64');
291
+
292
+ resp2 = await fetch(url, { headers: { 'x-payment': v1FallbackHeader } });
293
+ } catch(fallbackErr) {
294
+ console.error('[cryptoiz-mcp] V1 fallback also failed: ' + fallbackErr.message);
295
+ throw new Error('V2 failed (' + v2ErrBody.substring(0, 100) + '), V1 fallback also failed: ' + fallbackErr.message);
296
+ }
297
+ }
298
+
256
299
  if (resp2.status !== 200) {
257
300
  var errBody = await resp2.text();
258
301
  throw new Error('Payment failed (' + resp2.status + '): ' + errBody);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptoiz-mcp",
3
- "version": "4.15.1",
3
+ "version": "4.15.3",
4
4
  "description": "CryptoIZ MCP Server - Solana DEX trading signals via Claude Desktop with x402 USDC micropayments (V2 Dexter facilitator)",
5
5
  "main": "index.js",
6
6
  "type": "module",