@agether/sdk 1.6.3 → 1.6.5
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/cli.js +29 -4
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +29 -4
- package/dist/index.mjs +29 -4
- package/package.json +1 -1
- package/dist/cli.d.ts +0 -25
- package/dist/cli.d.ts.map +0 -1
- package/dist/clients/AgentIdentityClient.d.ts +0 -188
- package/dist/clients/AgentIdentityClient.d.ts.map +0 -1
- package/dist/clients/AgentIdentityClient.js +0 -333
- package/dist/clients/AgetherClient.d.ts +0 -63
- package/dist/clients/AgetherClient.d.ts.map +0 -1
- package/dist/clients/AgetherClient.js +0 -171
- package/dist/clients/MorphoClient.d.ts +0 -287
- package/dist/clients/MorphoClient.d.ts.map +0 -1
- package/dist/clients/MorphoClient.js +0 -951
- package/dist/clients/ScoringClient.d.ts +0 -89
- package/dist/clients/ScoringClient.d.ts.map +0 -1
- package/dist/clients/ScoringClient.js +0 -93
- package/dist/clients/X402Client.d.ts +0 -130
- package/dist/clients/X402Client.d.ts.map +0 -1
- package/dist/clients/X402Client.js +0 -301
- package/dist/index.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -121
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -43
- package/dist/utils/abis.d.ts +0 -18
- package/dist/utils/abis.d.ts.map +0 -1
- package/dist/utils/abis.js +0 -93
- package/dist/utils/config.d.ts +0 -34
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -115
- package/dist/utils/format.d.ts +0 -44
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js +0 -75
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScoringClient — Client for the Agether backend scoring API
|
|
3
|
-
*
|
|
4
|
-
* Endpoints:
|
|
5
|
-
* GET /score/:agentId — x402-gated, compute + submit score on-chain
|
|
6
|
-
* GET /score/:agentId/current — free, read current on-chain score
|
|
7
|
-
* GET /health — service health
|
|
8
|
-
* GET /status — detailed status
|
|
9
|
-
* GET /agents/:agentId/details — agent details
|
|
10
|
-
*/
|
|
11
|
-
import { ScoreResult } from '../types';
|
|
12
|
-
import { X402Config } from './X402Client';
|
|
13
|
-
export interface ScoringClientConfig {
|
|
14
|
-
/** Backend base URL (e.g. http://95.179.189.214:3001) */
|
|
15
|
-
endpoint: string;
|
|
16
|
-
/** x402 config for paid scoring calls (optional — if not set, paid calls will fail) */
|
|
17
|
-
x402?: X402Config;
|
|
18
|
-
}
|
|
19
|
-
export declare class ScoringClient {
|
|
20
|
-
private client;
|
|
21
|
-
private x402Client?;
|
|
22
|
-
private endpoint;
|
|
23
|
-
constructor(config: ScoringClientConfig);
|
|
24
|
-
/**
|
|
25
|
-
* Request a fresh score computation.
|
|
26
|
-
*
|
|
27
|
-
* This is x402-gated: the backend returns 402, the X402Client
|
|
28
|
-
* signs an EIP-3009 payment, and the backend computes + submits
|
|
29
|
-
* the score on-chain via AgentReputation.submitScore().
|
|
30
|
-
*
|
|
31
|
-
* Returns the ScoreResult with breakdown and txHash.
|
|
32
|
-
*/
|
|
33
|
-
requestScore(agentId: string | bigint): Promise<ScoreResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Get the current on-chain score (free, no payment required).
|
|
36
|
-
*/
|
|
37
|
-
getCurrentScore(agentId: string | bigint): Promise<{
|
|
38
|
-
agentId: string;
|
|
39
|
-
score: number;
|
|
40
|
-
timestamp: number;
|
|
41
|
-
signer: string;
|
|
42
|
-
fresh: boolean;
|
|
43
|
-
age: number;
|
|
44
|
-
}>;
|
|
45
|
-
/**
|
|
46
|
-
* Get detailed agent info from backend.
|
|
47
|
-
*/
|
|
48
|
-
getAgentDetails(agentId: string | bigint): Promise<{
|
|
49
|
-
agentId: string;
|
|
50
|
-
owner: string;
|
|
51
|
-
account: string;
|
|
52
|
-
accountExists: boolean;
|
|
53
|
-
kyaApproved: boolean;
|
|
54
|
-
score: number;
|
|
55
|
-
scoreFresh: boolean;
|
|
56
|
-
eligible: boolean;
|
|
57
|
-
}>;
|
|
58
|
-
/**
|
|
59
|
-
* Health check.
|
|
60
|
-
*/
|
|
61
|
-
getHealth(): Promise<{
|
|
62
|
-
status: string;
|
|
63
|
-
timestamp: string;
|
|
64
|
-
}>;
|
|
65
|
-
/**
|
|
66
|
-
* Detailed status (contracts, signer, chain).
|
|
67
|
-
*/
|
|
68
|
-
getStatus(): Promise<{
|
|
69
|
-
status: string;
|
|
70
|
-
chain: {
|
|
71
|
-
id: number;
|
|
72
|
-
name: string;
|
|
73
|
-
};
|
|
74
|
-
contracts: Record<string, string>;
|
|
75
|
-
scoring: {
|
|
76
|
-
priceUsdc: string;
|
|
77
|
-
x402PayToAddress: string;
|
|
78
|
-
};
|
|
79
|
-
signer: string;
|
|
80
|
-
}>;
|
|
81
|
-
/**
|
|
82
|
-
* Agent count and list.
|
|
83
|
-
*/
|
|
84
|
-
getAgentCount(): Promise<{
|
|
85
|
-
totalAgents: number;
|
|
86
|
-
totalAccounts: number;
|
|
87
|
-
}>;
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=ScoringClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ScoringClient.d.ts","sourceRoot":"","sources":["../../src/clients/ScoringClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,WAAW,EAAgB,MAAM,UAAU,CAAC;AACrD,OAAO,EAAc,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,mBAAmB;IAgBvC;;;;;;;;OAQG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA4BlE;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QACvD,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,OAAO,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IASF;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QACvD,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,EAAE,OAAO,CAAC;QACvB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IASF;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAKjE;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QACpC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE,MAAM,CAAA;SAAE,CAAC;QACzD,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IAKF;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CAI/E"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScoringClient — Client for the Agether backend scoring API
|
|
3
|
-
*
|
|
4
|
-
* Endpoints:
|
|
5
|
-
* GET /score/:agentId — x402-gated, compute + submit score on-chain
|
|
6
|
-
* GET /score/:agentId/current — free, read current on-chain score
|
|
7
|
-
* GET /health — service health
|
|
8
|
-
* GET /status — detailed status
|
|
9
|
-
* GET /agents/:agentId/details — agent details
|
|
10
|
-
*/
|
|
11
|
-
import axios from 'axios';
|
|
12
|
-
import { AgetherError } from '../types';
|
|
13
|
-
import { X402Client } from './X402Client';
|
|
14
|
-
export class ScoringClient {
|
|
15
|
-
constructor(config) {
|
|
16
|
-
this.endpoint = config.endpoint;
|
|
17
|
-
this.client = axios.create({
|
|
18
|
-
baseURL: config.endpoint,
|
|
19
|
-
headers: { 'Content-Type': 'application/json' },
|
|
20
|
-
timeout: 30000,
|
|
21
|
-
});
|
|
22
|
-
if (config.x402) {
|
|
23
|
-
this.x402Client = new X402Client(config.x402);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
// ════════════════════════════════════════════════════════
|
|
27
|
-
// Score (x402-gated — computes & submits on-chain)
|
|
28
|
-
// ════════════════════════════════════════════════════════
|
|
29
|
-
/**
|
|
30
|
-
* Request a fresh score computation.
|
|
31
|
-
*
|
|
32
|
-
* This is x402-gated: the backend returns 402, the X402Client
|
|
33
|
-
* signs an EIP-3009 payment, and the backend computes + submits
|
|
34
|
-
* the score on-chain via AgentReputation.submitScore().
|
|
35
|
-
*
|
|
36
|
-
* Returns the ScoreResult with breakdown and txHash.
|
|
37
|
-
*/
|
|
38
|
-
async requestScore(agentId) {
|
|
39
|
-
const id = agentId.toString();
|
|
40
|
-
if (!this.x402Client) {
|
|
41
|
-
throw new AgetherError('x402 config required for paid scoring. Provide x402 in ScoringClientConfig.', 'X402_NOT_CONFIGURED');
|
|
42
|
-
}
|
|
43
|
-
const result = await this.x402Client.get(`${this.endpoint}/score/${id}`);
|
|
44
|
-
if (!result.success || !result.data) {
|
|
45
|
-
throw new AgetherError(`Scoring request failed: ${result.error || 'unknown error'}`, 'SCORING_FAILED');
|
|
46
|
-
}
|
|
47
|
-
return result.data;
|
|
48
|
-
}
|
|
49
|
-
// ════════════════════════════════════════════════════════
|
|
50
|
-
// Current Score (free — reads on-chain)
|
|
51
|
-
// ════════════════════════════════════════════════════════
|
|
52
|
-
/**
|
|
53
|
-
* Get the current on-chain score (free, no payment required).
|
|
54
|
-
*/
|
|
55
|
-
async getCurrentScore(agentId) {
|
|
56
|
-
const response = await this.client.get(`/score/${agentId.toString()}/current`);
|
|
57
|
-
return response.data;
|
|
58
|
-
}
|
|
59
|
-
// ════════════════════════════════════════════════════════
|
|
60
|
-
// Agent Details
|
|
61
|
-
// ════════════════════════════════════════════════════════
|
|
62
|
-
/**
|
|
63
|
-
* Get detailed agent info from backend.
|
|
64
|
-
*/
|
|
65
|
-
async getAgentDetails(agentId) {
|
|
66
|
-
const response = await this.client.get(`/agents/${agentId.toString()}/details`);
|
|
67
|
-
return response.data;
|
|
68
|
-
}
|
|
69
|
-
// ════════════════════════════════════════════════════════
|
|
70
|
-
// Service Status
|
|
71
|
-
// ════════════════════════════════════════════════════════
|
|
72
|
-
/**
|
|
73
|
-
* Health check.
|
|
74
|
-
*/
|
|
75
|
-
async getHealth() {
|
|
76
|
-
const response = await this.client.get('/health');
|
|
77
|
-
return response.data;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Detailed status (contracts, signer, chain).
|
|
81
|
-
*/
|
|
82
|
-
async getStatus() {
|
|
83
|
-
const response = await this.client.get('/status');
|
|
84
|
-
return response.data;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Agent count and list.
|
|
88
|
-
*/
|
|
89
|
-
async getAgentCount() {
|
|
90
|
-
const response = await this.client.get('/agents/count');
|
|
91
|
-
return response.data;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* x402 HTTP Client — Make paid API calls via the x402 protocol (v2)
|
|
3
|
-
*
|
|
4
|
-
* Built on top of the official @x402/fetch + @x402/evm SDK.
|
|
5
|
-
* https://docs.x402.org/getting-started/quickstart-for-buyers
|
|
6
|
-
*
|
|
7
|
-
* Flow:
|
|
8
|
-
* 1. Client → Resource Server (normal request)
|
|
9
|
-
* 2. Resource Server → 402 with PAYMENT-REQUIRED header (base64 JSON)
|
|
10
|
-
* 3. @x402/fetch auto-picks PaymentRequirements, signs EIP-3009 via EVM scheme
|
|
11
|
-
* 4. Client → Resource Server (retries with PAYMENT-SIGNATURE header)
|
|
12
|
-
* 5. Resource Server → verifies via facilitator → settles → 200 + data
|
|
13
|
-
*
|
|
14
|
-
* Auto-Draw: When autoDraw is enabled and USDC balance is insufficient,
|
|
15
|
-
* the client automatically borrows from Morpho Blue before paying.
|
|
16
|
-
*
|
|
17
|
-
* Spending Limits: Optional daily spending cap (dailySpendLimitUsdc) and
|
|
18
|
-
* yield-limited spending (yieldLimitedSpending) to keep borrows within
|
|
19
|
-
* theoretical collateral yield.
|
|
20
|
-
*
|
|
21
|
-
* Chain support: Base (8453), Base Sepolia (84532), Ethereum (1).
|
|
22
|
-
*/
|
|
23
|
-
export interface X402Config {
|
|
24
|
-
privateKey: string;
|
|
25
|
-
rpcUrl: string;
|
|
26
|
-
backendUrl: string;
|
|
27
|
-
agentId?: string;
|
|
28
|
-
accountAddress?: string;
|
|
29
|
-
/**
|
|
30
|
-
* Auto-draw: automatically borrow from Morpho Blue when USDC balance
|
|
31
|
-
* is insufficient for x402 payment. Requires agentId to be set.
|
|
32
|
-
* Default: false
|
|
33
|
-
*/
|
|
34
|
-
autoDraw?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Daily spending limit in USDC (e.g. '100' for $100/day).
|
|
37
|
-
* Tracks cumulative daily borrows and rejects auto-draw if exceeded.
|
|
38
|
-
*/
|
|
39
|
-
dailySpendLimitUsdc?: string;
|
|
40
|
-
/**
|
|
41
|
-
* When true, auto-calculates the daily spending limit based on
|
|
42
|
-
* theoretical yield of deposited collateral. Overrides dailySpendLimitUsdc.
|
|
43
|
-
*/
|
|
44
|
-
yieldLimitedSpending?: boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Safety margin: borrow this much extra beyond what's needed (in USDC, e.g. '1').
|
|
47
|
-
* Helps avoid rounding issues. Default: '0.5'
|
|
48
|
-
*/
|
|
49
|
-
autoDrawBuffer?: string;
|
|
50
|
-
}
|
|
51
|
-
export interface X402Response<T = unknown> {
|
|
52
|
-
success: boolean;
|
|
53
|
-
data?: T;
|
|
54
|
-
error?: string;
|
|
55
|
-
paymentInfo?: {
|
|
56
|
-
amount: string;
|
|
57
|
-
asset: string;
|
|
58
|
-
network: string;
|
|
59
|
-
txHash?: string;
|
|
60
|
-
};
|
|
61
|
-
autoDrawInfo?: {
|
|
62
|
-
borrowed: string;
|
|
63
|
-
borrowTx: string;
|
|
64
|
-
reason: string;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/** One item inside the `accepts` array returned by the resource server */
|
|
68
|
-
export interface PaymentRequirements {
|
|
69
|
-
scheme: string;
|
|
70
|
-
network: string;
|
|
71
|
-
amount: string;
|
|
72
|
-
asset: string;
|
|
73
|
-
payTo: string;
|
|
74
|
-
maxTimeoutSeconds: number;
|
|
75
|
-
extra?: Record<string, unknown>;
|
|
76
|
-
}
|
|
77
|
-
/** Spending tracker — tracks cumulative daily borrows */
|
|
78
|
-
export interface SpendingTracker {
|
|
79
|
-
/** Date string (YYYY-MM-DD UTC) */
|
|
80
|
-
date: string;
|
|
81
|
-
/** Cumulative USDC borrowed today (6 decimal raw units) */
|
|
82
|
-
totalBorrowed: bigint;
|
|
83
|
-
/** Daily limit in raw units (6 decimals), 0 = unlimited */
|
|
84
|
-
dailyLimit: bigint;
|
|
85
|
-
}
|
|
86
|
-
export declare class X402Client {
|
|
87
|
-
private config;
|
|
88
|
-
private paidFetch;
|
|
89
|
-
private address;
|
|
90
|
-
private _spendingTracker;
|
|
91
|
-
constructor(config: X402Config);
|
|
92
|
-
get<T = unknown>(url: string, opts?: RequestInit): Promise<X402Response<T>>;
|
|
93
|
-
post<T = unknown>(url: string, body?: unknown, opts?: RequestInit): Promise<X402Response<T>>;
|
|
94
|
-
getAddress(): string;
|
|
95
|
-
/** Get the current spending tracker state */
|
|
96
|
-
getSpendingTracker(): SpendingTracker;
|
|
97
|
-
/** Get remaining daily spending allowance in USDC (human-readable) */
|
|
98
|
-
getRemainingDailyAllowance(): string;
|
|
99
|
-
/**
|
|
100
|
-
* Pay with auto-draw: Make an x402 request with automatic Morpho borrowing.
|
|
101
|
-
*
|
|
102
|
-
* Flow:
|
|
103
|
-
* 1. Check USDC balance on AgentAccount
|
|
104
|
-
* 2. Probe the URL to discover payment amount (if 402)
|
|
105
|
-
* 3. If insufficient USDC, calculate deficit
|
|
106
|
-
* 4. Check spending limit
|
|
107
|
-
* 5. Borrow from Morpho via MorphoClient
|
|
108
|
-
* 6. Proceed with x402 payment
|
|
109
|
-
*/
|
|
110
|
-
payWithAutoDraw<T = unknown>(url: string, opts?: RequestInit & {
|
|
111
|
-
morphoClient?: any;
|
|
112
|
-
}): Promise<X402Response<T>>;
|
|
113
|
-
private request;
|
|
114
|
-
/**
|
|
115
|
-
* Probe a URL to discover payment requirements without paying.
|
|
116
|
-
* Makes a request and parses the 402 PAYMENT-REQUIRED header.
|
|
117
|
-
* @returns Payment amount in raw USDC units (6 decimals), or null if not a 402.
|
|
118
|
-
*/
|
|
119
|
-
private _probePaymentAmount;
|
|
120
|
-
/** Reset spending tracker if it's a new day */
|
|
121
|
-
private _resetTrackerIfNewDay;
|
|
122
|
-
/** Track a new spending amount */
|
|
123
|
-
private _trackSpending;
|
|
124
|
-
/**
|
|
125
|
-
* Check if a borrow amount is within spending limits.
|
|
126
|
-
* Considers both fixed daily limits and yield-limited spending.
|
|
127
|
-
*/
|
|
128
|
-
private _checkSpendingLimit;
|
|
129
|
-
}
|
|
130
|
-
//# sourceMappingURL=X402Client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"X402Client.d.ts","sourceRoot":"","sources":["../../src/clients/X402Client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,MAAM,EAAE,UAAU;IAyBxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAI3E,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IASlG,UAAU,IAAI,MAAM;IAIpB,6CAA6C;IAC7C,kBAAkB,IAAI,eAAe;IAKrC,sEAAsE;IACtE,0BAA0B,IAAI,MAAM;IAOpC;;;;;;;;;;OAUG;IACG,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/B,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,WAAW,GAAG;QAAE,YAAY,CAAC,EAAE,GAAG,CAAA;KAAE,GAC1C,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YA+Eb,OAAO;IAyDrB;;;;OAIG;YACW,mBAAmB;IAiCjC,+CAA+C;IAC/C,OAAO,CAAC,qBAAqB;IAW7B,kCAAkC;IAClC,OAAO,CAAC,cAAc;IAKtB;;;OAGG;YACW,mBAAmB;CAoDlC"}
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* x402 HTTP Client — Make paid API calls via the x402 protocol (v2)
|
|
3
|
-
*
|
|
4
|
-
* Built on top of the official @x402/fetch + @x402/evm SDK.
|
|
5
|
-
* https://docs.x402.org/getting-started/quickstart-for-buyers
|
|
6
|
-
*
|
|
7
|
-
* Flow:
|
|
8
|
-
* 1. Client → Resource Server (normal request)
|
|
9
|
-
* 2. Resource Server → 402 with PAYMENT-REQUIRED header (base64 JSON)
|
|
10
|
-
* 3. @x402/fetch auto-picks PaymentRequirements, signs EIP-3009 via EVM scheme
|
|
11
|
-
* 4. Client → Resource Server (retries with PAYMENT-SIGNATURE header)
|
|
12
|
-
* 5. Resource Server → verifies via facilitator → settles → 200 + data
|
|
13
|
-
*
|
|
14
|
-
* Auto-Draw: When autoDraw is enabled and USDC balance is insufficient,
|
|
15
|
-
* the client automatically borrows from Morpho Blue before paying.
|
|
16
|
-
*
|
|
17
|
-
* Spending Limits: Optional daily spending cap (dailySpendLimitUsdc) and
|
|
18
|
-
* yield-limited spending (yieldLimitedSpending) to keep borrows within
|
|
19
|
-
* theoretical collateral yield.
|
|
20
|
-
*
|
|
21
|
-
* Chain support: Base (8453), Base Sepolia (84532), Ethereum (1).
|
|
22
|
-
*/
|
|
23
|
-
import { wrapFetchWithPayment } from '@x402/fetch';
|
|
24
|
-
import { x402Client } from '@x402/core/client';
|
|
25
|
-
import { registerExactEvmScheme } from '@x402/evm/exact/client';
|
|
26
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
27
|
-
// ──────────────────── Client ────────────────────
|
|
28
|
-
export class X402Client {
|
|
29
|
-
constructor(config) {
|
|
30
|
-
this.config = config;
|
|
31
|
-
// Create viem signer from private key
|
|
32
|
-
const privateKey = config.privateKey.startsWith('0x')
|
|
33
|
-
? config.privateKey
|
|
34
|
-
: `0x${config.privateKey}`;
|
|
35
|
-
const signer = privateKeyToAccount(privateKey);
|
|
36
|
-
this.address = signer.address;
|
|
37
|
-
// Create x402 client and register EVM scheme (handles EIP-3009 signing)
|
|
38
|
-
const client = new x402Client();
|
|
39
|
-
registerExactEvmScheme(client, { signer });
|
|
40
|
-
// Wrap native fetch with automatic 402 payment handling
|
|
41
|
-
this.paidFetch = wrapFetchWithPayment(fetch, client);
|
|
42
|
-
// Initialize spending tracker
|
|
43
|
-
const today = new Date().toISOString().split('T')[0];
|
|
44
|
-
const dailyLimit = config.dailySpendLimitUsdc
|
|
45
|
-
? BigInt(Math.round(parseFloat(config.dailySpendLimitUsdc) * 1e6))
|
|
46
|
-
: 0n;
|
|
47
|
-
this._spendingTracker = { date: today, totalBorrowed: 0n, dailyLimit };
|
|
48
|
-
}
|
|
49
|
-
async get(url, opts) {
|
|
50
|
-
return this.request(url, { ...opts, method: 'GET' });
|
|
51
|
-
}
|
|
52
|
-
async post(url, body, opts) {
|
|
53
|
-
return this.request(url, {
|
|
54
|
-
...opts,
|
|
55
|
-
method: 'POST',
|
|
56
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
57
|
-
headers: { 'Content-Type': 'application/json', ...opts?.headers },
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
getAddress() {
|
|
61
|
-
return this.address;
|
|
62
|
-
}
|
|
63
|
-
/** Get the current spending tracker state */
|
|
64
|
-
getSpendingTracker() {
|
|
65
|
-
this._resetTrackerIfNewDay();
|
|
66
|
-
return { ...this._spendingTracker };
|
|
67
|
-
}
|
|
68
|
-
/** Get remaining daily spending allowance in USDC (human-readable) */
|
|
69
|
-
getRemainingDailyAllowance() {
|
|
70
|
-
this._resetTrackerIfNewDay();
|
|
71
|
-
if (this._spendingTracker.dailyLimit === 0n)
|
|
72
|
-
return 'unlimited';
|
|
73
|
-
const remaining = this._spendingTracker.dailyLimit - this._spendingTracker.totalBorrowed;
|
|
74
|
-
return (Number(remaining > 0n ? remaining : 0n) / 1e6).toFixed(2);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Pay with auto-draw: Make an x402 request with automatic Morpho borrowing.
|
|
78
|
-
*
|
|
79
|
-
* Flow:
|
|
80
|
-
* 1. Check USDC balance on AgentAccount
|
|
81
|
-
* 2. Probe the URL to discover payment amount (if 402)
|
|
82
|
-
* 3. If insufficient USDC, calculate deficit
|
|
83
|
-
* 4. Check spending limit
|
|
84
|
-
* 5. Borrow from Morpho via MorphoClient
|
|
85
|
-
* 6. Proceed with x402 payment
|
|
86
|
-
*/
|
|
87
|
-
async payWithAutoDraw(url, opts) {
|
|
88
|
-
const { morphoClient, ...fetchOpts } = opts || {};
|
|
89
|
-
// If auto-draw is not enabled or no morphoClient, fall back to normal request
|
|
90
|
-
if (!this.config.autoDraw || !morphoClient) {
|
|
91
|
-
return this.request(url, fetchOpts);
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
// Step 1: Check current USDC balance on AgentAccount
|
|
95
|
-
const usdcBalance = await morphoClient.getUsdcBalance();
|
|
96
|
-
console.log(` [auto-draw] AgentAccount USDC balance: ${(Number(usdcBalance) / 1e6).toFixed(2)}`);
|
|
97
|
-
// Step 2: Probe the URL to discover payment amount
|
|
98
|
-
const paymentAmount = await this._probePaymentAmount(url, fetchOpts);
|
|
99
|
-
if (paymentAmount !== null) {
|
|
100
|
-
console.log(` [auto-draw] Payment required: ${(Number(paymentAmount) / 1e6).toFixed(6)} USDC`);
|
|
101
|
-
// Step 3: Check if we need to borrow
|
|
102
|
-
const bufferStr = this.config.autoDrawBuffer || '0.5';
|
|
103
|
-
const buffer = BigInt(Math.round(parseFloat(bufferStr) * 1e6));
|
|
104
|
-
const needed = paymentAmount + buffer;
|
|
105
|
-
if (usdcBalance < needed) {
|
|
106
|
-
const deficit = needed - usdcBalance;
|
|
107
|
-
console.log(` [auto-draw] Insufficient balance. Need to borrow ${(Number(deficit) / 1e6).toFixed(2)} USDC`);
|
|
108
|
-
// Step 4: Check spending limits
|
|
109
|
-
const limitCheck = await this._checkSpendingLimit(deficit, morphoClient);
|
|
110
|
-
if (!limitCheck.allowed) {
|
|
111
|
-
return {
|
|
112
|
-
success: false,
|
|
113
|
-
error: `Auto-draw blocked: ${limitCheck.reason}`,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
// Step 5: Check if borrowing is possible (collateral check)
|
|
117
|
-
const maxBorrowable = await morphoClient.getMaxBorrowable();
|
|
118
|
-
if (maxBorrowable.total < deficit) {
|
|
119
|
-
return {
|
|
120
|
-
success: false,
|
|
121
|
-
error: `Auto-draw failed: insufficient collateral. Need ${(Number(deficit) / 1e6).toFixed(2)} USDC but can only borrow ${(Number(maxBorrowable.total) / 1e6).toFixed(2)} USDC more.`,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
// Step 6: Borrow the deficit
|
|
125
|
-
const borrowAmount = (Number(deficit) / 1e6).toFixed(6);
|
|
126
|
-
console.log(` [auto-draw] Borrowing ${borrowAmount} USDC from Morpho...`);
|
|
127
|
-
const borrowResult = await morphoClient.borrow(borrowAmount);
|
|
128
|
-
console.log(` [auto-draw] Borrow tx: ${borrowResult.tx}`);
|
|
129
|
-
// Track spending
|
|
130
|
-
this._trackSpending(deficit);
|
|
131
|
-
// Step 7: Now proceed with the x402 payment
|
|
132
|
-
const result = await this.request(url, fetchOpts);
|
|
133
|
-
return {
|
|
134
|
-
...result,
|
|
135
|
-
autoDrawInfo: {
|
|
136
|
-
borrowed: borrowAmount,
|
|
137
|
-
borrowTx: borrowResult.tx,
|
|
138
|
-
reason: `USDC balance insufficient (had ${(Number(usdcBalance) / 1e6).toFixed(2)}, needed ${(Number(needed) / 1e6).toFixed(2)})`,
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// Balance sufficient or couldn't determine amount — proceed normally
|
|
144
|
-
return this.request(url, fetchOpts);
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
// If auto-draw fails, still try the normal request
|
|
148
|
-
console.log(` [auto-draw] Auto-draw check failed: ${error instanceof Error ? error.message : String(error)}. Proceeding with normal request.`);
|
|
149
|
-
return this.request(url, fetchOpts);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// ──────────── Core request — @x402/fetch handles 402 automatically ────────────
|
|
153
|
-
async request(url, options) {
|
|
154
|
-
try {
|
|
155
|
-
console.log(` [x402] ${options?.method || 'GET'} ${url}`);
|
|
156
|
-
const response = await this.paidFetch(url, {
|
|
157
|
-
...options,
|
|
158
|
-
headers: {
|
|
159
|
-
...options?.headers,
|
|
160
|
-
'X-Agent-Id': this.config.agentId || '',
|
|
161
|
-
},
|
|
162
|
-
});
|
|
163
|
-
if (response.ok) {
|
|
164
|
-
const data = await response.json();
|
|
165
|
-
// Check for settlement response header
|
|
166
|
-
const paymentResponse = response.headers.get('PAYMENT-RESPONSE');
|
|
167
|
-
let txHash;
|
|
168
|
-
if (paymentResponse) {
|
|
169
|
-
try {
|
|
170
|
-
const settlement = JSON.parse(Buffer.from(paymentResponse, 'base64').toString('utf-8'));
|
|
171
|
-
txHash = settlement.transaction;
|
|
172
|
-
}
|
|
173
|
-
catch { /* ignore */ }
|
|
174
|
-
}
|
|
175
|
-
return {
|
|
176
|
-
success: true,
|
|
177
|
-
data,
|
|
178
|
-
...(txHash ? {
|
|
179
|
-
paymentInfo: {
|
|
180
|
-
amount: '',
|
|
181
|
-
asset: 'USDC',
|
|
182
|
-
network: 'eip155:8453',
|
|
183
|
-
txHash,
|
|
184
|
-
},
|
|
185
|
-
} : {}),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
// If we get here, @x402/fetch already tried to pay but the server rejected
|
|
189
|
-
const errBody = await response.text();
|
|
190
|
-
return {
|
|
191
|
-
success: false,
|
|
192
|
-
error: `HTTP ${response.status}: ${errBody}`,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
catch (error) {
|
|
196
|
-
return {
|
|
197
|
-
success: false,
|
|
198
|
-
error: `Request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// ──────────── Auto-Draw Helpers ────────────
|
|
203
|
-
/**
|
|
204
|
-
* Probe a URL to discover payment requirements without paying.
|
|
205
|
-
* Makes a request and parses the 402 PAYMENT-REQUIRED header.
|
|
206
|
-
* @returns Payment amount in raw USDC units (6 decimals), or null if not a 402.
|
|
207
|
-
*/
|
|
208
|
-
async _probePaymentAmount(url, options) {
|
|
209
|
-
try {
|
|
210
|
-
const response = await fetch(url, {
|
|
211
|
-
...options,
|
|
212
|
-
headers: {
|
|
213
|
-
...options?.headers,
|
|
214
|
-
'X-Agent-Id': this.config.agentId || '',
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
if (response.status !== 402)
|
|
218
|
-
return null;
|
|
219
|
-
// Parse PAYMENT-REQUIRED header (base64 JSON)
|
|
220
|
-
const paymentHeader = response.headers.get('X-PAYMENT') || response.headers.get('PAYMENT-REQUIRED');
|
|
221
|
-
if (!paymentHeader)
|
|
222
|
-
return null;
|
|
223
|
-
try {
|
|
224
|
-
const decoded = JSON.parse(Buffer.from(paymentHeader, 'base64').toString('utf-8'));
|
|
225
|
-
const requirements = Array.isArray(decoded) ? decoded : decoded.accepts || [decoded];
|
|
226
|
-
if (requirements.length > 0) {
|
|
227
|
-
const amount = requirements[0].maxAmountRequired || requirements[0].amount;
|
|
228
|
-
if (amount) {
|
|
229
|
-
return BigInt(amount);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
catch { /* parse failed */ }
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
catch {
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
/** Reset spending tracker if it's a new day */
|
|
241
|
-
_resetTrackerIfNewDay() {
|
|
242
|
-
const today = new Date().toISOString().split('T')[0];
|
|
243
|
-
if (this._spendingTracker.date !== today) {
|
|
244
|
-
this._spendingTracker = {
|
|
245
|
-
date: today,
|
|
246
|
-
totalBorrowed: 0n,
|
|
247
|
-
dailyLimit: this._spendingTracker.dailyLimit,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
/** Track a new spending amount */
|
|
252
|
-
_trackSpending(amount) {
|
|
253
|
-
this._resetTrackerIfNewDay();
|
|
254
|
-
this._spendingTracker.totalBorrowed += amount;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Check if a borrow amount is within spending limits.
|
|
258
|
-
* Considers both fixed daily limits and yield-limited spending.
|
|
259
|
-
*/
|
|
260
|
-
async _checkSpendingLimit(amount, morphoClient) {
|
|
261
|
-
this._resetTrackerIfNewDay();
|
|
262
|
-
// If yield-limited spending is enabled, calculate dynamic limit
|
|
263
|
-
if (this.config.yieldLimitedSpending) {
|
|
264
|
-
try {
|
|
265
|
-
const status = await morphoClient.getStatus();
|
|
266
|
-
let totalDailyYieldUsdc = 0;
|
|
267
|
-
for (const pos of status.positions) {
|
|
268
|
-
if (parseFloat(pos.collateral) > 0) {
|
|
269
|
-
try {
|
|
270
|
-
const estimate = await morphoClient.getYieldEstimate(pos.collateralToken, pos.collateral, 1);
|
|
271
|
-
totalDailyYieldUsdc += estimate.estimatedYieldUsd;
|
|
272
|
-
}
|
|
273
|
-
catch { /* skip markets where yield calc fails */ }
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
const yieldLimit = BigInt(Math.round(totalDailyYieldUsdc * 1e6));
|
|
277
|
-
const newTotal = this._spendingTracker.totalBorrowed + amount;
|
|
278
|
-
if (yieldLimit > 0n && newTotal > yieldLimit) {
|
|
279
|
-
return {
|
|
280
|
-
allowed: false,
|
|
281
|
-
reason: `Yield-limited spending exceeded. Daily yield cap: $${(Number(yieldLimit) / 1e6).toFixed(2)}, already spent: $${(Number(this._spendingTracker.totalBorrowed) / 1e6).toFixed(2)}, requested: $${(Number(amount) / 1e6).toFixed(2)}`,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
catch {
|
|
286
|
-
// If yield calculation fails, fall through to fixed limit check
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
// Check fixed daily limit
|
|
290
|
-
if (this._spendingTracker.dailyLimit > 0n) {
|
|
291
|
-
const newTotal = this._spendingTracker.totalBorrowed + amount;
|
|
292
|
-
if (newTotal > this._spendingTracker.dailyLimit) {
|
|
293
|
-
return {
|
|
294
|
-
allowed: false,
|
|
295
|
-
reason: `Daily spending limit exceeded. Limit: $${(Number(this._spendingTracker.dailyLimit) / 1e6).toFixed(2)}, already spent: $${(Number(this._spendingTracker.totalBorrowed) / 1e6).toFixed(2)}, requested: $${(Number(amount) / 1e6).toFixed(2)}`,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return { allowed: true };
|
|
300
|
-
}
|
|
301
|
-
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,sBAAsB,EACtB,WAAW,EACX,cAAc,EACd,UAAU,GACX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,YAAY,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAI3G,cAAc,SAAS,CAAC;AAIxB,OAAO,EACL,UAAU,EACV,WAAW,EACX,SAAS,EACT,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,SAAS,EACT,SAAS,GACV,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,eAAe,EACf,SAAS,GACV,MAAM,cAAc,CAAC;AAItB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|