@atv-eth/x402-sdk 1.0.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 +195 -0
- package/index.d.ts +144 -0
- package/index.mjs +359 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @atv/x402-sdk
|
|
2
|
+
|
|
3
|
+
Official SDK for the **ATV x402 Premium API** — ENS resolution, identity profiles, social graphs, and wallet analytics with automatic USDC payments on Base.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @atv/x402-sdk viem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { ATVClient } from '@atv/x402-sdk';
|
|
15
|
+
|
|
16
|
+
// With x402 payments (USDC on Base)
|
|
17
|
+
const client = new ATVClient({
|
|
18
|
+
privateKey: process.env.WALLET_KEY,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Or with API key (prepaid credits)
|
|
22
|
+
const client = new ATVClient({
|
|
23
|
+
apiKey: 'atv_your_api_key',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Resolve ENS name
|
|
27
|
+
const result = await client.resolveENS('vitalik.eth');
|
|
28
|
+
console.log(result.address);
|
|
29
|
+
// → 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- **Automatic x402 payments** — Signs and pays with USDC on Base
|
|
35
|
+
- **Full TypeScript support** — Complete type definitions included
|
|
36
|
+
- **All API endpoints** — Identity, social, wallet, and utilities
|
|
37
|
+
- **Free tier support** — Works without wallet for 100 calls/day
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
### Identity & ENS
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// Resolve ENS name ($0.01)
|
|
45
|
+
await client.resolveENS('vitalik.eth');
|
|
46
|
+
|
|
47
|
+
// Reverse resolve ($0.01)
|
|
48
|
+
await client.reverseResolve('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
|
|
49
|
+
|
|
50
|
+
// Full profile ($0.05)
|
|
51
|
+
await client.getProfile('nick.eth');
|
|
52
|
+
|
|
53
|
+
// ENS valuation ($0.02)
|
|
54
|
+
await client.getENSValue('eth.eth');
|
|
55
|
+
|
|
56
|
+
// Expiration info ($0.01)
|
|
57
|
+
await client.getExpiration('myname.eth');
|
|
58
|
+
|
|
59
|
+
// Batch resolve ($0.08)
|
|
60
|
+
await client.batchENS(['vitalik.eth', 'nick.eth', 'brantly.eth']);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Social Graph
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// Follower counts ($0.01)
|
|
67
|
+
await client.getSocialStats('garypalmerjr.eth');
|
|
68
|
+
|
|
69
|
+
// Followers list ($0.02)
|
|
70
|
+
await client.getFollowers('nick.eth', 50);
|
|
71
|
+
|
|
72
|
+
// Following list ($0.02)
|
|
73
|
+
await client.getFollowing('nick.eth', 50);
|
|
74
|
+
|
|
75
|
+
// Mutual connections ($0.03)
|
|
76
|
+
await client.getMutuals('nick.eth');
|
|
77
|
+
|
|
78
|
+
// Reputation score ($0.03)
|
|
79
|
+
await client.getReputation('vitalik.eth');
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Wallet Analytics
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// ETH balance - multi-chain ($0.01)
|
|
86
|
+
await client.getBalance('0x...');
|
|
87
|
+
|
|
88
|
+
// ERC20 tokens ($0.02)
|
|
89
|
+
await client.getTokens('0x...');
|
|
90
|
+
|
|
91
|
+
// Transaction history ($0.02)
|
|
92
|
+
await client.getTransactions('0x...');
|
|
93
|
+
|
|
94
|
+
// NFT holdings ($0.03)
|
|
95
|
+
await client.getNFTs('0x...');
|
|
96
|
+
|
|
97
|
+
// ENS portfolio ($0.05)
|
|
98
|
+
await client.getPortfolio('0x...');
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Utilities
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// Gas prices - free tier ($0.001)
|
|
105
|
+
await client.getGas();
|
|
106
|
+
|
|
107
|
+
// Contract ABI ($0.02)
|
|
108
|
+
await client.getABI('0x...');
|
|
109
|
+
|
|
110
|
+
// Trending ENS ($0.02)
|
|
111
|
+
await client.getTrending();
|
|
112
|
+
|
|
113
|
+
// Leaderboard ($0.02)
|
|
114
|
+
await client.getLeaderboard();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Free Endpoints
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
// No payment required
|
|
121
|
+
await client.health();
|
|
122
|
+
await client.usage();
|
|
123
|
+
await client.discovery();
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Payment Methods
|
|
127
|
+
|
|
128
|
+
### x402 (USDC on Base)
|
|
129
|
+
|
|
130
|
+
Payments are handled automatically. You need:
|
|
131
|
+
- Wallet private key
|
|
132
|
+
- USDC on Base (chain ID 8453)
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const client = new ATVClient({
|
|
136
|
+
privateKey: '0x...',
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### API Key (Prepaid Credits)
|
|
141
|
+
|
|
142
|
+
Contact atv@web3domains.com for API key provisioning.
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
const client = new ATVClient({
|
|
146
|
+
apiKey: 'atv_yourkey',
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Check Balance
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
const balance = await client.getUSDCBalance();
|
|
154
|
+
console.log(`USDC Balance: ${balance}`);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const client = new ATVClient({
|
|
161
|
+
// API endpoint (default: https://api.web3domains.com)
|
|
162
|
+
baseUrl: 'https://api.web3domains.com',
|
|
163
|
+
|
|
164
|
+
// For x402 payments
|
|
165
|
+
privateKey: '0x...',
|
|
166
|
+
|
|
167
|
+
// OR for prepaid credits
|
|
168
|
+
apiKey: 'atv_...',
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Error Handling
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
try {
|
|
176
|
+
const result = await client.resolveENS('nonexistent.eth');
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error.message.includes('not found')) {
|
|
179
|
+
console.log('Name not registered');
|
|
180
|
+
} else if (error.message.includes('Payment required')) {
|
|
181
|
+
console.log('Insufficient USDC balance');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Links
|
|
187
|
+
|
|
188
|
+
- **API Docs:** https://api.web3domains.com/docs
|
|
189
|
+
- **OpenAPI:** https://api.web3domains.com/openapi.json
|
|
190
|
+
- **Support:** atv@web3domains.com
|
|
191
|
+
- **X/Twitter:** [@ATV_eth](https://twitter.com/ATV_eth)
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT © ATV (Agent Trust Vector)
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @atv/x402-sdk - ATV Premium API Client
|
|
3
|
+
* TypeScript definitions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Hex } from 'viem';
|
|
7
|
+
|
|
8
|
+
export interface ATVClientOptions {
|
|
9
|
+
/** API base URL (default: https://api.web3domains.com) */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
/** Wallet private key for x402 payments */
|
|
12
|
+
privateKey?: Hex;
|
|
13
|
+
/** API key for prepaid credits */
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ENSRecord {
|
|
18
|
+
name: string;
|
|
19
|
+
address: string;
|
|
20
|
+
records: {
|
|
21
|
+
avatar?: string | null;
|
|
22
|
+
twitter?: string | null;
|
|
23
|
+
url?: string | null;
|
|
24
|
+
description?: string | null;
|
|
25
|
+
[key: string]: string | null | undefined;
|
|
26
|
+
};
|
|
27
|
+
timestamp: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ReverseRecord {
|
|
31
|
+
address: string;
|
|
32
|
+
name: string | null;
|
|
33
|
+
timestamp: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Profile {
|
|
37
|
+
name: string;
|
|
38
|
+
address: string;
|
|
39
|
+
avatar?: string | null;
|
|
40
|
+
records: Record<string, string>;
|
|
41
|
+
followers: number;
|
|
42
|
+
following: number;
|
|
43
|
+
timestamp: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ENSValuation {
|
|
47
|
+
name: string;
|
|
48
|
+
estimatedUSD: number;
|
|
49
|
+
range: { low: number; high: number };
|
|
50
|
+
confidence: 'low' | 'medium' | 'high';
|
|
51
|
+
factors: string[];
|
|
52
|
+
length: number;
|
|
53
|
+
isNumeric: boolean;
|
|
54
|
+
renewal: string;
|
|
55
|
+
disclaimer: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ENSExpiration {
|
|
59
|
+
name: string;
|
|
60
|
+
expiresAt: string;
|
|
61
|
+
daysUntilExpiry: number;
|
|
62
|
+
isExpired: boolean;
|
|
63
|
+
isGracePeriod: boolean;
|
|
64
|
+
renewalCost: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SocialStats {
|
|
68
|
+
query: string;
|
|
69
|
+
followers: number;
|
|
70
|
+
following: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface GasPrices {
|
|
74
|
+
mainnet: { wei: string; gwei: string };
|
|
75
|
+
base: { wei: string; gwei: string };
|
|
76
|
+
optimism?: { wei: string; gwei: string };
|
|
77
|
+
arbitrum?: { wei: string; gwei: string };
|
|
78
|
+
timestamp: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface HealthStatus {
|
|
82
|
+
status: string;
|
|
83
|
+
version: string;
|
|
84
|
+
uptime: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface UsageStats {
|
|
88
|
+
used: number;
|
|
89
|
+
remaining: number;
|
|
90
|
+
limit: number;
|
|
91
|
+
resetIn: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export declare class ATVClient {
|
|
95
|
+
constructor(options?: ATVClientOptions);
|
|
96
|
+
|
|
97
|
+
/** Wallet address (if configured) */
|
|
98
|
+
readonly address: Hex | undefined;
|
|
99
|
+
|
|
100
|
+
/** Check USDC balance on Base */
|
|
101
|
+
getUSDCBalance(): Promise<string | null>;
|
|
102
|
+
|
|
103
|
+
/** Make a raw API request */
|
|
104
|
+
request<T = any>(endpoint: string, options?: RequestInit): Promise<T>;
|
|
105
|
+
|
|
106
|
+
// Free endpoints
|
|
107
|
+
health(): Promise<HealthStatus>;
|
|
108
|
+
usage(): Promise<UsageStats>;
|
|
109
|
+
discovery(): Promise<any>;
|
|
110
|
+
|
|
111
|
+
// Identity & ENS
|
|
112
|
+
resolveENS(name: string): Promise<ENSRecord>;
|
|
113
|
+
reverseResolve(address: string): Promise<ReverseRecord>;
|
|
114
|
+
getProfile(name: string): Promise<Profile>;
|
|
115
|
+
getAvatar(name: string): Promise<{ name: string; avatar: string | null }>;
|
|
116
|
+
getENSValue(name: string): Promise<ENSValuation>;
|
|
117
|
+
getExpiration(name: string): Promise<ENSExpiration>;
|
|
118
|
+
batchENS(names: string[]): Promise<ENSRecord[]>;
|
|
119
|
+
getPortfolio(address: string): Promise<any>;
|
|
120
|
+
|
|
121
|
+
// Social Graph
|
|
122
|
+
getSocialStats(name: string): Promise<SocialStats>;
|
|
123
|
+
getFollowers(name: string, limit?: number): Promise<any>;
|
|
124
|
+
getFollowing(name: string, limit?: number): Promise<any>;
|
|
125
|
+
getMutuals(name: string): Promise<any>;
|
|
126
|
+
getReputation(name: string): Promise<any>;
|
|
127
|
+
|
|
128
|
+
// Wallet Analytics
|
|
129
|
+
getBalance(address: string): Promise<any>;
|
|
130
|
+
getTokens(address: string): Promise<any>;
|
|
131
|
+
getTransactions(address: string): Promise<any>;
|
|
132
|
+
getTransfers(address: string): Promise<any>;
|
|
133
|
+
getNFTs(address: string): Promise<any>;
|
|
134
|
+
|
|
135
|
+
// Utilities
|
|
136
|
+
getGas(): Promise<GasPrices>;
|
|
137
|
+
getABI(address: string): Promise<any>;
|
|
138
|
+
getTrending(): Promise<any>;
|
|
139
|
+
getLeaderboard(): Promise<any>;
|
|
140
|
+
getATVInfo(): Promise<any>;
|
|
141
|
+
getFortune(): Promise<{ fortune: string }>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default ATVClient;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @atv/x402-sdk - ATV Premium API Client
|
|
3
|
+
*
|
|
4
|
+
* Official SDK for the ATV x402 Premium API.
|
|
5
|
+
* Handles x402 payment flow automatically with USDC on Base.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```javascript
|
|
9
|
+
* import { ATVClient } from '@atv/x402-sdk';
|
|
10
|
+
*
|
|
11
|
+
* const client = new ATVClient({
|
|
12
|
+
* privateKey: process.env.WALLET_KEY,
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* const profile = await client.getProfile('vitalik.eth');
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @version 1.0.0
|
|
19
|
+
* @license MIT
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { createWalletClient, createPublicClient, http, getAddress, formatUnits } from 'viem';
|
|
23
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
24
|
+
import { base } from 'viem/chains';
|
|
25
|
+
import crypto from 'crypto';
|
|
26
|
+
|
|
27
|
+
const DEFAULT_BASE_URL = 'https://api.web3domains.com';
|
|
28
|
+
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* ATV x402 API Client
|
|
32
|
+
*/
|
|
33
|
+
export class ATVClient {
|
|
34
|
+
/**
|
|
35
|
+
* Create a new ATV client
|
|
36
|
+
* @param {Object} options - Configuration options
|
|
37
|
+
* @param {string} [options.baseUrl] - API base URL (default: https://api.web3domains.com)
|
|
38
|
+
* @param {string} [options.privateKey] - Wallet private key for payments
|
|
39
|
+
* @param {string} [options.apiKey] - API key for prepaid credits (alternative to x402)
|
|
40
|
+
*/
|
|
41
|
+
constructor({ baseUrl, privateKey, apiKey } = {}) {
|
|
42
|
+
this.baseUrl = baseUrl || DEFAULT_BASE_URL;
|
|
43
|
+
this.apiKey = apiKey;
|
|
44
|
+
|
|
45
|
+
if (privateKey) {
|
|
46
|
+
this.account = privateKeyToAccount(privateKey);
|
|
47
|
+
this.walletClient = createWalletClient({
|
|
48
|
+
account: this.account,
|
|
49
|
+
chain: base,
|
|
50
|
+
transport: http(),
|
|
51
|
+
});
|
|
52
|
+
this.publicClient = createPublicClient({
|
|
53
|
+
chain: base,
|
|
54
|
+
transport: http(),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get wallet address (if configured)
|
|
61
|
+
*/
|
|
62
|
+
get address() {
|
|
63
|
+
return this.account?.address;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check USDC balance
|
|
68
|
+
*/
|
|
69
|
+
async getUSDCBalance() {
|
|
70
|
+
if (!this.publicClient || !this.account) return null;
|
|
71
|
+
|
|
72
|
+
const balance = await this.publicClient.readContract({
|
|
73
|
+
address: USDC_BASE,
|
|
74
|
+
abi: [{ name: 'balanceOf', type: 'function', inputs: [{ name: '', type: 'address' }], outputs: [{ name: '', type: 'uint256' }] }],
|
|
75
|
+
functionName: 'balanceOf',
|
|
76
|
+
args: [this.account.address],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return formatUnits(balance, 6);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Make an API request with automatic x402 payment handling
|
|
84
|
+
* @param {string} endpoint - API endpoint
|
|
85
|
+
* @param {Object} [options] - Fetch options
|
|
86
|
+
* @returns {Promise<any>} - API response
|
|
87
|
+
*/
|
|
88
|
+
async request(endpoint, options = {}) {
|
|
89
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
90
|
+
const headers = { ...options.headers };
|
|
91
|
+
|
|
92
|
+
// Add API key if configured
|
|
93
|
+
if (this.apiKey) {
|
|
94
|
+
headers['X-API-Key'] = this.apiKey;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const response = await fetch(url, { ...options, headers });
|
|
98
|
+
|
|
99
|
+
// Handle 402 Payment Required
|
|
100
|
+
if (response.status === 402) {
|
|
101
|
+
if (!this.walletClient) {
|
|
102
|
+
throw new Error('Payment required but no wallet configured. Provide privateKey or apiKey.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return this._handlePayment(endpoint, response, options);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const error = await response.json().catch(() => ({ error: response.statusText }));
|
|
110
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return response.json();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Handle x402 payment flow
|
|
118
|
+
* @private
|
|
119
|
+
*/
|
|
120
|
+
async _handlePayment(endpoint, initialResponse, options) {
|
|
121
|
+
const prHeader = initialResponse.headers.get('payment-required');
|
|
122
|
+
if (!prHeader) throw new Error('No PAYMENT-REQUIRED header');
|
|
123
|
+
|
|
124
|
+
const pr = JSON.parse(Buffer.from(prHeader, 'base64').toString());
|
|
125
|
+
const requirements = pr.accepts[0];
|
|
126
|
+
|
|
127
|
+
// Create EIP-3009 authorization
|
|
128
|
+
const nonce = '0x' + crypto.randomBytes(32).toString('hex');
|
|
129
|
+
const now = Math.floor(Date.now() / 1000);
|
|
130
|
+
|
|
131
|
+
const authorization = {
|
|
132
|
+
from: this.account.address,
|
|
133
|
+
to: requirements.payTo,
|
|
134
|
+
value: requirements.amount,
|
|
135
|
+
validAfter: (now - 60).toString(),
|
|
136
|
+
validBefore: (now + requirements.maxTimeoutSeconds).toString(),
|
|
137
|
+
nonce,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Sign with EIP-712
|
|
141
|
+
const chainId = parseInt(requirements.network.split(':')[1]);
|
|
142
|
+
|
|
143
|
+
const signature = await this.walletClient.signTypedData({
|
|
144
|
+
domain: {
|
|
145
|
+
name: requirements.extra.name,
|
|
146
|
+
version: requirements.extra.version,
|
|
147
|
+
chainId,
|
|
148
|
+
verifyingContract: getAddress(requirements.asset),
|
|
149
|
+
},
|
|
150
|
+
types: {
|
|
151
|
+
TransferWithAuthorization: [
|
|
152
|
+
{ name: 'from', type: 'address' },
|
|
153
|
+
{ name: 'to', type: 'address' },
|
|
154
|
+
{ name: 'value', type: 'uint256' },
|
|
155
|
+
{ name: 'validAfter', type: 'uint256' },
|
|
156
|
+
{ name: 'validBefore', type: 'uint256' },
|
|
157
|
+
{ name: 'nonce', type: 'bytes32' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
primaryType: 'TransferWithAuthorization',
|
|
161
|
+
message: {
|
|
162
|
+
from: getAddress(authorization.from),
|
|
163
|
+
to: getAddress(authorization.to),
|
|
164
|
+
value: BigInt(authorization.value),
|
|
165
|
+
validAfter: BigInt(authorization.validAfter),
|
|
166
|
+
validBefore: BigInt(authorization.validBefore),
|
|
167
|
+
nonce: authorization.nonce,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Create x402 v2 payload
|
|
172
|
+
const payload = {
|
|
173
|
+
x402Version: 2,
|
|
174
|
+
scheme: 'exact',
|
|
175
|
+
network: requirements.network,
|
|
176
|
+
accepted: requirements,
|
|
177
|
+
payload: { signature, authorization },
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Retry with payment
|
|
181
|
+
const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');
|
|
182
|
+
const paidResponse = await fetch(`${this.baseUrl}${endpoint}`, {
|
|
183
|
+
...options,
|
|
184
|
+
headers: {
|
|
185
|
+
...options.headers,
|
|
186
|
+
'PAYMENT-SIGNATURE': paymentHeader,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (!paidResponse.ok) {
|
|
191
|
+
const error = await paidResponse.json().catch(() => ({}));
|
|
192
|
+
throw new Error(error.error || `Payment failed: ${paidResponse.status}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return paidResponse.json();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ═══════════════════════════════════════════════════════════════
|
|
199
|
+
// FREE ENDPOINTS
|
|
200
|
+
// ═══════════════════════════════════════════════════════════════
|
|
201
|
+
|
|
202
|
+
/** Health check */
|
|
203
|
+
async health() {
|
|
204
|
+
return this.request('/health');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Check free tier usage */
|
|
208
|
+
async usage() {
|
|
209
|
+
return this.request('/api/usage');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** API discovery */
|
|
213
|
+
async discovery() {
|
|
214
|
+
return this.request('/.well-known/x402');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ═══════════════════════════════════════════════════════════════
|
|
218
|
+
// IDENTITY & ENS ($0.01 - $0.05)
|
|
219
|
+
// ═══════════════════════════════════════════════════════════════
|
|
220
|
+
|
|
221
|
+
/** Resolve ENS name to address */
|
|
222
|
+
async resolveENS(name) {
|
|
223
|
+
return this.request(`/api/ens/${encodeURIComponent(name)}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Reverse resolve address to ENS */
|
|
227
|
+
async reverseResolve(address) {
|
|
228
|
+
return this.request(`/api/reverse/${address}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Get full identity profile */
|
|
232
|
+
async getProfile(name) {
|
|
233
|
+
return this.request(`/api/profile/${encodeURIComponent(name)}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Get avatar URL */
|
|
237
|
+
async getAvatar(name) {
|
|
238
|
+
return this.request(`/api/avatar/${encodeURIComponent(name)}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Estimate ENS name value */
|
|
242
|
+
async getENSValue(name) {
|
|
243
|
+
return this.request(`/api/ens-value/${encodeURIComponent(name)}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Get ENS expiration info */
|
|
247
|
+
async getExpiration(name) {
|
|
248
|
+
return this.request(`/api/expiration/${encodeURIComponent(name)}`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Batch resolve multiple ENS names */
|
|
252
|
+
async batchENS(names) {
|
|
253
|
+
return this.request('/api/batch/ens', {
|
|
254
|
+
method: 'POST',
|
|
255
|
+
headers: { 'Content-Type': 'application/json' },
|
|
256
|
+
body: JSON.stringify({ names }),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Get ENS portfolio for address */
|
|
261
|
+
async getPortfolio(address) {
|
|
262
|
+
return this.request(`/api/portfolio/${address}`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ═══════════════════════════════════════════════════════════════
|
|
266
|
+
// SOCIAL GRAPH ($0.01 - $0.03)
|
|
267
|
+
// ═══════════════════════════════════════════════════════════════
|
|
268
|
+
|
|
269
|
+
/** Get follower/following counts */
|
|
270
|
+
async getSocialStats(name) {
|
|
271
|
+
return this.request(`/api/social/${encodeURIComponent(name)}`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Get followers list */
|
|
275
|
+
async getFollowers(name, limit = 20) {
|
|
276
|
+
return this.request(`/api/followers/${encodeURIComponent(name)}?limit=${limit}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Get following list */
|
|
280
|
+
async getFollowing(name, limit = 20) {
|
|
281
|
+
return this.request(`/api/following/${encodeURIComponent(name)}?limit=${limit}`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Get mutual followers */
|
|
285
|
+
async getMutuals(name) {
|
|
286
|
+
return this.request(`/api/mutuals/${encodeURIComponent(name)}`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Get reputation score */
|
|
290
|
+
async getReputation(name) {
|
|
291
|
+
return this.request(`/api/reputation/${encodeURIComponent(name)}`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ═══════════════════════════════════════════════════════════════
|
|
295
|
+
// WALLET ANALYTICS ($0.01 - $0.03)
|
|
296
|
+
// ═══════════════════════════════════════════════════════════════
|
|
297
|
+
|
|
298
|
+
/** Get ETH balance (multi-chain) */
|
|
299
|
+
async getBalance(address) {
|
|
300
|
+
return this.request(`/api/balance/${address}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Get ERC20 token balances */
|
|
304
|
+
async getTokens(address) {
|
|
305
|
+
return this.request(`/api/tokens/${address}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** Get transaction history */
|
|
309
|
+
async getTransactions(address) {
|
|
310
|
+
return this.request(`/api/txs/${address}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** Get token transfers */
|
|
314
|
+
async getTransfers(address) {
|
|
315
|
+
return this.request(`/api/transfers/${address}`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/** Get NFT holdings */
|
|
319
|
+
async getNFTs(address) {
|
|
320
|
+
return this.request(`/api/nfts/${address}`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ═══════════════════════════════════════════════════════════════
|
|
324
|
+
// UTILITIES ($0.001 - $0.02)
|
|
325
|
+
// ═══════════════════════════════════════════════════════════════
|
|
326
|
+
|
|
327
|
+
/** Get current gas prices */
|
|
328
|
+
async getGas() {
|
|
329
|
+
return this.request('/api/gas');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Get contract ABI */
|
|
333
|
+
async getABI(address) {
|
|
334
|
+
return this.request(`/api/abi/${address}`);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Get trending ENS activity */
|
|
338
|
+
async getTrending() {
|
|
339
|
+
return this.request('/api/trending');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Get top accounts leaderboard */
|
|
343
|
+
async getLeaderboard() {
|
|
344
|
+
return this.request('/api/leaderboard');
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** Get ATV agent info */
|
|
348
|
+
async getATVInfo() {
|
|
349
|
+
return this.request('/api/atv');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** Get random security wisdom */
|
|
353
|
+
async getFortune() {
|
|
354
|
+
return this.request('/api/fortune');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Default export
|
|
359
|
+
export default ATVClient;
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atv-eth/x402-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official SDK for the ATV x402 Premium API - ENS, identity, social graphs, and wallet analytics with automatic USDC payments on Base",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.mjs",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./index.mjs",
|
|
11
|
+
"types": "./index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"index.mjs",
|
|
16
|
+
"index.d.ts",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"x402",
|
|
21
|
+
"ens",
|
|
22
|
+
"ethereum",
|
|
23
|
+
"web3",
|
|
24
|
+
"identity",
|
|
25
|
+
"api",
|
|
26
|
+
"usdc",
|
|
27
|
+
"base",
|
|
28
|
+
"payments",
|
|
29
|
+
"atv"
|
|
30
|
+
],
|
|
31
|
+
"author": "ATV (Agent Trust Vector) <atv@web3domains.com>",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"homepage": "https://api.web3domains.com",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/ATV-eth/x402-sdk"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/ATV-eth/x402-sdk/issues"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"viem": "^2.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"viem": "^2.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|