@agent-fuel/sdk 0.2.0 → 0.3.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/dist/cli.js ADDED
@@ -0,0 +1,4528 @@
1
+ #!/usr/bin/env node
2
+ import { Command, Option } from 'commander';
3
+ import { PublicKey, Keypair, SystemProgram, Transaction, sendAndConfirmTransaction, Connection, TransactionInstruction } from '@solana/web3.js';
4
+ import { randomBytes } from 'crypto';
5
+ import { mkdirSync, writeFileSync, readFileSync } from 'fs';
6
+ import { dirname } from 'path';
7
+ import { BN, AnchorProvider, Wallet, Program, AnchorError } from '@coral-xyz/anchor';
8
+
9
+ var TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
10
+ var ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey(
11
+ "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
12
+ );
13
+ var SLOTS_PER_HOUR = 9e3;
14
+ function getAssociatedTokenAddress(mint, owner) {
15
+ const [ata] = PublicKey.findProgramAddressSync(
16
+ [owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()],
17
+ ASSOCIATED_TOKEN_PROGRAM_ID
18
+ );
19
+ return ata;
20
+ }
21
+ function createAssociatedTokenAccountIdempotentInstruction(payer, ata, owner, mint) {
22
+ return new TransactionInstruction({
23
+ programId: ASSOCIATED_TOKEN_PROGRAM_ID,
24
+ keys: [
25
+ { pubkey: payer, isSigner: true, isWritable: true },
26
+ { pubkey: ata, isSigner: false, isWritable: true },
27
+ { pubkey: owner, isSigner: false, isWritable: false },
28
+ { pubkey: mint, isSigner: false, isWritable: false },
29
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
30
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }
31
+ ],
32
+ data: Buffer.from([1])
33
+ });
34
+ }
35
+ function bnToNum(bn) {
36
+ return bn.toNumber();
37
+ }
38
+ function nameFromBytes(bytes) {
39
+ const buf = Buffer.from(bytes);
40
+ const end = buf.indexOf(0);
41
+ return (end === -1 ? buf : buf.subarray(0, end)).toString("utf8");
42
+ }
43
+ function categoryFromRaw(raw) {
44
+ if ("dataFeed" in raw) return "DataFeed";
45
+ if ("compute" in raw) return "Compute";
46
+ if ("swap" in raw) return "Swap";
47
+ if ("rpc" in raw) return "Rpc";
48
+ return "Other";
49
+ }
50
+ function decodeCreditVault(pubkey, raw) {
51
+ const total_deposited = bnToNum(raw.totalDeposited);
52
+ const total_withdrawn = bnToNum(raw.totalWithdrawn);
53
+ const total_spent = bnToNum(raw.totalSpent);
54
+ const total_claimed = bnToNum(raw.totalClaimed);
55
+ return {
56
+ pubkey,
57
+ owner: raw.owner,
58
+ agent: raw.agent,
59
+ usdc_mint: raw.usdcMint,
60
+ vault_token_account: raw.vaultTokenAccount,
61
+ total_deposited,
62
+ total_withdrawn,
63
+ total_spent,
64
+ total_claimed,
65
+ balance: total_deposited - total_withdrawn - total_spent + total_claimed,
66
+ frozen: raw.frozen,
67
+ created_slot: bnToNum(raw.createdSlot),
68
+ last_active_slot: bnToNum(raw.lastActiveSlot),
69
+ pending_count: bnToNum(raw.pendingCount)
70
+ };
71
+ }
72
+ var DEFAULT_PUBKEY = PublicKey.default.toBase58();
73
+ function decodeSpendPolicy(pubkey, raw) {
74
+ return {
75
+ pubkey,
76
+ vault: raw.vault,
77
+ whitelist: raw.whitelist.filter((pk) => pk.toBase58() !== DEFAULT_PUBKEY),
78
+ per_tx_limit_usdc: bnToNum(raw.perTxLimitUsdc),
79
+ hourly_limit_usdc: bnToNum(raw.hourlyLimitUsdc),
80
+ lifetime_limit_usdc: bnToNum(raw.lifetimeLimitUsdc),
81
+ hourly_window_start_slot: bnToNum(raw.hourlyWindowStartSlot),
82
+ hourly_window_spent_usdc: bnToNum(raw.hourlyWindowSpentUsdc),
83
+ allow_post_pay: raw.allowPostPay
84
+ };
85
+ }
86
+ function decodeServiceRegistry(pubkey, raw) {
87
+ return {
88
+ pubkey,
89
+ authority: raw.authority,
90
+ name: nameFromBytes(raw.name),
91
+ category: categoryFromRaw(raw.category),
92
+ total_agents_served: bnToNum(raw.totalAgentsServed),
93
+ total_volume_received_usdc: bnToNum(raw.totalVolumeReceivedUsdc),
94
+ active: raw.active,
95
+ first_active_slot: bnToNum(raw.firstActiveSlot),
96
+ last_active_slot: bnToNum(raw.lastActiveSlot)
97
+ };
98
+ }
99
+
100
+ // src/errors.ts
101
+ var AgentFuelError = class extends Error {
102
+ constructor(message) {
103
+ super(message);
104
+ this.name = "AgentFuelError";
105
+ }
106
+ };
107
+ var OwnerNotConfiguredError = class extends AgentFuelError {
108
+ constructor() {
109
+ super("vault owner is not configured: pass `owner` to `new AgentFuel({...})` or to the method");
110
+ this.name = "OwnerNotConfiguredError";
111
+ }
112
+ };
113
+ var AccountNotFoundError = class extends AgentFuelError {
114
+ account;
115
+ constructor(account) {
116
+ super(`account not found: ${account}`);
117
+ this.name = "AccountNotFoundError";
118
+ this.account = account;
119
+ }
120
+ };
121
+ var HttpError = class extends AgentFuelError {
122
+ status;
123
+ url;
124
+ body;
125
+ constructor(status, url, body) {
126
+ super(`HTTP ${status} from ${url}`);
127
+ this.name = "HttpError";
128
+ this.status = status;
129
+ this.url = url;
130
+ this.body = body;
131
+ }
132
+ };
133
+ var SpendPolicyError = class extends AgentFuelError {
134
+ constructor(message) {
135
+ super(message);
136
+ this.name = "SpendPolicyError";
137
+ }
138
+ };
139
+ var VaultFrozenError = class extends SpendPolicyError {
140
+ constructor() {
141
+ super("vault is frozen");
142
+ this.name = "VaultFrozenError";
143
+ }
144
+ };
145
+ var ZeroAmountError = class extends SpendPolicyError {
146
+ constructor() {
147
+ super("amount must be > 0");
148
+ this.name = "ZeroAmountError";
149
+ }
150
+ };
151
+ var PerTxLimitExceededError = class extends SpendPolicyError {
152
+ limit;
153
+ amount;
154
+ constructor(amount, limit) {
155
+ super(`per-tx limit exceeded: ${amount} > ${limit}`);
156
+ this.name = "PerTxLimitExceededError";
157
+ this.amount = amount;
158
+ this.limit = limit;
159
+ }
160
+ };
161
+ var HourlyLimitExceededError = class extends SpendPolicyError {
162
+ limit;
163
+ windowSpent;
164
+ amount;
165
+ constructor(amount, windowSpent, limit) {
166
+ super(`hourly limit exceeded: ${windowSpent} + ${amount} > ${limit}`);
167
+ this.name = "HourlyLimitExceededError";
168
+ this.amount = amount;
169
+ this.windowSpent = windowSpent;
170
+ this.limit = limit;
171
+ }
172
+ };
173
+ var LifetimeLimitExceededError = class extends SpendPolicyError {
174
+ limit;
175
+ totalSpent;
176
+ amount;
177
+ constructor(amount, totalSpent, limit) {
178
+ super(`lifetime limit exceeded: ${totalSpent} + ${amount} > ${limit}`);
179
+ this.name = "LifetimeLimitExceededError";
180
+ this.amount = amount;
181
+ this.totalSpent = totalSpent;
182
+ this.limit = limit;
183
+ }
184
+ };
185
+ var NotWhitelistedError = class extends SpendPolicyError {
186
+ service;
187
+ constructor(service) {
188
+ super(`service ${service} is not in the vault's whitelist`);
189
+ this.name = "NotWhitelistedError";
190
+ this.service = service;
191
+ }
192
+ };
193
+ var RecordPaymentError = class extends AgentFuelError {
194
+ constructor(message) {
195
+ super(message);
196
+ this.name = "RecordPaymentError";
197
+ }
198
+ };
199
+ var ReceiptAlreadyRecordedError = class extends RecordPaymentError {
200
+ receiptHash;
201
+ constructor(receiptHash) {
202
+ super("payment receipt was already recorded on chain");
203
+ this.name = "ReceiptAlreadyRecordedError";
204
+ this.receiptHash = receiptHash;
205
+ }
206
+ };
207
+ var ServiceInactiveError = class extends RecordPaymentError {
208
+ service;
209
+ constructor(service) {
210
+ super(`service ${service} is paused; record_payment rejected`);
211
+ this.name = "ServiceInactiveError";
212
+ this.service = service;
213
+ }
214
+ };
215
+
216
+ // src/guardrails.ts
217
+ function guardSpend(args) {
218
+ const { vault, policy, service, amountUsdc, currentSlot } = args;
219
+ if (vault.frozen) throw new VaultFrozenError();
220
+ if (amountUsdc <= 0) throw new ZeroAmountError();
221
+ if (policy.whitelist.length > 0) {
222
+ const allowed = policy.whitelist.some((pk) => pk.equals(service));
223
+ if (!allowed) throw new NotWhitelistedError(service.toBase58());
224
+ }
225
+ if (policy.per_tx_limit_usdc > 0 && amountUsdc > policy.per_tx_limit_usdc) {
226
+ throw new PerTxLimitExceededError(amountUsdc, policy.per_tx_limit_usdc);
227
+ }
228
+ if (policy.hourly_limit_usdc > 0) {
229
+ const windowElapsed = currentSlot - policy.hourly_window_start_slot >= SLOTS_PER_HOUR;
230
+ const windowSpent = windowElapsed ? 0 : policy.hourly_window_spent_usdc;
231
+ const newWindowTotal = windowSpent + amountUsdc;
232
+ if (newWindowTotal > policy.hourly_limit_usdc) {
233
+ throw new HourlyLimitExceededError(amountUsdc, windowSpent, policy.hourly_limit_usdc);
234
+ }
235
+ }
236
+ if (policy.lifetime_limit_usdc > 0) {
237
+ const newTotalSpent = vault.total_spent + amountUsdc;
238
+ if (newTotalSpent > policy.lifetime_limit_usdc) {
239
+ throw new LifetimeLimitExceededError(amountUsdc, vault.total_spent, policy.lifetime_limit_usdc);
240
+ }
241
+ }
242
+ }
243
+
244
+ // src/live.ts
245
+ var cachedCtor = null;
246
+ async function getWebSocketCtor() {
247
+ if (cachedCtor) return cachedCtor;
248
+ const globalCtor = globalThis.WebSocket;
249
+ if (globalCtor) {
250
+ cachedCtor = globalCtor;
251
+ return globalCtor;
252
+ }
253
+ cachedCtor = (async () => {
254
+ const mod = await import('ws');
255
+ return mod.WebSocket;
256
+ })();
257
+ return cachedCtor;
258
+ }
259
+ var WS_OPEN = 1;
260
+ var MAX_BACKOFF_MS = 3e4;
261
+ function subscribe(url, opts) {
262
+ let socket = null;
263
+ let alive = true;
264
+ let attempts = 0;
265
+ let reconnectTimer = null;
266
+ let currentStatus = "connecting";
267
+ function setStatus(next) {
268
+ currentStatus = next;
269
+ opts.onStatus?.(next);
270
+ }
271
+ async function connect() {
272
+ if (!alive) return;
273
+ setStatus(attempts === 0 ? "connecting" : "reconnecting");
274
+ const WS = await getWebSocketCtor();
275
+ if (!alive) return;
276
+ socket = new WS(url);
277
+ socket.addEventListener("open", () => {
278
+ attempts = 0;
279
+ setStatus("open");
280
+ });
281
+ socket.addEventListener("message", (ev) => {
282
+ if (typeof ev.data !== "string" || ev.data.length === 0) return;
283
+ try {
284
+ const parsed = JSON.parse(ev.data);
285
+ if (parsed.type === "event") opts.onFrame(parsed);
286
+ } catch {
287
+ }
288
+ });
289
+ socket.addEventListener("close", () => {
290
+ if (!alive) return;
291
+ attempts += 1;
292
+ const delay = Math.min(MAX_BACKOFF_MS, 1e3 * 2 ** (attempts - 1));
293
+ setStatus("reconnecting");
294
+ reconnectTimer = setTimeout(() => {
295
+ void connect();
296
+ }, delay);
297
+ });
298
+ socket.addEventListener("error", () => {
299
+ });
300
+ }
301
+ void connect();
302
+ return {
303
+ close() {
304
+ alive = false;
305
+ if (reconnectTimer !== null) clearTimeout(reconnectTimer);
306
+ if (socket && socket.readyState === WS_OPEN) {
307
+ socket.close(1e3, "client close");
308
+ }
309
+ socket = null;
310
+ setStatus("closed");
311
+ },
312
+ get status() {
313
+ return currentStatus;
314
+ }
315
+ };
316
+ }
317
+ function wsUrl(apiBase, path) {
318
+ if (apiBase.startsWith("https://")) return apiBase.replace(/^https/, "wss") + path;
319
+ if (apiBase.startsWith("http://")) return apiBase.replace(/^http/, "ws") + path;
320
+ return apiBase + path;
321
+ }
322
+
323
+ // src/idl/reputation.json
324
+ var reputation_default = {
325
+ address: "4GjB4xdm1VTPVM6KSiEEfJpD4u7BfY1qDx77StiFShvQ",
326
+ metadata: {
327
+ name: "reputation",
328
+ version: "0.1.0",
329
+ spec: "0.1.0",
330
+ description: "Agent Fuel \u2014 On-chain reputation primitive for AI agents on Solana",
331
+ repository: "https://github.com/TODO/agent_fuel"
332
+ },
333
+ instructions: [
334
+ {
335
+ name: "append_response",
336
+ discriminator: [
337
+ 162,
338
+ 210,
339
+ 186,
340
+ 50,
341
+ 180,
342
+ 4,
343
+ 47,
344
+ 104
345
+ ],
346
+ accounts: [
347
+ {
348
+ name: "responder",
349
+ writable: true,
350
+ signer: true
351
+ },
352
+ {
353
+ name: "agent_profile",
354
+ writable: true,
355
+ pda: {
356
+ seeds: [
357
+ {
358
+ kind: "const",
359
+ value: [
360
+ 97,
361
+ 103,
362
+ 101,
363
+ 110,
364
+ 116
365
+ ]
366
+ },
367
+ {
368
+ kind: "account",
369
+ path: "agent_profile.authority",
370
+ account: "AgentProfile"
371
+ }
372
+ ]
373
+ },
374
+ relations: [
375
+ "feedback_record"
376
+ ]
377
+ },
378
+ {
379
+ name: "feedback_record",
380
+ writable: true,
381
+ pda: {
382
+ seeds: [
383
+ {
384
+ kind: "const",
385
+ value: [
386
+ 102,
387
+ 101,
388
+ 101,
389
+ 100,
390
+ 98,
391
+ 97,
392
+ 99,
393
+ 107
394
+ ]
395
+ },
396
+ {
397
+ kind: "arg",
398
+ path: "payment_receipt_hash"
399
+ }
400
+ ]
401
+ }
402
+ },
403
+ {
404
+ name: "system_program",
405
+ address: "11111111111111111111111111111111"
406
+ }
407
+ ],
408
+ args: [
409
+ {
410
+ name: "payment_receipt_hash",
411
+ type: {
412
+ array: [
413
+ "u8",
414
+ 32
415
+ ]
416
+ }
417
+ },
418
+ {
419
+ name: "response_uri",
420
+ type: {
421
+ array: [
422
+ "u8",
423
+ 128
424
+ ]
425
+ }
426
+ },
427
+ {
428
+ name: "response_hash",
429
+ type: {
430
+ array: [
431
+ "u8",
432
+ 32
433
+ ]
434
+ }
435
+ }
436
+ ]
437
+ },
438
+ {
439
+ name: "compute_score",
440
+ discriminator: [
441
+ 161,
442
+ 101,
443
+ 4,
444
+ 93,
445
+ 120,
446
+ 62,
447
+ 41,
448
+ 20
449
+ ],
450
+ accounts: [
451
+ {
452
+ name: "caller",
453
+ writable: true,
454
+ signer: true
455
+ },
456
+ {
457
+ name: "agent_profile",
458
+ writable: true,
459
+ pda: {
460
+ seeds: [
461
+ {
462
+ kind: "const",
463
+ value: [
464
+ 97,
465
+ 103,
466
+ 101,
467
+ 110,
468
+ 116
469
+ ]
470
+ },
471
+ {
472
+ kind: "account",
473
+ path: "agent_profile.authority",
474
+ account: "AgentProfile"
475
+ }
476
+ ]
477
+ }
478
+ }
479
+ ],
480
+ args: []
481
+ },
482
+ {
483
+ name: "give_feedback",
484
+ discriminator: [
485
+ 145,
486
+ 136,
487
+ 123,
488
+ 3,
489
+ 215,
490
+ 165,
491
+ 98,
492
+ 41
493
+ ],
494
+ accounts: [
495
+ {
496
+ name: "service",
497
+ writable: true,
498
+ signer: true
499
+ },
500
+ {
501
+ name: "agent_profile",
502
+ writable: true,
503
+ pda: {
504
+ seeds: [
505
+ {
506
+ kind: "const",
507
+ value: [
508
+ 97,
509
+ 103,
510
+ 101,
511
+ 110,
512
+ 116
513
+ ]
514
+ },
515
+ {
516
+ kind: "account",
517
+ path: "agent_profile.authority",
518
+ account: "AgentProfile"
519
+ }
520
+ ]
521
+ }
522
+ },
523
+ {
524
+ name: "service_registry",
525
+ writable: true,
526
+ pda: {
527
+ seeds: [
528
+ {
529
+ kind: "const",
530
+ value: [
531
+ 115,
532
+ 101,
533
+ 114,
534
+ 118,
535
+ 105,
536
+ 99,
537
+ 101
538
+ ]
539
+ },
540
+ {
541
+ kind: "account",
542
+ path: "service"
543
+ }
544
+ ]
545
+ }
546
+ },
547
+ {
548
+ name: "agent_service_link",
549
+ writable: true,
550
+ pda: {
551
+ seeds: [
552
+ {
553
+ kind: "const",
554
+ value: [
555
+ 108,
556
+ 105,
557
+ 110,
558
+ 107
559
+ ]
560
+ },
561
+ {
562
+ kind: "account",
563
+ path: "agent_profile"
564
+ },
565
+ {
566
+ kind: "account",
567
+ path: "service_registry"
568
+ }
569
+ ]
570
+ }
571
+ },
572
+ {
573
+ name: "receipt_used",
574
+ pda: {
575
+ seeds: [
576
+ {
577
+ kind: "const",
578
+ value: [
579
+ 114,
580
+ 101,
581
+ 99,
582
+ 101,
583
+ 105,
584
+ 112,
585
+ 116
586
+ ]
587
+ },
588
+ {
589
+ kind: "arg",
590
+ path: "payment_receipt_hash"
591
+ }
592
+ ]
593
+ }
594
+ },
595
+ {
596
+ name: "feedback_record",
597
+ writable: true,
598
+ pda: {
599
+ seeds: [
600
+ {
601
+ kind: "const",
602
+ value: [
603
+ 102,
604
+ 101,
605
+ 101,
606
+ 100,
607
+ 98,
608
+ 97,
609
+ 99,
610
+ 107
611
+ ]
612
+ },
613
+ {
614
+ kind: "arg",
615
+ path: "payment_receipt_hash"
616
+ }
617
+ ]
618
+ }
619
+ },
620
+ {
621
+ name: "system_program",
622
+ address: "11111111111111111111111111111111"
623
+ }
624
+ ],
625
+ args: [
626
+ {
627
+ name: "payment_receipt_hash",
628
+ type: {
629
+ array: [
630
+ "u8",
631
+ 32
632
+ ]
633
+ }
634
+ },
635
+ {
636
+ name: "value",
637
+ type: "i8"
638
+ },
639
+ {
640
+ name: "tags",
641
+ type: "u32"
642
+ },
643
+ {
644
+ name: "evidence_uri",
645
+ type: {
646
+ array: [
647
+ "u8",
648
+ 128
649
+ ]
650
+ }
651
+ },
652
+ {
653
+ name: "evidence_hash",
654
+ type: {
655
+ array: [
656
+ "u8",
657
+ 32
658
+ ]
659
+ }
660
+ }
661
+ ]
662
+ },
663
+ {
664
+ name: "initialize_agent",
665
+ discriminator: [
666
+ 212,
667
+ 81,
668
+ 156,
669
+ 211,
670
+ 212,
671
+ 110,
672
+ 21,
673
+ 28
674
+ ],
675
+ accounts: [
676
+ {
677
+ name: "owner",
678
+ writable: true,
679
+ signer: true
680
+ },
681
+ {
682
+ name: "agent",
683
+ signer: true
684
+ },
685
+ {
686
+ name: "agent_profile",
687
+ writable: true,
688
+ pda: {
689
+ seeds: [
690
+ {
691
+ kind: "const",
692
+ value: [
693
+ 97,
694
+ 103,
695
+ 101,
696
+ 110,
697
+ 116
698
+ ]
699
+ },
700
+ {
701
+ kind: "account",
702
+ path: "agent"
703
+ }
704
+ ]
705
+ }
706
+ },
707
+ {
708
+ name: "system_program",
709
+ address: "11111111111111111111111111111111"
710
+ }
711
+ ],
712
+ args: [
713
+ {
714
+ name: "agent_uri",
715
+ type: {
716
+ array: [
717
+ "u8",
718
+ 128
719
+ ]
720
+ }
721
+ },
722
+ {
723
+ name: "external_agent_id",
724
+ type: "u64"
725
+ }
726
+ ]
727
+ },
728
+ {
729
+ name: "record_payment",
730
+ discriminator: [
731
+ 226,
732
+ 154,
733
+ 10,
734
+ 27,
735
+ 9,
736
+ 14,
737
+ 148,
738
+ 137
739
+ ],
740
+ accounts: [
741
+ {
742
+ name: "service",
743
+ writable: true,
744
+ signer: true
745
+ },
746
+ {
747
+ name: "agent_profile",
748
+ writable: true,
749
+ pda: {
750
+ seeds: [
751
+ {
752
+ kind: "const",
753
+ value: [
754
+ 97,
755
+ 103,
756
+ 101,
757
+ 110,
758
+ 116
759
+ ]
760
+ },
761
+ {
762
+ kind: "account",
763
+ path: "agent_profile.authority",
764
+ account: "AgentProfile"
765
+ }
766
+ ]
767
+ }
768
+ },
769
+ {
770
+ name: "service_registry",
771
+ writable: true,
772
+ pda: {
773
+ seeds: [
774
+ {
775
+ kind: "const",
776
+ value: [
777
+ 115,
778
+ 101,
779
+ 114,
780
+ 118,
781
+ 105,
782
+ 99,
783
+ 101
784
+ ]
785
+ },
786
+ {
787
+ kind: "account",
788
+ path: "service"
789
+ }
790
+ ]
791
+ }
792
+ },
793
+ {
794
+ name: "agent_service_link",
795
+ writable: true,
796
+ pda: {
797
+ seeds: [
798
+ {
799
+ kind: "const",
800
+ value: [
801
+ 108,
802
+ 105,
803
+ 110,
804
+ 107
805
+ ]
806
+ },
807
+ {
808
+ kind: "account",
809
+ path: "agent_profile"
810
+ },
811
+ {
812
+ kind: "account",
813
+ path: "service_registry"
814
+ }
815
+ ]
816
+ }
817
+ },
818
+ {
819
+ name: "receipt_used",
820
+ writable: true,
821
+ pda: {
822
+ seeds: [
823
+ {
824
+ kind: "const",
825
+ value: [
826
+ 114,
827
+ 101,
828
+ 99,
829
+ 101,
830
+ 105,
831
+ 112,
832
+ 116
833
+ ]
834
+ },
835
+ {
836
+ kind: "arg",
837
+ path: "payment_receipt_hash"
838
+ }
839
+ ]
840
+ }
841
+ },
842
+ {
843
+ name: "system_program",
844
+ address: "11111111111111111111111111111111"
845
+ }
846
+ ],
847
+ args: [
848
+ {
849
+ name: "amount_usdc",
850
+ type: "u64"
851
+ },
852
+ {
853
+ name: "payment_receipt_hash",
854
+ type: {
855
+ array: [
856
+ "u8",
857
+ 32
858
+ ]
859
+ }
860
+ }
861
+ ]
862
+ },
863
+ {
864
+ name: "register_service",
865
+ discriminator: [
866
+ 11,
867
+ 133,
868
+ 158,
869
+ 232,
870
+ 193,
871
+ 19,
872
+ 229,
873
+ 73
874
+ ],
875
+ accounts: [
876
+ {
877
+ name: "sponsor",
878
+ writable: true,
879
+ signer: true
880
+ },
881
+ {
882
+ name: "service",
883
+ signer: true
884
+ },
885
+ {
886
+ name: "service_registry",
887
+ writable: true,
888
+ pda: {
889
+ seeds: [
890
+ {
891
+ kind: "const",
892
+ value: [
893
+ 115,
894
+ 101,
895
+ 114,
896
+ 118,
897
+ 105,
898
+ 99,
899
+ 101
900
+ ]
901
+ },
902
+ {
903
+ kind: "account",
904
+ path: "service"
905
+ }
906
+ ]
907
+ }
908
+ },
909
+ {
910
+ name: "system_program",
911
+ address: "11111111111111111111111111111111"
912
+ }
913
+ ],
914
+ args: [
915
+ {
916
+ name: "name",
917
+ type: {
918
+ array: [
919
+ "u8",
920
+ 32
921
+ ]
922
+ }
923
+ },
924
+ {
925
+ name: "category",
926
+ type: {
927
+ defined: {
928
+ name: "ServiceCategory"
929
+ }
930
+ }
931
+ },
932
+ {
933
+ name: "service_uri",
934
+ type: {
935
+ array: [
936
+ "u8",
937
+ 128
938
+ ]
939
+ }
940
+ }
941
+ ]
942
+ },
943
+ {
944
+ name: "revoke_feedback",
945
+ discriminator: [
946
+ 211,
947
+ 37,
948
+ 230,
949
+ 82,
950
+ 118,
951
+ 216,
952
+ 137,
953
+ 206
954
+ ],
955
+ accounts: [
956
+ {
957
+ name: "service",
958
+ writable: true,
959
+ signer: true
960
+ },
961
+ {
962
+ name: "agent_profile",
963
+ writable: true,
964
+ pda: {
965
+ seeds: [
966
+ {
967
+ kind: "const",
968
+ value: [
969
+ 97,
970
+ 103,
971
+ 101,
972
+ 110,
973
+ 116
974
+ ]
975
+ },
976
+ {
977
+ kind: "account",
978
+ path: "agent_profile.authority",
979
+ account: "AgentProfile"
980
+ }
981
+ ]
982
+ },
983
+ relations: [
984
+ "feedback_record"
985
+ ]
986
+ },
987
+ {
988
+ name: "service_registry",
989
+ writable: true,
990
+ pda: {
991
+ seeds: [
992
+ {
993
+ kind: "const",
994
+ value: [
995
+ 115,
996
+ 101,
997
+ 114,
998
+ 118,
999
+ 105,
1000
+ 99,
1001
+ 101
1002
+ ]
1003
+ },
1004
+ {
1005
+ kind: "account",
1006
+ path: "service"
1007
+ }
1008
+ ]
1009
+ },
1010
+ relations: [
1011
+ "feedback_record"
1012
+ ]
1013
+ },
1014
+ {
1015
+ name: "feedback_record",
1016
+ writable: true,
1017
+ pda: {
1018
+ seeds: [
1019
+ {
1020
+ kind: "const",
1021
+ value: [
1022
+ 102,
1023
+ 101,
1024
+ 101,
1025
+ 100,
1026
+ 98,
1027
+ 97,
1028
+ 99,
1029
+ 107
1030
+ ]
1031
+ },
1032
+ {
1033
+ kind: "arg",
1034
+ path: "payment_receipt_hash"
1035
+ }
1036
+ ]
1037
+ }
1038
+ },
1039
+ {
1040
+ name: "system_program",
1041
+ address: "11111111111111111111111111111111"
1042
+ }
1043
+ ],
1044
+ args: [
1045
+ {
1046
+ name: "payment_receipt_hash",
1047
+ type: {
1048
+ array: [
1049
+ "u8",
1050
+ 32
1051
+ ]
1052
+ }
1053
+ }
1054
+ ]
1055
+ },
1056
+ {
1057
+ name: "set_service_active",
1058
+ discriminator: [
1059
+ 221,
1060
+ 172,
1061
+ 149,
1062
+ 49,
1063
+ 212,
1064
+ 184,
1065
+ 77,
1066
+ 101
1067
+ ],
1068
+ accounts: [
1069
+ {
1070
+ name: "service",
1071
+ signer: true
1072
+ },
1073
+ {
1074
+ name: "service_registry",
1075
+ writable: true,
1076
+ pda: {
1077
+ seeds: [
1078
+ {
1079
+ kind: "const",
1080
+ value: [
1081
+ 115,
1082
+ 101,
1083
+ 114,
1084
+ 118,
1085
+ 105,
1086
+ 99,
1087
+ 101
1088
+ ]
1089
+ },
1090
+ {
1091
+ kind: "account",
1092
+ path: "service"
1093
+ }
1094
+ ]
1095
+ }
1096
+ },
1097
+ {
1098
+ name: "authority",
1099
+ relations: [
1100
+ "service_registry"
1101
+ ]
1102
+ }
1103
+ ],
1104
+ args: [
1105
+ {
1106
+ name: "active",
1107
+ type: "bool"
1108
+ }
1109
+ ]
1110
+ }
1111
+ ],
1112
+ accounts: [
1113
+ {
1114
+ name: "AgentProfile",
1115
+ discriminator: [
1116
+ 60,
1117
+ 227,
1118
+ 42,
1119
+ 24,
1120
+ 0,
1121
+ 87,
1122
+ 86,
1123
+ 205
1124
+ ]
1125
+ },
1126
+ {
1127
+ name: "AgentServiceLink",
1128
+ discriminator: [
1129
+ 123,
1130
+ 74,
1131
+ 215,
1132
+ 240,
1133
+ 42,
1134
+ 88,
1135
+ 217,
1136
+ 216
1137
+ ]
1138
+ },
1139
+ {
1140
+ name: "FeedbackRecord",
1141
+ discriminator: [
1142
+ 15,
1143
+ 45,
1144
+ 246,
1145
+ 217,
1146
+ 63,
1147
+ 251,
1148
+ 69,
1149
+ 100
1150
+ ]
1151
+ },
1152
+ {
1153
+ name: "ReceiptUsed",
1154
+ discriminator: [
1155
+ 143,
1156
+ 21,
1157
+ 251,
1158
+ 75,
1159
+ 166,
1160
+ 7,
1161
+ 163,
1162
+ 137
1163
+ ]
1164
+ },
1165
+ {
1166
+ name: "ServiceRegistry",
1167
+ discriminator: [
1168
+ 105,
1169
+ 133,
1170
+ 96,
1171
+ 79,
1172
+ 207,
1173
+ 176,
1174
+ 202,
1175
+ 71
1176
+ ]
1177
+ }
1178
+ ],
1179
+ events: [
1180
+ {
1181
+ name: "AgentInitialized",
1182
+ discriminator: [
1183
+ 124,
1184
+ 252,
1185
+ 85,
1186
+ 27,
1187
+ 146,
1188
+ 101,
1189
+ 64,
1190
+ 160
1191
+ ]
1192
+ },
1193
+ {
1194
+ name: "FeedbackGiven",
1195
+ discriminator: [
1196
+ 64,
1197
+ 65,
1198
+ 2,
1199
+ 152,
1200
+ 174,
1201
+ 215,
1202
+ 156,
1203
+ 194
1204
+ ]
1205
+ },
1206
+ {
1207
+ name: "FeedbackRevoked",
1208
+ discriminator: [
1209
+ 205,
1210
+ 16,
1211
+ 31,
1212
+ 94,
1213
+ 54,
1214
+ 101,
1215
+ 16,
1216
+ 199
1217
+ ]
1218
+ },
1219
+ {
1220
+ name: "PaymentRecorded",
1221
+ discriminator: [
1222
+ 214,
1223
+ 3,
1224
+ 212,
1225
+ 116,
1226
+ 135,
1227
+ 35,
1228
+ 104,
1229
+ 98
1230
+ ]
1231
+ },
1232
+ {
1233
+ name: "ResponseAppended",
1234
+ discriminator: [
1235
+ 168,
1236
+ 169,
1237
+ 214,
1238
+ 193,
1239
+ 171,
1240
+ 1,
1241
+ 232,
1242
+ 123
1243
+ ]
1244
+ },
1245
+ {
1246
+ name: "ScoreComputed",
1247
+ discriminator: [
1248
+ 52,
1249
+ 76,
1250
+ 80,
1251
+ 33,
1252
+ 2,
1253
+ 43,
1254
+ 75,
1255
+ 109
1256
+ ]
1257
+ },
1258
+ {
1259
+ name: "ServiceActiveSet",
1260
+ discriminator: [
1261
+ 151,
1262
+ 122,
1263
+ 7,
1264
+ 40,
1265
+ 191,
1266
+ 139,
1267
+ 237,
1268
+ 52
1269
+ ]
1270
+ },
1271
+ {
1272
+ name: "ServiceRegistered",
1273
+ discriminator: [
1274
+ 25,
1275
+ 219,
1276
+ 76,
1277
+ 223,
1278
+ 57,
1279
+ 191,
1280
+ 117,
1281
+ 38
1282
+ ]
1283
+ }
1284
+ ],
1285
+ errors: [
1286
+ {
1287
+ code: 6e3,
1288
+ name: "Overflow",
1289
+ msg: "Counter or amount overflow"
1290
+ },
1291
+ {
1292
+ code: 6001,
1293
+ name: "ServiceInactive",
1294
+ msg: "Service is not active"
1295
+ },
1296
+ {
1297
+ code: 6002,
1298
+ name: "ZeroAmount",
1299
+ msg: "Payment amount must be greater than zero"
1300
+ },
1301
+ {
1302
+ code: 6003,
1303
+ name: "SelfRating",
1304
+ msg: "A service may not rate itself or the agent owner"
1305
+ },
1306
+ {
1307
+ code: 6004,
1308
+ name: "ReceiptMismatch",
1309
+ msg: "Receipt does not belong to this (agent, service) pair"
1310
+ },
1311
+ {
1312
+ code: 6005,
1313
+ name: "InvalidFeedbackValue",
1314
+ msg: "Feedback value is outside the allowed range"
1315
+ },
1316
+ {
1317
+ code: 6006,
1318
+ name: "UnauthorizedResponder",
1319
+ msg: "Responder must be the agent or its owner"
1320
+ },
1321
+ {
1322
+ code: 6007,
1323
+ name: "AlreadyHasResponse",
1324
+ msg: "Feedback already has a response"
1325
+ },
1326
+ {
1327
+ code: 6008,
1328
+ name: "AlreadyRevoked",
1329
+ msg: "Feedback has already been revoked"
1330
+ },
1331
+ {
1332
+ code: 6009,
1333
+ name: "FeedbackRateLimited",
1334
+ msg: "Feedback rate limit not yet expired for this (service, agent) pair"
1335
+ },
1336
+ {
1337
+ code: 6010,
1338
+ name: "UnauthorizedService",
1339
+ msg: "Only the service authority may perform this action"
1340
+ }
1341
+ ],
1342
+ types: [
1343
+ {
1344
+ name: "AgentInitialized",
1345
+ type: {
1346
+ kind: "struct",
1347
+ fields: [
1348
+ {
1349
+ name: "agent",
1350
+ type: "pubkey"
1351
+ },
1352
+ {
1353
+ name: "owner",
1354
+ type: "pubkey"
1355
+ },
1356
+ {
1357
+ name: "init_slot",
1358
+ type: "u64"
1359
+ }
1360
+ ]
1361
+ }
1362
+ },
1363
+ {
1364
+ name: "AgentProfile",
1365
+ type: {
1366
+ kind: "struct",
1367
+ fields: [
1368
+ {
1369
+ name: "authority",
1370
+ type: "pubkey"
1371
+ },
1372
+ {
1373
+ name: "owner",
1374
+ type: "pubkey"
1375
+ },
1376
+ {
1377
+ name: "agent_uri",
1378
+ type: {
1379
+ array: [
1380
+ "u8",
1381
+ 128
1382
+ ]
1383
+ }
1384
+ },
1385
+ {
1386
+ name: "external_agent_id",
1387
+ type: "u64"
1388
+ },
1389
+ {
1390
+ name: "total_transactions",
1391
+ type: "u64"
1392
+ },
1393
+ {
1394
+ name: "total_volume_usdc",
1395
+ type: "u64"
1396
+ },
1397
+ {
1398
+ name: "consecutive_success",
1399
+ type: "u32"
1400
+ },
1401
+ {
1402
+ name: "total_feedback_count",
1403
+ type: "u32"
1404
+ },
1405
+ {
1406
+ name: "active_negative_feedback_count",
1407
+ type: "u32"
1408
+ },
1409
+ {
1410
+ name: "services_used",
1411
+ type: "u16"
1412
+ },
1413
+ {
1414
+ name: "first_active_slot",
1415
+ type: "u64"
1416
+ },
1417
+ {
1418
+ name: "last_active_slot",
1419
+ type: "u64"
1420
+ },
1421
+ {
1422
+ name: "reputation_score",
1423
+ type: "u16"
1424
+ },
1425
+ {
1426
+ name: "bump",
1427
+ type: "u8"
1428
+ },
1429
+ {
1430
+ name: "_padding",
1431
+ type: {
1432
+ array: [
1433
+ "u8",
1434
+ 64
1435
+ ]
1436
+ }
1437
+ }
1438
+ ]
1439
+ }
1440
+ },
1441
+ {
1442
+ name: "AgentServiceLink",
1443
+ type: {
1444
+ kind: "struct",
1445
+ fields: [
1446
+ {
1447
+ name: "agent",
1448
+ type: "pubkey"
1449
+ },
1450
+ {
1451
+ name: "service",
1452
+ type: "pubkey"
1453
+ },
1454
+ {
1455
+ name: "total_transactions",
1456
+ type: "u64"
1457
+ },
1458
+ {
1459
+ name: "total_volume_usdc",
1460
+ type: "u64"
1461
+ },
1462
+ {
1463
+ name: "first_payment_slot",
1464
+ type: "u64"
1465
+ },
1466
+ {
1467
+ name: "last_payment_slot",
1468
+ type: "u64"
1469
+ },
1470
+ {
1471
+ name: "last_feedback_slot",
1472
+ type: "u64"
1473
+ },
1474
+ {
1475
+ name: "has_received_feedback",
1476
+ type: "bool"
1477
+ },
1478
+ {
1479
+ name: "bump",
1480
+ type: "u8"
1481
+ },
1482
+ {
1483
+ name: "_padding",
1484
+ type: {
1485
+ array: [
1486
+ "u8",
1487
+ 64
1488
+ ]
1489
+ }
1490
+ }
1491
+ ]
1492
+ }
1493
+ },
1494
+ {
1495
+ name: "FeedbackGiven",
1496
+ type: {
1497
+ kind: "struct",
1498
+ fields: [
1499
+ {
1500
+ name: "agent",
1501
+ type: "pubkey"
1502
+ },
1503
+ {
1504
+ name: "service",
1505
+ type: "pubkey"
1506
+ },
1507
+ {
1508
+ name: "feedback",
1509
+ type: "pubkey"
1510
+ },
1511
+ {
1512
+ name: "payment_receipt_hash",
1513
+ type: {
1514
+ array: [
1515
+ "u8",
1516
+ 32
1517
+ ]
1518
+ }
1519
+ },
1520
+ {
1521
+ name: "value",
1522
+ type: "i8"
1523
+ },
1524
+ {
1525
+ name: "tags",
1526
+ type: "u32"
1527
+ },
1528
+ {
1529
+ name: "slot",
1530
+ type: "u64"
1531
+ }
1532
+ ]
1533
+ }
1534
+ },
1535
+ {
1536
+ name: "FeedbackRecord",
1537
+ type: {
1538
+ kind: "struct",
1539
+ fields: [
1540
+ {
1541
+ name: "agent_profile",
1542
+ type: "pubkey"
1543
+ },
1544
+ {
1545
+ name: "service_registry",
1546
+ type: "pubkey"
1547
+ },
1548
+ {
1549
+ name: "payment_receipt_hash",
1550
+ type: {
1551
+ array: [
1552
+ "u8",
1553
+ 32
1554
+ ]
1555
+ }
1556
+ },
1557
+ {
1558
+ name: "value",
1559
+ type: "i8"
1560
+ },
1561
+ {
1562
+ name: "tags",
1563
+ type: "u32"
1564
+ },
1565
+ {
1566
+ name: "evidence_uri",
1567
+ type: {
1568
+ array: [
1569
+ "u8",
1570
+ 128
1571
+ ]
1572
+ }
1573
+ },
1574
+ {
1575
+ name: "evidence_hash",
1576
+ type: {
1577
+ array: [
1578
+ "u8",
1579
+ 32
1580
+ ]
1581
+ }
1582
+ },
1583
+ {
1584
+ name: "response_uri",
1585
+ type: {
1586
+ array: [
1587
+ "u8",
1588
+ 128
1589
+ ]
1590
+ }
1591
+ },
1592
+ {
1593
+ name: "response_hash",
1594
+ type: {
1595
+ array: [
1596
+ "u8",
1597
+ 32
1598
+ ]
1599
+ }
1600
+ },
1601
+ {
1602
+ name: "has_response",
1603
+ type: "bool"
1604
+ },
1605
+ {
1606
+ name: "revoked",
1607
+ type: "bool"
1608
+ },
1609
+ {
1610
+ name: "created_slot",
1611
+ type: "u64"
1612
+ },
1613
+ {
1614
+ name: "last_modified_slot",
1615
+ type: "u64"
1616
+ },
1617
+ {
1618
+ name: "bump",
1619
+ type: "u8"
1620
+ },
1621
+ {
1622
+ name: "_padding",
1623
+ type: {
1624
+ array: [
1625
+ "u8",
1626
+ 64
1627
+ ]
1628
+ }
1629
+ }
1630
+ ]
1631
+ }
1632
+ },
1633
+ {
1634
+ name: "FeedbackRevoked",
1635
+ type: {
1636
+ kind: "struct",
1637
+ fields: [
1638
+ {
1639
+ name: "agent",
1640
+ type: "pubkey"
1641
+ },
1642
+ {
1643
+ name: "service",
1644
+ type: "pubkey"
1645
+ },
1646
+ {
1647
+ name: "feedback",
1648
+ type: "pubkey"
1649
+ },
1650
+ {
1651
+ name: "was_negative",
1652
+ type: "bool"
1653
+ },
1654
+ {
1655
+ name: "slot",
1656
+ type: "u64"
1657
+ }
1658
+ ]
1659
+ }
1660
+ },
1661
+ {
1662
+ name: "PaymentRecorded",
1663
+ type: {
1664
+ kind: "struct",
1665
+ fields: [
1666
+ {
1667
+ name: "agent",
1668
+ type: "pubkey"
1669
+ },
1670
+ {
1671
+ name: "service",
1672
+ type: "pubkey"
1673
+ },
1674
+ {
1675
+ name: "amount_usdc",
1676
+ type: "u64"
1677
+ },
1678
+ {
1679
+ name: "payment_receipt_hash",
1680
+ type: {
1681
+ array: [
1682
+ "u8",
1683
+ 32
1684
+ ]
1685
+ }
1686
+ },
1687
+ {
1688
+ name: "was_new_pair",
1689
+ type: "bool"
1690
+ },
1691
+ {
1692
+ name: "slot",
1693
+ type: "u64"
1694
+ }
1695
+ ]
1696
+ }
1697
+ },
1698
+ {
1699
+ name: "ReceiptUsed",
1700
+ type: {
1701
+ kind: "struct",
1702
+ fields: [
1703
+ {
1704
+ name: "receipt_hash",
1705
+ type: {
1706
+ array: [
1707
+ "u8",
1708
+ 32
1709
+ ]
1710
+ }
1711
+ },
1712
+ {
1713
+ name: "agent_service_link",
1714
+ type: "pubkey"
1715
+ },
1716
+ {
1717
+ name: "recorded_slot",
1718
+ type: "u64"
1719
+ },
1720
+ {
1721
+ name: "bump",
1722
+ type: "u8"
1723
+ },
1724
+ {
1725
+ name: "_padding",
1726
+ type: {
1727
+ array: [
1728
+ "u8",
1729
+ 32
1730
+ ]
1731
+ }
1732
+ }
1733
+ ]
1734
+ }
1735
+ },
1736
+ {
1737
+ name: "ResponseAppended",
1738
+ type: {
1739
+ kind: "struct",
1740
+ fields: [
1741
+ {
1742
+ name: "agent",
1743
+ type: "pubkey"
1744
+ },
1745
+ {
1746
+ name: "feedback",
1747
+ type: "pubkey"
1748
+ },
1749
+ {
1750
+ name: "responder",
1751
+ type: "pubkey"
1752
+ },
1753
+ {
1754
+ name: "slot",
1755
+ type: "u64"
1756
+ }
1757
+ ]
1758
+ }
1759
+ },
1760
+ {
1761
+ name: "ScoreComputed",
1762
+ type: {
1763
+ kind: "struct",
1764
+ fields: [
1765
+ {
1766
+ name: "agent",
1767
+ type: "pubkey"
1768
+ },
1769
+ {
1770
+ name: "score",
1771
+ type: "u16"
1772
+ },
1773
+ {
1774
+ name: "slot",
1775
+ type: "u64"
1776
+ }
1777
+ ]
1778
+ }
1779
+ },
1780
+ {
1781
+ name: "ServiceActiveSet",
1782
+ type: {
1783
+ kind: "struct",
1784
+ fields: [
1785
+ {
1786
+ name: "service",
1787
+ type: "pubkey"
1788
+ },
1789
+ {
1790
+ name: "active",
1791
+ type: "bool"
1792
+ },
1793
+ {
1794
+ name: "slot",
1795
+ type: "u64"
1796
+ }
1797
+ ]
1798
+ }
1799
+ },
1800
+ {
1801
+ name: "ServiceCategory",
1802
+ type: {
1803
+ kind: "enum",
1804
+ variants: [
1805
+ {
1806
+ name: "DataFeed"
1807
+ },
1808
+ {
1809
+ name: "Compute"
1810
+ },
1811
+ {
1812
+ name: "Swap"
1813
+ },
1814
+ {
1815
+ name: "Rpc"
1816
+ },
1817
+ {
1818
+ name: "Other"
1819
+ }
1820
+ ]
1821
+ }
1822
+ },
1823
+ {
1824
+ name: "ServiceRegistered",
1825
+ type: {
1826
+ kind: "struct",
1827
+ fields: [
1828
+ {
1829
+ name: "service",
1830
+ type: "pubkey"
1831
+ },
1832
+ {
1833
+ name: "sponsor",
1834
+ docs: [
1835
+ 'Wallet that paid rent. Lets us answer "who registered this service?"',
1836
+ "without an extra column on the on-chain account."
1837
+ ],
1838
+ type: "pubkey"
1839
+ },
1840
+ {
1841
+ name: "name",
1842
+ type: {
1843
+ array: [
1844
+ "u8",
1845
+ 32
1846
+ ]
1847
+ }
1848
+ },
1849
+ {
1850
+ name: "category",
1851
+ type: {
1852
+ defined: {
1853
+ name: "ServiceCategory"
1854
+ }
1855
+ }
1856
+ },
1857
+ {
1858
+ name: "init_slot",
1859
+ type: "u64"
1860
+ }
1861
+ ]
1862
+ }
1863
+ },
1864
+ {
1865
+ name: "ServiceRegistry",
1866
+ type: {
1867
+ kind: "struct",
1868
+ fields: [
1869
+ {
1870
+ name: "authority",
1871
+ type: "pubkey"
1872
+ },
1873
+ {
1874
+ name: "name",
1875
+ type: {
1876
+ array: [
1877
+ "u8",
1878
+ 32
1879
+ ]
1880
+ }
1881
+ },
1882
+ {
1883
+ name: "service_uri",
1884
+ docs: [
1885
+ "Off-chain metadata URI (pricing, docs, endpoint, logo). Padded to 128 bytes;",
1886
+ "trailing NULs are trimmed when read. Mirrors `AgentProfile::agent_uri`."
1887
+ ],
1888
+ type: {
1889
+ array: [
1890
+ "u8",
1891
+ 128
1892
+ ]
1893
+ }
1894
+ },
1895
+ {
1896
+ name: "category",
1897
+ type: {
1898
+ defined: {
1899
+ name: "ServiceCategory"
1900
+ }
1901
+ }
1902
+ },
1903
+ {
1904
+ name: "total_agents_served",
1905
+ type: "u64"
1906
+ },
1907
+ {
1908
+ name: "total_volume_received_usdc",
1909
+ type: "u64"
1910
+ },
1911
+ {
1912
+ name: "active",
1913
+ type: "bool"
1914
+ },
1915
+ {
1916
+ name: "first_active_slot",
1917
+ type: "u64"
1918
+ },
1919
+ {
1920
+ name: "last_active_slot",
1921
+ type: "u64"
1922
+ },
1923
+ {
1924
+ name: "bump",
1925
+ type: "u8"
1926
+ },
1927
+ {
1928
+ name: "_padding",
1929
+ type: {
1930
+ array: [
1931
+ "u8",
1932
+ 64
1933
+ ]
1934
+ }
1935
+ }
1936
+ ]
1937
+ }
1938
+ }
1939
+ ]
1940
+ };
1941
+
1942
+ // src/idl/credit-vault.json
1943
+ var credit_vault_default = {
1944
+ address: "EsykPsafhHUeN7jA9DGqBiGuBsTBaFynLDVVpE4jFXDg",
1945
+ metadata: {
1946
+ name: "credit_vault",
1947
+ version: "0.1.0",
1948
+ spec: "0.1.0",
1949
+ description: "Agent Fuel \u2014 Budget-bound USDC spending vault for AI agents on Solana",
1950
+ repository: "https://github.com/TODO/agent_fuel"
1951
+ },
1952
+ instructions: [
1953
+ {
1954
+ name: "approve_spend",
1955
+ discriminator: [
1956
+ 248,
1957
+ 201,
1958
+ 151,
1959
+ 15,
1960
+ 28,
1961
+ 162,
1962
+ 112,
1963
+ 90
1964
+ ],
1965
+ accounts: [
1966
+ {
1967
+ name: "owner",
1968
+ writable: true,
1969
+ signer: true,
1970
+ relations: [
1971
+ "vault"
1972
+ ]
1973
+ },
1974
+ {
1975
+ name: "vault",
1976
+ writable: true,
1977
+ pda: {
1978
+ seeds: [
1979
+ {
1980
+ kind: "const",
1981
+ value: [
1982
+ 118,
1983
+ 97,
1984
+ 117,
1985
+ 108,
1986
+ 116
1987
+ ]
1988
+ },
1989
+ {
1990
+ kind: "account",
1991
+ path: "owner"
1992
+ },
1993
+ {
1994
+ kind: "account",
1995
+ path: "vault.agent",
1996
+ account: "CreditVault"
1997
+ }
1998
+ ]
1999
+ }
2000
+ },
2001
+ {
2002
+ name: "policy",
2003
+ writable: true,
2004
+ pda: {
2005
+ seeds: [
2006
+ {
2007
+ kind: "const",
2008
+ value: [
2009
+ 112,
2010
+ 111,
2011
+ 108,
2012
+ 105,
2013
+ 99,
2014
+ 121
2015
+ ]
2016
+ },
2017
+ {
2018
+ kind: "account",
2019
+ path: "vault"
2020
+ }
2021
+ ]
2022
+ }
2023
+ },
2024
+ {
2025
+ name: "pending_spend",
2026
+ writable: true,
2027
+ pda: {
2028
+ seeds: [
2029
+ {
2030
+ kind: "const",
2031
+ value: [
2032
+ 112,
2033
+ 101,
2034
+ 110,
2035
+ 100,
2036
+ 105,
2037
+ 110,
2038
+ 103
2039
+ ]
2040
+ },
2041
+ {
2042
+ kind: "account",
2043
+ path: "vault"
2044
+ },
2045
+ {
2046
+ kind: "account",
2047
+ path: "pending_spend.nonce",
2048
+ account: "PendingSpend"
2049
+ }
2050
+ ]
2051
+ }
2052
+ },
2053
+ {
2054
+ name: "vault_token_account",
2055
+ writable: true
2056
+ },
2057
+ {
2058
+ name: "service_token_account",
2059
+ writable: true
2060
+ },
2061
+ {
2062
+ name: "token_program",
2063
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2064
+ }
2065
+ ],
2066
+ args: []
2067
+ },
2068
+ {
2069
+ name: "cancel_spend",
2070
+ discriminator: [
2071
+ 122,
2072
+ 254,
2073
+ 101,
2074
+ 132,
2075
+ 241,
2076
+ 232,
2077
+ 205,
2078
+ 179
2079
+ ],
2080
+ accounts: [
2081
+ {
2082
+ name: "owner",
2083
+ writable: true,
2084
+ signer: true,
2085
+ relations: [
2086
+ "vault"
2087
+ ]
2088
+ },
2089
+ {
2090
+ name: "vault",
2091
+ pda: {
2092
+ seeds: [
2093
+ {
2094
+ kind: "const",
2095
+ value: [
2096
+ 118,
2097
+ 97,
2098
+ 117,
2099
+ 108,
2100
+ 116
2101
+ ]
2102
+ },
2103
+ {
2104
+ kind: "account",
2105
+ path: "owner"
2106
+ },
2107
+ {
2108
+ kind: "account",
2109
+ path: "vault.agent",
2110
+ account: "CreditVault"
2111
+ }
2112
+ ]
2113
+ }
2114
+ },
2115
+ {
2116
+ name: "pending_spend",
2117
+ writable: true,
2118
+ pda: {
2119
+ seeds: [
2120
+ {
2121
+ kind: "const",
2122
+ value: [
2123
+ 112,
2124
+ 101,
2125
+ 110,
2126
+ 100,
2127
+ 105,
2128
+ 110,
2129
+ 103
2130
+ ]
2131
+ },
2132
+ {
2133
+ kind: "account",
2134
+ path: "vault"
2135
+ },
2136
+ {
2137
+ kind: "account",
2138
+ path: "pending_spend.nonce",
2139
+ account: "PendingSpend"
2140
+ }
2141
+ ]
2142
+ }
2143
+ }
2144
+ ],
2145
+ args: []
2146
+ },
2147
+ {
2148
+ name: "claim",
2149
+ discriminator: [
2150
+ 62,
2151
+ 198,
2152
+ 214,
2153
+ 193,
2154
+ 213,
2155
+ 159,
2156
+ 108,
2157
+ 210
2158
+ ],
2159
+ accounts: [
2160
+ {
2161
+ name: "service",
2162
+ signer: true
2163
+ },
2164
+ {
2165
+ name: "vault",
2166
+ writable: true,
2167
+ pda: {
2168
+ seeds: [
2169
+ {
2170
+ kind: "const",
2171
+ value: [
2172
+ 118,
2173
+ 97,
2174
+ 117,
2175
+ 108,
2176
+ 116
2177
+ ]
2178
+ },
2179
+ {
2180
+ kind: "account",
2181
+ path: "vault.owner",
2182
+ account: "CreditVault"
2183
+ },
2184
+ {
2185
+ kind: "account",
2186
+ path: "vault.agent",
2187
+ account: "CreditVault"
2188
+ }
2189
+ ]
2190
+ }
2191
+ },
2192
+ {
2193
+ name: "policy",
2194
+ writable: true,
2195
+ pda: {
2196
+ seeds: [
2197
+ {
2198
+ kind: "const",
2199
+ value: [
2200
+ 112,
2201
+ 111,
2202
+ 108,
2203
+ 105,
2204
+ 99,
2205
+ 121
2206
+ ]
2207
+ },
2208
+ {
2209
+ kind: "account",
2210
+ path: "vault"
2211
+ }
2212
+ ]
2213
+ }
2214
+ },
2215
+ {
2216
+ name: "vault_token_account",
2217
+ writable: true
2218
+ },
2219
+ {
2220
+ name: "service_token_account",
2221
+ writable: true
2222
+ },
2223
+ {
2224
+ name: "token_program",
2225
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2226
+ }
2227
+ ],
2228
+ args: [
2229
+ {
2230
+ name: "amount_usdc",
2231
+ type: "u64"
2232
+ }
2233
+ ]
2234
+ },
2235
+ {
2236
+ name: "create_vault",
2237
+ discriminator: [
2238
+ 29,
2239
+ 237,
2240
+ 247,
2241
+ 208,
2242
+ 193,
2243
+ 82,
2244
+ 54,
2245
+ 135
2246
+ ],
2247
+ accounts: [
2248
+ {
2249
+ name: "owner",
2250
+ writable: true,
2251
+ signer: true
2252
+ },
2253
+ {
2254
+ name: "agent",
2255
+ docs: [
2256
+ "account need not exist on chain; we never read or write its data."
2257
+ ]
2258
+ },
2259
+ {
2260
+ name: "usdc_mint"
2261
+ },
2262
+ {
2263
+ name: "vault",
2264
+ writable: true,
2265
+ pda: {
2266
+ seeds: [
2267
+ {
2268
+ kind: "const",
2269
+ value: [
2270
+ 118,
2271
+ 97,
2272
+ 117,
2273
+ 108,
2274
+ 116
2275
+ ]
2276
+ },
2277
+ {
2278
+ kind: "account",
2279
+ path: "owner"
2280
+ },
2281
+ {
2282
+ kind: "account",
2283
+ path: "agent"
2284
+ }
2285
+ ]
2286
+ }
2287
+ },
2288
+ {
2289
+ name: "policy",
2290
+ writable: true,
2291
+ pda: {
2292
+ seeds: [
2293
+ {
2294
+ kind: "const",
2295
+ value: [
2296
+ 112,
2297
+ 111,
2298
+ 108,
2299
+ 105,
2300
+ 99,
2301
+ 121
2302
+ ]
2303
+ },
2304
+ {
2305
+ kind: "account",
2306
+ path: "vault"
2307
+ }
2308
+ ]
2309
+ }
2310
+ },
2311
+ {
2312
+ name: "vault_token_account",
2313
+ writable: true,
2314
+ pda: {
2315
+ seeds: [
2316
+ {
2317
+ kind: "account",
2318
+ path: "vault"
2319
+ },
2320
+ {
2321
+ kind: "const",
2322
+ value: [
2323
+ 6,
2324
+ 221,
2325
+ 246,
2326
+ 225,
2327
+ 215,
2328
+ 101,
2329
+ 161,
2330
+ 147,
2331
+ 217,
2332
+ 203,
2333
+ 225,
2334
+ 70,
2335
+ 206,
2336
+ 235,
2337
+ 121,
2338
+ 172,
2339
+ 28,
2340
+ 180,
2341
+ 133,
2342
+ 237,
2343
+ 95,
2344
+ 91,
2345
+ 55,
2346
+ 145,
2347
+ 58,
2348
+ 140,
2349
+ 245,
2350
+ 133,
2351
+ 126,
2352
+ 255,
2353
+ 0,
2354
+ 169
2355
+ ]
2356
+ },
2357
+ {
2358
+ kind: "account",
2359
+ path: "usdc_mint"
2360
+ }
2361
+ ],
2362
+ program: {
2363
+ kind: "const",
2364
+ value: [
2365
+ 140,
2366
+ 151,
2367
+ 37,
2368
+ 143,
2369
+ 78,
2370
+ 36,
2371
+ 137,
2372
+ 241,
2373
+ 187,
2374
+ 61,
2375
+ 16,
2376
+ 41,
2377
+ 20,
2378
+ 142,
2379
+ 13,
2380
+ 131,
2381
+ 11,
2382
+ 90,
2383
+ 19,
2384
+ 153,
2385
+ 218,
2386
+ 255,
2387
+ 16,
2388
+ 132,
2389
+ 4,
2390
+ 142,
2391
+ 123,
2392
+ 216,
2393
+ 219,
2394
+ 233,
2395
+ 248,
2396
+ 89
2397
+ ]
2398
+ }
2399
+ }
2400
+ },
2401
+ {
2402
+ name: "token_program",
2403
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2404
+ },
2405
+ {
2406
+ name: "associated_token_program",
2407
+ address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
2408
+ },
2409
+ {
2410
+ name: "system_program",
2411
+ address: "11111111111111111111111111111111"
2412
+ }
2413
+ ],
2414
+ args: [
2415
+ {
2416
+ name: "per_tx_limit_usdc",
2417
+ type: "u64"
2418
+ },
2419
+ {
2420
+ name: "hourly_limit_usdc",
2421
+ type: "u64"
2422
+ },
2423
+ {
2424
+ name: "lifetime_limit_usdc",
2425
+ type: "u64"
2426
+ },
2427
+ {
2428
+ name: "allow_post_pay",
2429
+ type: "bool"
2430
+ }
2431
+ ]
2432
+ },
2433
+ {
2434
+ name: "deposit",
2435
+ discriminator: [
2436
+ 242,
2437
+ 35,
2438
+ 198,
2439
+ 137,
2440
+ 82,
2441
+ 225,
2442
+ 242,
2443
+ 182
2444
+ ],
2445
+ accounts: [
2446
+ {
2447
+ name: "owner",
2448
+ writable: true,
2449
+ signer: true,
2450
+ relations: [
2451
+ "vault"
2452
+ ]
2453
+ },
2454
+ {
2455
+ name: "vault",
2456
+ writable: true,
2457
+ pda: {
2458
+ seeds: [
2459
+ {
2460
+ kind: "const",
2461
+ value: [
2462
+ 118,
2463
+ 97,
2464
+ 117,
2465
+ 108,
2466
+ 116
2467
+ ]
2468
+ },
2469
+ {
2470
+ kind: "account",
2471
+ path: "vault.owner",
2472
+ account: "CreditVault"
2473
+ },
2474
+ {
2475
+ kind: "account",
2476
+ path: "vault.agent",
2477
+ account: "CreditVault"
2478
+ }
2479
+ ]
2480
+ }
2481
+ },
2482
+ {
2483
+ name: "owner_token_account",
2484
+ writable: true
2485
+ },
2486
+ {
2487
+ name: "vault_token_account",
2488
+ writable: true
2489
+ },
2490
+ {
2491
+ name: "token_program",
2492
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2493
+ }
2494
+ ],
2495
+ args: [
2496
+ {
2497
+ name: "amount_usdc",
2498
+ type: "u64"
2499
+ }
2500
+ ]
2501
+ },
2502
+ {
2503
+ name: "freeze_vault",
2504
+ discriminator: [
2505
+ 144,
2506
+ 211,
2507
+ 63,
2508
+ 236,
2509
+ 97,
2510
+ 31,
2511
+ 170,
2512
+ 175
2513
+ ],
2514
+ accounts: [
2515
+ {
2516
+ name: "owner",
2517
+ signer: true,
2518
+ relations: [
2519
+ "vault"
2520
+ ]
2521
+ },
2522
+ {
2523
+ name: "vault",
2524
+ writable: true,
2525
+ pda: {
2526
+ seeds: [
2527
+ {
2528
+ kind: "const",
2529
+ value: [
2530
+ 118,
2531
+ 97,
2532
+ 117,
2533
+ 108,
2534
+ 116
2535
+ ]
2536
+ },
2537
+ {
2538
+ kind: "account",
2539
+ path: "vault.owner",
2540
+ account: "CreditVault"
2541
+ },
2542
+ {
2543
+ kind: "account",
2544
+ path: "vault.agent",
2545
+ account: "CreditVault"
2546
+ }
2547
+ ]
2548
+ }
2549
+ }
2550
+ ],
2551
+ args: []
2552
+ },
2553
+ {
2554
+ name: "request_spend",
2555
+ discriminator: [
2556
+ 127,
2557
+ 12,
2558
+ 23,
2559
+ 75,
2560
+ 137,
2561
+ 178,
2562
+ 148,
2563
+ 71
2564
+ ],
2565
+ accounts: [
2566
+ {
2567
+ name: "agent",
2568
+ writable: true,
2569
+ signer: true,
2570
+ relations: [
2571
+ "vault"
2572
+ ]
2573
+ },
2574
+ {
2575
+ name: "vault",
2576
+ writable: true,
2577
+ pda: {
2578
+ seeds: [
2579
+ {
2580
+ kind: "const",
2581
+ value: [
2582
+ 118,
2583
+ 97,
2584
+ 117,
2585
+ 108,
2586
+ 116
2587
+ ]
2588
+ },
2589
+ {
2590
+ kind: "account",
2591
+ path: "vault.owner",
2592
+ account: "CreditVault"
2593
+ },
2594
+ {
2595
+ kind: "account",
2596
+ path: "vault.agent",
2597
+ account: "CreditVault"
2598
+ }
2599
+ ]
2600
+ }
2601
+ },
2602
+ {
2603
+ name: "service_token_account",
2604
+ docs: [
2605
+ "The recipient token account. We only need it for its `owner` field",
2606
+ "(the service pubkey we record in PendingSpend); mint constraint is",
2607
+ "belt-and-suspenders since `approve_spend` re-checks both."
2608
+ ]
2609
+ },
2610
+ {
2611
+ name: "pending_spend",
2612
+ writable: true,
2613
+ pda: {
2614
+ seeds: [
2615
+ {
2616
+ kind: "const",
2617
+ value: [
2618
+ 112,
2619
+ 101,
2620
+ 110,
2621
+ 100,
2622
+ 105,
2623
+ 110,
2624
+ 103
2625
+ ]
2626
+ },
2627
+ {
2628
+ kind: "account",
2629
+ path: "vault"
2630
+ },
2631
+ {
2632
+ kind: "account",
2633
+ path: "vault.pending_count",
2634
+ account: "CreditVault"
2635
+ }
2636
+ ]
2637
+ }
2638
+ },
2639
+ {
2640
+ name: "system_program",
2641
+ address: "11111111111111111111111111111111"
2642
+ }
2643
+ ],
2644
+ args: [
2645
+ {
2646
+ name: "amount_usdc",
2647
+ type: "u64"
2648
+ }
2649
+ ]
2650
+ },
2651
+ {
2652
+ name: "spend",
2653
+ discriminator: [
2654
+ 242,
2655
+ 205,
2656
+ 255,
2657
+ 87,
2658
+ 101,
2659
+ 217,
2660
+ 245,
2661
+ 57
2662
+ ],
2663
+ accounts: [
2664
+ {
2665
+ name: "agent",
2666
+ signer: true,
2667
+ relations: [
2668
+ "vault"
2669
+ ]
2670
+ },
2671
+ {
2672
+ name: "vault",
2673
+ writable: true,
2674
+ pda: {
2675
+ seeds: [
2676
+ {
2677
+ kind: "const",
2678
+ value: [
2679
+ 118,
2680
+ 97,
2681
+ 117,
2682
+ 108,
2683
+ 116
2684
+ ]
2685
+ },
2686
+ {
2687
+ kind: "account",
2688
+ path: "vault.owner",
2689
+ account: "CreditVault"
2690
+ },
2691
+ {
2692
+ kind: "account",
2693
+ path: "vault.agent",
2694
+ account: "CreditVault"
2695
+ }
2696
+ ]
2697
+ }
2698
+ },
2699
+ {
2700
+ name: "policy",
2701
+ writable: true,
2702
+ pda: {
2703
+ seeds: [
2704
+ {
2705
+ kind: "const",
2706
+ value: [
2707
+ 112,
2708
+ 111,
2709
+ 108,
2710
+ 105,
2711
+ 99,
2712
+ 121
2713
+ ]
2714
+ },
2715
+ {
2716
+ kind: "account",
2717
+ path: "vault"
2718
+ }
2719
+ ]
2720
+ }
2721
+ },
2722
+ {
2723
+ name: "vault_token_account",
2724
+ writable: true
2725
+ },
2726
+ {
2727
+ name: "service_token_account",
2728
+ writable: true
2729
+ },
2730
+ {
2731
+ name: "token_program",
2732
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2733
+ }
2734
+ ],
2735
+ args: [
2736
+ {
2737
+ name: "amount_usdc",
2738
+ type: "u64"
2739
+ }
2740
+ ]
2741
+ },
2742
+ {
2743
+ name: "unfreeze_vault",
2744
+ discriminator: [
2745
+ 145,
2746
+ 244,
2747
+ 206,
2748
+ 234,
2749
+ 251,
2750
+ 250,
2751
+ 116,
2752
+ 183
2753
+ ],
2754
+ accounts: [
2755
+ {
2756
+ name: "owner",
2757
+ signer: true,
2758
+ relations: [
2759
+ "vault"
2760
+ ]
2761
+ },
2762
+ {
2763
+ name: "vault",
2764
+ writable: true,
2765
+ pda: {
2766
+ seeds: [
2767
+ {
2768
+ kind: "const",
2769
+ value: [
2770
+ 118,
2771
+ 97,
2772
+ 117,
2773
+ 108,
2774
+ 116
2775
+ ]
2776
+ },
2777
+ {
2778
+ kind: "account",
2779
+ path: "vault.owner",
2780
+ account: "CreditVault"
2781
+ },
2782
+ {
2783
+ kind: "account",
2784
+ path: "vault.agent",
2785
+ account: "CreditVault"
2786
+ }
2787
+ ]
2788
+ }
2789
+ }
2790
+ ],
2791
+ args: []
2792
+ },
2793
+ {
2794
+ name: "update_policy",
2795
+ discriminator: [
2796
+ 212,
2797
+ 245,
2798
+ 246,
2799
+ 7,
2800
+ 163,
2801
+ 151,
2802
+ 18,
2803
+ 57
2804
+ ],
2805
+ accounts: [
2806
+ {
2807
+ name: "owner",
2808
+ signer: true,
2809
+ relations: [
2810
+ "vault"
2811
+ ]
2812
+ },
2813
+ {
2814
+ name: "vault",
2815
+ pda: {
2816
+ seeds: [
2817
+ {
2818
+ kind: "const",
2819
+ value: [
2820
+ 118,
2821
+ 97,
2822
+ 117,
2823
+ 108,
2824
+ 116
2825
+ ]
2826
+ },
2827
+ {
2828
+ kind: "account",
2829
+ path: "vault.owner",
2830
+ account: "CreditVault"
2831
+ },
2832
+ {
2833
+ kind: "account",
2834
+ path: "vault.agent",
2835
+ account: "CreditVault"
2836
+ }
2837
+ ]
2838
+ }
2839
+ },
2840
+ {
2841
+ name: "policy",
2842
+ writable: true,
2843
+ pda: {
2844
+ seeds: [
2845
+ {
2846
+ kind: "const",
2847
+ value: [
2848
+ 112,
2849
+ 111,
2850
+ 108,
2851
+ 105,
2852
+ 99,
2853
+ 121
2854
+ ]
2855
+ },
2856
+ {
2857
+ kind: "account",
2858
+ path: "vault"
2859
+ }
2860
+ ]
2861
+ }
2862
+ }
2863
+ ],
2864
+ args: [
2865
+ {
2866
+ name: "new_per_tx_limit_usdc",
2867
+ type: "u64"
2868
+ },
2869
+ {
2870
+ name: "new_hourly_limit_usdc",
2871
+ type: "u64"
2872
+ },
2873
+ {
2874
+ name: "new_lifetime_limit_usdc",
2875
+ type: "u64"
2876
+ },
2877
+ {
2878
+ name: "new_allow_post_pay",
2879
+ type: "bool"
2880
+ },
2881
+ {
2882
+ name: "new_whitelist",
2883
+ type: {
2884
+ array: [
2885
+ "pubkey",
2886
+ 8
2887
+ ]
2888
+ }
2889
+ }
2890
+ ]
2891
+ },
2892
+ {
2893
+ name: "withdraw",
2894
+ discriminator: [
2895
+ 183,
2896
+ 18,
2897
+ 70,
2898
+ 156,
2899
+ 148,
2900
+ 109,
2901
+ 161,
2902
+ 34
2903
+ ],
2904
+ accounts: [
2905
+ {
2906
+ name: "owner",
2907
+ writable: true,
2908
+ signer: true,
2909
+ relations: [
2910
+ "vault"
2911
+ ]
2912
+ },
2913
+ {
2914
+ name: "vault",
2915
+ writable: true,
2916
+ pda: {
2917
+ seeds: [
2918
+ {
2919
+ kind: "const",
2920
+ value: [
2921
+ 118,
2922
+ 97,
2923
+ 117,
2924
+ 108,
2925
+ 116
2926
+ ]
2927
+ },
2928
+ {
2929
+ kind: "account",
2930
+ path: "vault.owner",
2931
+ account: "CreditVault"
2932
+ },
2933
+ {
2934
+ kind: "account",
2935
+ path: "vault.agent",
2936
+ account: "CreditVault"
2937
+ }
2938
+ ]
2939
+ }
2940
+ },
2941
+ {
2942
+ name: "vault_token_account",
2943
+ writable: true
2944
+ },
2945
+ {
2946
+ name: "owner_token_account",
2947
+ writable: true
2948
+ },
2949
+ {
2950
+ name: "token_program",
2951
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2952
+ }
2953
+ ],
2954
+ args: [
2955
+ {
2956
+ name: "amount_usdc",
2957
+ type: "u64"
2958
+ }
2959
+ ]
2960
+ }
2961
+ ],
2962
+ accounts: [
2963
+ {
2964
+ name: "CreditVault",
2965
+ discriminator: [
2966
+ 143,
2967
+ 180,
2968
+ 135,
2969
+ 248,
2970
+ 84,
2971
+ 85,
2972
+ 183,
2973
+ 70
2974
+ ]
2975
+ },
2976
+ {
2977
+ name: "PendingSpend",
2978
+ discriminator: [
2979
+ 193,
2980
+ 205,
2981
+ 85,
2982
+ 66,
2983
+ 25,
2984
+ 3,
2985
+ 67,
2986
+ 134
2987
+ ]
2988
+ },
2989
+ {
2990
+ name: "SpendPolicy",
2991
+ discriminator: [
2992
+ 139,
2993
+ 90,
2994
+ 209,
2995
+ 31,
2996
+ 205,
2997
+ 15,
2998
+ 68,
2999
+ 243
3000
+ ]
3001
+ }
3002
+ ],
3003
+ events: [
3004
+ {
3005
+ name: "Claimed",
3006
+ discriminator: [
3007
+ 217,
3008
+ 192,
3009
+ 123,
3010
+ 72,
3011
+ 108,
3012
+ 150,
3013
+ 248,
3014
+ 33
3015
+ ]
3016
+ },
3017
+ {
3018
+ name: "Deposited",
3019
+ discriminator: [
3020
+ 111,
3021
+ 141,
3022
+ 26,
3023
+ 45,
3024
+ 161,
3025
+ 35,
3026
+ 100,
3027
+ 57
3028
+ ]
3029
+ },
3030
+ {
3031
+ name: "PolicyUpdated",
3032
+ discriminator: [
3033
+ 225,
3034
+ 112,
3035
+ 112,
3036
+ 67,
3037
+ 95,
3038
+ 236,
3039
+ 245,
3040
+ 161
3041
+ ]
3042
+ },
3043
+ {
3044
+ name: "SpendRejected",
3045
+ discriminator: [
3046
+ 22,
3047
+ 233,
3048
+ 208,
3049
+ 109,
3050
+ 202,
3051
+ 231,
3052
+ 175,
3053
+ 22
3054
+ ]
3055
+ },
3056
+ {
3057
+ name: "SpendRequested",
3058
+ discriminator: [
3059
+ 144,
3060
+ 207,
3061
+ 254,
3062
+ 247,
3063
+ 81,
3064
+ 146,
3065
+ 84,
3066
+ 87
3067
+ ]
3068
+ },
3069
+ {
3070
+ name: "Spent",
3071
+ discriminator: [
3072
+ 43,
3073
+ 51,
3074
+ 164,
3075
+ 100,
3076
+ 191,
3077
+ 244,
3078
+ 174,
3079
+ 98
3080
+ ]
3081
+ },
3082
+ {
3083
+ name: "VaultCreated",
3084
+ discriminator: [
3085
+ 117,
3086
+ 25,
3087
+ 120,
3088
+ 254,
3089
+ 75,
3090
+ 236,
3091
+ 78,
3092
+ 115
3093
+ ]
3094
+ },
3095
+ {
3096
+ name: "VaultFrozen",
3097
+ discriminator: [
3098
+ 13,
3099
+ 199,
3100
+ 172,
3101
+ 111,
3102
+ 88,
3103
+ 10,
3104
+ 151,
3105
+ 247
3106
+ ]
3107
+ },
3108
+ {
3109
+ name: "VaultUnfrozen",
3110
+ discriminator: [
3111
+ 128,
3112
+ 194,
3113
+ 79,
3114
+ 155,
3115
+ 85,
3116
+ 31,
3117
+ 226,
3118
+ 170
3119
+ ]
3120
+ },
3121
+ {
3122
+ name: "Withdrawn",
3123
+ discriminator: [
3124
+ 20,
3125
+ 89,
3126
+ 223,
3127
+ 198,
3128
+ 194,
3129
+ 124,
3130
+ 219,
3131
+ 13
3132
+ ]
3133
+ }
3134
+ ],
3135
+ errors: [
3136
+ {
3137
+ code: 6e3,
3138
+ name: "Overflow",
3139
+ msg: "Counter or amount overflow"
3140
+ },
3141
+ {
3142
+ code: 6001,
3143
+ name: "ZeroAmount",
3144
+ msg: "Amount must be greater than zero"
3145
+ },
3146
+ {
3147
+ code: 6002,
3148
+ name: "Frozen",
3149
+ msg: "Vault is frozen"
3150
+ },
3151
+ {
3152
+ code: 6003,
3153
+ name: "NotWhitelisted",
3154
+ msg: "Service is not on the vault's whitelist"
3155
+ },
3156
+ {
3157
+ code: 6004,
3158
+ name: "PerTxLimitExceeded",
3159
+ msg: "Amount exceeds the per-transaction limit"
3160
+ },
3161
+ {
3162
+ code: 6005,
3163
+ name: "HourlyLimitExceeded",
3164
+ msg: "Amount exceeds the hourly rolling-window limit"
3165
+ },
3166
+ {
3167
+ code: 6006,
3168
+ name: "LifetimeLimitExceeded",
3169
+ msg: "Amount would exceed the lifetime spend ceiling"
3170
+ },
3171
+ {
3172
+ code: 6007,
3173
+ name: "AlreadyFrozen",
3174
+ msg: "Vault is already frozen"
3175
+ },
3176
+ {
3177
+ code: 6008,
3178
+ name: "NotFrozen",
3179
+ msg: "Vault is not frozen"
3180
+ },
3181
+ {
3182
+ code: 6009,
3183
+ name: "PostPayDisabled",
3184
+ msg: "Post-pay claims are disabled for this vault"
3185
+ },
3186
+ {
3187
+ code: 6010,
3188
+ name: "PendingSpendVaultMismatch",
3189
+ msg: "Pending spend belongs to a different vault"
3190
+ },
3191
+ {
3192
+ code: 6011,
3193
+ name: "PendingNonceOverflow",
3194
+ msg: "Pending spend counter would overflow"
3195
+ }
3196
+ ],
3197
+ types: [
3198
+ {
3199
+ name: "Claimed",
3200
+ type: {
3201
+ kind: "struct",
3202
+ fields: [
3203
+ {
3204
+ name: "vault",
3205
+ type: "pubkey"
3206
+ },
3207
+ {
3208
+ name: "service",
3209
+ type: "pubkey"
3210
+ },
3211
+ {
3212
+ name: "amount_usdc",
3213
+ type: "u64"
3214
+ },
3215
+ {
3216
+ name: "new_total_spent",
3217
+ type: "u64"
3218
+ },
3219
+ {
3220
+ name: "new_total_claimed",
3221
+ type: "u64"
3222
+ },
3223
+ {
3224
+ name: "slot",
3225
+ type: "u64"
3226
+ }
3227
+ ]
3228
+ }
3229
+ },
3230
+ {
3231
+ name: "CreditVault",
3232
+ type: {
3233
+ kind: "struct",
3234
+ fields: [
3235
+ {
3236
+ name: "owner",
3237
+ type: "pubkey"
3238
+ },
3239
+ {
3240
+ name: "agent",
3241
+ type: "pubkey"
3242
+ },
3243
+ {
3244
+ name: "usdc_mint",
3245
+ type: "pubkey"
3246
+ },
3247
+ {
3248
+ name: "vault_token_account",
3249
+ type: "pubkey"
3250
+ },
3251
+ {
3252
+ name: "total_deposited",
3253
+ type: "u64"
3254
+ },
3255
+ {
3256
+ name: "total_withdrawn",
3257
+ type: "u64"
3258
+ },
3259
+ {
3260
+ name: "total_spent",
3261
+ type: "u64"
3262
+ },
3263
+ {
3264
+ name: "total_claimed",
3265
+ type: "u64"
3266
+ },
3267
+ {
3268
+ name: "frozen",
3269
+ type: "bool"
3270
+ },
3271
+ {
3272
+ name: "created_slot",
3273
+ type: "u64"
3274
+ },
3275
+ {
3276
+ name: "last_active_slot",
3277
+ type: "u64"
3278
+ },
3279
+ {
3280
+ name: "bump",
3281
+ type: "u8"
3282
+ },
3283
+ {
3284
+ name: "pending_count",
3285
+ docs: [
3286
+ "Monotonic counter used as a PDA seed for PendingSpend accounts so",
3287
+ "every approval request gets a unique deterministic address.",
3288
+ "Borrowed 8 bytes from the original 64-byte padding so the account",
3289
+ "size stays at `ACCOUNT_SIZE` and existing vaults need no migration."
3290
+ ],
3291
+ type: "u64"
3292
+ },
3293
+ {
3294
+ name: "_padding",
3295
+ type: {
3296
+ array: [
3297
+ "u8",
3298
+ 56
3299
+ ]
3300
+ }
3301
+ }
3302
+ ]
3303
+ }
3304
+ },
3305
+ {
3306
+ name: "Deposited",
3307
+ type: {
3308
+ kind: "struct",
3309
+ fields: [
3310
+ {
3311
+ name: "vault",
3312
+ type: "pubkey"
3313
+ },
3314
+ {
3315
+ name: "owner",
3316
+ type: "pubkey"
3317
+ },
3318
+ {
3319
+ name: "amount_usdc",
3320
+ type: "u64"
3321
+ },
3322
+ {
3323
+ name: "new_total_deposited",
3324
+ type: "u64"
3325
+ },
3326
+ {
3327
+ name: "slot",
3328
+ type: "u64"
3329
+ }
3330
+ ]
3331
+ }
3332
+ },
3333
+ {
3334
+ name: "PendingSpend",
3335
+ docs: [
3336
+ "A spend request that exceeded one of the policy's rate limits. The agent",
3337
+ "creates this account by calling `request_spend`; the owner reviews from",
3338
+ "the mobile Alerts tab and either calls `approve_spend` (PDA-signed CPI",
3339
+ "transfer, account closed) or `cancel_spend` (account closed, no transfer).",
3340
+ "",
3341
+ 'Seeded by `["pending", vault, nonce_le]` where `nonce` is the value of',
3342
+ "`vault.pending_count` at request time, so each request has a unique",
3343
+ "deterministic address that both the agent and the owner can derive."
3344
+ ],
3345
+ type: {
3346
+ kind: "struct",
3347
+ fields: [
3348
+ {
3349
+ name: "vault",
3350
+ type: "pubkey"
3351
+ },
3352
+ {
3353
+ name: "agent",
3354
+ type: "pubkey"
3355
+ },
3356
+ {
3357
+ name: "service",
3358
+ docs: [
3359
+ "Owner of the destination token account (mirrors how `Spent` records",
3360
+ "service: `service_token_account.owner`)."
3361
+ ],
3362
+ type: "pubkey"
3363
+ },
3364
+ {
3365
+ name: "amount_usdc",
3366
+ type: "u64"
3367
+ },
3368
+ {
3369
+ name: "requested_slot",
3370
+ type: "u64"
3371
+ },
3372
+ {
3373
+ name: "nonce",
3374
+ type: "u64"
3375
+ },
3376
+ {
3377
+ name: "bump",
3378
+ type: "u8"
3379
+ },
3380
+ {
3381
+ name: "_padding",
3382
+ type: {
3383
+ array: [
3384
+ "u8",
3385
+ 31
3386
+ ]
3387
+ }
3388
+ }
3389
+ ]
3390
+ }
3391
+ },
3392
+ {
3393
+ name: "PolicyUpdated",
3394
+ type: {
3395
+ kind: "struct",
3396
+ fields: [
3397
+ {
3398
+ name: "vault",
3399
+ type: "pubkey"
3400
+ },
3401
+ {
3402
+ name: "owner",
3403
+ type: "pubkey"
3404
+ },
3405
+ {
3406
+ name: "per_tx_limit_usdc",
3407
+ type: "u64"
3408
+ },
3409
+ {
3410
+ name: "hourly_limit_usdc",
3411
+ type: "u64"
3412
+ },
3413
+ {
3414
+ name: "lifetime_limit_usdc",
3415
+ type: "u64"
3416
+ },
3417
+ {
3418
+ name: "allow_post_pay",
3419
+ type: "bool"
3420
+ },
3421
+ {
3422
+ name: "whitelist",
3423
+ type: {
3424
+ array: [
3425
+ "pubkey",
3426
+ 8
3427
+ ]
3428
+ }
3429
+ },
3430
+ {
3431
+ name: "slot",
3432
+ type: "u64"
3433
+ }
3434
+ ]
3435
+ }
3436
+ },
3437
+ {
3438
+ name: "SpendPolicy",
3439
+ type: {
3440
+ kind: "struct",
3441
+ fields: [
3442
+ {
3443
+ name: "vault",
3444
+ type: "pubkey"
3445
+ },
3446
+ {
3447
+ name: "whitelist",
3448
+ type: {
3449
+ array: [
3450
+ "pubkey",
3451
+ 8
3452
+ ]
3453
+ }
3454
+ },
3455
+ {
3456
+ name: "per_tx_limit_usdc",
3457
+ type: "u64"
3458
+ },
3459
+ {
3460
+ name: "hourly_limit_usdc",
3461
+ type: "u64"
3462
+ },
3463
+ {
3464
+ name: "lifetime_limit_usdc",
3465
+ type: "u64"
3466
+ },
3467
+ {
3468
+ name: "hourly_window_start_slot",
3469
+ type: "u64"
3470
+ },
3471
+ {
3472
+ name: "hourly_window_spent_usdc",
3473
+ type: "u64"
3474
+ },
3475
+ {
3476
+ name: "allow_post_pay",
3477
+ type: "bool"
3478
+ },
3479
+ {
3480
+ name: "bump",
3481
+ type: "u8"
3482
+ },
3483
+ {
3484
+ name: "_padding",
3485
+ type: {
3486
+ array: [
3487
+ "u8",
3488
+ 64
3489
+ ]
3490
+ }
3491
+ }
3492
+ ]
3493
+ }
3494
+ },
3495
+ {
3496
+ name: "SpendRejected",
3497
+ type: {
3498
+ kind: "struct",
3499
+ fields: [
3500
+ {
3501
+ name: "vault",
3502
+ type: "pubkey"
3503
+ },
3504
+ {
3505
+ name: "owner",
3506
+ type: "pubkey"
3507
+ },
3508
+ {
3509
+ name: "pending_spend",
3510
+ type: "pubkey"
3511
+ },
3512
+ {
3513
+ name: "nonce",
3514
+ type: "u64"
3515
+ },
3516
+ {
3517
+ name: "slot",
3518
+ type: "u64"
3519
+ }
3520
+ ]
3521
+ }
3522
+ },
3523
+ {
3524
+ name: "SpendRequested",
3525
+ type: {
3526
+ kind: "struct",
3527
+ fields: [
3528
+ {
3529
+ name: "vault",
3530
+ type: "pubkey"
3531
+ },
3532
+ {
3533
+ name: "agent",
3534
+ type: "pubkey"
3535
+ },
3536
+ {
3537
+ name: "service",
3538
+ type: "pubkey"
3539
+ },
3540
+ {
3541
+ name: "pending_spend",
3542
+ type: "pubkey"
3543
+ },
3544
+ {
3545
+ name: "amount_usdc",
3546
+ type: "u64"
3547
+ },
3548
+ {
3549
+ name: "nonce",
3550
+ type: "u64"
3551
+ },
3552
+ {
3553
+ name: "slot",
3554
+ type: "u64"
3555
+ }
3556
+ ]
3557
+ }
3558
+ },
3559
+ {
3560
+ name: "Spent",
3561
+ type: {
3562
+ kind: "struct",
3563
+ fields: [
3564
+ {
3565
+ name: "vault",
3566
+ type: "pubkey"
3567
+ },
3568
+ {
3569
+ name: "agent",
3570
+ type: "pubkey"
3571
+ },
3572
+ {
3573
+ name: "service",
3574
+ type: "pubkey"
3575
+ },
3576
+ {
3577
+ name: "amount_usdc",
3578
+ type: "u64"
3579
+ },
3580
+ {
3581
+ name: "new_total_spent",
3582
+ type: "u64"
3583
+ },
3584
+ {
3585
+ name: "slot",
3586
+ type: "u64"
3587
+ }
3588
+ ]
3589
+ }
3590
+ },
3591
+ {
3592
+ name: "VaultCreated",
3593
+ type: {
3594
+ kind: "struct",
3595
+ fields: [
3596
+ {
3597
+ name: "vault",
3598
+ type: "pubkey"
3599
+ },
3600
+ {
3601
+ name: "owner",
3602
+ type: "pubkey"
3603
+ },
3604
+ {
3605
+ name: "agent",
3606
+ type: "pubkey"
3607
+ },
3608
+ {
3609
+ name: "usdc_mint",
3610
+ type: "pubkey"
3611
+ },
3612
+ {
3613
+ name: "vault_token_account",
3614
+ type: "pubkey"
3615
+ },
3616
+ {
3617
+ name: "slot",
3618
+ type: "u64"
3619
+ }
3620
+ ]
3621
+ }
3622
+ },
3623
+ {
3624
+ name: "VaultFrozen",
3625
+ type: {
3626
+ kind: "struct",
3627
+ fields: [
3628
+ {
3629
+ name: "vault",
3630
+ type: "pubkey"
3631
+ },
3632
+ {
3633
+ name: "owner",
3634
+ type: "pubkey"
3635
+ },
3636
+ {
3637
+ name: "slot",
3638
+ type: "u64"
3639
+ }
3640
+ ]
3641
+ }
3642
+ },
3643
+ {
3644
+ name: "VaultUnfrozen",
3645
+ type: {
3646
+ kind: "struct",
3647
+ fields: [
3648
+ {
3649
+ name: "vault",
3650
+ type: "pubkey"
3651
+ },
3652
+ {
3653
+ name: "owner",
3654
+ type: "pubkey"
3655
+ },
3656
+ {
3657
+ name: "slot",
3658
+ type: "u64"
3659
+ }
3660
+ ]
3661
+ }
3662
+ },
3663
+ {
3664
+ name: "Withdrawn",
3665
+ type: {
3666
+ kind: "struct",
3667
+ fields: [
3668
+ {
3669
+ name: "vault",
3670
+ type: "pubkey"
3671
+ },
3672
+ {
3673
+ name: "owner",
3674
+ type: "pubkey"
3675
+ },
3676
+ {
3677
+ name: "amount_usdc",
3678
+ type: "u64"
3679
+ },
3680
+ {
3681
+ name: "new_total_withdrawn",
3682
+ type: "u64"
3683
+ },
3684
+ {
3685
+ name: "slot",
3686
+ type: "u64"
3687
+ }
3688
+ ]
3689
+ }
3690
+ }
3691
+ ]
3692
+ };
3693
+
3694
+ // src/program-ids.ts
3695
+ var PROGRAM_IDS = {
3696
+ reputation: new PublicKey(reputation_default.address),
3697
+ creditVault: new PublicKey(credit_vault_default.address)
3698
+ };
3699
+
3700
+ // src/pda.ts
3701
+ function toPubkey(value) {
3702
+ return value instanceof PublicKey ? value : new PublicKey(value);
3703
+ }
3704
+ function vaultPda(owner, agent) {
3705
+ const [pda] = PublicKey.findProgramAddressSync(
3706
+ [Buffer.from("vault"), toPubkey(owner).toBuffer(), toPubkey(agent).toBuffer()],
3707
+ PROGRAM_IDS.creditVault
3708
+ );
3709
+ return pda;
3710
+ }
3711
+ function policyPda(vault) {
3712
+ const [pda] = PublicKey.findProgramAddressSync(
3713
+ [Buffer.from("policy"), toPubkey(vault).toBuffer()],
3714
+ PROGRAM_IDS.creditVault
3715
+ );
3716
+ return pda;
3717
+ }
3718
+ function serviceRegistryPda(serviceAuthority) {
3719
+ const [pda] = PublicKey.findProgramAddressSync(
3720
+ [Buffer.from("service"), toPubkey(serviceAuthority).toBuffer()],
3721
+ PROGRAM_IDS.reputation
3722
+ );
3723
+ return pda;
3724
+ }
3725
+ function agentProfilePda(agent) {
3726
+ const [pda] = PublicKey.findProgramAddressSync(
3727
+ [Buffer.from("agent"), toPubkey(agent).toBuffer()],
3728
+ PROGRAM_IDS.reputation
3729
+ );
3730
+ return pda;
3731
+ }
3732
+ function agentServiceLinkPda(agentProfile, serviceRegistry) {
3733
+ const [pda] = PublicKey.findProgramAddressSync(
3734
+ [
3735
+ Buffer.from("link"),
3736
+ toPubkey(agentProfile).toBuffer(),
3737
+ toPubkey(serviceRegistry).toBuffer()
3738
+ ],
3739
+ PROGRAM_IDS.reputation
3740
+ );
3741
+ return pda;
3742
+ }
3743
+ function pendingSpendPda(vault, nonce) {
3744
+ const nonceBuf = Buffer.alloc(8);
3745
+ nonceBuf.writeBigUInt64LE(typeof nonce === "bigint" ? nonce : BigInt(nonce));
3746
+ const [pda] = PublicKey.findProgramAddressSync(
3747
+ [Buffer.from("pending"), toPubkey(vault).toBuffer(), nonceBuf],
3748
+ PROGRAM_IDS.creditVault
3749
+ );
3750
+ return pda;
3751
+ }
3752
+ function receiptUsedPda(receiptHash) {
3753
+ if (receiptHash.length !== 32) {
3754
+ throw new Error(`receiptUsedPda expects a 32-byte hash, got ${receiptHash.length}`);
3755
+ }
3756
+ const [pda] = PublicKey.findProgramAddressSync(
3757
+ [Buffer.from("receipt"), Buffer.from(receiptHash)],
3758
+ PROGRAM_IDS.reputation
3759
+ );
3760
+ return pda;
3761
+ }
3762
+ function buildProvider(connection, keypair) {
3763
+ return new AnchorProvider(connection, new Wallet(keypair), AnchorProvider.defaultOptions());
3764
+ }
3765
+ function creditVaultProgram(provider) {
3766
+ return new Program(credit_vault_default, provider);
3767
+ }
3768
+ function reputationProgram(provider) {
3769
+ return new Program(reputation_default, provider);
3770
+ }
3771
+
3772
+ // src/pay.ts
3773
+ async function pay(args) {
3774
+ const { agent, service, connection, amountUsdc } = args;
3775
+ const owner = toPubkey(args.owner);
3776
+ if (amountUsdc <= 0) {
3777
+ throw new ZeroAmountError();
3778
+ }
3779
+ if (args.receiptHash.length !== 32) {
3780
+ throw new Error(
3781
+ `pay: receiptHash must be 32 bytes, got ${args.receiptHash.length}`
3782
+ );
3783
+ }
3784
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3785
+ const policyAddr = policyPda(vaultAddr);
3786
+ const provider = buildProvider(connection, agent);
3787
+ const cv = creditVaultProgram(provider);
3788
+ const rep = reputationProgram(provider);
3789
+ const [rawVault, rawPolicy, currentSlot] = await Promise.all([
3790
+ cv.account.creditVault.fetchNullable(vaultAddr),
3791
+ cv.account.spendPolicy.fetchNullable(policyAddr),
3792
+ connection.getSlot()
3793
+ ]);
3794
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3795
+ if (!rawPolicy) throw new AccountNotFoundError(policyAddr.toBase58());
3796
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3797
+ const policy = decodeSpendPolicy(policyAddr, rawPolicy);
3798
+ guardSpend({
3799
+ vault,
3800
+ policy,
3801
+ service: service.publicKey,
3802
+ amountUsdc,
3803
+ currentSlot
3804
+ });
3805
+ const serviceTokenAccount = getAssociatedTokenAddress(
3806
+ vault.usdc_mint,
3807
+ service.publicKey
3808
+ );
3809
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(
3810
+ agent.publicKey,
3811
+ serviceTokenAccount,
3812
+ service.publicKey,
3813
+ vault.usdc_mint
3814
+ );
3815
+ const agentProfile = agentProfilePda(agent.publicKey);
3816
+ const serviceRegistry = serviceRegistryPda(service.publicKey);
3817
+ const link = agentServiceLinkPda(agentProfile, serviceRegistry);
3818
+ const receipt = receiptUsedPda(args.receiptHash);
3819
+ const spendBuilder = cv.methods.spend(new BN(amountUsdc)).accounts({
3820
+ agent: agent.publicKey,
3821
+ vault: vaultAddr,
3822
+ policy: policyAddr,
3823
+ vaultTokenAccount: vault.vault_token_account,
3824
+ serviceTokenAccount,
3825
+ tokenProgram: TOKEN_PROGRAM_ID
3826
+ });
3827
+ const recordBuilder = rep.methods.recordPayment(new BN(amountUsdc), args.receiptHash).accounts({
3828
+ service: service.publicKey,
3829
+ agentProfile,
3830
+ serviceRegistry,
3831
+ agentServiceLink: link,
3832
+ receiptUsed: receipt,
3833
+ systemProgram: SystemProgram.programId
3834
+ });
3835
+ const spendIx = await spendBuilder.instruction();
3836
+ const recordIx = await recordBuilder.instruction();
3837
+ const tx = new Transaction().add(createAtaIx, spendIx, recordIx);
3838
+ try {
3839
+ const signature = await sendAndConfirmTransaction(
3840
+ connection,
3841
+ tx,
3842
+ [agent, service],
3843
+ { commitment: "confirmed" }
3844
+ );
3845
+ return { signature };
3846
+ } catch (err) {
3847
+ throw mapPayError(err, {
3848
+ service: service.publicKey,
3849
+ amountUsdc,
3850
+ vault,
3851
+ policy,
3852
+ receiptHash: args.receiptHash
3853
+ });
3854
+ }
3855
+ }
3856
+ function mapPayError(err, ctx) {
3857
+ const message = err instanceof Error ? err.message : String(err);
3858
+ if (/already in use/i.test(message)) {
3859
+ return new ReceiptAlreadyRecordedError(ctx.receiptHash);
3860
+ }
3861
+ if (!(err instanceof AnchorError)) return err;
3862
+ switch (err.error.errorCode.number) {
3863
+ case 6001:
3864
+ return new ZeroAmountError();
3865
+ case 6002:
3866
+ return new VaultFrozenError();
3867
+ case 6003:
3868
+ return new NotWhitelistedError(ctx.service.toBase58());
3869
+ case 6004:
3870
+ return new PerTxLimitExceededError(ctx.amountUsdc, ctx.policy.per_tx_limit_usdc);
3871
+ case 6005:
3872
+ return new HourlyLimitExceededError(
3873
+ ctx.amountUsdc,
3874
+ ctx.policy.hourly_window_spent_usdc,
3875
+ ctx.policy.hourly_limit_usdc
3876
+ );
3877
+ case 6006:
3878
+ return new LifetimeLimitExceededError(
3879
+ ctx.amountUsdc,
3880
+ ctx.vault.total_spent,
3881
+ ctx.policy.lifetime_limit_usdc
3882
+ );
3883
+ // Reputation errors:
3884
+ case 6e3:
3885
+ return new RecordPaymentError("counter overflow on chain");
3886
+ case 6011:
3887
+ return new ServiceInactiveError(ctx.service.toBase58());
3888
+ default:
3889
+ return err;
3890
+ }
3891
+ }
3892
+ async function requestSpend(args) {
3893
+ const { agent, connection, amountUsdc } = args;
3894
+ const owner = toPubkey(args.owner);
3895
+ const service = toPubkey(args.service);
3896
+ if (amountUsdc <= 0) {
3897
+ throw new Error("requestSpend: amountUsdc must be > 0");
3898
+ }
3899
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3900
+ const provider = buildProvider(connection, agent);
3901
+ const cv = creditVaultProgram(provider);
3902
+ const rawVault = await cv.account.creditVault.fetchNullable(vaultAddr);
3903
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3904
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3905
+ const nonce = vault.pending_count;
3906
+ const pendingSpend = pendingSpendPda(vaultAddr, nonce);
3907
+ const serviceTokenAccount = getAssociatedTokenAddress(
3908
+ vault.usdc_mint,
3909
+ service
3910
+ );
3911
+ const signature = await cv.methods.requestSpend(new BN(amountUsdc)).accounts({
3912
+ agent: agent.publicKey,
3913
+ vault: vaultAddr,
3914
+ serviceTokenAccount,
3915
+ pendingSpend,
3916
+ systemProgram: SystemProgram.programId
3917
+ }).signers([agent]).rpc();
3918
+ return { signature, pendingSpend, nonce };
3919
+ }
3920
+ var NAME_BYTES = 32;
3921
+ var URI_BYTES = 128;
3922
+ async function registerService(args) {
3923
+ const { sponsor, service, connection } = args;
3924
+ if (args.name.length === 0) {
3925
+ throw new Error("registerService: name must not be empty");
3926
+ }
3927
+ if (Buffer.byteLength(args.name, "utf8") > NAME_BYTES) {
3928
+ throw new Error(
3929
+ `registerService: name exceeds ${NAME_BYTES} bytes (got ${Buffer.byteLength(args.name, "utf8")})`
3930
+ );
3931
+ }
3932
+ const uri = args.serviceUri ?? "";
3933
+ if (Buffer.byteLength(uri, "utf8") > URI_BYTES) {
3934
+ throw new Error(
3935
+ `registerService: serviceUri exceeds ${URI_BYTES} bytes (got ${Buffer.byteLength(uri, "utf8")})`
3936
+ );
3937
+ }
3938
+ const registry = serviceRegistryPda(service.publicKey);
3939
+ const provider = buildProvider(connection, sponsor);
3940
+ const rep = reputationProgram(provider);
3941
+ const signature = await rep.methods.registerService(
3942
+ packFixed(args.name, NAME_BYTES),
3943
+ categoryArg(args.category),
3944
+ packFixed(uri, URI_BYTES)
3945
+ ).accounts({
3946
+ sponsor: sponsor.publicKey,
3947
+ service: service.publicKey,
3948
+ serviceRegistry: registry,
3949
+ systemProgram: SystemProgram.programId
3950
+ }).signers([sponsor, service]).rpc();
3951
+ return { signature };
3952
+ }
3953
+ function packFixed(s, length) {
3954
+ const buf = Buffer.alloc(length);
3955
+ buf.write(s, 0, "utf8");
3956
+ return Array.from(buf);
3957
+ }
3958
+ function categoryArg(c) {
3959
+ switch (c) {
3960
+ case "DataFeed":
3961
+ return { dataFeed: {} };
3962
+ case "Compute":
3963
+ return { compute: {} };
3964
+ case "Swap":
3965
+ return { swap: {} };
3966
+ case "Rpc":
3967
+ return { rpc: {} };
3968
+ case "Other":
3969
+ return { other: {} };
3970
+ }
3971
+ }
3972
+
3973
+ // src/client.ts
3974
+ var DEFAULT_API_BASE = "http://localhost:8080";
3975
+ var AgentFuel = class {
3976
+ agent;
3977
+ cluster;
3978
+ connection;
3979
+ apiBase;
3980
+ owner;
3981
+ _creditVault;
3982
+ _reputation;
3983
+ constructor(opts) {
3984
+ this.agent = opts.agent;
3985
+ this.cluster = opts.cluster;
3986
+ this.connection = typeof opts.rpc === "string" ? new Connection(opts.rpc, "confirmed") : opts.rpc;
3987
+ this.apiBase = opts.apiBase ?? DEFAULT_API_BASE;
3988
+ this.owner = opts.owner ? toPubkey(opts.owner) : void 0;
3989
+ }
3990
+ get agentPubkey() {
3991
+ return this.agent.publicKey;
3992
+ }
3993
+ get creditVault() {
3994
+ if (!this._creditVault) {
3995
+ this._creditVault = creditVaultProgram(buildProvider(this.connection, this.agent));
3996
+ }
3997
+ return this._creditVault;
3998
+ }
3999
+ get reputation() {
4000
+ if (!this._reputation) {
4001
+ this._reputation = reputationProgram(buildProvider(this.connection, this.agent));
4002
+ }
4003
+ return this._reputation;
4004
+ }
4005
+ resolveOwner(override) {
4006
+ const value = override ?? this.owner;
4007
+ if (!value) throw new OwnerNotConfiguredError();
4008
+ return toPubkey(value);
4009
+ }
4010
+ async getScore(agent) {
4011
+ const target = agent ? toPubkey(agent) : this.agentPubkey;
4012
+ const agentStr = target.toBase58();
4013
+ const url = `${this.apiBase.replace(/\/$/, "")}/reputation/${agentStr}`;
4014
+ const res = await fetch(url);
4015
+ if (res.status === 404) throw new AccountNotFoundError(agentStr);
4016
+ if (!res.ok) throw new HttpError(res.status, url, await safeText(res));
4017
+ return await res.json();
4018
+ }
4019
+ async getVaultBalance(ref) {
4020
+ const owner = this.resolveOwner(ref?.owner);
4021
+ const agent = ref?.agent ? toPubkey(ref.agent) : this.agentPubkey;
4022
+ const pda = vaultPda(owner, agent);
4023
+ const raw = await this.creditVault.account.creditVault.fetchNullable(pda);
4024
+ if (!raw) throw new AccountNotFoundError(pda.toBase58());
4025
+ return decodeCreditVault(pda, raw);
4026
+ }
4027
+ async getPolicy(ref) {
4028
+ const owner = this.resolveOwner(ref?.owner);
4029
+ const agent = ref?.agent ? toPubkey(ref.agent) : this.agentPubkey;
4030
+ const vault = vaultPda(owner, agent);
4031
+ const pda = policyPda(vault);
4032
+ const raw = await this.creditVault.account.spendPolicy.fetchNullable(pda);
4033
+ if (!raw) throw new AccountNotFoundError(pda.toBase58());
4034
+ return decodeSpendPolicy(pda, raw);
4035
+ }
4036
+ async checkService(serviceAuthority) {
4037
+ const pda = serviceRegistryPda(serviceAuthority);
4038
+ const raw = await this.reputation.account.serviceRegistry.fetchNullable(pda);
4039
+ if (!raw) throw new AccountNotFoundError(pda.toBase58());
4040
+ return decodeServiceRegistry(pda, raw);
4041
+ }
4042
+ async spend(args) {
4043
+ const owner = this.resolveOwner(args.owner);
4044
+ const service = toPubkey(args.service);
4045
+ const amountUsdc = args.amountUsdc;
4046
+ const vault = await this.getVaultBalance({ owner, agent: this.agentPubkey });
4047
+ const policy = await this.getPolicy({ owner, agent: this.agentPubkey });
4048
+ const currentSlot = await this.connection.getSlot();
4049
+ guardSpend({ vault, policy, service, amountUsdc, currentSlot });
4050
+ const serviceTokenAccount = getAssociatedTokenAddress(vault.usdc_mint, service);
4051
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(
4052
+ this.agentPubkey,
4053
+ serviceTokenAccount,
4054
+ service,
4055
+ vault.usdc_mint
4056
+ );
4057
+ try {
4058
+ const signature = await this.creditVault.methods.spend(new BN(amountUsdc)).accounts({
4059
+ agent: this.agentPubkey,
4060
+ vault: vault.pubkey,
4061
+ policy: policy.pubkey,
4062
+ vaultTokenAccount: vault.vault_token_account,
4063
+ serviceTokenAccount,
4064
+ tokenProgram: TOKEN_PROGRAM_ID
4065
+ }).preInstructions([createAtaIx]).signers([this.agent]).rpc();
4066
+ return { signature };
4067
+ } catch (err) {
4068
+ throw mapSpendError(err, { service, amountUsdc, vault, policy });
4069
+ }
4070
+ }
4071
+ /// Atomic spend + record_payment in one transaction. Use this instead
4072
+ /// of `spend()` + `recordPayment()` when you want the vault burn and
4073
+ /// the reputation accrual to be all-or-nothing. The service keypair
4074
+ /// co-signs.
4075
+ async pay(args) {
4076
+ return pay({
4077
+ agent: this.agent,
4078
+ owner: this.resolveOwner(args.owner),
4079
+ service: args.service,
4080
+ amountUsdc: args.amountUsdc,
4081
+ receiptHash: args.receiptHash,
4082
+ connection: this.connection
4083
+ });
4084
+ }
4085
+ /// Submit an over-limit spend request the owner can approve from the
4086
+ /// mobile app. Returns the `pendingSpend` PDA so the bot can poll for
4087
+ /// resolution.
4088
+ async requestSpend(args) {
4089
+ return requestSpend({
4090
+ agent: this.agent,
4091
+ owner: this.resolveOwner(args.owner),
4092
+ service: args.service,
4093
+ amountUsdc: args.amountUsdc,
4094
+ connection: this.connection
4095
+ });
4096
+ }
4097
+ /// Register a service on chain. The `sponsor` (typically `this.agent`'s
4098
+ /// owner wallet) pays rent; the `service` keypair is the long-lived
4099
+ /// identity that will co-sign every future `record_payment`.
4100
+ async registerService(args) {
4101
+ return registerService({ ...args, connection: this.connection });
4102
+ }
4103
+ /// Triggers an on-chain recomputation of the agent's reputation score.
4104
+ /// Permissionless — any signer can call it; we use the agent itself since
4105
+ /// the SDK already has its keypair available and it already pays tx fees
4106
+ /// for spends. The instruction reads the agent's already-public counters
4107
+ /// (volume, diversity, streak, tenure, feedback), recalculates the score
4108
+ /// to a single u16 ≤ 1000, and emits a `ScoreComputed` event. The webhook
4109
+ /// picks that up; the next `getScore()` returns the fresh value.
4110
+ async computeScore() {
4111
+ const profile = agentProfilePda(this.agentPubkey);
4112
+ const signature = await this.reputation.methods.computeScore().accounts({
4113
+ caller: this.agentPubkey,
4114
+ agentProfile: profile
4115
+ }).signers([this.agent]).rpc();
4116
+ return { signature };
4117
+ }
4118
+ onEvent(callback, options) {
4119
+ const target = options?.agent ? toPubkey(options.agent) : this.agentPubkey;
4120
+ const url = wsUrl(this.apiBase, `/ws/agents/${target.toBase58()}`);
4121
+ const subOpts = {
4122
+ onFrame: callback
4123
+ };
4124
+ if (options?.onStatus) subOpts.onStatus = options.onStatus;
4125
+ return subscribe(url, subOpts);
4126
+ }
4127
+ };
4128
+ function mapSpendError(err, ctx) {
4129
+ if (!(err instanceof AnchorError)) return err;
4130
+ switch (err.error.errorCode.number) {
4131
+ case 6001:
4132
+ return new ZeroAmountError();
4133
+ case 6002:
4134
+ return new VaultFrozenError();
4135
+ case 6003:
4136
+ return new NotWhitelistedError(ctx.service.toBase58());
4137
+ case 6004:
4138
+ return new PerTxLimitExceededError(ctx.amountUsdc, ctx.policy.per_tx_limit_usdc);
4139
+ case 6005:
4140
+ return new HourlyLimitExceededError(
4141
+ ctx.amountUsdc,
4142
+ ctx.policy.hourly_window_spent_usdc,
4143
+ ctx.policy.hourly_limit_usdc
4144
+ );
4145
+ case 6006:
4146
+ return new LifetimeLimitExceededError(
4147
+ ctx.amountUsdc,
4148
+ ctx.vault.total_spent,
4149
+ ctx.policy.lifetime_limit_usdc
4150
+ );
4151
+ default:
4152
+ return err;
4153
+ }
4154
+ }
4155
+ async function safeText(res) {
4156
+ try {
4157
+ return await res.text();
4158
+ } catch {
4159
+ return void 0;
4160
+ }
4161
+ }
4162
+
4163
+ // src/cli.ts
4164
+ var VERSION = "0.3.0";
4165
+ var RPC_DEFAULTS = {
4166
+ "mainnet-beta": "https://api.mainnet-beta.solana.com",
4167
+ devnet: "https://api.devnet.solana.com",
4168
+ testnet: "https://api.testnet.solana.com",
4169
+ localnet: "http://127.0.0.1:8899"
4170
+ };
4171
+ var DEFAULT_API_BASE2 = "https://api.agentfuel.online";
4172
+ function readGlobalOpts(cmd) {
4173
+ const root = rootOf(cmd);
4174
+ const o = root.opts();
4175
+ const g = {
4176
+ cluster: o.cluster,
4177
+ apiBase: o.apiBase ?? DEFAULT_API_BASE2,
4178
+ json: o.json ?? false
4179
+ };
4180
+ if (o.rpc !== void 0) g.rpc = o.rpc;
4181
+ return g;
4182
+ }
4183
+ function rootOf(cmd) {
4184
+ let cur = cmd;
4185
+ while (cur.parent) cur = cur.parent;
4186
+ return cur;
4187
+ }
4188
+ function connectionFor(g) {
4189
+ return new Connection(g.rpc ?? RPC_DEFAULTS[g.cluster], "confirmed");
4190
+ }
4191
+ function loadKeypair(path) {
4192
+ let raw;
4193
+ try {
4194
+ raw = readFileSync(path, "utf8");
4195
+ } catch (e) {
4196
+ throw new Error(`could not read keypair file '${path}': ${errMsg(e)}`);
4197
+ }
4198
+ let bytes;
4199
+ try {
4200
+ bytes = JSON.parse(raw);
4201
+ } catch (e) {
4202
+ throw new Error(
4203
+ `keypair file '${path}' is not valid JSON (expected a 64-byte array, the same format \`solana-keygen new\` writes): ${errMsg(e)}`
4204
+ );
4205
+ }
4206
+ if (!Array.isArray(bytes) || bytes.length !== 64) {
4207
+ throw new Error(
4208
+ `keypair file '${path}' must contain a JSON array of exactly 64 bytes (got ${Array.isArray(bytes) ? `${bytes.length}` : typeof bytes})`
4209
+ );
4210
+ }
4211
+ return Keypair.fromSecretKey(Uint8Array.from(bytes));
4212
+ }
4213
+ function parsePubkey(s, label) {
4214
+ try {
4215
+ return new PublicKey(s);
4216
+ } catch {
4217
+ throw new Error(`${label} is not a valid base58 pubkey: ${s}`);
4218
+ }
4219
+ }
4220
+ function parseAmountToMicro(s) {
4221
+ const n = Number(s);
4222
+ if (!Number.isFinite(n) || n <= 0) {
4223
+ throw new Error(`--amount must be a positive number (USDC), got '${s}'`);
4224
+ }
4225
+ const micro2 = Math.round(n * 1e6);
4226
+ if (micro2 <= 0) throw new Error(`--amount too small: ${s}`);
4227
+ return micro2;
4228
+ }
4229
+ function parseCategory(s) {
4230
+ const lower = s.toLowerCase();
4231
+ switch (lower) {
4232
+ case "datafeed":
4233
+ case "data-feed":
4234
+ return "DataFeed";
4235
+ case "compute":
4236
+ return "Compute";
4237
+ case "swap":
4238
+ return "Swap";
4239
+ case "rpc":
4240
+ return "Rpc";
4241
+ case "other":
4242
+ return "Other";
4243
+ default:
4244
+ throw new Error(
4245
+ `--category must be one of: DataFeed, Compute, Swap, Rpc, Other (got '${s}')`
4246
+ );
4247
+ }
4248
+ }
4249
+ function parseReceiptHash(s) {
4250
+ if (!s) return randomBytes(32);
4251
+ const hex = s.startsWith("0x") ? s.slice(2) : s;
4252
+ if (hex.length !== 64 || !/^[0-9a-fA-F]+$/.test(hex)) {
4253
+ throw new Error(
4254
+ `--receipt-hash must be 32 bytes hex (64 hex chars, with or without 0x prefix)`
4255
+ );
4256
+ }
4257
+ return Uint8Array.from(Buffer.from(hex, "hex"));
4258
+ }
4259
+ function readOnlyFuel(g) {
4260
+ return new AgentFuel({
4261
+ agent: Keypair.generate(),
4262
+ cluster: g.cluster,
4263
+ rpc: connectionFor(g),
4264
+ apiBase: g.apiBase
4265
+ });
4266
+ }
4267
+ function emit(g, human, data) {
4268
+ if (g.json) {
4269
+ process.stdout.write(JSON.stringify(data, jsonReplacer, 2) + "\n");
4270
+ } else {
4271
+ process.stdout.write(human() + "\n");
4272
+ }
4273
+ }
4274
+ function jsonReplacer(_key, value) {
4275
+ if (value instanceof PublicKey) return value.toBase58();
4276
+ if (value instanceof Uint8Array) return Buffer.from(value).toString("hex");
4277
+ return value;
4278
+ }
4279
+ function errMsg(e) {
4280
+ return e instanceof Error ? e.message : String(e);
4281
+ }
4282
+ function explorerUrl(cluster, sig) {
4283
+ const suffix = cluster === "mainnet-beta" ? "" : `?cluster=${cluster}`;
4284
+ return `https://explorer.solana.com/tx/${sig}${suffix}`;
4285
+ }
4286
+ var program = new Command();
4287
+ program.name("agent-fuel").description(
4288
+ "Agent Fuel CLI \u2014 inspect vaults, register services, fire payments from the terminal."
4289
+ ).version(VERSION).addOption(
4290
+ new Option("--cluster <name>", "Solana cluster").choices(["mainnet-beta", "devnet", "testnet", "localnet"]).default("devnet")
4291
+ ).option("--rpc <url>", "override the default RPC URL for the chosen cluster").option(
4292
+ "--api-base <url>",
4293
+ "Agent Fuel backend base URL (used by read commands)",
4294
+ DEFAULT_API_BASE2
4295
+ ).option("--json", "emit machine-readable JSON instead of human text");
4296
+ program.command("score <agent>").description("Show the latest reputation snapshot for an agent (REST, no key).").action(async (agent, _opts, cmd) => {
4297
+ const g = readGlobalOpts(cmd);
4298
+ const agentPk = parsePubkey(agent, "<agent>");
4299
+ const fuel = readOnlyFuel(g);
4300
+ const score = await fuel.getScore(agentPk);
4301
+ emit(g, () => formatScore(score), score);
4302
+ });
4303
+ program.command("vault <owner> <agent>").description("Show on-chain credit vault state for the (owner, agent) pair.").action(async (owner, agent, _opts, cmd) => {
4304
+ const g = readGlobalOpts(cmd);
4305
+ const ownerPk = parsePubkey(owner, "<owner>");
4306
+ const agentPk = parsePubkey(agent, "<agent>");
4307
+ const fuel = readOnlyFuel(g);
4308
+ const vault = await fuel.getVaultBalance({ owner: ownerPk, agent: agentPk });
4309
+ emit(g, () => formatVault(vault), vault);
4310
+ });
4311
+ program.command("policy <owner> <agent>").description("Show the spend policy guarding an (owner, agent) vault.").action(async (owner, agent, _opts, cmd) => {
4312
+ const g = readGlobalOpts(cmd);
4313
+ const ownerPk = parsePubkey(owner, "<owner>");
4314
+ const agentPk = parsePubkey(agent, "<agent>");
4315
+ const fuel = readOnlyFuel(g);
4316
+ const policy = await fuel.getPolicy({ owner: ownerPk, agent: agentPk });
4317
+ emit(g, () => formatPolicy(policy), policy);
4318
+ });
4319
+ program.command("service <authority>").description("Look up a registered service by its authority pubkey.").action(async (authority, _opts, cmd) => {
4320
+ const g = readGlobalOpts(cmd);
4321
+ const authPk = parsePubkey(authority, "<authority>");
4322
+ const fuel = readOnlyFuel(g);
4323
+ const svc = await fuel.checkService(authPk);
4324
+ emit(g, () => formatService(svc), svc);
4325
+ });
4326
+ program.command("pay").description(
4327
+ "Atomically spend from a vault and record the payment for reputation."
4328
+ ).requiredOption("--keypair <path>", "agent keypair (signs the spend half)").requiredOption("--service-keypair <path>", "service keypair (co-signs)").requiredOption("--owner <pubkey>", "vault owner pubkey").requiredOption("--amount <usdc>", "amount in USDC (e.g. 0.5)").option(
4329
+ "--receipt-hash <hex>",
4330
+ "32-byte receipt hash as hex (auto-generated if omitted)"
4331
+ ).action(
4332
+ async (opts, cmd) => {
4333
+ const g = readGlobalOpts(cmd);
4334
+ const agent = loadKeypair(opts.keypair);
4335
+ const service = loadKeypair(opts.serviceKeypair);
4336
+ const owner = parsePubkey(opts.owner, "--owner");
4337
+ const amountUsdc = parseAmountToMicro(opts.amount);
4338
+ const receiptHash = parseReceiptHash(opts.receiptHash);
4339
+ const result = await pay({
4340
+ agent,
4341
+ service,
4342
+ owner,
4343
+ amountUsdc,
4344
+ receiptHash,
4345
+ connection: connectionFor(g)
4346
+ });
4347
+ emit(
4348
+ g,
4349
+ () => [
4350
+ `paid ${opts.amount} USDC`,
4351
+ ` agent ${agent.publicKey.toBase58()}`,
4352
+ ` service ${service.publicKey.toBase58()}`,
4353
+ ` signature ${result.signature}`,
4354
+ ` ${explorerUrl(g.cluster, result.signature)}`
4355
+ ].join("\n"),
4356
+ { ...result, receipt_hash: Buffer.from(receiptHash).toString("hex") }
4357
+ );
4358
+ }
4359
+ );
4360
+ program.command("request-spend").description(
4361
+ "Submit an over-limit spend that the owner must approve from the app."
4362
+ ).requiredOption("--keypair <path>", "agent keypair (submits the request)").requiredOption("--owner <pubkey>", "vault owner pubkey").requiredOption("--service <pubkey>", "service authority pubkey").requiredOption("--amount <usdc>", "amount in USDC (e.g. 5.0)").action(
4363
+ async (opts, cmd) => {
4364
+ const g = readGlobalOpts(cmd);
4365
+ const agent = loadKeypair(opts.keypair);
4366
+ const owner = parsePubkey(opts.owner, "--owner");
4367
+ const service = parsePubkey(opts.service, "--service");
4368
+ const amountUsdc = parseAmountToMicro(opts.amount);
4369
+ const result = await requestSpend({
4370
+ agent,
4371
+ owner,
4372
+ service,
4373
+ amountUsdc,
4374
+ connection: connectionFor(g)
4375
+ });
4376
+ emit(
4377
+ g,
4378
+ () => [
4379
+ `requested ${opts.amount} USDC (over-limit, awaiting owner approval)`,
4380
+ ` pending ${result.pendingSpend.toBase58()}`,
4381
+ ` nonce ${result.nonce}`,
4382
+ ` signature ${result.signature}`,
4383
+ ` ${explorerUrl(g.cluster, result.signature)}`
4384
+ ].join("\n"),
4385
+ result
4386
+ );
4387
+ }
4388
+ );
4389
+ program.command("register-service").description("Register a new service on chain (two-signer).").requiredOption("--sponsor <path>", "sponsor keypair (pays rent, submits tx)").requiredOption(
4390
+ "--service-keypair <path>",
4391
+ "service keypair (long-lived signing identity)"
4392
+ ).requiredOption("--name <name>", "service name (max 32 bytes UTF-8)").requiredOption(
4393
+ "--category <c>",
4394
+ "DataFeed | Compute | Swap | Rpc | Other"
4395
+ ).option("--uri <url>", "optional off-chain metadata URI (max 128 bytes)").action(
4396
+ async (opts, cmd) => {
4397
+ const g = readGlobalOpts(cmd);
4398
+ const sponsor = loadKeypair(opts.sponsor);
4399
+ const service = loadKeypair(opts.serviceKeypair);
4400
+ const category = parseCategory(opts.category);
4401
+ const registerArgs = {
4402
+ sponsor,
4403
+ service,
4404
+ name: opts.name,
4405
+ category,
4406
+ connection: connectionFor(g)
4407
+ };
4408
+ if (opts.uri !== void 0) registerArgs.serviceUri = opts.uri;
4409
+ const result = await registerService(registerArgs);
4410
+ emit(
4411
+ g,
4412
+ () => [
4413
+ `registered service "${opts.name}" (${category})`,
4414
+ ` authority ${service.publicKey.toBase58()}`,
4415
+ ` sponsor ${sponsor.publicKey.toBase58()}`,
4416
+ ` signature ${result.signature}`,
4417
+ ` ${explorerUrl(g.cluster, result.signature)}`
4418
+ ].join("\n"),
4419
+ result
4420
+ );
4421
+ }
4422
+ );
4423
+ program.command("keygen").description(
4424
+ "Generate a new Solana keypair (compatible with solana-keygen JSON format)."
4425
+ ).option(
4426
+ "--out <path>",
4427
+ "write the secret-key JSON to a file (parent dirs created)"
4428
+ ).action((opts, cmd) => {
4429
+ const g = readGlobalOpts(cmd);
4430
+ const kp = Keypair.generate();
4431
+ const bytes = Array.from(kp.secretKey);
4432
+ const pub = kp.publicKey.toBase58();
4433
+ if (opts.out) {
4434
+ mkdirSync(dirname(opts.out), { recursive: true });
4435
+ writeFileSync(opts.out, JSON.stringify(bytes), { mode: 384 });
4436
+ emit(
4437
+ g,
4438
+ () => `wrote keypair to ${opts.out}
4439
+ pubkey ${pub}`,
4440
+ { pubkey: pub, path: opts.out }
4441
+ );
4442
+ } else {
4443
+ if (g.json) {
4444
+ emit(g, () => "", { pubkey: pub, secret_key: bytes });
4445
+ } else {
4446
+ process.stderr.write(JSON.stringify(bytes) + "\n");
4447
+ process.stdout.write(`pubkey ${pub}
4448
+ `);
4449
+ }
4450
+ }
4451
+ });
4452
+ function formatScore(s) {
4453
+ return [
4454
+ `agent ${s.agent}`,
4455
+ `score ${s.score ?? "(unscored)"}`,
4456
+ `transactions ${s.total_transactions}`,
4457
+ `services used ${s.services_used}`,
4458
+ `volume USDC ${micro(s.total_volume_usdc)}`,
4459
+ `consecutive ok ${s.consecutive_success}`,
4460
+ `feedback total ${s.total_feedback_count}`,
4461
+ `feedback negative ${s.active_negative_feedback_count}`,
4462
+ `last active slot ${s.last_active_slot}`,
4463
+ `updated ${s.updated_at}`
4464
+ ].join("\n");
4465
+ }
4466
+ function formatVault(v) {
4467
+ return [
4468
+ `vault ${v.pubkey.toBase58()}`,
4469
+ `owner ${v.owner.toBase58()}`,
4470
+ `agent ${v.agent.toBase58()}`,
4471
+ `usdc mint ${v.usdc_mint.toBase58()}`,
4472
+ `vault token acct ${v.vault_token_account.toBase58()}`,
4473
+ `balance ${micro(v.balance)} USDC`,
4474
+ ` deposited ${micro(v.total_deposited)}`,
4475
+ ` withdrawn ${micro(v.total_withdrawn)}`,
4476
+ ` spent ${micro(v.total_spent)}`,
4477
+ ` claimed ${micro(v.total_claimed)}`,
4478
+ `frozen ${v.frozen}`,
4479
+ `pending count ${v.pending_count}`,
4480
+ `last active slot ${v.last_active_slot}`
4481
+ ].join("\n");
4482
+ }
4483
+ function formatPolicy(p) {
4484
+ const whitelist = p.whitelist.length ? p.whitelist.map((pk) => ` - ${pk.toBase58()}`).join("\n") : " (empty \u2014 no whitelist enforcement)";
4485
+ return [
4486
+ `policy ${p.pubkey.toBase58()}`,
4487
+ `vault ${p.vault.toBase58()}`,
4488
+ `per-tx limit ${micro(p.per_tx_limit_usdc)} USDC`,
4489
+ `hourly limit ${micro(p.hourly_limit_usdc)} USDC`,
4490
+ `lifetime limit ${micro(p.lifetime_limit_usdc)} USDC`,
4491
+ `hourly window slot ${p.hourly_window_start_slot}`,
4492
+ `hourly spent ${micro(p.hourly_window_spent_usdc)} USDC`,
4493
+ `allow post-pay ${p.allow_post_pay}`,
4494
+ `whitelist:`,
4495
+ whitelist
4496
+ ].join("\n");
4497
+ }
4498
+ function formatService(s) {
4499
+ return [
4500
+ `registry ${s.pubkey.toBase58()}`,
4501
+ `authority ${s.authority.toBase58()}`,
4502
+ `name ${s.name}`,
4503
+ `category ${s.category}`,
4504
+ `active ${s.active}`,
4505
+ `agents served ${s.total_agents_served}`,
4506
+ `volume received ${micro(s.total_volume_received_usdc)} USDC`,
4507
+ `first active slot ${s.first_active_slot}`,
4508
+ `last active slot ${s.last_active_slot}`
4509
+ ].join("\n");
4510
+ }
4511
+ function micro(n) {
4512
+ return (n / 1e6).toFixed(6);
4513
+ }
4514
+ program.exitOverride();
4515
+ program.parseAsync(process.argv).catch((err) => {
4516
+ if (typeof err === "object" && err !== null && "code" in err) {
4517
+ const code = err.code;
4518
+ if (code === "commander.help" || code === "commander.helpDisplayed" || code === "commander.version") {
4519
+ process.exit(0);
4520
+ }
4521
+ }
4522
+ const msg = errMsg(err);
4523
+ process.stderr.write(`agent-fuel: ${msg}
4524
+ `);
4525
+ process.exit(1);
4526
+ });
4527
+ //# sourceMappingURL=cli.js.map
4528
+ //# sourceMappingURL=cli.js.map