@gistplus/client 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 +280 -0
- package/dist/client.d.ts +116 -0
- package/dist/client.js +161 -0
- package/dist/http-client.d.ts +47 -0
- package/dist/http-client.js +138 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +33 -0
- package/dist/session-manager.d.ts +50 -0
- package/dist/session-manager.js +107 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# @gistplus/client
|
|
2
|
+
|
|
3
|
+
[](https://x.com/gistplus)
|
|
4
|
+
|
|
5
|
+
Client SDK for AI agents and applications to interact with Gist Plus providers.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @gistplus/client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What is This?
|
|
14
|
+
|
|
15
|
+
This package enables **AI agents and applications** to:
|
|
16
|
+
- 🤝 Negotiate pricing with API providers
|
|
17
|
+
- 💰 Create prepaid sessions
|
|
18
|
+
- 🚀 Execute requests with automatic payment
|
|
19
|
+
- ✅ Verify cryptographic receipts
|
|
20
|
+
- 💵 Get refunds for unused balance
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Connection, Keypair } from '@solana/web3.js';
|
|
26
|
+
import { GistClient } from '@gistplus/client';
|
|
27
|
+
|
|
28
|
+
// Initialize
|
|
29
|
+
const connection = new Connection('https://api.devnet.solana.com');
|
|
30
|
+
const wallet = Keypair.generate(); // Your agent's wallet
|
|
31
|
+
const client = new GistClient({ connection, wallet });
|
|
32
|
+
|
|
33
|
+
// 1. Create Intent (express your needs)
|
|
34
|
+
const intent = client.createIntent({
|
|
35
|
+
capability: 'gpt-4-inference',
|
|
36
|
+
maxPricePerRequest: 0.01,
|
|
37
|
+
token: 'USDC',
|
|
38
|
+
sla: { maxLatencyMs: 2000 }
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 2. Negotiate with provider
|
|
42
|
+
const offer = await client.negotiate('https://api.provider.com', intent);
|
|
43
|
+
|
|
44
|
+
// 3. Create prepaid session
|
|
45
|
+
const session = await client.createSession(offer);
|
|
46
|
+
|
|
47
|
+
// 4. Execute requests (payment automatic!)
|
|
48
|
+
const result = await client.executeRequest(session.sessionId, {
|
|
49
|
+
prompt: 'Explain quantum computing'
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
console.log(result.data); // API response
|
|
53
|
+
console.log(result.receipt); // Cryptographic proof
|
|
54
|
+
|
|
55
|
+
// 5. Close session and get refund
|
|
56
|
+
await client.closeSession(session.sessionId);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Core Features
|
|
60
|
+
|
|
61
|
+
### Automatic Negotiation
|
|
62
|
+
```typescript
|
|
63
|
+
// Agent expresses maximum price
|
|
64
|
+
const intent = client.createIntent({
|
|
65
|
+
maxPricePerRequest: 0.01,
|
|
66
|
+
capability: 'ai-inference'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Provider responds with actual price
|
|
70
|
+
const offer = await client.negotiate(endpoint, intent);
|
|
71
|
+
|
|
72
|
+
// Verify it's within budget
|
|
73
|
+
if (offer.pricePerRequest <= intent.maxPricePerRequest) {
|
|
74
|
+
// Accept!
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Prepaid Sessions
|
|
79
|
+
```typescript
|
|
80
|
+
// Deposit once, make many requests
|
|
81
|
+
const session = await client.createSession(offer, {
|
|
82
|
+
depositAmount: 1.0 // 1 USDC
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Make multiple requests without per-request transactions
|
|
86
|
+
await client.executeRequest(session.sessionId, request1);
|
|
87
|
+
await client.executeRequest(session.sessionId, request2);
|
|
88
|
+
await client.executeRequest(session.sessionId, request3);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Receipt Verification
|
|
92
|
+
```typescript
|
|
93
|
+
const result = await client.executeRequest(sessionId, data);
|
|
94
|
+
|
|
95
|
+
// Every request gets a cryptographic receipt
|
|
96
|
+
console.log(result.receipt);
|
|
97
|
+
/*
|
|
98
|
+
{
|
|
99
|
+
receiptId: "receipt_123",
|
|
100
|
+
inputHash: "sha256(...)", // Tamper-proof
|
|
101
|
+
outputHash: "sha256(...)", // Tamper-proof
|
|
102
|
+
signature: "...", // Provider's signature
|
|
103
|
+
slaVerification: {
|
|
104
|
+
met: true,
|
|
105
|
+
metrics: { latency: { expected: 2000, actual: 1234 } }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
*/
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### SLA Enforcement
|
|
112
|
+
```typescript
|
|
113
|
+
// Request SLA guarantees
|
|
114
|
+
const intent = client.createIntent({
|
|
115
|
+
sla: {
|
|
116
|
+
maxLatencyMs: 2000, // Must respond within 2s
|
|
117
|
+
minUptimePercent: 99.0, // Must have 99% uptime
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// If provider breaches SLA, automatic refund!
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### GistClient
|
|
127
|
+
|
|
128
|
+
#### Constructor
|
|
129
|
+
```typescript
|
|
130
|
+
new GistClient({
|
|
131
|
+
connection: Connection, // Solana connection
|
|
132
|
+
wallet: Keypair, // Your wallet
|
|
133
|
+
httpConfig?: { // Optional HTTP settings
|
|
134
|
+
timeout?: number,
|
|
135
|
+
headers?: Record<string, string>
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Methods
|
|
141
|
+
|
|
142
|
+
**createIntent(options)**
|
|
143
|
+
```typescript
|
|
144
|
+
client.createIntent({
|
|
145
|
+
capability: string,
|
|
146
|
+
maxPricePerRequest: number,
|
|
147
|
+
token: 'SOL' | 'USDC' | 'USDT' | 'BONK',
|
|
148
|
+
sla?: { maxLatencyMs?, minUptimePercent? },
|
|
149
|
+
maxSessionBudget?: number,
|
|
150
|
+
sessionDurationMs?: number,
|
|
151
|
+
metadata?: Record<string, any>
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**negotiate(endpoint, intent)**
|
|
156
|
+
```typescript
|
|
157
|
+
const offer = await client.negotiate(
|
|
158
|
+
'https://api.provider.com',
|
|
159
|
+
intent
|
|
160
|
+
);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**createSession(offer, options?)**
|
|
164
|
+
```typescript
|
|
165
|
+
const session = await client.createSession(offer, {
|
|
166
|
+
depositAmount?: number, // Custom deposit
|
|
167
|
+
anchorOnChain?: boolean // Store on Solana (optional)
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**executeRequest(sessionId, data)**
|
|
172
|
+
```typescript
|
|
173
|
+
const result = await client.executeRequest(
|
|
174
|
+
sessionId,
|
|
175
|
+
{ prompt: 'Hello' }
|
|
176
|
+
);
|
|
177
|
+
// Returns: { data, receipt }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**closeSession(sessionId)**
|
|
181
|
+
```typescript
|
|
182
|
+
const refund = await client.closeSession(sessionId);
|
|
183
|
+
// Returns: { refundAmount, txSignature }
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**getSession(sessionId)**
|
|
187
|
+
```typescript
|
|
188
|
+
const session = client.getSession(sessionId);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**getActiveSessions()**
|
|
192
|
+
```typescript
|
|
193
|
+
const sessions = client.getActiveSessions();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Examples
|
|
197
|
+
|
|
198
|
+
### AI Inference
|
|
199
|
+
```typescript
|
|
200
|
+
const intent = client.createIntent({
|
|
201
|
+
capability: 'gpt-4-inference',
|
|
202
|
+
maxPricePerRequest: 0.01,
|
|
203
|
+
token: 'USDC'
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const offer = await client.negotiate('https://ai-api.com', intent);
|
|
207
|
+
const session = await client.createSession(offer);
|
|
208
|
+
|
|
209
|
+
const result = await client.executeRequest(session.sessionId, {
|
|
210
|
+
prompt: 'Write a poem about Solana'
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
console.log(result.data.text);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Image Generation
|
|
217
|
+
```typescript
|
|
218
|
+
const intent = client.createIntent({
|
|
219
|
+
capability: 'image-generation',
|
|
220
|
+
maxPricePerRequest: 0.05,
|
|
221
|
+
token: 'USDC'
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const offer = await client.negotiate('https://image-api.com', intent);
|
|
225
|
+
const session = await client.createSession(offer);
|
|
226
|
+
|
|
227
|
+
const result = await client.executeRequest(session.sessionId, {
|
|
228
|
+
prompt: 'A futuristic city on Mars',
|
|
229
|
+
style: 'photorealistic'
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
console.log(result.data.imageUrl);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Data Analysis
|
|
236
|
+
```typescript
|
|
237
|
+
const intent = client.createIntent({
|
|
238
|
+
capability: 'data-analysis',
|
|
239
|
+
maxPricePerRequest: 0.001,
|
|
240
|
+
token: 'USDC'
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const offer = await client.negotiate('https://data-api.com', intent);
|
|
244
|
+
const session = await client.createSession(offer);
|
|
245
|
+
|
|
246
|
+
const result = await client.executeRequest(session.sessionId, {
|
|
247
|
+
dataset: myData,
|
|
248
|
+
operation: 'statistical-summary'
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
console.log(result.data.analysis);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Error Handling
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
try {
|
|
258
|
+
const offer = await client.negotiate(endpoint, intent);
|
|
259
|
+
const session = await client.createSession(offer);
|
|
260
|
+
const result = await client.executeRequest(session.sessionId, data);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
if (error instanceof InvalidOfferError) {
|
|
263
|
+
console.error('Offer validation failed');
|
|
264
|
+
} else if (error instanceof SessionExpiredError) {
|
|
265
|
+
console.error('Session expired, create new one');
|
|
266
|
+
} else if (error instanceof InsufficientFundsError) {
|
|
267
|
+
console.error('Session balance depleted');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Related Packages
|
|
273
|
+
|
|
274
|
+
- **[@gistplus/core](https://www.npmjs.com/package/@gistplus/core)** - Core protocol (auto-installed)
|
|
275
|
+
- **[@gistplus/server](https://www.npmjs.com/package/@gistplus/server)** - For API providers
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
Apache 2.0
|
|
280
|
+
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GistClient - Main client interface for Gist Plus protocol
|
|
3
|
+
*/
|
|
4
|
+
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
5
|
+
import { Intent, Offer, Session, Receipt, SLA, SupportedToken } from '@gistplus/core';
|
|
6
|
+
export interface GistClientConfig {
|
|
7
|
+
/** Solana connection */
|
|
8
|
+
connection: Connection;
|
|
9
|
+
/** Agent's keypair for signing transactions */
|
|
10
|
+
wallet: Keypair;
|
|
11
|
+
/** Optional HTTP client config */
|
|
12
|
+
httpConfig?: {
|
|
13
|
+
timeout?: number;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface CreateIntentOptions {
|
|
18
|
+
capability: string;
|
|
19
|
+
maxPricePerRequest: number;
|
|
20
|
+
token: SupportedToken;
|
|
21
|
+
maxSessionBudget?: number;
|
|
22
|
+
sessionDurationMs?: number;
|
|
23
|
+
sla?: SLA;
|
|
24
|
+
metadata?: Record<string, any>;
|
|
25
|
+
}
|
|
26
|
+
export interface NegotiateOptions {
|
|
27
|
+
/** Custom headers for the request */
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
/** Timeout in milliseconds */
|
|
30
|
+
timeout?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface CreateSessionOptions {
|
|
33
|
+
/** Custom deposit amount (defaults to maxSessionBudget from Intent) */
|
|
34
|
+
depositAmount?: number;
|
|
35
|
+
/** Whether to anchor session on-chain (costs extra transaction fee) */
|
|
36
|
+
anchorOnChain?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* GistClient - Primary interface for Gist Plus protocol
|
|
40
|
+
*
|
|
41
|
+
* Enables AI agents to:
|
|
42
|
+
* 1. Create Intents expressing their needs
|
|
43
|
+
* 2. Negotiate Offers with providers
|
|
44
|
+
* 3. Create prepaid Sessions
|
|
45
|
+
* 4. Execute requests and verify Receipts
|
|
46
|
+
*/
|
|
47
|
+
export declare class GistClient {
|
|
48
|
+
private connection;
|
|
49
|
+
private wallet;
|
|
50
|
+
private httpClient;
|
|
51
|
+
private sessionManager;
|
|
52
|
+
constructor(config: GistClientConfig);
|
|
53
|
+
/**
|
|
54
|
+
* Create a new Intent
|
|
55
|
+
*/
|
|
56
|
+
createIntent(options: CreateIntentOptions): Intent;
|
|
57
|
+
/**
|
|
58
|
+
* Negotiate an Offer with a provider
|
|
59
|
+
*
|
|
60
|
+
* Sends Intent to provider's endpoint and receives a signed Offer.
|
|
61
|
+
*
|
|
62
|
+
* @param providerEndpoint - Provider's endpoint URL
|
|
63
|
+
* @param intent - Intent object
|
|
64
|
+
* @param options - Negotiation options
|
|
65
|
+
* @returns Signed Offer from provider
|
|
66
|
+
*/
|
|
67
|
+
negotiate(providerEndpoint: string, intent: Intent, options?: NegotiateOptions): Promise<Offer>;
|
|
68
|
+
/**
|
|
69
|
+
* Create a Session from an accepted Offer
|
|
70
|
+
*
|
|
71
|
+
* Transfers funds to the provider and creates a prepaid session.
|
|
72
|
+
*
|
|
73
|
+
* @param offer - Accepted Offer
|
|
74
|
+
* @param options - Session creation options
|
|
75
|
+
* @returns Active Session
|
|
76
|
+
*/
|
|
77
|
+
createSession(offer: Offer, options?: CreateSessionOptions): Promise<Session>;
|
|
78
|
+
/**
|
|
79
|
+
* Get an active session by ID
|
|
80
|
+
*/
|
|
81
|
+
getSession(sessionId: string): Session | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Execute a request within a Session
|
|
84
|
+
*
|
|
85
|
+
* @param sessionId - Session ID
|
|
86
|
+
* @param requestData - Request payload
|
|
87
|
+
* @returns Response data and Receipt
|
|
88
|
+
*/
|
|
89
|
+
executeRequest(sessionId: string, requestData: any): Promise<{
|
|
90
|
+
data: any;
|
|
91
|
+
receipt: Receipt;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Close a session and claim refund for remaining balance
|
|
95
|
+
*/
|
|
96
|
+
closeSession(sessionId: string): Promise<{
|
|
97
|
+
refundAmount: number;
|
|
98
|
+
txSignature: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Get all active sessions
|
|
102
|
+
*/
|
|
103
|
+
getActiveSessions(): Session[];
|
|
104
|
+
/**
|
|
105
|
+
* Transfer funds to provider (SOL or SPL token)
|
|
106
|
+
*/
|
|
107
|
+
private transferFunds;
|
|
108
|
+
/**
|
|
109
|
+
* Calculate default deposit amount from Offer
|
|
110
|
+
*/
|
|
111
|
+
private calculateDefaultDeposit;
|
|
112
|
+
/**
|
|
113
|
+
* Get wallet public key
|
|
114
|
+
*/
|
|
115
|
+
get publicKey(): PublicKey;
|
|
116
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GistClient - Main client interface for Gist Plus protocol
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GistClient = void 0;
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
8
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
9
|
+
const core_1 = require("@gistplus/core");
|
|
10
|
+
const http_client_1 = require("./http-client");
|
|
11
|
+
const session_manager_1 = require("./session-manager");
|
|
12
|
+
/**
|
|
13
|
+
* GistClient - Primary interface for Gist Plus protocol
|
|
14
|
+
*
|
|
15
|
+
* Enables AI agents to:
|
|
16
|
+
* 1. Create Intents expressing their needs
|
|
17
|
+
* 2. Negotiate Offers with providers
|
|
18
|
+
* 3. Create prepaid Sessions
|
|
19
|
+
* 4. Execute requests and verify Receipts
|
|
20
|
+
*/
|
|
21
|
+
class GistClient {
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.connection = config.connection;
|
|
24
|
+
this.wallet = config.wallet;
|
|
25
|
+
this.httpClient = new http_client_1.HttpClient(config.httpConfig);
|
|
26
|
+
this.sessionManager = new session_manager_1.SessionManager(this.connection, this.wallet);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a new Intent
|
|
30
|
+
*/
|
|
31
|
+
createIntent(options) {
|
|
32
|
+
return (0, core_1.createIntent)({
|
|
33
|
+
...options,
|
|
34
|
+
agentPubkey: this.wallet.publicKey,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Negotiate an Offer with a provider
|
|
39
|
+
*
|
|
40
|
+
* Sends Intent to provider's endpoint and receives a signed Offer.
|
|
41
|
+
*
|
|
42
|
+
* @param providerEndpoint - Provider's endpoint URL
|
|
43
|
+
* @param intent - Intent object
|
|
44
|
+
* @param options - Negotiation options
|
|
45
|
+
* @returns Signed Offer from provider
|
|
46
|
+
*/
|
|
47
|
+
async negotiate(providerEndpoint, intent, options) {
|
|
48
|
+
// Send Intent to provider
|
|
49
|
+
const offer = await this.httpClient.sendIntent(providerEndpoint, intent, options);
|
|
50
|
+
// Verify Offer signature and validity
|
|
51
|
+
(0, core_1.verifyOffer)(offer);
|
|
52
|
+
return offer;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a Session from an accepted Offer
|
|
56
|
+
*
|
|
57
|
+
* Transfers funds to the provider and creates a prepaid session.
|
|
58
|
+
*
|
|
59
|
+
* @param offer - Accepted Offer
|
|
60
|
+
* @param options - Session creation options
|
|
61
|
+
* @returns Active Session
|
|
62
|
+
*/
|
|
63
|
+
async createSession(offer, options) {
|
|
64
|
+
// Calculate deposit amount
|
|
65
|
+
const depositAmount = options?.depositAmount || this.calculateDefaultDeposit(offer);
|
|
66
|
+
// Transfer funds to provider
|
|
67
|
+
const txSignature = await this.transferFunds(offer.providerPubkey, offer.token, depositAmount);
|
|
68
|
+
// Create session with provider
|
|
69
|
+
const session = await this.httpClient.createSession(offer, depositAmount, txSignature);
|
|
70
|
+
// Register session with manager
|
|
71
|
+
this.sessionManager.registerSession(session);
|
|
72
|
+
return session;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get an active session by ID
|
|
76
|
+
*/
|
|
77
|
+
getSession(sessionId) {
|
|
78
|
+
return this.sessionManager.getSession(sessionId);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Execute a request within a Session
|
|
82
|
+
*
|
|
83
|
+
* @param sessionId - Session ID
|
|
84
|
+
* @param requestData - Request payload
|
|
85
|
+
* @returns Response data and Receipt
|
|
86
|
+
*/
|
|
87
|
+
async executeRequest(sessionId, requestData) {
|
|
88
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
89
|
+
if (!session) {
|
|
90
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
91
|
+
}
|
|
92
|
+
// Execute request via HTTP client
|
|
93
|
+
const result = await this.httpClient.executeRequest(session, requestData);
|
|
94
|
+
// Update session state
|
|
95
|
+
this.sessionManager.updateSessionAfterRequest(sessionId, result.receipt);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Close a session and claim refund for remaining balance
|
|
100
|
+
*/
|
|
101
|
+
async closeSession(sessionId) {
|
|
102
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
103
|
+
if (!session) {
|
|
104
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
105
|
+
}
|
|
106
|
+
// Request refund from provider
|
|
107
|
+
const refundResponse = await this.httpClient.closeSession(session);
|
|
108
|
+
// Mark session as closed
|
|
109
|
+
this.sessionManager.closeSession(sessionId);
|
|
110
|
+
return refundResponse;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get all active sessions
|
|
114
|
+
*/
|
|
115
|
+
getActiveSessions() {
|
|
116
|
+
return this.sessionManager.getActiveSessions();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Transfer funds to provider (SOL or SPL token)
|
|
120
|
+
*/
|
|
121
|
+
async transferFunds(providerPubkey, token, amount) {
|
|
122
|
+
const provider = new web3_js_1.PublicKey(providerPubkey);
|
|
123
|
+
if (token === 'SOL') {
|
|
124
|
+
// Transfer SOL
|
|
125
|
+
const transaction = new web3_js_1.Transaction().add(web3_js_1.SystemProgram.transfer({
|
|
126
|
+
fromPubkey: this.wallet.publicKey,
|
|
127
|
+
toPubkey: provider,
|
|
128
|
+
lamports: amount * 1e9, // Convert SOL to lamports
|
|
129
|
+
}));
|
|
130
|
+
const signature = await (0, web3_js_1.sendAndConfirmTransaction)(this.connection, transaction, [this.wallet]);
|
|
131
|
+
return signature;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Transfer SPL token
|
|
135
|
+
const mintAddress = new web3_js_1.PublicKey(core_1.TOKEN_MINTS[token]);
|
|
136
|
+
// Get or create associated token accounts
|
|
137
|
+
const fromTokenAccount = await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(this.connection, this.wallet, mintAddress, this.wallet.publicKey);
|
|
138
|
+
const toTokenAccount = await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(this.connection, this.wallet, mintAddress, provider);
|
|
139
|
+
// Create transfer instruction
|
|
140
|
+
const transaction = new web3_js_1.Transaction().add((0, spl_token_1.createTransferInstruction)(fromTokenAccount.address, toTokenAccount.address, this.wallet.publicKey, amount * 1e6, // Assuming 6 decimals for USDC/USDT
|
|
141
|
+
[], spl_token_1.TOKEN_PROGRAM_ID));
|
|
142
|
+
const signature = await (0, web3_js_1.sendAndConfirmTransaction)(this.connection, transaction, [this.wallet]);
|
|
143
|
+
return signature;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Calculate default deposit amount from Offer
|
|
148
|
+
*/
|
|
149
|
+
calculateDefaultDeposit(offer) {
|
|
150
|
+
// Default: enough for 10 requests or session duration worth
|
|
151
|
+
const minRequests = 10;
|
|
152
|
+
return offer.pricePerRequest * minRequests;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get wallet public key
|
|
156
|
+
*/
|
|
157
|
+
get publicKey() {
|
|
158
|
+
return this.wallet.publicKey;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.GistClient = GistClient;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Client for Gist Plus protocol communication
|
|
3
|
+
*/
|
|
4
|
+
import { Intent, Offer, Session, Receipt } from '@gistplus/core';
|
|
5
|
+
export interface HttpClientConfig {
|
|
6
|
+
timeout?: number;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* HttpClient handles HTTP communication with Gist Plus providers
|
|
11
|
+
*/
|
|
12
|
+
export declare class HttpClient {
|
|
13
|
+
private axios;
|
|
14
|
+
constructor(config?: HttpClientConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Send Intent to provider and receive Offer
|
|
17
|
+
*
|
|
18
|
+
* Makes a request to provider endpoint, receives 402 Quote Required,
|
|
19
|
+
* sends Intent, and receives signed Offer.
|
|
20
|
+
*/
|
|
21
|
+
sendIntent(endpoint: string, intent: Intent, options?: {
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
}): Promise<Offer>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a Session with provider
|
|
27
|
+
*/
|
|
28
|
+
createSession(offer: Offer, depositAmount: number, txSignature: string): Promise<Session>;
|
|
29
|
+
/**
|
|
30
|
+
* Execute a request within a Session
|
|
31
|
+
*/
|
|
32
|
+
executeRequest(session: Session, requestData: any): Promise<{
|
|
33
|
+
data: any;
|
|
34
|
+
receipt: Receipt;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Close a session and request refund
|
|
38
|
+
*/
|
|
39
|
+
closeSession(session: Session): Promise<{
|
|
40
|
+
refundAmount: number;
|
|
41
|
+
txSignature: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Get provider endpoint for session
|
|
45
|
+
*/
|
|
46
|
+
private getSessionEndpoint;
|
|
47
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP Client for Gist Plus protocol communication
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.HttpClient = void 0;
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
const core_1 = require("@gistplus/core");
|
|
12
|
+
/**
|
|
13
|
+
* HttpClient handles HTTP communication with Gist Plus providers
|
|
14
|
+
*/
|
|
15
|
+
class HttpClient {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.axios = axios_1.default.create({
|
|
18
|
+
timeout: config?.timeout || 30000,
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
...config?.headers,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Send Intent to provider and receive Offer
|
|
27
|
+
*
|
|
28
|
+
* Makes a request to provider endpoint, receives 402 Quote Required,
|
|
29
|
+
* sends Intent, and receives signed Offer.
|
|
30
|
+
*/
|
|
31
|
+
async sendIntent(endpoint, intent, options) {
|
|
32
|
+
try {
|
|
33
|
+
// Send Intent to provider
|
|
34
|
+
const response = await this.axios.post(endpoint, {}, {
|
|
35
|
+
headers: {
|
|
36
|
+
[core_1.HEADERS.INTENT]: JSON.stringify(intent),
|
|
37
|
+
...options?.headers,
|
|
38
|
+
},
|
|
39
|
+
timeout: options?.timeout,
|
|
40
|
+
});
|
|
41
|
+
// Provider should respond with Offer in header
|
|
42
|
+
const offerHeader = response.headers[core_1.HEADERS.OFFER.toLowerCase()];
|
|
43
|
+
if (!offerHeader) {
|
|
44
|
+
throw new Error('Provider did not return an Offer');
|
|
45
|
+
}
|
|
46
|
+
const offer = JSON.parse(offerHeader);
|
|
47
|
+
return offer;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (axios_1.default.isAxiosError(error) && error.response?.status === core_1.HTTP_STATUS.QUOTE_REQUIRED) {
|
|
51
|
+
// Expected 402 response with Offer
|
|
52
|
+
const offerHeader = error.response.headers[core_1.HEADERS.OFFER.toLowerCase()];
|
|
53
|
+
if (offerHeader) {
|
|
54
|
+
const offer = JSON.parse(offerHeader);
|
|
55
|
+
return offer;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Failed to negotiate with provider: ${error}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a Session with provider
|
|
63
|
+
*/
|
|
64
|
+
async createSession(offer, depositAmount, txSignature) {
|
|
65
|
+
try {
|
|
66
|
+
const response = await this.axios.post(`${offer.endpoint}/session/create`, {
|
|
67
|
+
offerId: offer.offerId,
|
|
68
|
+
depositAmount,
|
|
69
|
+
txSignature,
|
|
70
|
+
});
|
|
71
|
+
if (response.status !== core_1.HTTP_STATUS.SESSION_STARTED && response.status !== 201) {
|
|
72
|
+
throw new Error(`Unexpected status code: ${response.status}`);
|
|
73
|
+
}
|
|
74
|
+
const session = response.data;
|
|
75
|
+
return session;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw new Error(`Failed to create session: ${error}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Execute a request within a Session
|
|
83
|
+
*/
|
|
84
|
+
async executeRequest(session, requestData) {
|
|
85
|
+
try {
|
|
86
|
+
// Get provider endpoint from session metadata or construct it
|
|
87
|
+
const endpoint = this.getSessionEndpoint(session);
|
|
88
|
+
const response = await this.axios.post(endpoint, requestData, {
|
|
89
|
+
headers: {
|
|
90
|
+
[core_1.HEADERS.SESSION_ID]: session.sessionId,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
// Extract receipt from header
|
|
94
|
+
const receiptHeader = response.headers[core_1.HEADERS.RECEIPT.toLowerCase()];
|
|
95
|
+
if (!receiptHeader) {
|
|
96
|
+
throw new Error('Provider did not return a Receipt');
|
|
97
|
+
}
|
|
98
|
+
const receipt = JSON.parse(receiptHeader);
|
|
99
|
+
// Verify receipt signature
|
|
100
|
+
(0, core_1.verifyReceipt)(receipt);
|
|
101
|
+
return {
|
|
102
|
+
data: response.data,
|
|
103
|
+
receipt,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Failed to execute request: ${error}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Close a session and request refund
|
|
112
|
+
*/
|
|
113
|
+
async closeSession(session) {
|
|
114
|
+
try {
|
|
115
|
+
const endpoint = this.getSessionEndpoint(session);
|
|
116
|
+
const response = await this.axios.post(`${endpoint}/close`, {
|
|
117
|
+
sessionId: session.sessionId,
|
|
118
|
+
}, {
|
|
119
|
+
headers: {
|
|
120
|
+
[core_1.HEADERS.SESSION_ID]: session.sessionId,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return response.data;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
throw new Error(`Failed to close session: ${error}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get provider endpoint for session
|
|
131
|
+
*/
|
|
132
|
+
getSessionEndpoint(session) {
|
|
133
|
+
// In a real implementation, this might be stored in session metadata
|
|
134
|
+
// For now, construct from provider's base endpoint
|
|
135
|
+
return session.metadata?.endpoint || `https://provider/${session.providerPubkey}`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.HttpClient = HttpClient;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gistplus/client
|
|
3
|
+
*
|
|
4
|
+
* Client SDK for AI agents and applications to interact with Gist Plus providers.
|
|
5
|
+
* Handles Intent creation, Offer negotiation, Session management, and Receipt verification.
|
|
6
|
+
*/
|
|
7
|
+
export * from './client';
|
|
8
|
+
export * from './http-client';
|
|
9
|
+
export * from './session-manager';
|
|
10
|
+
export { Intent, Offer, Session, Receipt, SLA, SessionState, createIntent, verifyOffer, verifyReceipt, SUPPORTED_TOKENS, SupportedToken, } from '@gistplus/core';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @gistplus/client
|
|
4
|
+
*
|
|
5
|
+
* Client SDK for AI agents and applications to interact with Gist Plus providers.
|
|
6
|
+
* Handles Intent creation, Offer negotiation, Session management, and Receipt verification.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.SUPPORTED_TOKENS = exports.verifyReceipt = exports.verifyOffer = exports.createIntent = exports.SessionState = void 0;
|
|
24
|
+
__exportStar(require("./client"), exports);
|
|
25
|
+
__exportStar(require("./http-client"), exports);
|
|
26
|
+
__exportStar(require("./session-manager"), exports);
|
|
27
|
+
// Re-export core types for convenience
|
|
28
|
+
var core_1 = require("@gistplus/core");
|
|
29
|
+
Object.defineProperty(exports, "SessionState", { enumerable: true, get: function () { return core_1.SessionState; } });
|
|
30
|
+
Object.defineProperty(exports, "createIntent", { enumerable: true, get: function () { return core_1.createIntent; } });
|
|
31
|
+
Object.defineProperty(exports, "verifyOffer", { enumerable: true, get: function () { return core_1.verifyOffer; } });
|
|
32
|
+
Object.defineProperty(exports, "verifyReceipt", { enumerable: true, get: function () { return core_1.verifyReceipt; } });
|
|
33
|
+
Object.defineProperty(exports, "SUPPORTED_TOKENS", { enumerable: true, get: function () { return core_1.SUPPORTED_TOKENS; } });
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionManager - Manages active sessions and their state
|
|
3
|
+
*/
|
|
4
|
+
import { Connection, Keypair } from '@solana/web3.js';
|
|
5
|
+
import { Session, Receipt } from '@gistplus/core';
|
|
6
|
+
/**
|
|
7
|
+
* SessionManager tracks and manages active Gist Plus sessions
|
|
8
|
+
*/
|
|
9
|
+
export declare class SessionManager {
|
|
10
|
+
private sessions;
|
|
11
|
+
private connection;
|
|
12
|
+
private wallet;
|
|
13
|
+
constructor(connection: Connection, wallet: Keypair);
|
|
14
|
+
/**
|
|
15
|
+
* Register a new session
|
|
16
|
+
*/
|
|
17
|
+
registerSession(session: Session): void;
|
|
18
|
+
/**
|
|
19
|
+
* Get a session by ID
|
|
20
|
+
*/
|
|
21
|
+
getSession(sessionId: string): Session | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Update session after a request is completed
|
|
24
|
+
*/
|
|
25
|
+
updateSessionAfterRequest(sessionId: string, receipt: Receipt): void;
|
|
26
|
+
/**
|
|
27
|
+
* Close a session
|
|
28
|
+
*/
|
|
29
|
+
closeSession(sessionId: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Get all active sessions
|
|
32
|
+
*/
|
|
33
|
+
getActiveSessions(): Session[];
|
|
34
|
+
/**
|
|
35
|
+
* Get all sessions
|
|
36
|
+
*/
|
|
37
|
+
getAllSessions(): Session[];
|
|
38
|
+
/**
|
|
39
|
+
* Clean up expired sessions
|
|
40
|
+
*/
|
|
41
|
+
private cleanup;
|
|
42
|
+
/**
|
|
43
|
+
* Start background cleanup task
|
|
44
|
+
*/
|
|
45
|
+
private startCleanupTask;
|
|
46
|
+
/**
|
|
47
|
+
* Get session count
|
|
48
|
+
*/
|
|
49
|
+
getSessionCount(): number;
|
|
50
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SessionManager - Manages active sessions and their state
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SessionManager = void 0;
|
|
7
|
+
const core_1 = require("@gistplus/core");
|
|
8
|
+
/**
|
|
9
|
+
* SessionManager tracks and manages active Gist Plus sessions
|
|
10
|
+
*/
|
|
11
|
+
class SessionManager {
|
|
12
|
+
constructor(connection, wallet) {
|
|
13
|
+
this.sessions = new Map();
|
|
14
|
+
this.connection = connection;
|
|
15
|
+
this.wallet = wallet;
|
|
16
|
+
// Start background cleanup task
|
|
17
|
+
this.startCleanupTask();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a new session
|
|
21
|
+
*/
|
|
22
|
+
registerSession(session) {
|
|
23
|
+
this.sessions.set(session.sessionId, session);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a session by ID
|
|
27
|
+
*/
|
|
28
|
+
getSession(sessionId) {
|
|
29
|
+
const session = this.sessions.get(sessionId);
|
|
30
|
+
if (!session) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// Check if session has expired and update state
|
|
34
|
+
if (!(0, core_1.isSessionActive)(session) && session.state === core_1.SessionState.ACTIVE) {
|
|
35
|
+
const expiredSession = (0, core_1.expireSession)(session);
|
|
36
|
+
this.sessions.set(sessionId, expiredSession);
|
|
37
|
+
return expiredSession;
|
|
38
|
+
}
|
|
39
|
+
return session;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Update session after a request is completed
|
|
43
|
+
*/
|
|
44
|
+
updateSessionAfterRequest(sessionId, receipt) {
|
|
45
|
+
const session = this.sessions.get(sessionId);
|
|
46
|
+
if (!session) {
|
|
47
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
48
|
+
}
|
|
49
|
+
// Deduct amount from session
|
|
50
|
+
const updatedSession = (0, core_1.deductFromSession)(session, receipt.amountCharged);
|
|
51
|
+
this.sessions.set(sessionId, updatedSession);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Close a session
|
|
55
|
+
*/
|
|
56
|
+
closeSession(sessionId) {
|
|
57
|
+
this.sessions.delete(sessionId);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all active sessions
|
|
61
|
+
*/
|
|
62
|
+
getActiveSessions() {
|
|
63
|
+
const activeSessions = [];
|
|
64
|
+
for (const session of this.sessions.values()) {
|
|
65
|
+
if ((0, core_1.isSessionActive)(session)) {
|
|
66
|
+
activeSessions.push(session);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return activeSessions;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get all sessions
|
|
73
|
+
*/
|
|
74
|
+
getAllSessions() {
|
|
75
|
+
return Array.from(this.sessions.values());
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clean up expired sessions
|
|
79
|
+
*/
|
|
80
|
+
cleanup() {
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
83
|
+
if (session.state === core_1.SessionState.EXPIRED || now > session.expiresAt) {
|
|
84
|
+
// Keep expired sessions for a grace period (1 hour)
|
|
85
|
+
if (now > session.expiresAt + 3600000) {
|
|
86
|
+
this.sessions.delete(sessionId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Start background cleanup task
|
|
93
|
+
*/
|
|
94
|
+
startCleanupTask() {
|
|
95
|
+
// Clean up every 5 minutes
|
|
96
|
+
setInterval(() => {
|
|
97
|
+
this.cleanup();
|
|
98
|
+
}, 300000);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get session count
|
|
102
|
+
*/
|
|
103
|
+
getSessionCount() {
|
|
104
|
+
return this.sessions.size;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.SessionManager = SessionManager;
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gistplus/client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Client SDK for Gist Plus - enables agents and applications to negotiate, transact, and verify with providers",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "jest",
|
|
17
|
+
"clean": "rimraf dist"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"gistplus",
|
|
21
|
+
"gist",
|
|
22
|
+
"client",
|
|
23
|
+
"solana",
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"payments"
|
|
26
|
+
],
|
|
27
|
+
"author": "Gist Plus",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/gistplus/gistplus"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/gistplus/gistplus#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/gistplus/gistplus/issues"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@gistplus/core": "^0.1.0",
|
|
39
|
+
"@solana/web3.js": "^1.87.6",
|
|
40
|
+
"@solana/spl-token": "^0.3.9",
|
|
41
|
+
"axios": "^1.6.5"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"typescript": "^5.3.3",
|
|
45
|
+
"@types/node": "^20.10.6",
|
|
46
|
+
"jest": "^29.7.0",
|
|
47
|
+
"@types/jest": "^29.5.11",
|
|
48
|
+
"rimraf": "^5.0.5"
|
|
49
|
+
}
|
|
50
|
+
}
|