8004-solana 0.2.2 → 0.4.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/LICENSE +1 -1
- package/README.md +105 -25
- package/dist/core/agent-mint-resolver.d.ts +53 -29
- package/dist/core/agent-mint-resolver.d.ts.map +1 -1
- package/dist/core/agent-mint-resolver.js +117 -72
- package/dist/core/agent-mint-resolver.js.map +1 -1
- package/dist/core/atom-pda.d.ts +34 -0
- package/dist/core/atom-pda.d.ts.map +1 -0
- package/dist/core/atom-pda.js +45 -0
- package/dist/core/atom-pda.js.map +1 -0
- package/dist/core/atom-schemas.d.ts +221 -0
- package/dist/core/atom-schemas.d.ts.map +1 -0
- package/dist/core/atom-schemas.js +393 -0
- package/dist/core/atom-schemas.js.map +1 -0
- package/dist/core/borsh-schemas.d.ts +112 -186
- package/dist/core/borsh-schemas.d.ts.map +1 -1
- package/dist/core/borsh-schemas.js +502 -426
- package/dist/core/borsh-schemas.js.map +1 -1
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +11 -4
- package/dist/core/client.js.map +1 -1
- package/dist/core/config-reader.d.ts +36 -6
- package/dist/core/config-reader.d.ts.map +1 -1
- package/dist/core/config-reader.js +83 -9
- package/dist/core/config-reader.js.map +1 -1
- package/dist/core/endpoint-crawler.d.ts.map +1 -1
- package/dist/core/endpoint-crawler.js +15 -9
- package/dist/core/endpoint-crawler.js.map +1 -1
- package/dist/core/feedback-manager-solana.d.ts +93 -53
- package/dist/core/feedback-manager-solana.d.ts.map +1 -1
- package/dist/core/feedback-manager-solana.js +247 -140
- package/dist/core/feedback-manager-solana.js.map +1 -1
- package/dist/core/indexer-client.d.ts +285 -0
- package/dist/core/indexer-client.d.ts.map +1 -0
- package/dist/core/indexer-client.js +372 -0
- package/dist/core/indexer-client.js.map +1 -0
- package/dist/core/indexer-defaults.d.ts +23 -0
- package/dist/core/indexer-defaults.d.ts.map +1 -0
- package/dist/core/indexer-defaults.js +35 -0
- package/dist/core/indexer-defaults.js.map +1 -0
- package/dist/core/indexer-errors.d.ts +49 -0
- package/dist/core/indexer-errors.d.ts.map +1 -0
- package/dist/core/indexer-errors.js +67 -0
- package/dist/core/indexer-errors.js.map +1 -0
- package/dist/core/indexer-types.d.ts +87 -0
- package/dist/core/indexer-types.d.ts.map +1 -0
- package/dist/core/indexer-types.js +78 -0
- package/dist/core/indexer-types.js.map +1 -0
- package/dist/core/instruction-builder.d.ts +92 -26
- package/dist/core/instruction-builder.d.ts.map +1 -1
- package/dist/core/instruction-builder.js +240 -49
- package/dist/core/instruction-builder.js.map +1 -1
- package/dist/core/instruction-discriminators.d.ts +18 -1
- package/dist/core/instruction-discriminators.d.ts.map +1 -1
- package/dist/core/instruction-discriminators.js +19 -1
- package/dist/core/instruction-discriminators.js.map +1 -1
- package/dist/core/ipfs-client.d.ts +20 -0
- package/dist/core/ipfs-client.d.ts.map +1 -1
- package/dist/core/ipfs-client.js +194 -33
- package/dist/core/ipfs-client.js.map +1 -1
- package/dist/core/oasf-validator.d.ts +1 -0
- package/dist/core/oasf-validator.d.ts.map +1 -1
- package/dist/core/oasf-validator.js +32 -5
- package/dist/core/oasf-validator.js.map +1 -1
- package/dist/core/pda-helpers.d.ts +45 -53
- package/dist/core/pda-helpers.d.ts.map +1 -1
- package/dist/core/pda-helpers.js +60 -91
- package/dist/core/pda-helpers.js.map +1 -1
- package/dist/core/programs.d.ts +8 -0
- package/dist/core/programs.d.ts.map +1 -1
- package/dist/core/programs.js +9 -1
- package/dist/core/programs.js.map +1 -1
- package/dist/core/sdk-solana.d.ts +348 -106
- package/dist/core/sdk-solana.d.ts.map +1 -1
- package/dist/core/sdk-solana.js +707 -259
- package/dist/core/sdk-solana.js.map +1 -1
- package/dist/core/transaction-builder.d.ts +151 -45
- package/dist/core/transaction-builder.d.ts.map +1 -1
- package/dist/core/transaction-builder.js +615 -217
- package/dist/core/transaction-builder.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -2
- package/dist/index.js.map +1 -1
- package/dist/models/collection-metadata.d.ts +97 -0
- package/dist/models/collection-metadata.d.ts.map +1 -0
- package/dist/models/collection-metadata.js +72 -0
- package/dist/models/collection-metadata.js.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1 -0
- package/dist/models/index.js.map +1 -1
- package/dist/models/interfaces.d.ts +6 -28
- package/dist/models/interfaces.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +6 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +6 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +107 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/registration-file-builder.d.ts.map +1 -1
- package/dist/utils/registration-file-builder.js +12 -2
- package/dist/utils/registration-file-builder.js.map +1 -1
- package/dist/utils/validation.d.ts +8 -20
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +94 -36
- package/dist/utils/validation.js.map +1 -1
- package/package.json +4 -6
- package/dist/core/feedback-auth.d.ts +0 -184
- package/dist/core/feedback-auth.d.ts.map +0 -1
- package/dist/core/feedback-auth.js +0 -232
- package/dist/core/feedback-auth.js.map +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
[](https://github.com/QuantuLabs/8004-solana)
|
|
9
9
|
[](https://github.com/QuantuLabs/8004-solana)
|
|
10
10
|
|
|
11
|
+
> **[How to register your first agent in 5 steps](./docs/quickstart.html)**
|
|
12
|
+
|
|
11
13
|
---
|
|
12
14
|
|
|
13
15
|
## About
|
|
@@ -52,7 +54,77 @@ const signer = Keypair.fromSecretKey(Uint8Array.from(privateKey));
|
|
|
52
54
|
const sdk = new SolanaSDK({ signer });
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
### 2.
|
|
57
|
+
### 2. Create a Collection (Optional)
|
|
58
|
+
|
|
59
|
+
Users can create their own collections to organize agents:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {
|
|
63
|
+
SolanaSDK,
|
|
64
|
+
IPFSClient,
|
|
65
|
+
buildCollectionMetadataJson
|
|
66
|
+
} from '8004-solana';
|
|
67
|
+
|
|
68
|
+
// 1. Build collection metadata using the helper
|
|
69
|
+
const collectionData = buildCollectionMetadataJson({
|
|
70
|
+
name: 'My AI Agents',
|
|
71
|
+
description: 'Production AI agents for automation',
|
|
72
|
+
image: 'ipfs://QmLogo...',
|
|
73
|
+
category: 'automation',
|
|
74
|
+
tags: ['enterprise', 'api'],
|
|
75
|
+
project: {
|
|
76
|
+
name: 'Acme Corp',
|
|
77
|
+
socials: {
|
|
78
|
+
website: 'https://acme.ai',
|
|
79
|
+
x: 'acme_ai'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 2. Upload metadata to IPFS
|
|
85
|
+
const ipfs = new IPFSClient({ pinataJwt: process.env.PINATA_JWT });
|
|
86
|
+
const collectionCid = await ipfs.addJson(collectionData);
|
|
87
|
+
|
|
88
|
+
// 3. Create collection on-chain
|
|
89
|
+
const sdk = new SolanaSDK({ signer });
|
|
90
|
+
const collectionResult = await sdk.createCollection(
|
|
91
|
+
collectionData.name, // Collection name (max 32 bytes)
|
|
92
|
+
`ipfs://${collectionCid}` // Collection metadata URI
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
console.log('Collection:', collectionResult.collection?.toBase58());
|
|
96
|
+
|
|
97
|
+
// 4. Register agents in your collection
|
|
98
|
+
const agentResult = await sdk.registerAgent(
|
|
99
|
+
'ipfs://QmAgentMetadata...', // Agent metadata URI
|
|
100
|
+
collectionResult.collection // Your collection
|
|
101
|
+
);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Collection Metadata JSON Schema:**
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"name": "Acme AI Agents",
|
|
109
|
+
"description": "Production-ready AI agents for enterprise automation",
|
|
110
|
+
"image": "ipfs://QmXxx.../logo.png",
|
|
111
|
+
"external_url": "https://acme.ai/agents",
|
|
112
|
+
"project": {
|
|
113
|
+
"name": "Acme Corporation",
|
|
114
|
+
"socials": {
|
|
115
|
+
"website": "https://acme.ai",
|
|
116
|
+
"x": "acme_ai",
|
|
117
|
+
"github": "acme-ai"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"category": "automation",
|
|
121
|
+
"tags": ["enterprise", "automation", "api"]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> See full schemas: [`schemas/collection-metadata.schema.json`](schemas/collection-metadata.schema.json) and [`schemas/agent-metadata.schema.json`](schemas/agent-metadata.schema.json)
|
|
126
|
+
|
|
127
|
+
### 3. Register an Agent (Detailed)
|
|
56
128
|
|
|
57
129
|
**Step 1: Setup IPFS Client**
|
|
58
130
|
|
|
@@ -110,8 +182,15 @@ const metadataUri = `ipfs://${metadataCid}`;
|
|
|
110
182
|
|
|
111
183
|
```typescript
|
|
112
184
|
const sdk = new SolanaSDK({ signer });
|
|
185
|
+
|
|
186
|
+
// Register in default collection
|
|
113
187
|
const result = await sdk.registerAgent(metadataUri);
|
|
114
|
-
console.log(`Agent
|
|
188
|
+
console.log(`Agent registered! Asset: ${result.asset.toBase58()}`);
|
|
189
|
+
|
|
190
|
+
// Or register in your own collection
|
|
191
|
+
// Note: Only the collection creator can register agents in their collection
|
|
192
|
+
const myCollection = new PublicKey('YourCollectionPublicKey...');
|
|
193
|
+
const result2 = await sdk.registerAgent(metadataUri, myCollection);
|
|
115
194
|
```
|
|
116
195
|
|
|
117
196
|
**Alternative: Use Web URLs**
|
|
@@ -130,11 +209,14 @@ const metadata = buildRegistrationFileJson({
|
|
|
130
209
|
await sdk.registerAgent('https://my-server.com/agent-metadata.json');
|
|
131
210
|
```
|
|
132
211
|
|
|
133
|
-
###
|
|
212
|
+
### 4. Load Agent Data
|
|
134
213
|
|
|
135
214
|
```typescript
|
|
136
|
-
|
|
137
|
-
|
|
215
|
+
import { PublicKey } from '@solana/web3.js';
|
|
216
|
+
|
|
217
|
+
// Fetch agent by asset (PublicKey)
|
|
218
|
+
const agentAsset = new PublicKey('AgentAssetPublicKey...');
|
|
219
|
+
const agent = await sdk.loadAgent(agentAsset);
|
|
138
220
|
|
|
139
221
|
if (agent) {
|
|
140
222
|
console.log(`Name: ${agent.nft_name}`);
|
|
@@ -144,58 +226,56 @@ if (agent) {
|
|
|
144
226
|
}
|
|
145
227
|
|
|
146
228
|
// Or fetch all agents owned by a wallet (requires custom RPC)
|
|
147
|
-
import { PublicKey } from '@solana/web3.js';
|
|
148
|
-
|
|
149
229
|
const ownerWallet = new PublicKey('YourWalletAddress...');
|
|
150
230
|
const myAgents = await sdk.getAgentsByOwner(ownerWallet);
|
|
151
231
|
|
|
152
232
|
for (const agent of myAgents) {
|
|
153
|
-
console.log(`Agent
|
|
233
|
+
console.log(`Agent: ${agent.nft_name} (${agent.getAssetPublicKey().toBase58().slice(0,8)}...)`);
|
|
154
234
|
}
|
|
155
235
|
```
|
|
156
236
|
|
|
157
|
-
###
|
|
237
|
+
### 5. Give Feedback
|
|
158
238
|
|
|
159
239
|
```typescript
|
|
160
240
|
// Submit feedback for an agent (as a client/user)
|
|
161
241
|
// Score is 0-100, tags are optional keywords
|
|
162
|
-
await sdk.giveFeedback(
|
|
163
|
-
score: 85,
|
|
164
|
-
tag1: 'helpful',
|
|
165
|
-
tag2: 'accurate',
|
|
166
|
-
|
|
167
|
-
|
|
242
|
+
await sdk.giveFeedback(agentAsset, {
|
|
243
|
+
score: 85, // Rating out of 100
|
|
244
|
+
tag1: 'helpful', // Optional: first tag
|
|
245
|
+
tag2: 'accurate', // Optional: second tag
|
|
246
|
+
feedbackUri: 'ipfs://QmFeedbackDetails', // Optional: detailed feedback file
|
|
247
|
+
feedbackHash: Buffer.alloc(32), // Optional: SHA256 hash of file
|
|
168
248
|
});
|
|
169
249
|
```
|
|
170
250
|
|
|
171
|
-
###
|
|
251
|
+
### 6. Get Reputation
|
|
172
252
|
|
|
173
253
|
```typescript
|
|
174
254
|
// Get aggregated reputation stats
|
|
175
|
-
const summary = await sdk.getSummary(
|
|
255
|
+
const summary = await sdk.getSummary(agentAsset);
|
|
176
256
|
console.log(`Average Score: ${summary.averageScore}/100`);
|
|
177
257
|
console.log(`Total Feedbacks: ${summary.totalFeedbacks}`);
|
|
178
258
|
console.log(`Next Index: ${summary.nextFeedbackIndex}`);
|
|
179
259
|
|
|
180
260
|
// Read all individual feedbacks (requires custom RPC)
|
|
181
|
-
const feedbacks = await sdk.readAllFeedback(
|
|
261
|
+
const feedbacks = await sdk.readAllFeedback(agentAsset);
|
|
182
262
|
for (const fb of feedbacks) {
|
|
183
263
|
console.log(`Score: ${fb.score}, Client: ${fb.client.toBase58()}`);
|
|
184
264
|
}
|
|
185
265
|
```
|
|
186
266
|
|
|
187
|
-
###
|
|
267
|
+
### 7. Bulk Queries (Indexer)
|
|
188
268
|
|
|
189
269
|
```typescript
|
|
190
270
|
// Get ALL agents with their feedbacks in just 4 RPC calls
|
|
191
271
|
const agents = await sdk.getAllAgents({ includeFeedbacks: true });
|
|
192
272
|
for (const { account, feedbacks } of agents) {
|
|
193
|
-
console.log(`Agent
|
|
273
|
+
console.log(`Agent ${account.getAssetPublicKey().toBase58().slice(0,8)}...: ${feedbacks?.length || 0} feedbacks`);
|
|
194
274
|
}
|
|
195
275
|
|
|
196
|
-
// Or get ALL feedbacks separately as a Map
|
|
276
|
+
// Or get ALL feedbacks separately as a Map (keyed by asset string)
|
|
197
277
|
const feedbacksMap = await sdk.getAllFeedbacks();
|
|
198
|
-
const
|
|
278
|
+
const agentFeedbacks = feedbacksMap.get(agentAsset.toBase58()) || [];
|
|
199
279
|
```
|
|
200
280
|
|
|
201
281
|
> **Note**: For advanced queries like `getAllAgents()`, `getAllFeedbacks()`, or `readAllFeedback()`, a custom RPC provider is required.
|
|
@@ -210,7 +290,7 @@ const agent83Feedbacks = feedbacksMap.get(83n) || [];
|
|
|
210
290
|
- **[OASF Taxonomies](docs/OASF.md)** - Skills and domains reference
|
|
211
291
|
- **[Changelog](docs/CHANGELOG.md)** - Version history and breaking changes
|
|
212
292
|
|
|
213
|
-
**Program ID:** `
|
|
293
|
+
**Program ID (Devnet):** `HHCVWcqsziJMmp43u2UAgAfH2cBjUFxVdW1M3C3NqzvT`
|
|
214
294
|
|
|
215
295
|
---
|
|
216
296
|
|
|
@@ -312,7 +392,7 @@ See the `examples/` directory for complete usage examples:
|
|
|
312
392
|
| [`agent-update.ts`](examples/agent-update.ts) | On-chain metadata & URI update |
|
|
313
393
|
| [`transfer-agent.ts`](examples/transfer-agent.ts) | Transfer agent ownership |
|
|
314
394
|
| [`server-mode.ts`](examples/server-mode.ts) | Server/client architecture with skipSend |
|
|
315
|
-
| [`basic-indexer.ts`](examples/basic-indexer.ts) |
|
|
395
|
+
| [`basic-indexer.ts`](examples/basic-indexer.ts) | Indexer reference → [8004-solana-indexer](https://github.com/QuantuLabs/8004-solana-indexer) |
|
|
316
396
|
|
|
317
397
|
Run examples:
|
|
318
398
|
```bash
|
|
@@ -352,4 +432,4 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
352
432
|
|
|
353
433
|
---
|
|
354
434
|
|
|
355
|
-
**Built for the Solana ecosystem** | v0.
|
|
435
|
+
**Built for the Solana ecosystem** | v0.4.0
|
|
@@ -1,44 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent
|
|
3
|
-
*
|
|
2
|
+
* Agent Resolver
|
|
3
|
+
* v0.3.0 - Asset-based identification
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - Each AgentAccount contains agent_id and agent_mint
|
|
8
|
-
* - Load all agents once and cache for O(1) subsequent lookups
|
|
5
|
+
* NOTE: This class is largely deprecated in v0.3.0 since agents are now
|
|
6
|
+
* identified directly by their Metaplex Core asset pubkey, not by sequential IDs.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - Single getProgramAccounts call fetches all mappings
|
|
8
|
+
* The class is kept for backwards compatibility but most methods are deprecated.
|
|
9
|
+
* Use the asset pubkey directly instead of resolving from agent_id.
|
|
13
10
|
*/
|
|
14
11
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
12
|
+
import { AgentAccount } from './borsh-schemas.js';
|
|
13
|
+
export interface LoadAgentsOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of accounts to load (default: 1000)
|
|
16
|
+
* Security: Prevents OOM from unbounded getProgramAccounts
|
|
17
|
+
*/
|
|
18
|
+
maxAccounts?: number;
|
|
19
|
+
/**
|
|
20
|
+
* If true, throw on malformed accounts instead of skipping
|
|
21
|
+
* Default: false (skip malformed accounts with warning)
|
|
22
|
+
*/
|
|
23
|
+
strictParsing?: boolean;
|
|
24
|
+
}
|
|
15
25
|
/**
|
|
16
|
-
* Agent
|
|
17
|
-
*
|
|
26
|
+
* Agent Resolver
|
|
27
|
+
* v0.3.0 - Validates assets and loads agent accounts
|
|
28
|
+
*
|
|
29
|
+
* @deprecated In v0.3.0, agents are identified by their asset pubkey directly.
|
|
30
|
+
* Use asset pubkeys instead of agent_id numbers.
|
|
31
|
+
*
|
|
32
|
+
* Security: Thread-safety protection added in v0.3.0 - cache updates are atomic.
|
|
18
33
|
*/
|
|
19
34
|
export declare class AgentMintResolver {
|
|
20
|
-
private
|
|
35
|
+
private assetCache;
|
|
21
36
|
private connection;
|
|
22
37
|
private cacheLoaded;
|
|
38
|
+
private loadingPromise;
|
|
23
39
|
constructor(connection: Connection, _collectionMint?: PublicKey);
|
|
24
40
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
41
|
+
* @deprecated Use asset pubkey directly. In v0.3.0, agents are identified by asset, not agent_id.
|
|
42
|
+
*
|
|
43
|
+
* For backwards compatibility, this method now throws an error.
|
|
44
|
+
* Use getAgentByAsset() instead.
|
|
45
|
+
*/
|
|
46
|
+
resolve(_agentId: bigint): Promise<PublicKey>;
|
|
47
|
+
/**
|
|
48
|
+
* Get AgentAccount by asset pubkey - v0.3.0
|
|
49
|
+
* @param asset - Metaplex Core asset pubkey
|
|
50
|
+
* @returns AgentAccount or null if not found
|
|
51
|
+
*/
|
|
52
|
+
getAgentByAsset(asset: PublicKey): Promise<AgentAccount | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Check if an asset is a registered agent
|
|
55
|
+
* @param asset - Metaplex Core asset pubkey
|
|
56
|
+
* @returns true if the asset is a registered agent
|
|
29
57
|
*/
|
|
30
|
-
|
|
58
|
+
isRegisteredAgent(asset: PublicKey): Promise<boolean>;
|
|
31
59
|
/**
|
|
32
|
-
* Load all agents from Identity Registry
|
|
33
|
-
*
|
|
60
|
+
* Load all agents from Identity Registry
|
|
61
|
+
* Security: Limited to maxAccounts (default 1000) to prevent OOM
|
|
34
62
|
*/
|
|
35
|
-
|
|
63
|
+
loadAllAgents(options?: LoadAgentsOptions): Promise<Map<string, AgentAccount>>;
|
|
64
|
+
private doLoadAllAgents;
|
|
36
65
|
/**
|
|
37
|
-
*
|
|
38
|
-
* @param agentId - Agent ID
|
|
39
|
-
* @param mint - Agent mint address
|
|
66
|
+
* @deprecated Use asset pubkey directly. No need to cache agent_id → asset mapping.
|
|
40
67
|
*/
|
|
41
|
-
addToCache(
|
|
68
|
+
addToCache(_agentId: bigint, _mint: PublicKey): void;
|
|
42
69
|
/**
|
|
43
70
|
* Clear the cache (useful for testing or forcing refresh)
|
|
44
71
|
*/
|
|
@@ -48,12 +75,9 @@ export declare class AgentMintResolver {
|
|
|
48
75
|
*/
|
|
49
76
|
refresh(): Promise<void>;
|
|
50
77
|
/**
|
|
51
|
-
*
|
|
52
|
-
* More efficient than resolving one at a time
|
|
53
|
-
* @param agentIds - Array of agent IDs to resolve
|
|
54
|
-
* @returns Map of agent_id → agent_mint
|
|
78
|
+
* @deprecated Use loadAllAgents() instead. Agent IDs no longer exist.
|
|
55
79
|
*/
|
|
56
|
-
batchResolve(
|
|
80
|
+
batchResolve(_agentIds: bigint[]): Promise<Map<bigint, PublicKey>>;
|
|
57
81
|
/**
|
|
58
82
|
* Get cache size (number of loaded agents)
|
|
59
83
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-mint-resolver.d.ts","sourceRoot":"","sources":["../../src/core/agent-mint-resolver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-mint-resolver.d.ts","sourceRoot":"","sources":["../../src/core/agent-mint-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAYlD,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,cAAc,CAAmD;gBAE7D,UAAU,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,SAAS;IAI/D;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAQnD;;;;OAIG;IACG,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAyBrE;;;;OAIG;IACG,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAK3D;;;OAGG;IACG,aAAa,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAS1E,eAAe;IAqE7B;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAIpD;;OAEG;IACH,UAAU,IAAI,IAAI;IAMlB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAOxE;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -1,63 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent
|
|
3
|
-
*
|
|
2
|
+
* Agent Resolver
|
|
3
|
+
* v0.3.0 - Asset-based identification
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - Each AgentAccount contains agent_id and agent_mint
|
|
8
|
-
* - Load all agents once and cache for O(1) subsequent lookups
|
|
5
|
+
* NOTE: This class is largely deprecated in v0.3.0 since agents are now
|
|
6
|
+
* identified directly by their Metaplex Core asset pubkey, not by sequential IDs.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - Single getProgramAccounts call fetches all mappings
|
|
8
|
+
* The class is kept for backwards compatibility but most methods are deprecated.
|
|
9
|
+
* Use the asset pubkey directly instead of resolving from agent_id.
|
|
13
10
|
*/
|
|
14
11
|
import { AgentAccount } from './borsh-schemas.js';
|
|
15
12
|
import { ACCOUNT_DISCRIMINATORS } from './instruction-discriminators.js';
|
|
16
|
-
import { IDENTITY_PROGRAM_ID } from './pda-helpers.js';
|
|
13
|
+
import { IDENTITY_PROGRAM_ID, PDAHelpers } from './pda-helpers.js';
|
|
14
|
+
import { logger } from '../utils/logger.js';
|
|
17
15
|
import bs58 from 'bs58';
|
|
18
16
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* Security: Default limit for getProgramAccounts to prevent OOM
|
|
18
|
+
* For production with large agent registries, use an indexer instead.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_MAX_ACCOUNTS = 1000;
|
|
21
|
+
/**
|
|
22
|
+
* Agent Resolver
|
|
23
|
+
* v0.3.0 - Validates assets and loads agent accounts
|
|
24
|
+
*
|
|
25
|
+
* @deprecated In v0.3.0, agents are identified by their asset pubkey directly.
|
|
26
|
+
* Use asset pubkeys instead of agent_id numbers.
|
|
27
|
+
*
|
|
28
|
+
* Security: Thread-safety protection added in v0.3.0 - cache updates are atomic.
|
|
21
29
|
*/
|
|
22
30
|
export class AgentMintResolver {
|
|
31
|
+
assetCache = new Map();
|
|
32
|
+
connection;
|
|
33
|
+
cacheLoaded = false;
|
|
34
|
+
loadingPromise = null;
|
|
23
35
|
constructor(connection, _collectionMint) {
|
|
24
|
-
this.cache = new Map();
|
|
25
|
-
this.cacheLoaded = false;
|
|
26
36
|
this.connection = connection;
|
|
27
|
-
// collectionMint is no longer needed (was for Metaplex filtering)
|
|
28
37
|
}
|
|
29
38
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
39
|
+
* @deprecated Use asset pubkey directly. In v0.3.0, agents are identified by asset, not agent_id.
|
|
40
|
+
*
|
|
41
|
+
* For backwards compatibility, this method now throws an error.
|
|
42
|
+
* Use getAgentByAsset() instead.
|
|
34
43
|
*/
|
|
35
|
-
async resolve(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
async resolve(_agentId) {
|
|
45
|
+
throw new Error('AgentMintResolver.resolve() is deprecated in v0.3.0. ' +
|
|
46
|
+
'Agents are now identified by asset pubkey, not agent_id. ' +
|
|
47
|
+
'Use asset pubkey directly or getAgentByAsset() to validate an asset.');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get AgentAccount by asset pubkey - v0.3.0
|
|
51
|
+
* @param asset - Metaplex Core asset pubkey
|
|
52
|
+
* @returns AgentAccount or null if not found
|
|
53
|
+
*/
|
|
54
|
+
async getAgentByAsset(asset) {
|
|
55
|
+
const cacheKey = asset.toBase58();
|
|
56
|
+
// Check cache first
|
|
57
|
+
if (this.assetCache.has(cacheKey)) {
|
|
58
|
+
return this.assetCache.get(cacheKey);
|
|
40
59
|
}
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
// Derive AgentAccount PDA
|
|
61
|
+
const [agentPda] = PDAHelpers.getAgentPDA(asset);
|
|
62
|
+
try {
|
|
63
|
+
const accountInfo = await this.connection.getAccountInfo(agentPda);
|
|
64
|
+
if (!accountInfo) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const agentAccount = AgentAccount.deserialize(Buffer.from(accountInfo.data));
|
|
68
|
+
this.assetCache.set(cacheKey, agentAccount);
|
|
69
|
+
return agentAccount;
|
|
44
70
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!mint) {
|
|
48
|
-
throw new Error(`Agent #${agentId} not found. The agent may not exist.`);
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
49
73
|
}
|
|
50
|
-
return mint;
|
|
51
74
|
}
|
|
52
75
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
76
|
+
* Check if an asset is a registered agent
|
|
77
|
+
* @param asset - Metaplex Core asset pubkey
|
|
78
|
+
* @returns true if the asset is a registered agent
|
|
55
79
|
*/
|
|
56
|
-
async
|
|
80
|
+
async isRegisteredAgent(asset) {
|
|
81
|
+
const agent = await this.getAgentByAsset(asset);
|
|
82
|
+
return agent !== null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Load all agents from Identity Registry
|
|
86
|
+
* Security: Limited to maxAccounts (default 1000) to prevent OOM
|
|
87
|
+
*/
|
|
88
|
+
async loadAllAgents(options = {}) {
|
|
89
|
+
if (this.loadingPromise) {
|
|
90
|
+
return await this.loadingPromise;
|
|
91
|
+
}
|
|
92
|
+
this.loadingPromise = this.doLoadAllAgents(options);
|
|
93
|
+
return await this.loadingPromise;
|
|
94
|
+
}
|
|
95
|
+
async doLoadAllAgents(options) {
|
|
96
|
+
const maxAccounts = options.maxAccounts ?? DEFAULT_MAX_ACCOUNTS;
|
|
97
|
+
const strictParsing = options.strictParsing ?? false;
|
|
57
98
|
try {
|
|
58
|
-
// Get AgentAccount discriminator bytes for filtering
|
|
59
99
|
const discriminatorBytes = bs58.encode(ACCOUNT_DISCRIMINATORS.AgentAccount);
|
|
60
|
-
// Fetch ALL AgentAccount PDAs from Identity Registry (single RPC call)
|
|
61
100
|
const accounts = await this.connection.getProgramAccounts(IDENTITY_PROGRAM_ID, {
|
|
62
101
|
filters: [
|
|
63
102
|
{
|
|
@@ -68,41 +107,60 @@ export class AgentMintResolver {
|
|
|
68
107
|
},
|
|
69
108
|
],
|
|
70
109
|
});
|
|
71
|
-
//
|
|
72
|
-
|
|
110
|
+
// Security: Warn if limit reached - may indicate need for indexer
|
|
111
|
+
const limitReached = accounts.length > maxAccounts;
|
|
112
|
+
if (limitReached) {
|
|
113
|
+
logger.warn(`getProgramAccounts returned ${accounts.length} agents, limiting to ${maxAccounts}. ` +
|
|
114
|
+
`Consider using an indexer for production.`);
|
|
115
|
+
}
|
|
116
|
+
// Security: Build in temp map, then atomic swap to prevent race conditions
|
|
117
|
+
const tempCache = new Map();
|
|
118
|
+
let skippedAccounts = 0;
|
|
119
|
+
const accountsToProcess = accounts.slice(0, maxAccounts);
|
|
120
|
+
for (const { account } of accountsToProcess) {
|
|
73
121
|
try {
|
|
74
122
|
const agentAccount = AgentAccount.deserialize(Buffer.from(account.data));
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
this.cache.set(agentId, agentMint);
|
|
123
|
+
const assetPubkey = agentAccount.getAssetPublicKey();
|
|
124
|
+
tempCache.set(assetPubkey.toBase58(), agentAccount);
|
|
78
125
|
}
|
|
79
|
-
catch {
|
|
80
|
-
|
|
81
|
-
|
|
126
|
+
catch (parseError) {
|
|
127
|
+
if (strictParsing) {
|
|
128
|
+
throw new Error(`Failed to parse AgentAccount: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`);
|
|
129
|
+
}
|
|
130
|
+
skippedAccounts++;
|
|
82
131
|
}
|
|
83
132
|
}
|
|
133
|
+
// Security: Log warning if accounts were skipped (may indicate corruption)
|
|
134
|
+
if (skippedAccounts > 0) {
|
|
135
|
+
logger.warn(`Skipped ${skippedAccounts} malformed AgentAccount(s) during load. ` +
|
|
136
|
+
`Use strictParsing: true to fail on parse errors.`);
|
|
137
|
+
}
|
|
138
|
+
// Atomic swap - prevents race condition with concurrent reads
|
|
139
|
+
this.assetCache = tempCache;
|
|
84
140
|
this.cacheLoaded = true;
|
|
85
|
-
|
|
141
|
+
this.loadingPromise = null;
|
|
142
|
+
return this.assetCache;
|
|
86
143
|
}
|
|
87
144
|
catch (error) {
|
|
88
|
-
|
|
89
|
-
|
|
145
|
+
this.loadingPromise = null;
|
|
146
|
+
// Security: Don't leak internal error details
|
|
147
|
+
logger.error('Failed to load agents from Identity Registry', error);
|
|
148
|
+
throw new Error('Failed to load agents from Identity Registry');
|
|
90
149
|
}
|
|
91
150
|
}
|
|
92
151
|
/**
|
|
93
|
-
*
|
|
94
|
-
* @param agentId - Agent ID
|
|
95
|
-
* @param mint - Agent mint address
|
|
152
|
+
* @deprecated Use asset pubkey directly. No need to cache agent_id → asset mapping.
|
|
96
153
|
*/
|
|
97
|
-
addToCache(
|
|
98
|
-
|
|
154
|
+
addToCache(_agentId, _mint) {
|
|
155
|
+
// No-op in v0.3.0
|
|
99
156
|
}
|
|
100
157
|
/**
|
|
101
158
|
* Clear the cache (useful for testing or forcing refresh)
|
|
102
159
|
*/
|
|
103
160
|
clearCache() {
|
|
104
|
-
this.
|
|
161
|
+
this.assetCache.clear();
|
|
105
162
|
this.cacheLoaded = false;
|
|
163
|
+
this.loadingPromise = null;
|
|
106
164
|
}
|
|
107
165
|
/**
|
|
108
166
|
* Force reload all agents from chain
|
|
@@ -112,30 +170,17 @@ export class AgentMintResolver {
|
|
|
112
170
|
await this.loadAllAgents();
|
|
113
171
|
}
|
|
114
172
|
/**
|
|
115
|
-
*
|
|
116
|
-
* More efficient than resolving one at a time
|
|
117
|
-
* @param agentIds - Array of agent IDs to resolve
|
|
118
|
-
* @returns Map of agent_id → agent_mint
|
|
173
|
+
* @deprecated Use loadAllAgents() instead. Agent IDs no longer exist.
|
|
119
174
|
*/
|
|
120
|
-
async batchResolve(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
await this.loadAllAgents();
|
|
124
|
-
}
|
|
125
|
-
const results = new Map();
|
|
126
|
-
for (const agentId of agentIds) {
|
|
127
|
-
const mint = this.cache.get(agentId.toString());
|
|
128
|
-
if (mint) {
|
|
129
|
-
results.set(agentId, mint);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return results;
|
|
175
|
+
async batchResolve(_agentIds) {
|
|
176
|
+
throw new Error('AgentMintResolver.batchResolve() is deprecated in v0.3.0. ' +
|
|
177
|
+
'Use loadAllAgents() to get all registered agents.');
|
|
133
178
|
}
|
|
134
179
|
/**
|
|
135
180
|
* Get cache size (number of loaded agents)
|
|
136
181
|
*/
|
|
137
182
|
get size() {
|
|
138
|
-
return this.
|
|
183
|
+
return this.assetCache.size;
|
|
139
184
|
}
|
|
140
185
|
}
|
|
141
186
|
//# sourceMappingURL=agent-mint-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-mint-resolver.js","sourceRoot":"","sources":["../../src/core/agent-mint-resolver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-mint-resolver.js","sourceRoot":"","sources":["../../src/core/agent-mint-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAelC;;;;;;;;GAQG;AACH,MAAM,OAAO,iBAAiB;IACpB,UAAU,GAA8B,IAAI,GAAG,EAAE,CAAC;IAClD,UAAU,CAAa;IACvB,WAAW,GAAY,KAAK,CAAC;IAC7B,cAAc,GAA8C,IAAI,CAAC;IAEzE,YAAY,UAAsB,EAAE,eAA2B;QAC7D,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,IAAI,KAAK,CACb,uDAAuD;YACvD,2DAA2D;YAC3D,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,KAAgB;QACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAElC,oBAAoB;QACpB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QACxC,CAAC;QAED,0BAA0B;QAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACnE,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7E,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC5C,OAAO,YAAY,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB,CAAC,KAAgB;QACtC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,KAAK,KAAK,IAAI,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,UAA6B,EAAE;QACjD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACpD,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,OAA0B;QACtD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,oBAAoB,CAAC;QAChE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;QAErD,IAAI,CAAC;YACH,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC;YAE5E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,mBAAmB,EAAE;gBAC7E,OAAO,EAAE;oBACP;wBACE,MAAM,EAAE;4BACN,MAAM,EAAE,CAAC;4BACT,KAAK,EAAE,kBAAkB;yBAC1B;qBACF;iBACF;aACF,CAAC,CAAC;YAEH,kEAAkE;YAClE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,WAAW,CAAC;YACnD,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CACT,+BAA+B,QAAQ,CAAC,MAAM,wBAAwB,WAAW,IAAI;oBACrF,2CAA2C,CAC5C,CAAC;YACJ,CAAC;YAED,2EAA2E;YAC3E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;YAClD,IAAI,eAAe,GAAG,CAAC,CAAC;YACxB,MAAM,iBAAiB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;YAEzD,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,iBAAiB,EAAE,CAAC;gBAC5C,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;oBACzE,MAAM,WAAW,GAAG,YAAY,CAAC,iBAAiB,EAAE,CAAC;oBACrD,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,CAAC;gBACtD,CAAC;gBAAC,OAAO,UAAU,EAAE,CAAC;oBACpB,IAAI,aAAa,EAAE,CAAC;wBAClB,MAAM,IAAI,KAAK,CACb,iCAAiC,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACtG,CAAC;oBACJ,CAAC;oBACD,eAAe,EAAE,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,2EAA2E;YAC3E,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,CACT,WAAW,eAAe,0CAA0C;oBACpE,kDAAkD,CACnD,CAAC;YACJ,CAAC;YAED,8DAA8D;YAC9D,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAE3B,OAAO,IAAI,CAAC,UAAU,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,8CAA8C;YAC9C,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,QAAgB,EAAE,KAAgB;QAC3C,kBAAkB;IACpB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,SAAmB;QACpC,MAAM,IAAI,KAAK,CACb,4DAA4D;YAC5D,mDAAmD,CACpD,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF"}
|