@x402janus/sdk 0.1.0
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/README.md +94 -0
- package/dist/client.d.ts +81 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +212 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/payment.d.ts +31 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +186 -0
- package/dist/payment.js.map +1 -0
- package/dist/types.d.ts +412 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +147 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @x402janus/sdk
|
|
2
|
+
|
|
3
|
+
Wallet security for AI agents. One API call. Forensic wallet analysis. Deterministic risk score.
|
|
4
|
+
|
|
5
|
+
**x402-native** — no API keys, no accounts. Your agent pays per scan with USDC on Base.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @x402janus/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { JanusClient } from "@x402janus/sdk";
|
|
17
|
+
|
|
18
|
+
const janus = new JanusClient({
|
|
19
|
+
privateKey: process.env.PRIVATE_KEY, // Agent wallet key
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const result = await janus.scan("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18");
|
|
23
|
+
|
|
24
|
+
if (result.safe) {
|
|
25
|
+
// proceed with transaction
|
|
26
|
+
} else {
|
|
27
|
+
console.log("Blocked:", result.findings);
|
|
28
|
+
console.log("Revoke txs:", result.revokeTxs);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How Payment Works
|
|
33
|
+
|
|
34
|
+
1. Your agent calls `janus.scan(address)`
|
|
35
|
+
2. The SDK hits the x402janus API, which returns HTTP 402 with payment requirements
|
|
36
|
+
3. The SDK signs an EIP-3009 `TransferWithAuthorization` for the required USDC amount
|
|
37
|
+
4. The signed payment is sent in the `X-PAYMENT` header on retry
|
|
38
|
+
5. The Thirdweb facilitator verifies and settles USDC on Base
|
|
39
|
+
6. Scan results are returned
|
|
40
|
+
|
|
41
|
+
**Your agent needs:**
|
|
42
|
+
- A private key (for signing — never sent to the API)
|
|
43
|
+
- USDC on Base (for scan payments)
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `new JanusClient(config?)`
|
|
48
|
+
|
|
49
|
+
| Option | Type | Default | Description |
|
|
50
|
+
|--------|------|---------|-------------|
|
|
51
|
+
| `privateKey` | `string` | `process.env.PRIVATE_KEY` | Agent wallet private key |
|
|
52
|
+
| `baseUrl` | `string` | `https://x402janus.com` | API endpoint |
|
|
53
|
+
| `defaultTier` | `"quick" \| "standard" \| "deep"` | `"quick"` | Default scan tier |
|
|
54
|
+
|
|
55
|
+
### `janus.scan(address, options?)`
|
|
56
|
+
|
|
57
|
+
Scan a wallet for security risks.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const result = await janus.scan("0x...", { tier: "deep" });
|
|
61
|
+
// result: { scanId, safe, risk, findings, revokeTxs }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `janus.approvals(address)`
|
|
65
|
+
|
|
66
|
+
List active token approvals with risk assessment.
|
|
67
|
+
|
|
68
|
+
### `janus.revoke(address)`
|
|
69
|
+
|
|
70
|
+
Get pre-built revoke transactions for dangerous approvals.
|
|
71
|
+
|
|
72
|
+
### `janus.health()`
|
|
73
|
+
|
|
74
|
+
Check API health status.
|
|
75
|
+
|
|
76
|
+
## Scan Tiers
|
|
77
|
+
|
|
78
|
+
| Tier | Price | Response Time | Coverage |
|
|
79
|
+
|------|-------|---------------|----------|
|
|
80
|
+
| `quick` | $0.01 | <3s | Deterministic risk score, approval list |
|
|
81
|
+
| `standard` | $0.05 | <10s | + AI threat analysis |
|
|
82
|
+
| `deep` | $0.25 | <30s | + Full graph analysis, drainer fingerprinting |
|
|
83
|
+
|
|
84
|
+
## Types
|
|
85
|
+
|
|
86
|
+
All types are exported with Zod schemas for runtime validation:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { ScanResult, ScanResultSchema, Finding, RevokeTx } from "@x402janus/sdk";
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module client
|
|
3
|
+
* JanusClient — the main entry point for @x402janus/sdk.
|
|
4
|
+
*
|
|
5
|
+
* Performs wallet security scans via the x402janus API with x402 micropayment.
|
|
6
|
+
*/
|
|
7
|
+
import { type ScanResult, type ApprovalsResult, type RevokeTx, type HealthResult, type JanusClientConfig, type ScanOptions } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* JanusClient — scan wallets for security risks via x402janus.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { JanusClient } from "@x402janus/sdk";
|
|
14
|
+
*
|
|
15
|
+
* const janus = new JanusClient({ privateKey: process.env.PRIVATE_KEY });
|
|
16
|
+
* const result = await janus.scan("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18");
|
|
17
|
+
*
|
|
18
|
+
* if (result.safe) {
|
|
19
|
+
* // proceed with transaction
|
|
20
|
+
* } else {
|
|
21
|
+
* console.log("Blocked:", result.findings);
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class JanusClient {
|
|
26
|
+
private readonly baseUrl;
|
|
27
|
+
private readonly privateKey;
|
|
28
|
+
private readonly defaultTier;
|
|
29
|
+
private readonly facilitatorUrl;
|
|
30
|
+
constructor(config?: JanusClientConfig);
|
|
31
|
+
/**
|
|
32
|
+
* Scan a wallet for security risks.
|
|
33
|
+
*
|
|
34
|
+
* @param address - Ethereum wallet address (0x...)
|
|
35
|
+
* @param options - Optional scan configuration
|
|
36
|
+
* @returns Structured scan result with risk score, findings, and revoke transactions
|
|
37
|
+
* @throws If the address is invalid, payment fails, or the API returns an error
|
|
38
|
+
*/
|
|
39
|
+
scan(address: string, options?: ScanOptions): Promise<ScanResult>;
|
|
40
|
+
/**
|
|
41
|
+
* List all active token approvals for a wallet.
|
|
42
|
+
*
|
|
43
|
+
* @param address - Ethereum wallet address (0x...)
|
|
44
|
+
* @returns List of approvals with risk assessment
|
|
45
|
+
*/
|
|
46
|
+
approvals(address: string): Promise<ApprovalsResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Build revoke transactions for dangerous approvals.
|
|
49
|
+
*
|
|
50
|
+
* @param address - Ethereum wallet address (0x...)
|
|
51
|
+
* @returns Array of pre-built revoke transactions
|
|
52
|
+
*/
|
|
53
|
+
revoke(address: string): Promise<RevokeTx[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Check API health status.
|
|
56
|
+
*
|
|
57
|
+
* @returns Health status of the x402janus API
|
|
58
|
+
*/
|
|
59
|
+
health(): Promise<HealthResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Handle the x402 payment flow: parse 402 requirements, sign, retry.
|
|
62
|
+
*/
|
|
63
|
+
private handlePaymentFlow;
|
|
64
|
+
/**
|
|
65
|
+
* Extract payment requirements from a 402 response body.
|
|
66
|
+
*/
|
|
67
|
+
private extractPaymentRequirements;
|
|
68
|
+
/**
|
|
69
|
+
* Validate a scan result, enforcing the safety invariant.
|
|
70
|
+
*
|
|
71
|
+
* @param paid - Whether this response came after a verified payment.
|
|
72
|
+
* If false, `safe` is forced to `false` as a security measure.
|
|
73
|
+
*/
|
|
74
|
+
private validateScanResult;
|
|
75
|
+
/**
|
|
76
|
+
* Validate an Ethereum address.
|
|
77
|
+
* @throws If the address is not a valid 0x-prefixed hex string
|
|
78
|
+
*/
|
|
79
|
+
private validateAddress;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EASL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AASpB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,GAAE,iBAAsB;IAgB1C;;;;;;;OAOG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA2BvE;;;;;OAKG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA6B1D;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAKlD;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAWrC;;OAEG;YACW,iBAAiB;IA6D/B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAclC;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACH,OAAO,CAAC,eAAe;CAKxB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module client
|
|
3
|
+
* JanusClient — the main entry point for @x402janus/sdk.
|
|
4
|
+
*
|
|
5
|
+
* Performs wallet security scans via the x402janus API with x402 micropayment.
|
|
6
|
+
*/
|
|
7
|
+
import { ScanTierSchema, ScanResultSchema, ApprovalsResultSchema, HealthResultSchema, PaymentRequirementsSchema, TIER_PRICES, } from "./types.js";
|
|
8
|
+
import { signX402Payment } from "./payment.js";
|
|
9
|
+
/** Ethereum address regex (0x + 40 hex chars) */
|
|
10
|
+
const ETH_ADDRESS = /^0x[a-fA-F0-9]{40}$/;
|
|
11
|
+
/** Maximum retry-after sleep (30 seconds) — prevents unbounded waits */
|
|
12
|
+
const MAX_RETRY_SLEEP_MS = 30_000;
|
|
13
|
+
/**
|
|
14
|
+
* JanusClient — scan wallets for security risks via x402janus.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { JanusClient } from "@x402janus/sdk";
|
|
19
|
+
*
|
|
20
|
+
* const janus = new JanusClient({ privateKey: process.env.PRIVATE_KEY });
|
|
21
|
+
* const result = await janus.scan("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18");
|
|
22
|
+
*
|
|
23
|
+
* if (result.safe) {
|
|
24
|
+
* // proceed with transaction
|
|
25
|
+
* } else {
|
|
26
|
+
* console.log("Blocked:", result.findings);
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class JanusClient {
|
|
31
|
+
baseUrl;
|
|
32
|
+
privateKey;
|
|
33
|
+
defaultTier;
|
|
34
|
+
facilitatorUrl;
|
|
35
|
+
constructor(config = {}) {
|
|
36
|
+
this.baseUrl = (config.baseUrl ?? "https://x402janus.com").replace(/\/$/, "");
|
|
37
|
+
this.defaultTier = config.defaultTier ?? "quick";
|
|
38
|
+
this.facilitatorUrl =
|
|
39
|
+
config.facilitatorUrl ??
|
|
40
|
+
process.env.FACILITATOR_URL ??
|
|
41
|
+
"https://x402.org";
|
|
42
|
+
// Resolve private key — never expose in errors
|
|
43
|
+
const pk = config.privateKey ?? process.env.PRIVATE_KEY;
|
|
44
|
+
this.privateKey = pk || undefined;
|
|
45
|
+
// Validate default tier
|
|
46
|
+
ScanTierSchema.parse(this.defaultTier);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Scan a wallet for security risks.
|
|
50
|
+
*
|
|
51
|
+
* @param address - Ethereum wallet address (0x...)
|
|
52
|
+
* @param options - Optional scan configuration
|
|
53
|
+
* @returns Structured scan result with risk score, findings, and revoke transactions
|
|
54
|
+
* @throws If the address is invalid, payment fails, or the API returns an error
|
|
55
|
+
*/
|
|
56
|
+
async scan(address, options) {
|
|
57
|
+
this.validateAddress(address);
|
|
58
|
+
const tier = options?.tier ?? this.defaultTier;
|
|
59
|
+
ScanTierSchema.parse(tier);
|
|
60
|
+
const url = `${this.baseUrl}/api/guardian/scan/${address}?tier=${tier}`;
|
|
61
|
+
// First request — expect 402 with payment requirements
|
|
62
|
+
const initial = await fetch(url, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
});
|
|
66
|
+
if (initial.status === 402) {
|
|
67
|
+
// Parse payment requirements and sign
|
|
68
|
+
return this.handlePaymentFlow(url, initial, tier);
|
|
69
|
+
}
|
|
70
|
+
if (initial.ok) {
|
|
71
|
+
// Free tier or already paid — parse and validate
|
|
72
|
+
const data = await initial.json();
|
|
73
|
+
return this.validateScanResult(data);
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Scan failed: HTTP ${initial.status} ${initial.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* List all active token approvals for a wallet.
|
|
79
|
+
*
|
|
80
|
+
* @param address - Ethereum wallet address (0x...)
|
|
81
|
+
* @returns List of approvals with risk assessment
|
|
82
|
+
*/
|
|
83
|
+
async approvals(address) {
|
|
84
|
+
this.validateAddress(address);
|
|
85
|
+
const url = `${this.baseUrl}/api/guardian/scan/${address}?tier=quick&mode=approvals`;
|
|
86
|
+
const initial = await fetch(url, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
});
|
|
90
|
+
if (initial.status === 402 && this.privateKey) {
|
|
91
|
+
const paymentResult = await this.handlePaymentFlow(url, initial, "quick");
|
|
92
|
+
// Map scan result to approvals format
|
|
93
|
+
return {
|
|
94
|
+
wallet: address,
|
|
95
|
+
approvals: [],
|
|
96
|
+
riskCount: { low: 0, medium: 0, high: 0, critical: 0 },
|
|
97
|
+
...paymentResult,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (initial.ok) {
|
|
101
|
+
const data = await initial.json();
|
|
102
|
+
return ApprovalsResultSchema.parse(data);
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`Approvals failed: HTTP ${initial.status}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build revoke transactions for dangerous approvals.
|
|
108
|
+
*
|
|
109
|
+
* @param address - Ethereum wallet address (0x...)
|
|
110
|
+
* @returns Array of pre-built revoke transactions
|
|
111
|
+
*/
|
|
112
|
+
async revoke(address) {
|
|
113
|
+
const result = await this.scan(address, { tier: "standard" });
|
|
114
|
+
return result.revokeTxs;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check API health status.
|
|
118
|
+
*
|
|
119
|
+
* @returns Health status of the x402janus API
|
|
120
|
+
*/
|
|
121
|
+
async health() {
|
|
122
|
+
const resp = await fetch(`${this.baseUrl}/api/health`);
|
|
123
|
+
if (!resp.ok) {
|
|
124
|
+
throw new Error(`Health check failed: HTTP ${resp.status}`);
|
|
125
|
+
}
|
|
126
|
+
const data = await resp.json();
|
|
127
|
+
return HealthResultSchema.parse(data);
|
|
128
|
+
}
|
|
129
|
+
// ─── Private helpers ─────────────────────────────────────────────────────
|
|
130
|
+
/**
|
|
131
|
+
* Handle the x402 payment flow: parse 402 requirements, sign, retry.
|
|
132
|
+
*/
|
|
133
|
+
async handlePaymentFlow(url, response, tier) {
|
|
134
|
+
if (!this.privateKey) {
|
|
135
|
+
throw new Error(`Scan tier "${tier}" (${TIER_PRICES[tier].dollars}) requires a private key for x402 payment. ` +
|
|
136
|
+
`Pass privateKey in config or set PRIVATE_KEY env var.`);
|
|
137
|
+
}
|
|
138
|
+
// Parse payment requirements from 402 response
|
|
139
|
+
const body = await response.json();
|
|
140
|
+
const requirements = this.extractPaymentRequirements(body);
|
|
141
|
+
// Sign the payment
|
|
142
|
+
const paymentHeader = await signX402Payment(this.privateKey, requirements);
|
|
143
|
+
// Retry with payment header
|
|
144
|
+
const paid = await fetch(url, {
|
|
145
|
+
method: "POST",
|
|
146
|
+
headers: {
|
|
147
|
+
"Content-Type": "application/json",
|
|
148
|
+
"X-PAYMENT": paymentHeader,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
// Handle retry-after (rate limiting)
|
|
152
|
+
if (paid.status === 429) {
|
|
153
|
+
const retryAfter = paid.headers.get("retry-after");
|
|
154
|
+
const sleepMs = Math.min((retryAfter ? parseInt(retryAfter, 10) * 1000 : 5000), MAX_RETRY_SLEEP_MS);
|
|
155
|
+
await new Promise((r) => setTimeout(r, sleepMs));
|
|
156
|
+
const retry = await fetch(url, {
|
|
157
|
+
method: "POST",
|
|
158
|
+
headers: {
|
|
159
|
+
"Content-Type": "application/json",
|
|
160
|
+
"X-PAYMENT": paymentHeader,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
if (!retry.ok) {
|
|
164
|
+
throw new Error(`Scan failed after retry: HTTP ${retry.status}`);
|
|
165
|
+
}
|
|
166
|
+
const data = await retry.json();
|
|
167
|
+
return this.validateScanResult(data, true);
|
|
168
|
+
}
|
|
169
|
+
if (!paid.ok) {
|
|
170
|
+
throw new Error(`Scan failed after payment: HTTP ${paid.status} ${paid.statusText}`);
|
|
171
|
+
}
|
|
172
|
+
const data = await paid.json();
|
|
173
|
+
return this.validateScanResult(data, true);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Extract payment requirements from a 402 response body.
|
|
177
|
+
*/
|
|
178
|
+
extractPaymentRequirements(body) {
|
|
179
|
+
if (typeof body !== "object" || body === null) {
|
|
180
|
+
throw new Error("Invalid 402 response: no payment requirements");
|
|
181
|
+
}
|
|
182
|
+
const obj = body;
|
|
183
|
+
const reqs = obj.paymentRequirements ?? obj.requirements ?? obj;
|
|
184
|
+
// Handle array format (take first)
|
|
185
|
+
const single = Array.isArray(reqs) ? reqs[0] : reqs;
|
|
186
|
+
return PaymentRequirementsSchema.parse(single);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Validate a scan result, enforcing the safety invariant.
|
|
190
|
+
*
|
|
191
|
+
* @param paid - Whether this response came after a verified payment.
|
|
192
|
+
* If false, `safe` is forced to `false` as a security measure.
|
|
193
|
+
*/
|
|
194
|
+
validateScanResult(data, paid = false) {
|
|
195
|
+
const result = ScanResultSchema.parse(data);
|
|
196
|
+
// Security invariant: never return safe=true without payment verification
|
|
197
|
+
if (!paid && result.safe) {
|
|
198
|
+
return { ...result, safe: false };
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Validate an Ethereum address.
|
|
204
|
+
* @throws If the address is not a valid 0x-prefixed hex string
|
|
205
|
+
*/
|
|
206
|
+
validateAddress(address) {
|
|
207
|
+
if (!ETH_ADDRESS.test(address)) {
|
|
208
|
+
throw new Error(`Invalid Ethereum address: ${address.slice(0, 10)}...`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @x402janus/sdk — AI wallet security for agents.
|
|
3
|
+
*
|
|
4
|
+
* One API call. Forensic wallet analysis. Deterministic risk score.
|
|
5
|
+
* x402-native pay-per-scan on Base.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { JanusClient } from "@x402janus/sdk";
|
|
10
|
+
*
|
|
11
|
+
* const janus = new JanusClient({ privateKey: process.env.PRIVATE_KEY });
|
|
12
|
+
* const result = await janus.scan("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18");
|
|
13
|
+
*
|
|
14
|
+
* if (result.safe) {
|
|
15
|
+
* // proceed with transaction
|
|
16
|
+
* } else {
|
|
17
|
+
* console.log("Blocked:", result.findings);
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
export { JanusClient } from "./client.js";
|
|
24
|
+
export type { ScanTier, ScanResult, Finding, FindingSeverity, RevokeTx, Approval, ApprovalsResult, HealthResult, JanusClientConfig, ScanOptions, PaymentRequirements, } from "./types.js";
|
|
25
|
+
export { ScanTierSchema, ScanResultSchema, FindingSchema, RevokeTxSchema, ApprovalSchema, ApprovalsResultSchema, HealthResultSchema, PaymentRequirementsSchema, TIER_PRICES, } from "./types.js";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,YAAY,EACV,QAAQ,EACR,UAAU,EACV,OAAO,EACP,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @x402janus/sdk — AI wallet security for agents.
|
|
3
|
+
*
|
|
4
|
+
* One API call. Forensic wallet analysis. Deterministic risk score.
|
|
5
|
+
* x402-native pay-per-scan on Base.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { JanusClient } from "@x402janus/sdk";
|
|
10
|
+
*
|
|
11
|
+
* const janus = new JanusClient({ privateKey: process.env.PRIVATE_KEY });
|
|
12
|
+
* const result = await janus.scan("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18");
|
|
13
|
+
*
|
|
14
|
+
* if (result.safe) {
|
|
15
|
+
* // proceed with transaction
|
|
16
|
+
* } else {
|
|
17
|
+
* console.log("Blocked:", result.findings);
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
export { JanusClient } from "./client.js";
|
|
24
|
+
// Re-export schemas for runtime validation
|
|
25
|
+
export { ScanTierSchema, ScanResultSchema, FindingSchema, RevokeTxSchema, ApprovalSchema, ApprovalsResultSchema, HealthResultSchema, PaymentRequirementsSchema, TIER_PRICES, } from "./types.js";
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiB1C,2CAA2C;AAC3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module payment
|
|
3
|
+
* x402 micropayment signing for @x402janus/sdk.
|
|
4
|
+
*
|
|
5
|
+
* Implements EIP-3009 TransferWithAuthorization — the standard used by
|
|
6
|
+
* Circle's USDC on Base. Signs the authorization using the agent's private
|
|
7
|
+
* key and encodes it as a base64 payload for the PAYMENT-SIGNATURE header.
|
|
8
|
+
*
|
|
9
|
+
* **Security**: The private key is used only within this module for signing.
|
|
10
|
+
* It is never included in return values, error messages, or console output.
|
|
11
|
+
*/
|
|
12
|
+
import type { PaymentRequirements } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* Sign an x402 payment using EIP-3009 TransferWithAuthorization.
|
|
15
|
+
*
|
|
16
|
+
* This implements the client side of the x402 payment protocol:
|
|
17
|
+
* 1. Builds the authorization parameters (from, to, value, validity window, nonce)
|
|
18
|
+
* 2. Signs them with the agent's private key via EIP-712
|
|
19
|
+
* 3. Encodes the signed payload as base64 for the `PAYMENT-SIGNATURE` header
|
|
20
|
+
*
|
|
21
|
+
* The function defaults to `TransferWithAuthorization` (EIP-3009) which is
|
|
22
|
+
* what Circle's USDC on Base supports. If the server's extra field specifies
|
|
23
|
+
* `primaryType: "Permit"`, an EIP-2612 Permit signature is used instead.
|
|
24
|
+
*
|
|
25
|
+
* @param privateKey - The payer's private key. **Never logged or thrown.**
|
|
26
|
+
* @param requirements - Payment requirements from the server's 402 response
|
|
27
|
+
* @returns Base64-encoded signed payment payload string
|
|
28
|
+
* @throws {Error} If scheme is unsupported or signing fails (key never exposed)
|
|
29
|
+
*/
|
|
30
|
+
export declare function signX402Payment(privateKey: `0x${string}`, requirements: PaymentRequirements): Promise<string>;
|
|
31
|
+
//# sourceMappingURL=payment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAkEtD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,KAAK,MAAM,EAAE,EACzB,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,MAAM,CAAC,CAgHjB"}
|
package/dist/payment.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module payment
|
|
3
|
+
* x402 micropayment signing for @x402janus/sdk.
|
|
4
|
+
*
|
|
5
|
+
* Implements EIP-3009 TransferWithAuthorization — the standard used by
|
|
6
|
+
* Circle's USDC on Base. Signs the authorization using the agent's private
|
|
7
|
+
* key and encodes it as a base64 payload for the PAYMENT-SIGNATURE header.
|
|
8
|
+
*
|
|
9
|
+
* **Security**: The private key is used only within this module for signing.
|
|
10
|
+
* It is never included in return values, error messages, or console output.
|
|
11
|
+
*/
|
|
12
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
13
|
+
import { toHex } from "viem";
|
|
14
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
15
|
+
/** x402 protocol version supported by this SDK */
|
|
16
|
+
const X402_VERSION = 2;
|
|
17
|
+
/** x402 schemes we can handle */
|
|
18
|
+
const SUPPORTED_SCHEMES = new Set(["exact"]);
|
|
19
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Parse an EVM chain ID from a CAIP-2 network identifier.
|
|
22
|
+
* @param network - e.g. "eip155:8453"
|
|
23
|
+
* @returns The chain ID as a number (e.g. 8453)
|
|
24
|
+
* @throws {Error} If the format is unrecognised
|
|
25
|
+
*/
|
|
26
|
+
function parseChainId(network) {
|
|
27
|
+
const match = /^eip155:(\d+)$/.exec(network);
|
|
28
|
+
if (!match || !match[1]) {
|
|
29
|
+
throw new Error(`Unsupported network format: "${network}". Expected "eip155:<chainId>".`);
|
|
30
|
+
}
|
|
31
|
+
return parseInt(match[1], 10);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate a cryptographically random 32-byte nonce for EIP-3009.
|
|
35
|
+
* Uses the Web Crypto API (available natively in Node.js 18+).
|
|
36
|
+
*
|
|
37
|
+
* EIP-3009 nonces are non-sequential bytes32 values; once used,
|
|
38
|
+
* the contract marks them as spent to prevent replay attacks.
|
|
39
|
+
*/
|
|
40
|
+
async function generateNonce() {
|
|
41
|
+
const bytes = new Uint8Array(32);
|
|
42
|
+
if (typeof globalThis !== "undefined" &&
|
|
43
|
+
typeof globalThis.crypto !== "undefined" &&
|
|
44
|
+
typeof globalThis.crypto.getRandomValues === "function") {
|
|
45
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Node.js without globalThis.crypto (older Node versions)
|
|
49
|
+
const { webcrypto } = await import("node:crypto");
|
|
50
|
+
webcrypto.getRandomValues(bytes);
|
|
51
|
+
}
|
|
52
|
+
return toHex(bytes);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Base64-encode a string (works in both Node.js and browser environments).
|
|
56
|
+
*/
|
|
57
|
+
function encodeBase64(data) {
|
|
58
|
+
if (typeof Buffer !== "undefined") {
|
|
59
|
+
return Buffer.from(data, "utf-8").toString("base64");
|
|
60
|
+
}
|
|
61
|
+
// Browser / edge runtime
|
|
62
|
+
return btoa(data);
|
|
63
|
+
}
|
|
64
|
+
// ─── Core signing function ────────────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Sign an x402 payment using EIP-3009 TransferWithAuthorization.
|
|
67
|
+
*
|
|
68
|
+
* This implements the client side of the x402 payment protocol:
|
|
69
|
+
* 1. Builds the authorization parameters (from, to, value, validity window, nonce)
|
|
70
|
+
* 2. Signs them with the agent's private key via EIP-712
|
|
71
|
+
* 3. Encodes the signed payload as base64 for the `PAYMENT-SIGNATURE` header
|
|
72
|
+
*
|
|
73
|
+
* The function defaults to `TransferWithAuthorization` (EIP-3009) which is
|
|
74
|
+
* what Circle's USDC on Base supports. If the server's extra field specifies
|
|
75
|
+
* `primaryType: "Permit"`, an EIP-2612 Permit signature is used instead.
|
|
76
|
+
*
|
|
77
|
+
* @param privateKey - The payer's private key. **Never logged or thrown.**
|
|
78
|
+
* @param requirements - Payment requirements from the server's 402 response
|
|
79
|
+
* @returns Base64-encoded signed payment payload string
|
|
80
|
+
* @throws {Error} If scheme is unsupported or signing fails (key never exposed)
|
|
81
|
+
*/
|
|
82
|
+
export async function signX402Payment(privateKey, requirements) {
|
|
83
|
+
if (!SUPPORTED_SCHEMES.has(requirements.scheme)) {
|
|
84
|
+
throw new Error(`Unsupported x402 scheme: "${requirements.scheme}". Supported: ${[...SUPPORTED_SCHEMES].join(", ")}`);
|
|
85
|
+
}
|
|
86
|
+
const chainId = parseChainId(requirements.network);
|
|
87
|
+
// Build account from private key — key stays inside this closure
|
|
88
|
+
const account = privateKeyToAccount(privateKey);
|
|
89
|
+
const now = Math.floor(Date.now() / 1000);
|
|
90
|
+
// Allow 24 hours retroactive validity to smooth over clock skew
|
|
91
|
+
const validAfterBigInt = BigInt(now - 86_400);
|
|
92
|
+
// Upper bound: current time + server-specified timeout
|
|
93
|
+
const validBeforeBigInt = BigInt(now + requirements.maxTimeoutSeconds);
|
|
94
|
+
const nonce = await generateNonce();
|
|
95
|
+
const extra = requirements.extra;
|
|
96
|
+
const tokenName = extra?.["name"] ?? "USD Coin";
|
|
97
|
+
const tokenVersion = extra?.["version"] ?? "2";
|
|
98
|
+
const primaryType = extra?.["primaryType"] ?? "TransferWithAuthorization";
|
|
99
|
+
let signature;
|
|
100
|
+
try {
|
|
101
|
+
if (primaryType === "Permit") {
|
|
102
|
+
// EIP-2612 Permit (for tokens that don't support EIP-3009)
|
|
103
|
+
signature = await account.signTypedData({
|
|
104
|
+
domain: {
|
|
105
|
+
name: tokenName,
|
|
106
|
+
version: tokenVersion,
|
|
107
|
+
chainId,
|
|
108
|
+
verifyingContract: requirements.asset,
|
|
109
|
+
},
|
|
110
|
+
types: {
|
|
111
|
+
Permit: [
|
|
112
|
+
{ name: "owner", type: "address" },
|
|
113
|
+
{ name: "spender", type: "address" },
|
|
114
|
+
{ name: "value", type: "uint256" },
|
|
115
|
+
{ name: "nonce", type: "uint256" },
|
|
116
|
+
{ name: "deadline", type: "uint256" },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
primaryType: "Permit",
|
|
120
|
+
message: {
|
|
121
|
+
owner: account.address,
|
|
122
|
+
spender: requirements.payTo,
|
|
123
|
+
value: BigInt(requirements.maxAmountRequired),
|
|
124
|
+
// For Permit, nonce would normally be fetched on-chain. Here we use 0
|
|
125
|
+
// as a placeholder — real deployments should fetch via nonces(owner).
|
|
126
|
+
nonce: 0n,
|
|
127
|
+
deadline: validBeforeBigInt,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// EIP-3009 TransferWithAuthorization (default — USDC on Base)
|
|
133
|
+
signature = await account.signTypedData({
|
|
134
|
+
domain: {
|
|
135
|
+
name: tokenName,
|
|
136
|
+
version: tokenVersion,
|
|
137
|
+
chainId,
|
|
138
|
+
verifyingContract: requirements.asset,
|
|
139
|
+
},
|
|
140
|
+
types: {
|
|
141
|
+
TransferWithAuthorization: [
|
|
142
|
+
{ name: "from", type: "address" },
|
|
143
|
+
{ name: "to", type: "address" },
|
|
144
|
+
{ name: "value", type: "uint256" },
|
|
145
|
+
{ name: "validAfter", type: "uint256" },
|
|
146
|
+
{ name: "validBefore", type: "uint256" },
|
|
147
|
+
{ name: "nonce", type: "bytes32" },
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
primaryType: "TransferWithAuthorization",
|
|
151
|
+
message: {
|
|
152
|
+
from: account.address,
|
|
153
|
+
to: requirements.payTo,
|
|
154
|
+
value: BigInt(requirements.maxAmountRequired),
|
|
155
|
+
validAfter: validAfterBigInt,
|
|
156
|
+
validBefore: validBeforeBigInt,
|
|
157
|
+
nonce,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
// Catch and re-throw without any key material
|
|
164
|
+
const msg = err instanceof Error ? err.message : "Unknown signing error";
|
|
165
|
+
throw new Error(`x402 payment signing failed: ${msg}`);
|
|
166
|
+
}
|
|
167
|
+
// Build the payment payload (x402 v2 format)
|
|
168
|
+
const payload = {
|
|
169
|
+
x402Version: X402_VERSION,
|
|
170
|
+
scheme: requirements.scheme,
|
|
171
|
+
network: requirements.network,
|
|
172
|
+
payload: {
|
|
173
|
+
signature,
|
|
174
|
+
authorization: {
|
|
175
|
+
from: account.address,
|
|
176
|
+
to: requirements.payTo,
|
|
177
|
+
value: requirements.maxAmountRequired,
|
|
178
|
+
validAfter: validAfterBigInt.toString(),
|
|
179
|
+
validBefore: validBeforeBigInt.toString(),
|
|
180
|
+
nonce,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
return encodeBase64(JSON.stringify(payload));
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=payment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.js","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module types
|
|
3
|
+
* All public types and Zod schemas for @x402janus/sdk.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
/**
|
|
7
|
+
* Scan tier controlling analysis depth and x402 micropayment amount.
|
|
8
|
+
*
|
|
9
|
+
* | Tier | Price | Description |
|
|
10
|
+
* |----------|--------|-----------------------------------------------------|
|
|
11
|
+
* | quick | $0.01 | Fast heuristic scan — known drainers & risk signals |
|
|
12
|
+
* | standard | $0.05 | Graph analysis + threat-intel correlation |
|
|
13
|
+
* | deep | $0.25 | Full forensic scan + approval chain tracing |
|
|
14
|
+
*/
|
|
15
|
+
export declare const ScanTierSchema: z.ZodEnum<["quick", "standard", "deep"]>;
|
|
16
|
+
/** @see {@link ScanTierSchema} */
|
|
17
|
+
export type ScanTier = z.infer<typeof ScanTierSchema>;
|
|
18
|
+
/**
|
|
19
|
+
* USDC pricing for each scan tier (6-decimal precision, Base mainnet).
|
|
20
|
+
* `units` is the raw USDC atomic value passed in the x402 payment header.
|
|
21
|
+
*/
|
|
22
|
+
export declare const TIER_PRICES: Readonly<Record<ScanTier, {
|
|
23
|
+
dollars: string;
|
|
24
|
+
units: string;
|
|
25
|
+
}>>;
|
|
26
|
+
/**
|
|
27
|
+
* Severity level for a security finding.
|
|
28
|
+
*/
|
|
29
|
+
export type FindingSeverity = "critical" | "high" | "medium" | "low" | "info";
|
|
30
|
+
/**
|
|
31
|
+
* A single security finding returned in a wallet scan.
|
|
32
|
+
*/
|
|
33
|
+
export declare const FindingSchema: z.ZodObject<{
|
|
34
|
+
/** Machine-readable finding type (e.g. "unlimited_approval", "known_drainer") */
|
|
35
|
+
type: z.ZodString;
|
|
36
|
+
/** Severity of the finding */
|
|
37
|
+
severity: z.ZodEnum<["critical", "high", "medium", "low", "info"]>;
|
|
38
|
+
/** Human-readable description */
|
|
39
|
+
description: z.ZodString;
|
|
40
|
+
/** Relevant contract or counterparty address, if applicable */
|
|
41
|
+
address: z.ZodOptional<z.ZodString>;
|
|
42
|
+
/** Protocol name associated with the finding, if known */
|
|
43
|
+
protocol: z.ZodOptional<z.ZodString>;
|
|
44
|
+
/** Token amount at risk (human-readable), if applicable */
|
|
45
|
+
amount: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
type: string;
|
|
48
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
49
|
+
description: string;
|
|
50
|
+
address?: string | undefined;
|
|
51
|
+
protocol?: string | undefined;
|
|
52
|
+
amount?: string | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
type: string;
|
|
55
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
56
|
+
description: string;
|
|
57
|
+
address?: string | undefined;
|
|
58
|
+
protocol?: string | undefined;
|
|
59
|
+
amount?: string | undefined;
|
|
60
|
+
}>;
|
|
61
|
+
/** @see {@link FindingSchema} */
|
|
62
|
+
export type Finding = z.infer<typeof FindingSchema>;
|
|
63
|
+
/**
|
|
64
|
+
* A revoke transaction that the agent can sign and submit to remove a risky approval.
|
|
65
|
+
* Transactions are pre-built by the x402janus API — submit them as-is.
|
|
66
|
+
*/
|
|
67
|
+
export declare const RevokeTxSchema: z.ZodObject<{
|
|
68
|
+
/** Target contract address (the token contract) */
|
|
69
|
+
to: z.ZodString;
|
|
70
|
+
/** ABI-encoded calldata (e.g., `approve(spender, 0)`) */
|
|
71
|
+
data: z.ZodString;
|
|
72
|
+
/** EVM chain ID (e.g., 8453 for Base) */
|
|
73
|
+
chainId: z.ZodNumber;
|
|
74
|
+
/** Human-readable description of what this revoke does */
|
|
75
|
+
description: z.ZodString;
|
|
76
|
+
}, "strip", z.ZodTypeAny, {
|
|
77
|
+
description: string;
|
|
78
|
+
to: string;
|
|
79
|
+
data: string;
|
|
80
|
+
chainId: number;
|
|
81
|
+
}, {
|
|
82
|
+
description: string;
|
|
83
|
+
to: string;
|
|
84
|
+
data: string;
|
|
85
|
+
chainId: number;
|
|
86
|
+
}>;
|
|
87
|
+
/** @see {@link RevokeTxSchema} */
|
|
88
|
+
export type RevokeTx = z.infer<typeof RevokeTxSchema>;
|
|
89
|
+
/**
|
|
90
|
+
* Full result of a wallet security scan.
|
|
91
|
+
*
|
|
92
|
+
* **Security invariant**: `safe` is always `false` when payment was not
|
|
93
|
+
* successfully verified. Never trust `safe: true` from an unpaid response.
|
|
94
|
+
*/
|
|
95
|
+
export declare const ScanResultSchema: z.ZodObject<{
|
|
96
|
+
/** Unique identifier for this scan (for audit/logging) */
|
|
97
|
+
scanId: z.ZodString;
|
|
98
|
+
/**
|
|
99
|
+
* Whether the wallet is considered safe.
|
|
100
|
+
* This value is overridden to `false` if payment was not verified.
|
|
101
|
+
*/
|
|
102
|
+
safe: z.ZodBoolean;
|
|
103
|
+
/** Risk score from 0 (clean) to 100 (critical risk) */
|
|
104
|
+
risk: z.ZodNumber;
|
|
105
|
+
/** List of security findings */
|
|
106
|
+
findings: z.ZodArray<z.ZodObject<{
|
|
107
|
+
/** Machine-readable finding type (e.g. "unlimited_approval", "known_drainer") */
|
|
108
|
+
type: z.ZodString;
|
|
109
|
+
/** Severity of the finding */
|
|
110
|
+
severity: z.ZodEnum<["critical", "high", "medium", "low", "info"]>;
|
|
111
|
+
/** Human-readable description */
|
|
112
|
+
description: z.ZodString;
|
|
113
|
+
/** Relevant contract or counterparty address, if applicable */
|
|
114
|
+
address: z.ZodOptional<z.ZodString>;
|
|
115
|
+
/** Protocol name associated with the finding, if known */
|
|
116
|
+
protocol: z.ZodOptional<z.ZodString>;
|
|
117
|
+
/** Token amount at risk (human-readable), if applicable */
|
|
118
|
+
amount: z.ZodOptional<z.ZodString>;
|
|
119
|
+
}, "strip", z.ZodTypeAny, {
|
|
120
|
+
type: string;
|
|
121
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
122
|
+
description: string;
|
|
123
|
+
address?: string | undefined;
|
|
124
|
+
protocol?: string | undefined;
|
|
125
|
+
amount?: string | undefined;
|
|
126
|
+
}, {
|
|
127
|
+
type: string;
|
|
128
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
129
|
+
description: string;
|
|
130
|
+
address?: string | undefined;
|
|
131
|
+
protocol?: string | undefined;
|
|
132
|
+
amount?: string | undefined;
|
|
133
|
+
}>, "many">;
|
|
134
|
+
/** Pre-built revoke transactions for risky approvals */
|
|
135
|
+
revokeTxs: z.ZodArray<z.ZodObject<{
|
|
136
|
+
/** Target contract address (the token contract) */
|
|
137
|
+
to: z.ZodString;
|
|
138
|
+
/** ABI-encoded calldata (e.g., `approve(spender, 0)`) */
|
|
139
|
+
data: z.ZodString;
|
|
140
|
+
/** EVM chain ID (e.g., 8453 for Base) */
|
|
141
|
+
chainId: z.ZodNumber;
|
|
142
|
+
/** Human-readable description of what this revoke does */
|
|
143
|
+
description: z.ZodString;
|
|
144
|
+
}, "strip", z.ZodTypeAny, {
|
|
145
|
+
description: string;
|
|
146
|
+
to: string;
|
|
147
|
+
data: string;
|
|
148
|
+
chainId: number;
|
|
149
|
+
}, {
|
|
150
|
+
description: string;
|
|
151
|
+
to: string;
|
|
152
|
+
data: string;
|
|
153
|
+
chainId: number;
|
|
154
|
+
}>, "many">;
|
|
155
|
+
}, "strip", z.ZodTypeAny, {
|
|
156
|
+
scanId: string;
|
|
157
|
+
safe: boolean;
|
|
158
|
+
risk: number;
|
|
159
|
+
findings: {
|
|
160
|
+
type: string;
|
|
161
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
162
|
+
description: string;
|
|
163
|
+
address?: string | undefined;
|
|
164
|
+
protocol?: string | undefined;
|
|
165
|
+
amount?: string | undefined;
|
|
166
|
+
}[];
|
|
167
|
+
revokeTxs: {
|
|
168
|
+
description: string;
|
|
169
|
+
to: string;
|
|
170
|
+
data: string;
|
|
171
|
+
chainId: number;
|
|
172
|
+
}[];
|
|
173
|
+
}, {
|
|
174
|
+
scanId: string;
|
|
175
|
+
safe: boolean;
|
|
176
|
+
risk: number;
|
|
177
|
+
findings: {
|
|
178
|
+
type: string;
|
|
179
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
180
|
+
description: string;
|
|
181
|
+
address?: string | undefined;
|
|
182
|
+
protocol?: string | undefined;
|
|
183
|
+
amount?: string | undefined;
|
|
184
|
+
}[];
|
|
185
|
+
revokeTxs: {
|
|
186
|
+
description: string;
|
|
187
|
+
to: string;
|
|
188
|
+
data: string;
|
|
189
|
+
chainId: number;
|
|
190
|
+
}[];
|
|
191
|
+
}>;
|
|
192
|
+
/** @see {@link ScanResultSchema} */
|
|
193
|
+
export type ScanResult = z.infer<typeof ScanResultSchema>;
|
|
194
|
+
/**
|
|
195
|
+
* A single ERC-20 token approval with risk assessment.
|
|
196
|
+
*/
|
|
197
|
+
export declare const ApprovalSchema: z.ZodObject<{
|
|
198
|
+
/** Address that has been approved to spend tokens */
|
|
199
|
+
spender: z.ZodString;
|
|
200
|
+
/** Token contract address */
|
|
201
|
+
token: z.ZodString;
|
|
202
|
+
/** Token symbol (e.g., "USDC"), if known */
|
|
203
|
+
tokenSymbol: z.ZodOptional<z.ZodString>;
|
|
204
|
+
/** Approved allowance amount (as string to handle large values) */
|
|
205
|
+
allowance: z.ZodString;
|
|
206
|
+
/** Risk level of this approval */
|
|
207
|
+
risk: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
208
|
+
/** Human-readable details about why this is risky */
|
|
209
|
+
details: z.ZodOptional<z.ZodString>;
|
|
210
|
+
}, "strip", z.ZodTypeAny, {
|
|
211
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
212
|
+
spender: string;
|
|
213
|
+
token: string;
|
|
214
|
+
allowance: string;
|
|
215
|
+
tokenSymbol?: string | undefined;
|
|
216
|
+
details?: string | undefined;
|
|
217
|
+
}, {
|
|
218
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
219
|
+
spender: string;
|
|
220
|
+
token: string;
|
|
221
|
+
allowance: string;
|
|
222
|
+
tokenSymbol?: string | undefined;
|
|
223
|
+
details?: string | undefined;
|
|
224
|
+
}>;
|
|
225
|
+
/** @see {@link ApprovalSchema} */
|
|
226
|
+
export type Approval = z.infer<typeof ApprovalSchema>;
|
|
227
|
+
/**
|
|
228
|
+
* Aggregated approvals result for a wallet.
|
|
229
|
+
*/
|
|
230
|
+
export declare const ApprovalsResultSchema: z.ZodObject<{
|
|
231
|
+
/** The wallet address that was queried */
|
|
232
|
+
wallet: z.ZodString;
|
|
233
|
+
/** All active token approvals */
|
|
234
|
+
approvals: z.ZodArray<z.ZodObject<{
|
|
235
|
+
/** Address that has been approved to spend tokens */
|
|
236
|
+
spender: z.ZodString;
|
|
237
|
+
/** Token contract address */
|
|
238
|
+
token: z.ZodString;
|
|
239
|
+
/** Token symbol (e.g., "USDC"), if known */
|
|
240
|
+
tokenSymbol: z.ZodOptional<z.ZodString>;
|
|
241
|
+
/** Approved allowance amount (as string to handle large values) */
|
|
242
|
+
allowance: z.ZodString;
|
|
243
|
+
/** Risk level of this approval */
|
|
244
|
+
risk: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
245
|
+
/** Human-readable details about why this is risky */
|
|
246
|
+
details: z.ZodOptional<z.ZodString>;
|
|
247
|
+
}, "strip", z.ZodTypeAny, {
|
|
248
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
249
|
+
spender: string;
|
|
250
|
+
token: string;
|
|
251
|
+
allowance: string;
|
|
252
|
+
tokenSymbol?: string | undefined;
|
|
253
|
+
details?: string | undefined;
|
|
254
|
+
}, {
|
|
255
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
256
|
+
spender: string;
|
|
257
|
+
token: string;
|
|
258
|
+
allowance: string;
|
|
259
|
+
tokenSymbol?: string | undefined;
|
|
260
|
+
details?: string | undefined;
|
|
261
|
+
}>, "many">;
|
|
262
|
+
/** Count of approvals at each risk level */
|
|
263
|
+
riskCount: z.ZodObject<{
|
|
264
|
+
low: z.ZodNumber;
|
|
265
|
+
medium: z.ZodNumber;
|
|
266
|
+
high: z.ZodNumber;
|
|
267
|
+
critical: z.ZodNumber;
|
|
268
|
+
}, "strip", z.ZodTypeAny, {
|
|
269
|
+
critical: number;
|
|
270
|
+
high: number;
|
|
271
|
+
medium: number;
|
|
272
|
+
low: number;
|
|
273
|
+
}, {
|
|
274
|
+
critical: number;
|
|
275
|
+
high: number;
|
|
276
|
+
medium: number;
|
|
277
|
+
low: number;
|
|
278
|
+
}>;
|
|
279
|
+
}, "strip", z.ZodTypeAny, {
|
|
280
|
+
wallet: string;
|
|
281
|
+
approvals: {
|
|
282
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
283
|
+
spender: string;
|
|
284
|
+
token: string;
|
|
285
|
+
allowance: string;
|
|
286
|
+
tokenSymbol?: string | undefined;
|
|
287
|
+
details?: string | undefined;
|
|
288
|
+
}[];
|
|
289
|
+
riskCount: {
|
|
290
|
+
critical: number;
|
|
291
|
+
high: number;
|
|
292
|
+
medium: number;
|
|
293
|
+
low: number;
|
|
294
|
+
};
|
|
295
|
+
}, {
|
|
296
|
+
wallet: string;
|
|
297
|
+
approvals: {
|
|
298
|
+
risk: "critical" | "high" | "medium" | "low";
|
|
299
|
+
spender: string;
|
|
300
|
+
token: string;
|
|
301
|
+
allowance: string;
|
|
302
|
+
tokenSymbol?: string | undefined;
|
|
303
|
+
details?: string | undefined;
|
|
304
|
+
}[];
|
|
305
|
+
riskCount: {
|
|
306
|
+
critical: number;
|
|
307
|
+
high: number;
|
|
308
|
+
medium: number;
|
|
309
|
+
low: number;
|
|
310
|
+
};
|
|
311
|
+
}>;
|
|
312
|
+
/** @see {@link ApprovalsResultSchema} */
|
|
313
|
+
export type ApprovalsResult = z.infer<typeof ApprovalsResultSchema>;
|
|
314
|
+
/**
|
|
315
|
+
* API health status.
|
|
316
|
+
*/
|
|
317
|
+
export declare const HealthResultSchema: z.ZodObject<{
|
|
318
|
+
/** Service health status */
|
|
319
|
+
status: z.ZodEnum<["ok", "degraded", "down"]>;
|
|
320
|
+
/** API version string, if available */
|
|
321
|
+
version: z.ZodOptional<z.ZodString>;
|
|
322
|
+
/** Process uptime in seconds, if available */
|
|
323
|
+
uptime: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
}, "strip", z.ZodTypeAny, {
|
|
325
|
+
status: "ok" | "degraded" | "down";
|
|
326
|
+
version?: string | undefined;
|
|
327
|
+
uptime?: number | undefined;
|
|
328
|
+
}, {
|
|
329
|
+
status: "ok" | "degraded" | "down";
|
|
330
|
+
version?: string | undefined;
|
|
331
|
+
uptime?: number | undefined;
|
|
332
|
+
}>;
|
|
333
|
+
/** @see {@link HealthResultSchema} */
|
|
334
|
+
export type HealthResult = z.infer<typeof HealthResultSchema>;
|
|
335
|
+
/**
|
|
336
|
+
* Payment requirements parsed from a 402 response.
|
|
337
|
+
* Used internally by JanusClient to build the payment signature.
|
|
338
|
+
*/
|
|
339
|
+
export declare const PaymentRequirementsSchema: z.ZodObject<{
|
|
340
|
+
/** Payment scheme (currently only "exact" is supported) */
|
|
341
|
+
scheme: z.ZodString;
|
|
342
|
+
/** CAIP-2 network identifier (e.g., "eip155:8453") */
|
|
343
|
+
network: z.ZodString;
|
|
344
|
+
/** Maximum amount required in token atomic units */
|
|
345
|
+
maxAmountRequired: z.ZodString;
|
|
346
|
+
/** Payment token contract address (Base USDC) */
|
|
347
|
+
asset: z.ZodString;
|
|
348
|
+
/** Payment recipient address */
|
|
349
|
+
payTo: z.ZodString;
|
|
350
|
+
/** Maximum seconds the payment authorization is valid for */
|
|
351
|
+
maxTimeoutSeconds: z.ZodNumber;
|
|
352
|
+
/** Extra EIP-712 domain metadata (name, version, etc.) */
|
|
353
|
+
extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
354
|
+
}, "strip", z.ZodTypeAny, {
|
|
355
|
+
scheme: string;
|
|
356
|
+
network: string;
|
|
357
|
+
maxAmountRequired: string;
|
|
358
|
+
asset: string;
|
|
359
|
+
payTo: string;
|
|
360
|
+
maxTimeoutSeconds: number;
|
|
361
|
+
extra?: Record<string, unknown> | undefined;
|
|
362
|
+
}, {
|
|
363
|
+
scheme: string;
|
|
364
|
+
network: string;
|
|
365
|
+
maxAmountRequired: string;
|
|
366
|
+
asset: string;
|
|
367
|
+
payTo: string;
|
|
368
|
+
maxTimeoutSeconds: number;
|
|
369
|
+
extra?: Record<string, unknown> | undefined;
|
|
370
|
+
}>;
|
|
371
|
+
/** @see {@link PaymentRequirementsSchema} */
|
|
372
|
+
export type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;
|
|
373
|
+
/**
|
|
374
|
+
* Configuration for {@link JanusClient}.
|
|
375
|
+
*/
|
|
376
|
+
export interface JanusClientConfig {
|
|
377
|
+
/**
|
|
378
|
+
* Base URL for the x402janus API.
|
|
379
|
+
* @default "https://x402janus.com"
|
|
380
|
+
*/
|
|
381
|
+
baseUrl?: string | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* Agent's private key for signing x402 micropayments.
|
|
384
|
+
* Required for paid tiers (standard, deep).
|
|
385
|
+
* Falls back to `process.env.PRIVATE_KEY` if not set.
|
|
386
|
+
*
|
|
387
|
+
* **Security**: The private key is stored in memory only and never
|
|
388
|
+
* exposed in error messages, logs, or API responses.
|
|
389
|
+
*/
|
|
390
|
+
privateKey?: string | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* Default scan tier when not specified per-call.
|
|
393
|
+
* @default "quick"
|
|
394
|
+
*/
|
|
395
|
+
defaultTier?: ScanTier | undefined;
|
|
396
|
+
/**
|
|
397
|
+
* Thirdweb/x402 facilitator URL for payment verification.
|
|
398
|
+
* Falls back to `process.env.FACILITATOR_URL` then the Thirdweb default.
|
|
399
|
+
* @default "https://api.thirdweb.com/v1/payments/x402"
|
|
400
|
+
*/
|
|
401
|
+
facilitatorUrl?: string | undefined;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Options for a single wallet scan call.
|
|
405
|
+
*/
|
|
406
|
+
export interface ScanOptions {
|
|
407
|
+
/**
|
|
408
|
+
* Override the default tier for this scan.
|
|
409
|
+
*/
|
|
410
|
+
tier?: ScanTier | undefined;
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module types
|
|
3
|
+
* All public types and Zod schemas for @x402janus/sdk.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
// ─── Tier ────────────────────────────────────────────────────────────────────
|
|
7
|
+
/**
|
|
8
|
+
* Scan tier controlling analysis depth and x402 micropayment amount.
|
|
9
|
+
*
|
|
10
|
+
* | Tier | Price | Description |
|
|
11
|
+
* |----------|--------|-----------------------------------------------------|
|
|
12
|
+
* | quick | $0.01 | Fast heuristic scan — known drainers & risk signals |
|
|
13
|
+
* | standard | $0.05 | Graph analysis + threat-intel correlation |
|
|
14
|
+
* | deep | $0.25 | Full forensic scan + approval chain tracing |
|
|
15
|
+
*/
|
|
16
|
+
export const ScanTierSchema = z.enum(["quick", "standard", "deep"]);
|
|
17
|
+
/**
|
|
18
|
+
* USDC pricing for each scan tier (6-decimal precision, Base mainnet).
|
|
19
|
+
* `units` is the raw USDC atomic value passed in the x402 payment header.
|
|
20
|
+
*/
|
|
21
|
+
export const TIER_PRICES = {
|
|
22
|
+
quick: { dollars: "$0.01", units: "10000" },
|
|
23
|
+
standard: { dollars: "$0.05", units: "50000" },
|
|
24
|
+
deep: { dollars: "$0.25", units: "250000" },
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A single security finding returned in a wallet scan.
|
|
28
|
+
*/
|
|
29
|
+
export const FindingSchema = z.object({
|
|
30
|
+
/** Machine-readable finding type (e.g. "unlimited_approval", "known_drainer") */
|
|
31
|
+
type: z.string(),
|
|
32
|
+
/** Severity of the finding */
|
|
33
|
+
severity: z.enum(["critical", "high", "medium", "low", "info"]),
|
|
34
|
+
/** Human-readable description */
|
|
35
|
+
description: z.string(),
|
|
36
|
+
/** Relevant contract or counterparty address, if applicable */
|
|
37
|
+
address: z.string().optional(),
|
|
38
|
+
/** Protocol name associated with the finding, if known */
|
|
39
|
+
protocol: z.string().optional(),
|
|
40
|
+
/** Token amount at risk (human-readable), if applicable */
|
|
41
|
+
amount: z.string().optional(),
|
|
42
|
+
});
|
|
43
|
+
// ─── RevokeTx ────────────────────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* A revoke transaction that the agent can sign and submit to remove a risky approval.
|
|
46
|
+
* Transactions are pre-built by the x402janus API — submit them as-is.
|
|
47
|
+
*/
|
|
48
|
+
export const RevokeTxSchema = z.object({
|
|
49
|
+
/** Target contract address (the token contract) */
|
|
50
|
+
to: z.string(),
|
|
51
|
+
/** ABI-encoded calldata (e.g., `approve(spender, 0)`) */
|
|
52
|
+
data: z.string(),
|
|
53
|
+
/** EVM chain ID (e.g., 8453 for Base) */
|
|
54
|
+
chainId: z.number().int().positive(),
|
|
55
|
+
/** Human-readable description of what this revoke does */
|
|
56
|
+
description: z.string(),
|
|
57
|
+
});
|
|
58
|
+
// ─── ScanResult ──────────────────────────────────────────────────────────────
|
|
59
|
+
/**
|
|
60
|
+
* Full result of a wallet security scan.
|
|
61
|
+
*
|
|
62
|
+
* **Security invariant**: `safe` is always `false` when payment was not
|
|
63
|
+
* successfully verified. Never trust `safe: true` from an unpaid response.
|
|
64
|
+
*/
|
|
65
|
+
export const ScanResultSchema = z.object({
|
|
66
|
+
/** Unique identifier for this scan (for audit/logging) */
|
|
67
|
+
scanId: z.string(),
|
|
68
|
+
/**
|
|
69
|
+
* Whether the wallet is considered safe.
|
|
70
|
+
* This value is overridden to `false` if payment was not verified.
|
|
71
|
+
*/
|
|
72
|
+
safe: z.boolean(),
|
|
73
|
+
/** Risk score from 0 (clean) to 100 (critical risk) */
|
|
74
|
+
risk: z.number().min(0).max(100),
|
|
75
|
+
/** List of security findings */
|
|
76
|
+
findings: z.array(FindingSchema),
|
|
77
|
+
/** Pre-built revoke transactions for risky approvals */
|
|
78
|
+
revokeTxs: z.array(RevokeTxSchema),
|
|
79
|
+
});
|
|
80
|
+
// ─── Approvals ───────────────────────────────────────────────────────────────
|
|
81
|
+
/**
|
|
82
|
+
* A single ERC-20 token approval with risk assessment.
|
|
83
|
+
*/
|
|
84
|
+
export const ApprovalSchema = z.object({
|
|
85
|
+
/** Address that has been approved to spend tokens */
|
|
86
|
+
spender: z.string(),
|
|
87
|
+
/** Token contract address */
|
|
88
|
+
token: z.string(),
|
|
89
|
+
/** Token symbol (e.g., "USDC"), if known */
|
|
90
|
+
tokenSymbol: z.string().optional(),
|
|
91
|
+
/** Approved allowance amount (as string to handle large values) */
|
|
92
|
+
allowance: z.string(),
|
|
93
|
+
/** Risk level of this approval */
|
|
94
|
+
risk: z.enum(["low", "medium", "high", "critical"]),
|
|
95
|
+
/** Human-readable details about why this is risky */
|
|
96
|
+
details: z.string().optional(),
|
|
97
|
+
});
|
|
98
|
+
/**
|
|
99
|
+
* Aggregated approvals result for a wallet.
|
|
100
|
+
*/
|
|
101
|
+
export const ApprovalsResultSchema = z.object({
|
|
102
|
+
/** The wallet address that was queried */
|
|
103
|
+
wallet: z.string(),
|
|
104
|
+
/** All active token approvals */
|
|
105
|
+
approvals: z.array(ApprovalSchema),
|
|
106
|
+
/** Count of approvals at each risk level */
|
|
107
|
+
riskCount: z.object({
|
|
108
|
+
low: z.number().int().min(0),
|
|
109
|
+
medium: z.number().int().min(0),
|
|
110
|
+
high: z.number().int().min(0),
|
|
111
|
+
critical: z.number().int().min(0),
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
// ─── Health ──────────────────────────────────────────────────────────────────
|
|
115
|
+
/**
|
|
116
|
+
* API health status.
|
|
117
|
+
*/
|
|
118
|
+
export const HealthResultSchema = z.object({
|
|
119
|
+
/** Service health status */
|
|
120
|
+
status: z.enum(["ok", "degraded", "down"]),
|
|
121
|
+
/** API version string, if available */
|
|
122
|
+
version: z.string().optional(),
|
|
123
|
+
/** Process uptime in seconds, if available */
|
|
124
|
+
uptime: z.number().optional(),
|
|
125
|
+
});
|
|
126
|
+
// ─── x402 Payment Requirements ───────────────────────────────────────────────
|
|
127
|
+
/**
|
|
128
|
+
* Payment requirements parsed from a 402 response.
|
|
129
|
+
* Used internally by JanusClient to build the payment signature.
|
|
130
|
+
*/
|
|
131
|
+
export const PaymentRequirementsSchema = z.object({
|
|
132
|
+
/** Payment scheme (currently only "exact" is supported) */
|
|
133
|
+
scheme: z.string(),
|
|
134
|
+
/** CAIP-2 network identifier (e.g., "eip155:8453") */
|
|
135
|
+
network: z.string(),
|
|
136
|
+
/** Maximum amount required in token atomic units */
|
|
137
|
+
maxAmountRequired: z.string().regex(/^\d+$/, "must be a decimal integer string"),
|
|
138
|
+
/** Payment token contract address (Base USDC) */
|
|
139
|
+
asset: z.string(),
|
|
140
|
+
/** Payment recipient address */
|
|
141
|
+
payTo: z.string(),
|
|
142
|
+
/** Maximum seconds the payment authorization is valid for */
|
|
143
|
+
maxTimeoutSeconds: z.number().int().positive(),
|
|
144
|
+
/** Extra EIP-712 domain metadata (name, version, etc.) */
|
|
145
|
+
extra: z.record(z.unknown()).optional(),
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@x402janus/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for x402janus wallet security scans with automatic x402 micropayment handling",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"clean": "rm -rf dist"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"viem": "^2.21.0",
|
|
25
|
+
"zod": "^3.22.0"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"x402",
|
|
33
|
+
"wallet",
|
|
34
|
+
"security",
|
|
35
|
+
"scan",
|
|
36
|
+
"base",
|
|
37
|
+
"ethereum",
|
|
38
|
+
"drainer",
|
|
39
|
+
"approvals",
|
|
40
|
+
"ai-agent"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/x402janus/sdk"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
}
|
|
50
|
+
}
|