@dcentralab/d402-client 0.3.4 → 0.3.7
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/dist/index.d.mts +155 -3
- package/dist/index.d.ts +155 -3
- package/dist/index.js +236 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +232 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/LICENSE +0 -22
package/dist/index.js
CHANGED
|
@@ -299,12 +299,12 @@ __export(signer_exports, {
|
|
|
299
299
|
async function signD402Payment(params) {
|
|
300
300
|
const {
|
|
301
301
|
operatorAccount,
|
|
302
|
+
walletClient,
|
|
302
303
|
paymentRequirement,
|
|
303
304
|
iatpWalletAddress,
|
|
304
305
|
requestPath,
|
|
305
306
|
d402Version = 1
|
|
306
307
|
} = params;
|
|
307
|
-
const consumerWallet = iatpWalletAddress || operatorAccount.address;
|
|
308
308
|
let finalRequestPath = requestPath || paymentRequirement.resource || "/mcp";
|
|
309
309
|
if (!finalRequestPath || finalRequestPath.trim() === "") {
|
|
310
310
|
finalRequestPath = "/mcp";
|
|
@@ -321,27 +321,39 @@ async function signD402Payment(params) {
|
|
|
321
321
|
name: walletName,
|
|
322
322
|
version: walletVersion,
|
|
323
323
|
chainId,
|
|
324
|
-
verifyingContract:
|
|
324
|
+
verifyingContract: iatpWalletAddress
|
|
325
325
|
};
|
|
326
326
|
const message = {
|
|
327
|
-
wallet:
|
|
327
|
+
wallet: iatpWalletAddress,
|
|
328
328
|
provider: paymentRequirement.payTo,
|
|
329
329
|
token: paymentRequirement.asset,
|
|
330
330
|
amount: BigInt(paymentRequirement.maxAmountRequired),
|
|
331
331
|
deadline: BigInt(validBefore),
|
|
332
332
|
requestPath: finalRequestPath
|
|
333
333
|
};
|
|
334
|
-
|
|
335
|
-
|
|
334
|
+
let signature;
|
|
335
|
+
if (walletClient) {
|
|
336
|
+
signature = await walletClient.signTypedData({
|
|
337
|
+
account: operatorAccount,
|
|
338
|
+
domain,
|
|
339
|
+
types: {
|
|
340
|
+
PullFundsForSettlement: EIP712_TYPES.PullFundsForSettlement
|
|
341
|
+
},
|
|
342
|
+
primaryType: "PullFundsForSettlement",
|
|
343
|
+
message
|
|
344
|
+
});
|
|
345
|
+
} else if (operatorAccount.signTypedData) {
|
|
346
|
+
signature = await operatorAccount.signTypedData({
|
|
347
|
+
domain,
|
|
348
|
+
types: {
|
|
349
|
+
PullFundsForSettlement: EIP712_TYPES.PullFundsForSettlement
|
|
350
|
+
},
|
|
351
|
+
primaryType: "PullFundsForSettlement",
|
|
352
|
+
message
|
|
353
|
+
});
|
|
354
|
+
} else {
|
|
355
|
+
throw new Error("Account does not support signTypedData. Pass walletClient for wagmi support.");
|
|
336
356
|
}
|
|
337
|
-
const signature = await operatorAccount.signTypedData({
|
|
338
|
-
domain,
|
|
339
|
-
types: {
|
|
340
|
-
PullFundsForSettlement: EIP712_TYPES.PullFundsForSettlement
|
|
341
|
-
},
|
|
342
|
-
primaryType: "PullFundsForSettlement",
|
|
343
|
-
message
|
|
344
|
-
});
|
|
345
357
|
const signedPayment = {
|
|
346
358
|
d402Version,
|
|
347
359
|
scheme: paymentRequirement.scheme,
|
|
@@ -349,7 +361,7 @@ async function signD402Payment(params) {
|
|
|
349
361
|
payload: {
|
|
350
362
|
signature,
|
|
351
363
|
authorization: {
|
|
352
|
-
from:
|
|
364
|
+
from: iatpWalletAddress,
|
|
353
365
|
to: paymentRequirement.payTo,
|
|
354
366
|
value: paymentRequirement.maxAmountRequired,
|
|
355
367
|
validAfter,
|
|
@@ -408,6 +420,131 @@ var init_encoder = __esm({
|
|
|
408
420
|
}
|
|
409
421
|
});
|
|
410
422
|
|
|
423
|
+
// src/mcp/session.ts
|
|
424
|
+
var session_exports = {};
|
|
425
|
+
__export(session_exports, {
|
|
426
|
+
DEFAULT_JSONRPC_VERSION: () => DEFAULT_JSONRPC_VERSION,
|
|
427
|
+
DEFAULT_REQUEST_ID: () => DEFAULT_REQUEST_ID,
|
|
428
|
+
initMcpSession: () => initMcpSession
|
|
429
|
+
});
|
|
430
|
+
async function initMcpSession(endpoint) {
|
|
431
|
+
const response = await fetch(endpoint, {
|
|
432
|
+
method: "POST",
|
|
433
|
+
headers: {
|
|
434
|
+
"Content-Type": "application/json",
|
|
435
|
+
"Accept": "application/json, text/event-stream"
|
|
436
|
+
},
|
|
437
|
+
body: JSON.stringify({
|
|
438
|
+
jsonrpc: DEFAULT_JSONRPC_VERSION,
|
|
439
|
+
id: DEFAULT_REQUEST_ID,
|
|
440
|
+
method: "initialize",
|
|
441
|
+
params: {
|
|
442
|
+
protocolVersion: "2024-11-05",
|
|
443
|
+
capabilities: {},
|
|
444
|
+
clientInfo: { name: "d402-client", version: "1.0" }
|
|
445
|
+
}
|
|
446
|
+
})
|
|
447
|
+
});
|
|
448
|
+
if (!response.ok) {
|
|
449
|
+
throw new Error(`MCP init failed: ${response.status} ${response.statusText}`);
|
|
450
|
+
}
|
|
451
|
+
return response.headers.get("mcp-session-id");
|
|
452
|
+
}
|
|
453
|
+
var DEFAULT_REQUEST_ID, DEFAULT_JSONRPC_VERSION;
|
|
454
|
+
var init_session = __esm({
|
|
455
|
+
"src/mcp/session.ts"() {
|
|
456
|
+
DEFAULT_REQUEST_ID = "init-1";
|
|
457
|
+
DEFAULT_JSONRPC_VERSION = "2.0";
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// src/mcp/payload.ts
|
|
462
|
+
var payload_exports = {};
|
|
463
|
+
__export(payload_exports, {
|
|
464
|
+
buildMcpHeaders: () => buildMcpHeaders,
|
|
465
|
+
buildToolCallPayload: () => buildToolCallPayload
|
|
466
|
+
});
|
|
467
|
+
function buildToolCallPayload(toolName, args, requestId = DEFAULT_REQUEST_ID) {
|
|
468
|
+
return {
|
|
469
|
+
jsonrpc: DEFAULT_JSONRPC_VERSION,
|
|
470
|
+
id: requestId,
|
|
471
|
+
method: "tools/call",
|
|
472
|
+
params: {
|
|
473
|
+
name: toolName,
|
|
474
|
+
arguments: args
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function buildMcpHeaders(sessionId) {
|
|
479
|
+
const headers = {
|
|
480
|
+
"Content-Type": "application/json",
|
|
481
|
+
"Accept": "application/json, text/event-stream"
|
|
482
|
+
};
|
|
483
|
+
if (sessionId) {
|
|
484
|
+
headers["mcp-session-id"] = sessionId;
|
|
485
|
+
}
|
|
486
|
+
return headers;
|
|
487
|
+
}
|
|
488
|
+
var init_payload = __esm({
|
|
489
|
+
"src/mcp/payload.ts"() {
|
|
490
|
+
init_session();
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// src/mcp/response.ts
|
|
495
|
+
var response_exports = {};
|
|
496
|
+
__export(response_exports, {
|
|
497
|
+
extractToolResult: () => extractToolResult,
|
|
498
|
+
parseMcpResponse: () => parseMcpResponse
|
|
499
|
+
});
|
|
500
|
+
async function parseMcpResponse(response) {
|
|
501
|
+
const contentType = response.headers.get("content-type") || "";
|
|
502
|
+
if (contentType.includes("text/event-stream")) {
|
|
503
|
+
return parseSSEResponse(await response.text());
|
|
504
|
+
} else {
|
|
505
|
+
return await response.json();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
function parseSSEResponse(text) {
|
|
509
|
+
const lines = text.split("\n");
|
|
510
|
+
for (const line of lines) {
|
|
511
|
+
if (line.startsWith("data: ")) {
|
|
512
|
+
const jsonStr = line.substring(6);
|
|
513
|
+
try {
|
|
514
|
+
return JSON.parse(jsonStr);
|
|
515
|
+
} catch {
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
id: "unknown",
|
|
522
|
+
result: { raw: text },
|
|
523
|
+
error: {
|
|
524
|
+
code: -32700,
|
|
525
|
+
message: "Could not parse SSE response",
|
|
526
|
+
data: text
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function extractToolResult(response) {
|
|
531
|
+
if (response.error) {
|
|
532
|
+
throw new Error(`MCP error ${response.error.code}: ${response.error.message}`);
|
|
533
|
+
}
|
|
534
|
+
if (response.result && typeof response.result === "object") {
|
|
535
|
+
const result = response.result;
|
|
536
|
+
if (result.structuredContent) {
|
|
537
|
+
return result.structuredContent;
|
|
538
|
+
}
|
|
539
|
+
return result;
|
|
540
|
+
}
|
|
541
|
+
return response.result;
|
|
542
|
+
}
|
|
543
|
+
var init_response = __esm({
|
|
544
|
+
"src/mcp/response.ts"() {
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
411
548
|
// src/payment/selector.ts
|
|
412
549
|
init_errors();
|
|
413
550
|
function selectPaymentRequirement(requirements, options = {}) {
|
|
@@ -5041,7 +5178,7 @@ function getContractConfig(contractName, network = "sepolia") {
|
|
|
5041
5178
|
|
|
5042
5179
|
// src/wallet/creation.ts
|
|
5043
5180
|
async function createIATPWallet(params) {
|
|
5044
|
-
const { ownerAccount, network = "sepolia", rpcUrl } = params;
|
|
5181
|
+
const { ownerAccount, walletClient: externalWalletClient, network = "sepolia", rpcUrl } = params;
|
|
5045
5182
|
const factoryConfig = getContractConfig("IATPWalletFactory" /* IATP_WALLET_FACTORY */, network);
|
|
5046
5183
|
if (!factoryConfig) {
|
|
5047
5184
|
throw new Error(`IATPWalletFactory not found for network: ${network}`);
|
|
@@ -5053,7 +5190,7 @@ async function createIATPWallet(params) {
|
|
|
5053
5190
|
chain,
|
|
5054
5191
|
transport
|
|
5055
5192
|
});
|
|
5056
|
-
const walletClient = viem.createWalletClient({
|
|
5193
|
+
const walletClient = externalWalletClient ?? viem.createWalletClient({
|
|
5057
5194
|
account: ownerAccount,
|
|
5058
5195
|
chain,
|
|
5059
5196
|
transport
|
|
@@ -5062,14 +5199,14 @@ async function createIATPWallet(params) {
|
|
|
5062
5199
|
if (balance === 0n) {
|
|
5063
5200
|
throw new Error("Owner has no ETH for gas. Please fund the account.");
|
|
5064
5201
|
}
|
|
5065
|
-
const
|
|
5202
|
+
const hash = await walletClient.writeContract({
|
|
5066
5203
|
account: ownerAccount,
|
|
5067
5204
|
address: factoryConfig.address,
|
|
5068
5205
|
abi: factoryConfig.abi,
|
|
5069
5206
|
functionName: "createWallet",
|
|
5070
|
-
args: [operatorAddress, 0, "", ""]
|
|
5207
|
+
args: [operatorAddress, 0, "", ""],
|
|
5208
|
+
chain
|
|
5071
5209
|
});
|
|
5072
|
-
const hash = await walletClient.writeContract(request);
|
|
5073
5210
|
const receipt = await publicClient.waitForTransactionReceipt({
|
|
5074
5211
|
hash,
|
|
5075
5212
|
timeout: 3e5
|
|
@@ -5247,6 +5384,7 @@ var D402Client = class {
|
|
|
5247
5384
|
*/
|
|
5248
5385
|
constructor(config) {
|
|
5249
5386
|
this.operatorAccount = config.operatorAccount;
|
|
5387
|
+
this.walletClient = config.walletClient;
|
|
5250
5388
|
this.iatpWalletAddress = config.iatpWalletAddress;
|
|
5251
5389
|
this.maxValue = config.maxValue;
|
|
5252
5390
|
this.networkFilter = config.networkFilter;
|
|
@@ -5390,7 +5528,15 @@ var D402Client = class {
|
|
|
5390
5528
|
const { parseAllPaymentRequirements: parseAllPaymentRequirements2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
|
|
5391
5529
|
const { signD402Payment: signD402Payment2 } = await Promise.resolve().then(() => (init_signer(), signer_exports));
|
|
5392
5530
|
const { encodePayment: encodePayment2 } = await Promise.resolve().then(() => (init_encoder(), encoder_exports));
|
|
5393
|
-
|
|
5531
|
+
const enhancedInit = {
|
|
5532
|
+
...init,
|
|
5533
|
+
headers: {
|
|
5534
|
+
...init?.headers,
|
|
5535
|
+
// Preserve existing Accept header or set default for MCP compatibility
|
|
5536
|
+
"Accept": init?.headers?.["Accept"] || "application/json, text/event-stream"
|
|
5537
|
+
}
|
|
5538
|
+
};
|
|
5539
|
+
let response = await fetch(url, enhancedInit);
|
|
5394
5540
|
if (response.status !== 402) {
|
|
5395
5541
|
return response;
|
|
5396
5542
|
}
|
|
@@ -5399,14 +5545,15 @@ var D402Client = class {
|
|
|
5399
5545
|
const selectedRequirement = this.selectPaymentRequirement(requirements);
|
|
5400
5546
|
const signedPayment = await signD402Payment2({
|
|
5401
5547
|
operatorAccount: this.operatorAccount,
|
|
5548
|
+
walletClient: this.walletClient,
|
|
5402
5549
|
paymentRequirement: selectedRequirement,
|
|
5403
5550
|
iatpWalletAddress: this.iatpWalletAddress
|
|
5404
5551
|
});
|
|
5405
5552
|
const paymentHeader = encodePayment2(signedPayment);
|
|
5406
5553
|
response = await fetch(url, {
|
|
5407
|
-
...
|
|
5554
|
+
...enhancedInit,
|
|
5408
5555
|
headers: {
|
|
5409
|
-
...
|
|
5556
|
+
...enhancedInit.headers,
|
|
5410
5557
|
"X-Payment": paymentHeader,
|
|
5411
5558
|
"Access-Control-Expose-Headers": "X-Payment-Response"
|
|
5412
5559
|
}
|
|
@@ -5416,6 +5563,63 @@ var D402Client = class {
|
|
|
5416
5563
|
throw error;
|
|
5417
5564
|
}
|
|
5418
5565
|
}
|
|
5566
|
+
// ========================================================================
|
|
5567
|
+
// MCP Methods - Simplified API for MCP tool calls
|
|
5568
|
+
// ========================================================================
|
|
5569
|
+
/**
|
|
5570
|
+
* Call an MCP tool with automatic session initialization and payment handling.
|
|
5571
|
+
*
|
|
5572
|
+
* This is the simplest way to call an MCP tool. It handles:
|
|
5573
|
+
* - MCP session initialization
|
|
5574
|
+
* - JSON-RPC payload construction
|
|
5575
|
+
* - HTTP 402 payment flow
|
|
5576
|
+
* - SSE/JSON response parsing
|
|
5577
|
+
*
|
|
5578
|
+
* @param endpoint - MCP server endpoint URL
|
|
5579
|
+
* @param toolName - Name of the tool to call
|
|
5580
|
+
* @param input - Tool arguments
|
|
5581
|
+
* @param options - Optional configuration
|
|
5582
|
+
* @returns The tool's result data
|
|
5583
|
+
*
|
|
5584
|
+
* @example
|
|
5585
|
+
* ```ts
|
|
5586
|
+
* const client = new D402Client({
|
|
5587
|
+
* operatorAccount: walletClient.account,
|
|
5588
|
+
* walletClient,
|
|
5589
|
+
* iatpWalletAddress,
|
|
5590
|
+
* })
|
|
5591
|
+
*
|
|
5592
|
+
* // Simple one-liner!
|
|
5593
|
+
* const result = await client.mcpCall(
|
|
5594
|
+
* 'https://my-mcp.example.com/mcp',
|
|
5595
|
+
* 'google_search',
|
|
5596
|
+
* { q: 'test search' }
|
|
5597
|
+
* )
|
|
5598
|
+
*
|
|
5599
|
+
* console.log(result) // { searchResults: [...] }
|
|
5600
|
+
* ```
|
|
5601
|
+
*/
|
|
5602
|
+
async mcpCall(endpoint, toolName, input, options) {
|
|
5603
|
+
const { initMcpSession: initMcpSession2 } = await Promise.resolve().then(() => (init_session(), session_exports));
|
|
5604
|
+
const { buildToolCallPayload: buildToolCallPayload2, buildMcpHeaders: buildMcpHeaders2 } = await Promise.resolve().then(() => (init_payload(), payload_exports));
|
|
5605
|
+
const { parseMcpResponse: parseMcpResponse2, extractToolResult: extractToolResult2 } = await Promise.resolve().then(() => (init_response(), response_exports));
|
|
5606
|
+
let sessionId = null;
|
|
5607
|
+
if (!options?.skipInit) {
|
|
5608
|
+
try {
|
|
5609
|
+
sessionId = await initMcpSession2(endpoint);
|
|
5610
|
+
} catch {
|
|
5611
|
+
}
|
|
5612
|
+
}
|
|
5613
|
+
const headers = buildMcpHeaders2(sessionId);
|
|
5614
|
+
const payload = buildToolCallPayload2(toolName, input, options?.requestId);
|
|
5615
|
+
const response = await this.fetch(endpoint, {
|
|
5616
|
+
method: "POST",
|
|
5617
|
+
headers,
|
|
5618
|
+
body: JSON.stringify(payload)
|
|
5619
|
+
});
|
|
5620
|
+
const parsed = await parseMcpResponse2(response);
|
|
5621
|
+
return extractToolResult2(parsed);
|
|
5622
|
+
}
|
|
5419
5623
|
};
|
|
5420
5624
|
|
|
5421
5625
|
// src/index.ts
|
|
@@ -5423,6 +5627,11 @@ init_signer();
|
|
|
5423
5627
|
init_parser();
|
|
5424
5628
|
init_encoder();
|
|
5425
5629
|
|
|
5630
|
+
// src/mcp/index.ts
|
|
5631
|
+
init_session();
|
|
5632
|
+
init_payload();
|
|
5633
|
+
init_response();
|
|
5634
|
+
|
|
5426
5635
|
// src/settlement/queries.ts
|
|
5427
5636
|
async function getLockedBalanceForProvider(params) {
|
|
5428
5637
|
const { publicClient, providerAddress, tokenAddress, network = "sepolia" } = params;
|
|
@@ -5497,12 +5706,15 @@ init_errors();
|
|
|
5497
5706
|
|
|
5498
5707
|
exports.ContractName = ContractName;
|
|
5499
5708
|
exports.D402Client = D402Client;
|
|
5709
|
+
exports.buildMcpHeaders = buildMcpHeaders;
|
|
5710
|
+
exports.buildToolCallPayload = buildToolCallPayload;
|
|
5500
5711
|
exports.createIATPWallet = createIATPWallet;
|
|
5501
5712
|
exports.createPaymentSelector = createPaymentSelector;
|
|
5502
5713
|
exports.decodePayment = decodePayment;
|
|
5503
5714
|
exports.decodePaymentResponse = decodePaymentResponse;
|
|
5504
5715
|
exports.encodePayment = encodePayment;
|
|
5505
5716
|
exports.executeWithdrawal = executeWithdrawal;
|
|
5717
|
+
exports.extractToolResult = extractToolResult;
|
|
5506
5718
|
exports.findMatchingPaymentRequirement = findMatchingPaymentRequirement;
|
|
5507
5719
|
exports.formatMoney = formatMoney;
|
|
5508
5720
|
exports.generateNonce = generateNonce;
|
|
@@ -5517,9 +5729,11 @@ exports.getUnlockedBalanceForProvider = getUnlockedBalanceForProvider;
|
|
|
5517
5729
|
exports.getUsdcAddress = getUsdcAddress;
|
|
5518
5730
|
exports.getWalletsByOwner = getWalletsByOwner;
|
|
5519
5731
|
exports.getWithdrawalRequest = getWithdrawalRequest;
|
|
5732
|
+
exports.initMcpSession = initMcpSession;
|
|
5520
5733
|
exports.isValidAddress = isValidAddress;
|
|
5521
5734
|
exports.normalizeAddress = normalizeAddress;
|
|
5522
5735
|
exports.parseAllPaymentRequirements = parseAllPaymentRequirements;
|
|
5736
|
+
exports.parseMcpResponse = parseMcpResponse;
|
|
5523
5737
|
exports.parseMoney = parseMoney;
|
|
5524
5738
|
exports.parsePaymentRequirement = parsePaymentRequirement;
|
|
5525
5739
|
exports.requestWithdrawal = requestWithdrawal;
|