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