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