@circuit-llm/vault 0.2.1

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/index.js ADDED
@@ -0,0 +1,1577 @@
1
+ // src/index.ts
2
+ import * as anchor4 from "@anchor-lang/core";
3
+
4
+ // src/idl/idl.ts
5
+ var idl = {
6
+ "address": "9AmhsDD9AwUM57pLwYsmNWhjdAP5vTy2HXxqbdKRaxXA",
7
+ "metadata": {
8
+ "name": "circuit_agent_vault",
9
+ "version": "0.1.0",
10
+ "spec": "0.1.0",
11
+ "description": "Created with Anchor"
12
+ },
13
+ "instructions": [
14
+ {
15
+ "name": "close_vault",
16
+ "docs": [
17
+ "OWNER-ONLY. Close the vault and return ALL remaining lamports to the owner (Anchor `close`).",
18
+ "Phase 1 is SOL-only; Phase 3 adds a guard that token balances are zero before close."
19
+ ],
20
+ "discriminator": [
21
+ 141,
22
+ 103,
23
+ 17,
24
+ 126,
25
+ 72,
26
+ 75,
27
+ 29,
28
+ 29
29
+ ],
30
+ "accounts": [
31
+ {
32
+ "name": "vault",
33
+ "writable": true,
34
+ "pda": {
35
+ "seeds": [
36
+ {
37
+ "kind": "const",
38
+ "value": [
39
+ 118,
40
+ 97,
41
+ 117,
42
+ 108,
43
+ 116
44
+ ]
45
+ },
46
+ {
47
+ "kind": "account",
48
+ "path": "owner"
49
+ },
50
+ {
51
+ "kind": "account",
52
+ "path": "vault.agent_seed",
53
+ "account": "Vault"
54
+ }
55
+ ]
56
+ }
57
+ },
58
+ {
59
+ "name": "owner",
60
+ "writable": true,
61
+ "signer": true,
62
+ "relations": [
63
+ "vault"
64
+ ]
65
+ }
66
+ ],
67
+ "args": []
68
+ },
69
+ {
70
+ "name": "deposit",
71
+ "docs": [
72
+ "Fund the vault with SOL. Anyone may deposit (it's the owner's address either way); the",
73
+ "owner is the only one who can ever take it back out."
74
+ ],
75
+ "discriminator": [
76
+ 242,
77
+ 35,
78
+ 198,
79
+ 137,
80
+ 82,
81
+ 225,
82
+ 242,
83
+ 182
84
+ ],
85
+ "accounts": [
86
+ {
87
+ "name": "vault",
88
+ "writable": true,
89
+ "pda": {
90
+ "seeds": [
91
+ {
92
+ "kind": "const",
93
+ "value": [
94
+ 118,
95
+ 97,
96
+ 117,
97
+ 108,
98
+ 116
99
+ ]
100
+ },
101
+ {
102
+ "kind": "account",
103
+ "path": "vault.owner",
104
+ "account": "Vault"
105
+ },
106
+ {
107
+ "kind": "account",
108
+ "path": "vault.agent_seed",
109
+ "account": "Vault"
110
+ }
111
+ ]
112
+ }
113
+ },
114
+ {
115
+ "name": "depositor",
116
+ "writable": true,
117
+ "signer": true
118
+ },
119
+ {
120
+ "name": "system_program",
121
+ "address": "11111111111111111111111111111111"
122
+ }
123
+ ],
124
+ "args": [
125
+ {
126
+ "name": "amount",
127
+ "type": "u64"
128
+ }
129
+ ]
130
+ },
131
+ {
132
+ "name": "init_vault",
133
+ "docs": [
134
+ "Create a vault. The signer becomes the sovereign OWNER; `delegate` is the agent key that",
135
+ "will (Phase 2) be allowed to trade but never withdraw. One vault per (owner, agent_seed)."
136
+ ],
137
+ "discriminator": [
138
+ 77,
139
+ 79,
140
+ 85,
141
+ 150,
142
+ 33,
143
+ 217,
144
+ 52,
145
+ 106
146
+ ],
147
+ "accounts": [
148
+ {
149
+ "name": "vault",
150
+ "writable": true,
151
+ "pda": {
152
+ "seeds": [
153
+ {
154
+ "kind": "const",
155
+ "value": [
156
+ 118,
157
+ 97,
158
+ 117,
159
+ 108,
160
+ 116
161
+ ]
162
+ },
163
+ {
164
+ "kind": "account",
165
+ "path": "owner"
166
+ },
167
+ {
168
+ "kind": "arg",
169
+ "path": "agent_seed"
170
+ }
171
+ ]
172
+ }
173
+ },
174
+ {
175
+ "name": "owner",
176
+ "writable": true,
177
+ "signer": true
178
+ },
179
+ {
180
+ "name": "system_program",
181
+ "address": "11111111111111111111111111111111"
182
+ }
183
+ ],
184
+ "args": [
185
+ {
186
+ "name": "agent_seed",
187
+ "type": {
188
+ "array": [
189
+ "u8",
190
+ 32
191
+ ]
192
+ }
193
+ },
194
+ {
195
+ "name": "delegate",
196
+ "type": "pubkey"
197
+ },
198
+ {
199
+ "name": "max_trade_lamports",
200
+ "type": "u64"
201
+ },
202
+ {
203
+ "name": "daily_limit_lamports",
204
+ "type": "u64"
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ "name": "set_delegate",
210
+ "docs": [
211
+ "OWNER-ONLY. Rotate or revoke the agent's trading key. Bumps `epoch` so a stale delegate is",
212
+ "fenced out (Phase 2 trades check it)."
213
+ ],
214
+ "discriminator": [
215
+ 242,
216
+ 30,
217
+ 46,
218
+ 76,
219
+ 108,
220
+ 235,
221
+ 128,
222
+ 181
223
+ ],
224
+ "accounts": [
225
+ {
226
+ "name": "vault",
227
+ "writable": true,
228
+ "pda": {
229
+ "seeds": [
230
+ {
231
+ "kind": "const",
232
+ "value": [
233
+ 118,
234
+ 97,
235
+ 117,
236
+ 108,
237
+ 116
238
+ ]
239
+ },
240
+ {
241
+ "kind": "account",
242
+ "path": "owner"
243
+ },
244
+ {
245
+ "kind": "account",
246
+ "path": "vault.agent_seed",
247
+ "account": "Vault"
248
+ }
249
+ ]
250
+ }
251
+ },
252
+ {
253
+ "name": "owner",
254
+ "writable": true,
255
+ "signer": true,
256
+ "relations": [
257
+ "vault"
258
+ ]
259
+ }
260
+ ],
261
+ "args": [
262
+ {
263
+ "name": "new_delegate",
264
+ "type": "pubkey"
265
+ }
266
+ ]
267
+ },
268
+ {
269
+ "name": "set_routes",
270
+ "docs": [
271
+ "OWNER-ONLY. Set the route allowlist (up to 4 swap programs). Pass an empty list to clear it",
272
+ "(back to any-program / guard-only). Defense in depth: lock trading to audited routers so the",
273
+ "guard isn't the sole boundary."
274
+ ],
275
+ "discriminator": [
276
+ 95,
277
+ 172,
278
+ 119,
279
+ 157,
280
+ 123,
281
+ 127,
282
+ 91,
283
+ 208
284
+ ],
285
+ "accounts": [
286
+ {
287
+ "name": "vault",
288
+ "writable": true,
289
+ "pda": {
290
+ "seeds": [
291
+ {
292
+ "kind": "const",
293
+ "value": [
294
+ 118,
295
+ 97,
296
+ 117,
297
+ 108,
298
+ 116
299
+ ]
300
+ },
301
+ {
302
+ "kind": "account",
303
+ "path": "owner"
304
+ },
305
+ {
306
+ "kind": "account",
307
+ "path": "vault.agent_seed",
308
+ "account": "Vault"
309
+ }
310
+ ]
311
+ }
312
+ },
313
+ {
314
+ "name": "owner",
315
+ "writable": true,
316
+ "signer": true,
317
+ "relations": [
318
+ "vault"
319
+ ]
320
+ }
321
+ ],
322
+ "args": [
323
+ {
324
+ "name": "programs",
325
+ "type": {
326
+ "vec": "pubkey"
327
+ }
328
+ }
329
+ ]
330
+ },
331
+ {
332
+ "name": "set_rule",
333
+ "docs": [
334
+ "OWNER-ONLY. Commit (or clear) the Verified-Intents price rule. `op == 0` disables it. When set,",
335
+ "every trade must present a fresh `oracle`-signed price for `feed` satisfying `price <op> threshold`",
336
+ "(verified via an Ed25519 sibling instruction). This is enforced by the chain, not a server."
337
+ ],
338
+ "discriminator": [
339
+ 237,
340
+ 148,
341
+ 178,
342
+ 172,
343
+ 127,
344
+ 70,
345
+ 114,
346
+ 103
347
+ ],
348
+ "accounts": [
349
+ {
350
+ "name": "vault",
351
+ "writable": true,
352
+ "pda": {
353
+ "seeds": [
354
+ {
355
+ "kind": "const",
356
+ "value": [
357
+ 118,
358
+ 97,
359
+ 117,
360
+ 108,
361
+ 116
362
+ ]
363
+ },
364
+ {
365
+ "kind": "account",
366
+ "path": "owner"
367
+ },
368
+ {
369
+ "kind": "account",
370
+ "path": "vault.agent_seed",
371
+ "account": "Vault"
372
+ }
373
+ ]
374
+ }
375
+ },
376
+ {
377
+ "name": "owner",
378
+ "writable": true,
379
+ "signer": true,
380
+ "relations": [
381
+ "vault"
382
+ ]
383
+ }
384
+ ],
385
+ "args": [
386
+ {
387
+ "name": "oracle",
388
+ "type": "pubkey"
389
+ },
390
+ {
391
+ "name": "feed",
392
+ "type": {
393
+ "array": [
394
+ "u8",
395
+ 32
396
+ ]
397
+ }
398
+ },
399
+ {
400
+ "name": "op",
401
+ "type": "u8"
402
+ },
403
+ {
404
+ "name": "threshold",
405
+ "type": "i64"
406
+ },
407
+ {
408
+ "name": "max_age",
409
+ "type": "i64"
410
+ },
411
+ {
412
+ "name": "in_mint",
413
+ "type": "pubkey"
414
+ },
415
+ {
416
+ "name": "out_mint",
417
+ "type": "pubkey"
418
+ },
419
+ {
420
+ "name": "max_slippage_bps",
421
+ "type": "u16"
422
+ }
423
+ ]
424
+ },
425
+ {
426
+ "name": "trade",
427
+ "docs": [
428
+ "DELEGATE-ONLY. Execute a swap through ANY program (the agent supplies the program + accounts +",
429
+ "data via remaining_accounts), then GUARD the result on the vault's OWN accounts:",
430
+ "\u2022 the vault spends at most `amount_in` of the input, and",
431
+ "\u2022 receives at least `min_out` of the output \u2190 the anti-theft line, and",
432
+ "\u2022 no OTHER vault-owned token account is involved, and",
433
+ "\u2022 NO approval/authority/ownership changed (catches approve / setAuthority that move no balance).",
434
+ `The route is untrusted; the OUTCOME is verified. That's what makes "trade anything, can't`,
435
+ 'extract" true. (Phase 2: cap is in input base units; SOL-notional + slippage-vs-quote is Phase 3.)'
436
+ ],
437
+ "discriminator": [
438
+ 178,
439
+ 144,
440
+ 26,
441
+ 216,
442
+ 241,
443
+ 187,
444
+ 206,
445
+ 130
446
+ ],
447
+ "accounts": [
448
+ {
449
+ "name": "vault",
450
+ "writable": true,
451
+ "pda": {
452
+ "seeds": [
453
+ {
454
+ "kind": "const",
455
+ "value": [
456
+ 118,
457
+ 97,
458
+ 117,
459
+ 108,
460
+ 116
461
+ ]
462
+ },
463
+ {
464
+ "kind": "account",
465
+ "path": "vault.owner",
466
+ "account": "Vault"
467
+ },
468
+ {
469
+ "kind": "account",
470
+ "path": "vault.agent_seed",
471
+ "account": "Vault"
472
+ }
473
+ ]
474
+ }
475
+ },
476
+ {
477
+ "name": "delegate",
478
+ "signer": true,
479
+ "relations": [
480
+ "vault"
481
+ ]
482
+ },
483
+ {
484
+ "name": "vault_input",
485
+ "writable": true
486
+ },
487
+ {
488
+ "name": "vault_output",
489
+ "writable": true
490
+ },
491
+ {
492
+ "name": "swap_program"
493
+ },
494
+ {
495
+ "name": "token_program"
496
+ },
497
+ {
498
+ "name": "instructions",
499
+ "docs": [
500
+ "(Verified Intents). Address-checked; only read when a rule is active."
501
+ ],
502
+ "address": "Sysvar1nstructions1111111111111111111111111"
503
+ }
504
+ ],
505
+ "args": [
506
+ {
507
+ "name": "amount_in",
508
+ "type": "u64"
509
+ },
510
+ {
511
+ "name": "min_out",
512
+ "type": "u64"
513
+ },
514
+ {
515
+ "name": "swap_data",
516
+ "type": "bytes"
517
+ }
518
+ ]
519
+ },
520
+ {
521
+ "name": "unwrap_sol",
522
+ "docs": [
523
+ "OWNER-ONLY. Close the vault's wSOL account, returning ALL its lamports (rent + wrapped SOL) to the",
524
+ "vault PDA as native SOL \u2014 destination is the vault ONLY, never arbitrary. Owner-only (not delegate):",
525
+ "the agent trades in wSOL and never needs to unwrap; restricting it removes a delegate rent-griefing",
526
+ "vector (repeatedly closing the wSOL account) at no cost to the trading flow (audit hardening)."
527
+ ],
528
+ "discriminator": [
529
+ 99,
530
+ 40,
531
+ 14,
532
+ 105,
533
+ 45,
534
+ 107,
535
+ 172,
536
+ 201
537
+ ],
538
+ "accounts": [
539
+ {
540
+ "name": "vault",
541
+ "writable": true,
542
+ "pda": {
543
+ "seeds": [
544
+ {
545
+ "kind": "const",
546
+ "value": [
547
+ 118,
548
+ 97,
549
+ 117,
550
+ 108,
551
+ 116
552
+ ]
553
+ },
554
+ {
555
+ "kind": "account",
556
+ "path": "vault.owner",
557
+ "account": "Vault"
558
+ },
559
+ {
560
+ "kind": "account",
561
+ "path": "vault.agent_seed",
562
+ "account": "Vault"
563
+ }
564
+ ]
565
+ }
566
+ },
567
+ {
568
+ "name": "actor",
569
+ "signer": true
570
+ },
571
+ {
572
+ "name": "wsol",
573
+ "writable": true
574
+ },
575
+ {
576
+ "name": "token_program",
577
+ "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
578
+ }
579
+ ],
580
+ "args": []
581
+ },
582
+ {
583
+ "name": "update_config",
584
+ "docs": [
585
+ "OWNER-ONLY. Update trading policy + the pause kill-switch. Withdraw still works when paused",
586
+ "(the owner is always sovereign over their funds)."
587
+ ],
588
+ "discriminator": [
589
+ 29,
590
+ 158,
591
+ 252,
592
+ 191,
593
+ 10,
594
+ 83,
595
+ 219,
596
+ 99
597
+ ],
598
+ "accounts": [
599
+ {
600
+ "name": "vault",
601
+ "writable": true,
602
+ "pda": {
603
+ "seeds": [
604
+ {
605
+ "kind": "const",
606
+ "value": [
607
+ 118,
608
+ 97,
609
+ 117,
610
+ 108,
611
+ 116
612
+ ]
613
+ },
614
+ {
615
+ "kind": "account",
616
+ "path": "owner"
617
+ },
618
+ {
619
+ "kind": "account",
620
+ "path": "vault.agent_seed",
621
+ "account": "Vault"
622
+ }
623
+ ]
624
+ }
625
+ },
626
+ {
627
+ "name": "owner",
628
+ "writable": true,
629
+ "signer": true,
630
+ "relations": [
631
+ "vault"
632
+ ]
633
+ }
634
+ ],
635
+ "args": [
636
+ {
637
+ "name": "max_trade_lamports",
638
+ "type": "u64"
639
+ },
640
+ {
641
+ "name": "daily_limit_lamports",
642
+ "type": "u64"
643
+ },
644
+ {
645
+ "name": "paused",
646
+ "type": "bool"
647
+ }
648
+ ]
649
+ },
650
+ {
651
+ "name": "withdraw",
652
+ "docs": [
653
+ "OWNER-ONLY. Move SOL out of the vault to the owner. The rent-exempt minimum is protected",
654
+ "so the account stays alive. This is the only exit in Phase 1; the delegate has no path here."
655
+ ],
656
+ "discriminator": [
657
+ 183,
658
+ 18,
659
+ 70,
660
+ 156,
661
+ 148,
662
+ 109,
663
+ 161,
664
+ 34
665
+ ],
666
+ "accounts": [
667
+ {
668
+ "name": "vault",
669
+ "writable": true,
670
+ "pda": {
671
+ "seeds": [
672
+ {
673
+ "kind": "const",
674
+ "value": [
675
+ 118,
676
+ 97,
677
+ 117,
678
+ 108,
679
+ 116
680
+ ]
681
+ },
682
+ {
683
+ "kind": "account",
684
+ "path": "owner"
685
+ },
686
+ {
687
+ "kind": "account",
688
+ "path": "vault.agent_seed",
689
+ "account": "Vault"
690
+ }
691
+ ]
692
+ }
693
+ },
694
+ {
695
+ "name": "owner",
696
+ "writable": true,
697
+ "signer": true,
698
+ "relations": [
699
+ "vault"
700
+ ]
701
+ }
702
+ ],
703
+ "args": [
704
+ {
705
+ "name": "amount",
706
+ "type": "u64"
707
+ }
708
+ ]
709
+ },
710
+ {
711
+ "name": "wrap_sol",
712
+ "docs": [
713
+ "OWNER-or-DELEGATE. Fund the vault's wSOL trading account with `amount` SOL from the ACTOR's",
714
+ "wallet (system transfer + sync_native). wSOL is what DEXes trade; the agent then swaps it for",
715
+ "tokens via `trade`. Typically the owner calls this to provide trading capital (the agent has no",
716
+ "funds of its own). The wSOL account is authority'd by the vault, so the actor can't redirect it."
717
+ ],
718
+ "discriminator": [
719
+ 47,
720
+ 62,
721
+ 155,
722
+ 172,
723
+ 131,
724
+ 205,
725
+ 37,
726
+ 201
727
+ ],
728
+ "accounts": [
729
+ {
730
+ "name": "vault",
731
+ "pda": {
732
+ "seeds": [
733
+ {
734
+ "kind": "const",
735
+ "value": [
736
+ 118,
737
+ 97,
738
+ 117,
739
+ 108,
740
+ 116
741
+ ]
742
+ },
743
+ {
744
+ "kind": "account",
745
+ "path": "vault.owner",
746
+ "account": "Vault"
747
+ },
748
+ {
749
+ "kind": "account",
750
+ "path": "vault.agent_seed",
751
+ "account": "Vault"
752
+ }
753
+ ]
754
+ }
755
+ },
756
+ {
757
+ "name": "actor",
758
+ "writable": true,
759
+ "signer": true
760
+ },
761
+ {
762
+ "name": "wsol",
763
+ "writable": true
764
+ },
765
+ {
766
+ "name": "token_program",
767
+ "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
768
+ },
769
+ {
770
+ "name": "system_program",
771
+ "address": "11111111111111111111111111111111"
772
+ }
773
+ ],
774
+ "args": [
775
+ {
776
+ "name": "amount",
777
+ "type": "u64"
778
+ }
779
+ ]
780
+ }
781
+ ],
782
+ "accounts": [
783
+ {
784
+ "name": "Vault",
785
+ "discriminator": [
786
+ 211,
787
+ 8,
788
+ 232,
789
+ 43,
790
+ 2,
791
+ 152,
792
+ 117,
793
+ 119
794
+ ]
795
+ }
796
+ ],
797
+ "events": [
798
+ {
799
+ "name": "DelegateSet",
800
+ "discriminator": [
801
+ 103,
802
+ 126,
803
+ 239,
804
+ 131,
805
+ 201,
806
+ 31,
807
+ 212,
808
+ 253
809
+ ]
810
+ },
811
+ {
812
+ "name": "Deposited",
813
+ "discriminator": [
814
+ 111,
815
+ 141,
816
+ 26,
817
+ 45,
818
+ 161,
819
+ 35,
820
+ 100,
821
+ 57
822
+ ]
823
+ },
824
+ {
825
+ "name": "RoutesSet",
826
+ "discriminator": [
827
+ 187,
828
+ 180,
829
+ 223,
830
+ 221,
831
+ 112,
832
+ 127,
833
+ 192,
834
+ 36
835
+ ]
836
+ },
837
+ {
838
+ "name": "RuleSet",
839
+ "discriminator": [
840
+ 141,
841
+ 22,
842
+ 70,
843
+ 140,
844
+ 45,
845
+ 27,
846
+ 175,
847
+ 119
848
+ ]
849
+ },
850
+ {
851
+ "name": "SolUnwrapped",
852
+ "discriminator": [
853
+ 251,
854
+ 11,
855
+ 67,
856
+ 67,
857
+ 145,
858
+ 148,
859
+ 119,
860
+ 192
861
+ ]
862
+ },
863
+ {
864
+ "name": "SolWrapped",
865
+ "discriminator": [
866
+ 13,
867
+ 17,
868
+ 193,
869
+ 193,
870
+ 199,
871
+ 177,
872
+ 177,
873
+ 23
874
+ ]
875
+ },
876
+ {
877
+ "name": "TradeExecuted",
878
+ "discriminator": [
879
+ 41,
880
+ 110,
881
+ 64,
882
+ 129,
883
+ 60,
884
+ 79,
885
+ 179,
886
+ 80
887
+ ]
888
+ },
889
+ {
890
+ "name": "VaultInitialized",
891
+ "discriminator": [
892
+ 180,
893
+ 43,
894
+ 207,
895
+ 2,
896
+ 18,
897
+ 71,
898
+ 3,
899
+ 75
900
+ ]
901
+ },
902
+ {
903
+ "name": "Withdrawn",
904
+ "discriminator": [
905
+ 20,
906
+ 89,
907
+ 223,
908
+ 198,
909
+ 194,
910
+ 124,
911
+ 219,
912
+ 13
913
+ ]
914
+ }
915
+ ],
916
+ "errors": [
917
+ {
918
+ "code": 6e3,
919
+ "name": "NotOwner",
920
+ "msg": "only the vault owner may perform this action"
921
+ },
922
+ {
923
+ "code": 6001,
924
+ "name": "InsufficientFunds",
925
+ "msg": "amount exceeds the withdrawable balance (rent-exempt minimum is protected)"
926
+ },
927
+ {
928
+ "code": 6002,
929
+ "name": "BadAmount",
930
+ "msg": "amount must be greater than zero"
931
+ },
932
+ {
933
+ "code": 6003,
934
+ "name": "Overflow",
935
+ "msg": "arithmetic overflow"
936
+ },
937
+ {
938
+ "code": 6004,
939
+ "name": "NotDelegate",
940
+ "msg": "only the vault delegate may trade"
941
+ },
942
+ {
943
+ "code": 6005,
944
+ "name": "Paused",
945
+ "msg": "trading is paused"
946
+ },
947
+ {
948
+ "code": 6006,
949
+ "name": "OverTradeCap",
950
+ "msg": "amount_in exceeds the per-trade cap (or is zero)"
951
+ },
952
+ {
953
+ "code": 6007,
954
+ "name": "BadMinOut",
955
+ "msg": "min_out must be greater than zero"
956
+ },
957
+ {
958
+ "code": 6008,
959
+ "name": "OverDailyCap",
960
+ "msg": "trade exceeds the daily cap"
961
+ },
962
+ {
963
+ "code": 6009,
964
+ "name": "ForeignVaultAccount",
965
+ "msg": "the swap may not touch another vault-owned token account"
966
+ },
967
+ {
968
+ "code": 6010,
969
+ "name": "InputIncreased",
970
+ "msg": "vault input balance increased \u2014 not a swap"
971
+ },
972
+ {
973
+ "code": 6011,
974
+ "name": "OutputDecreased",
975
+ "msg": "vault output balance decreased \u2014 value left the vault"
976
+ },
977
+ {
978
+ "code": 6012,
979
+ "name": "Slippage",
980
+ "msg": "received less than min_out (value left the vault / slippage)"
981
+ },
982
+ {
983
+ "code": 6013,
984
+ "name": "ApprovalGranted",
985
+ "msg": "an approval/delegate was granted on a vault account"
986
+ },
987
+ {
988
+ "code": 6014,
989
+ "name": "AuthorityChanged",
990
+ "msg": "a vault account's authority/mint/ownership changed"
991
+ },
992
+ {
993
+ "code": 6015,
994
+ "name": "NotOwnerOrDelegate",
995
+ "msg": "only the vault owner or delegate may wrap/unwrap"
996
+ },
997
+ {
998
+ "code": 6016,
999
+ "name": "NotWsol",
1000
+ "msg": "the account is not a wrapped-SOL (native mint) account"
1001
+ },
1002
+ {
1003
+ "code": 6017,
1004
+ "name": "TooManyRoutes",
1005
+ "msg": "at most 4 allowed route programs"
1006
+ },
1007
+ {
1008
+ "code": 6018,
1009
+ "name": "RouteNotAllowed",
1010
+ "msg": "swap program is not in the vault's route allowlist"
1011
+ },
1012
+ {
1013
+ "code": 6019,
1014
+ "name": "BadRule",
1015
+ "msg": "invalid rule (op must be 0..=4; max_age required when active)"
1016
+ },
1017
+ {
1018
+ "code": 6020,
1019
+ "name": "NoOracleSig",
1020
+ "msg": "no Ed25519 oracle-signature instruction found in the transaction"
1021
+ },
1022
+ {
1023
+ "code": 6021,
1024
+ "name": "WrongOracle",
1025
+ "msg": "the signed price is not from the vault's committed oracle"
1026
+ },
1027
+ {
1028
+ "code": 6022,
1029
+ "name": "BadAttestation",
1030
+ "msg": "malformed oracle attestation / Ed25519 instruction"
1031
+ },
1032
+ {
1033
+ "code": 6023,
1034
+ "name": "WrongFeed",
1035
+ "msg": "the attestation is for a different price feed"
1036
+ },
1037
+ {
1038
+ "code": 6024,
1039
+ "name": "StaleAttestation",
1040
+ "msg": "the oracle price is stale (outside the freshness window)"
1041
+ },
1042
+ {
1043
+ "code": 6025,
1044
+ "name": "RuleNotSatisfied",
1045
+ "msg": "the trade is not justified by the committed rule (price condition not met)"
1046
+ },
1047
+ {
1048
+ "code": 6026,
1049
+ "name": "WrongDirection",
1050
+ "msg": "the trade's mints don't match the rule's pinned direction"
1051
+ },
1052
+ {
1053
+ "code": 6027,
1054
+ "name": "PriceFloor",
1055
+ "msg": "min_out is below the oracle-attested execution floor (bad rate)"
1056
+ },
1057
+ {
1058
+ "code": 6028,
1059
+ "name": "LamportsDecreased",
1060
+ "msg": "the swap debited the vault's native lamports"
1061
+ }
1062
+ ],
1063
+ "types": [
1064
+ {
1065
+ "name": "DelegateSet",
1066
+ "type": {
1067
+ "kind": "struct",
1068
+ "fields": [
1069
+ {
1070
+ "name": "vault",
1071
+ "type": "pubkey"
1072
+ },
1073
+ {
1074
+ "name": "delegate",
1075
+ "type": "pubkey"
1076
+ },
1077
+ {
1078
+ "name": "epoch",
1079
+ "type": "u64"
1080
+ }
1081
+ ]
1082
+ }
1083
+ },
1084
+ {
1085
+ "name": "Deposited",
1086
+ "type": {
1087
+ "kind": "struct",
1088
+ "fields": [
1089
+ {
1090
+ "name": "vault",
1091
+ "type": "pubkey"
1092
+ },
1093
+ {
1094
+ "name": "amount",
1095
+ "type": "u64"
1096
+ }
1097
+ ]
1098
+ }
1099
+ },
1100
+ {
1101
+ "name": "RoutesSet",
1102
+ "type": {
1103
+ "kind": "struct",
1104
+ "fields": [
1105
+ {
1106
+ "name": "vault",
1107
+ "type": "pubkey"
1108
+ },
1109
+ {
1110
+ "name": "count",
1111
+ "type": "u8"
1112
+ }
1113
+ ]
1114
+ }
1115
+ },
1116
+ {
1117
+ "name": "RuleSet",
1118
+ "type": {
1119
+ "kind": "struct",
1120
+ "fields": [
1121
+ {
1122
+ "name": "vault",
1123
+ "type": "pubkey"
1124
+ },
1125
+ {
1126
+ "name": "oracle",
1127
+ "type": "pubkey"
1128
+ },
1129
+ {
1130
+ "name": "op",
1131
+ "type": "u8"
1132
+ }
1133
+ ]
1134
+ }
1135
+ },
1136
+ {
1137
+ "name": "SolUnwrapped",
1138
+ "type": {
1139
+ "kind": "struct",
1140
+ "fields": [
1141
+ {
1142
+ "name": "vault",
1143
+ "type": "pubkey"
1144
+ }
1145
+ ]
1146
+ }
1147
+ },
1148
+ {
1149
+ "name": "SolWrapped",
1150
+ "type": {
1151
+ "kind": "struct",
1152
+ "fields": [
1153
+ {
1154
+ "name": "vault",
1155
+ "type": "pubkey"
1156
+ },
1157
+ {
1158
+ "name": "amount",
1159
+ "type": "u64"
1160
+ }
1161
+ ]
1162
+ }
1163
+ },
1164
+ {
1165
+ "name": "TradeExecuted",
1166
+ "type": {
1167
+ "kind": "struct",
1168
+ "fields": [
1169
+ {
1170
+ "name": "vault",
1171
+ "type": "pubkey"
1172
+ },
1173
+ {
1174
+ "name": "spent",
1175
+ "type": "u64"
1176
+ },
1177
+ {
1178
+ "name": "received",
1179
+ "type": "u64"
1180
+ }
1181
+ ]
1182
+ }
1183
+ },
1184
+ {
1185
+ "name": "Vault",
1186
+ "type": {
1187
+ "kind": "struct",
1188
+ "fields": [
1189
+ {
1190
+ "name": "owner",
1191
+ "type": "pubkey"
1192
+ },
1193
+ {
1194
+ "name": "delegate",
1195
+ "type": "pubkey"
1196
+ },
1197
+ {
1198
+ "name": "agent_seed",
1199
+ "type": {
1200
+ "array": [
1201
+ "u8",
1202
+ 32
1203
+ ]
1204
+ }
1205
+ },
1206
+ {
1207
+ "name": "max_trade_lamports",
1208
+ "type": "u64"
1209
+ },
1210
+ {
1211
+ "name": "daily_limit_lamports",
1212
+ "type": "u64"
1213
+ },
1214
+ {
1215
+ "name": "day_start_ts",
1216
+ "type": "i64"
1217
+ },
1218
+ {
1219
+ "name": "day_spent_lamports",
1220
+ "type": "u64"
1221
+ },
1222
+ {
1223
+ "name": "last_trade_ts",
1224
+ "type": "i64"
1225
+ },
1226
+ {
1227
+ "name": "epoch",
1228
+ "type": "u64"
1229
+ },
1230
+ {
1231
+ "name": "paused",
1232
+ "type": "bool"
1233
+ },
1234
+ {
1235
+ "name": "oracle",
1236
+ "type": "pubkey"
1237
+ },
1238
+ {
1239
+ "name": "rule_feed",
1240
+ "type": {
1241
+ "array": [
1242
+ "u8",
1243
+ 32
1244
+ ]
1245
+ }
1246
+ },
1247
+ {
1248
+ "name": "rule_op",
1249
+ "type": "u8"
1250
+ },
1251
+ {
1252
+ "name": "rule_threshold",
1253
+ "type": "i64"
1254
+ },
1255
+ {
1256
+ "name": "rule_max_age",
1257
+ "type": "i64"
1258
+ },
1259
+ {
1260
+ "name": "rule_in_mint",
1261
+ "type": "pubkey"
1262
+ },
1263
+ {
1264
+ "name": "rule_out_mint",
1265
+ "type": "pubkey"
1266
+ },
1267
+ {
1268
+ "name": "max_slippage_bps",
1269
+ "type": "u16"
1270
+ },
1271
+ {
1272
+ "name": "allowed_programs",
1273
+ "type": {
1274
+ "array": [
1275
+ "pubkey",
1276
+ 4
1277
+ ]
1278
+ }
1279
+ },
1280
+ {
1281
+ "name": "bump",
1282
+ "type": "u8"
1283
+ }
1284
+ ]
1285
+ }
1286
+ },
1287
+ {
1288
+ "name": "VaultInitialized",
1289
+ "type": {
1290
+ "kind": "struct",
1291
+ "fields": [
1292
+ {
1293
+ "name": "vault",
1294
+ "type": "pubkey"
1295
+ },
1296
+ {
1297
+ "name": "owner",
1298
+ "type": "pubkey"
1299
+ },
1300
+ {
1301
+ "name": "delegate",
1302
+ "type": "pubkey"
1303
+ }
1304
+ ]
1305
+ }
1306
+ },
1307
+ {
1308
+ "name": "Withdrawn",
1309
+ "type": {
1310
+ "kind": "struct",
1311
+ "fields": [
1312
+ {
1313
+ "name": "vault",
1314
+ "type": "pubkey"
1315
+ },
1316
+ {
1317
+ "name": "to",
1318
+ "type": "pubkey"
1319
+ },
1320
+ {
1321
+ "name": "amount",
1322
+ "type": "u64"
1323
+ }
1324
+ ]
1325
+ }
1326
+ }
1327
+ ]
1328
+ };
1329
+ var idl_default = idl;
1330
+
1331
+ // src/vault-client.ts
1332
+ import * as anchor from "@anchor-lang/core";
1333
+ var TOKEN_PROGRAM_ID = new anchor.web3.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
1334
+ var TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
1335
+ var VAULT_SEED = Buffer.from("vault");
1336
+ var toBN = (n) => n instanceof anchor.BN ? n : new anchor.BN(n.toString());
1337
+ var seedBuf = (s) => {
1338
+ const b = Buffer.from(s);
1339
+ if (b.length !== 32) throw new Error(`agentSeed must be 32 bytes, got ${b.length}`);
1340
+ return b;
1341
+ };
1342
+ var VaultClient = class {
1343
+ program;
1344
+ programId;
1345
+ constructor(program) {
1346
+ this.program = program;
1347
+ this.programId = program.programId;
1348
+ }
1349
+ /** Derive the vault PDA for (owner, agentSeed). No private key exists for it — it's a program address. */
1350
+ vaultPda(owner, agentSeed) {
1351
+ return anchor.web3.PublicKey.findProgramAddressSync([VAULT_SEED, owner.toBuffer(), seedBuf(agentSeed)], this.programId)[0];
1352
+ }
1353
+ /** Fetch the on-chain vault state (config, delegate, rule, routes). */
1354
+ async fetch(ref) {
1355
+ return this.program.account.vault.fetch(this.vaultPda(ref.owner, ref.agentSeed));
1356
+ }
1357
+ // ── owner: lifecycle ─────────────────────────────────────────────────────────────
1358
+ /** Create a vault. The signer becomes the owner; `delegate` is the agent that may trade. */
1359
+ async initVault(p) {
1360
+ const vault = this.vaultPda(p.owner, p.agentSeed);
1361
+ const signature = await this.program.methods.initVault(Array.from(seedBuf(p.agentSeed)), p.delegate, toBN(p.maxTradeLamports), toBN(p.dailyLimitLamports)).accountsPartial({ vault, owner: p.owner, systemProgram: anchor.web3.SystemProgram.programId }).signers([p.ownerSigner]).rpc();
1362
+ return { vault, signature };
1363
+ }
1364
+ /** Fund the vault with SOL. Anyone may deposit; only the owner can take it back out. */
1365
+ async deposit(ref, depositor, amountLamports) {
1366
+ return this.program.methods.deposit(toBN(amountLamports)).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), depositor: depositor.publicKey, systemProgram: anchor.web3.SystemProgram.programId }).signers([depositor]).rpc();
1367
+ }
1368
+ /** OWNER-ONLY. Move SOL out of the vault to the owner. The only exit; the delegate has no path here. */
1369
+ async withdraw(ref, ownerSigner, amountLamports) {
1370
+ return this.program.methods.withdraw(toBN(amountLamports)).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1371
+ }
1372
+ /** OWNER-ONLY. Rotate or revoke the agent's trading key (bumps the fence epoch). */
1373
+ async setDelegate(ref, ownerSigner, newDelegate) {
1374
+ return this.program.methods.setDelegate(newDelegate).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1375
+ }
1376
+ /** OWNER-ONLY. Update trading policy + the pause kill-switch. Withdraw still works when paused. */
1377
+ async updateConfig(ref, ownerSigner, cfg) {
1378
+ return this.program.methods.updateConfig(toBN(cfg.maxTradeLamports), toBN(cfg.dailyLimitLamports), cfg.paused).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1379
+ }
1380
+ /** OWNER-ONLY. Restrict trading to an allowlist of audited routers (≤4). Empty = any program. */
1381
+ async setRoutes(ref, ownerSigner, programs) {
1382
+ return this.program.methods.setRoutes(programs).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1383
+ }
1384
+ /**
1385
+ * OWNER-ONLY. Commit (or clear) the Verified-Intents price rule. With a rule active, every trade
1386
+ * must carry a fresh oracle-signed price satisfying the condition (see `oracleAttestation`) AND —
1387
+ * if `inMint`/`outMint` are set — match that exact swap direction. `op: 0` clears the rule.
1388
+ */
1389
+ async setRule(ref, ownerSigner, rule) {
1390
+ return this.program.methods.setRule(
1391
+ rule.oracle,
1392
+ Array.from(seedBuf(rule.feed)),
1393
+ rule.op,
1394
+ toBN(rule.threshold),
1395
+ toBN(rule.maxAge),
1396
+ rule.inMint ?? anchor.web3.PublicKey.default,
1397
+ rule.outMint ?? anchor.web3.PublicKey.default,
1398
+ rule.maxSlippageBps ?? 0
1399
+ ).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1400
+ }
1401
+ /** OWNER-ONLY. Clear any committed rule (trades resume with no attestation). */
1402
+ async clearRule(ref, ownerSigner) {
1403
+ return this.setRule(ref, ownerSigner, { oracle: anchor.web3.PublicKey.default, feed: Buffer.alloc(32), op: 0, threshold: 0, maxAge: 0, maxSlippageBps: 0 });
1404
+ }
1405
+ /** OWNER-ONLY. Close the vault and return all remaining lamports to the owner. */
1406
+ async closeVault(ref, ownerSigner) {
1407
+ return this.program.methods.closeVault().accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), owner: ref.owner }).signers([ownerSigner]).rpc();
1408
+ }
1409
+ // ── wSOL ──────────────────────────────────────────────────────────────────────────
1410
+ /** OWNER-or-DELEGATE. Wrap SOL into the vault's wSOL account (funded from `actor`). */
1411
+ async wrapSol(ref, actor, wsol, amountLamports) {
1412
+ return this.program.methods.wrapSol(toBN(amountLamports)).accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), actor: actor.publicKey, wsol, tokenProgram: TOKEN_PROGRAM_ID, systemProgram: anchor.web3.SystemProgram.programId }).signers([actor]).rpc();
1413
+ }
1414
+ /** OWNER-or-DELEGATE. Unwrap: close the vault's wSOL account back to native SOL in the vault PDA. */
1415
+ async unwrapSol(ref, actor, wsol) {
1416
+ return this.program.methods.unwrapSol().accountsPartial({ vault: this.vaultPda(ref.owner, ref.agentSeed), actor: actor.publicKey, wsol, tokenProgram: TOKEN_PROGRAM_ID }).signers([actor]).rpc();
1417
+ }
1418
+ // ── delegate: the trade adapter ─────────────────────────────────────────────────────
1419
+ /**
1420
+ * DELEGATE-ONLY. Execute a swap through the guarded vault. `swapIx` is the DEX instruction for the
1421
+ * route the agent picked (Jupiter, Orca, a test AMM — any program); this wraps it as the vault's
1422
+ * guarded CPI and lets the on-chain guard verify the result (input spent ≤ amountIn, output
1423
+ * received ≥ minOut, nothing else moved, no authority change). The agent never touches a private key
1424
+ * that can withdraw — the worst it can do is a bad-but-bounded trade.
1425
+ */
1426
+ async trade(p) {
1427
+ const vault = this.vaultPda(p.owner, p.agentSeed);
1428
+ const remaining = p.swapIx.keys.map((k) => ({
1429
+ pubkey: k.pubkey,
1430
+ isSigner: k.isSigner && !k.pubkey.equals(vault),
1431
+ isWritable: k.isWritable
1432
+ }));
1433
+ const tradeIx = await this.program.methods.trade(toBN(p.amountIn), toBN(p.minOut), Buffer.from(p.swapIx.data)).accountsPartial({
1434
+ vault,
1435
+ delegate: p.delegate.publicKey,
1436
+ vaultInput: p.vaultInput,
1437
+ vaultOutput: p.vaultOutput,
1438
+ swapProgram: p.swapIx.programId,
1439
+ tokenProgram: p.tokenProgram ?? TOKEN_PROGRAM_ID,
1440
+ instructions: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY
1441
+ }).remainingAccounts(remaining).instruction();
1442
+ const provider = this.program.provider;
1443
+ const conn = provider.connection;
1444
+ const luts = (await Promise.all((p.addressLookupTables ?? []).map((a) => conn.getAddressLookupTable(a).then((r) => r.value)))).filter((x) => x != null);
1445
+ const instructions = [
1446
+ ...p.preInstructions ?? [],
1447
+ // e.g. Jupiter's compute-budget ixs (a real swap needs a raised CU limit)
1448
+ // The Verified-Intents attestation must be a sibling instruction BEFORE the trade so the runtime
1449
+ // verifies the Ed25519 signature and the vault can introspect which (pubkey, message) it covered.
1450
+ ...p.oracleIx ? [p.oracleIx] : [],
1451
+ tradeIx
1452
+ ];
1453
+ const { blockhash } = await conn.getLatestBlockhash();
1454
+ const msg = new anchor.web3.TransactionMessage({ payerKey: provider.wallet.publicKey, recentBlockhash: blockhash, instructions }).compileToV0Message(luts);
1455
+ return provider.sendAndConfirm(new anchor.web3.VersionedTransaction(msg), [p.delegate]);
1456
+ }
1457
+ /**
1458
+ * Build the Ed25519 attestation instruction a Verified-Intents trade must carry. The oracle signs
1459
+ * `feed(32) | price(i64 LE) | ts(i64 LE)`; the runtime verifies the signature and the vault confirms
1460
+ * which (pubkey, message) it covered. This is the on-chain half of the verified-intents mechanism.
1461
+ */
1462
+ static oracleAttestation(oracle, feed, price, tsUnixSecs) {
1463
+ const msg = Buffer.alloc(48);
1464
+ seedBuf(feed).copy(msg, 0);
1465
+ msg.writeBigInt64LE(BigInt(price.toString()), 32);
1466
+ msg.writeBigInt64LE(BigInt(tsUnixSecs.toString()), 40);
1467
+ return anchor.web3.Ed25519Program.createInstructionWithPrivateKey({ privateKey: oracle.secretKey, message: msg });
1468
+ }
1469
+ };
1470
+
1471
+ // src/jupiter.ts
1472
+ import * as anchor2 from "@anchor-lang/core";
1473
+ var JUPITER_V6 = "https://quote-api.jup.ag/v6";
1474
+ var jsonToIx = (j) => new anchor2.web3.TransactionInstruction({
1475
+ programId: new anchor2.web3.PublicKey(j.programId),
1476
+ keys: j.accounts.map((a) => ({ pubkey: new anchor2.web3.PublicKey(a.pubkey), isSigner: a.isSigner, isWritable: a.isWritable })),
1477
+ data: Buffer.from(j.data, "base64")
1478
+ });
1479
+ async function jupiterSwapInstruction(q, vaultAuthority, fetchFn = fetch) {
1480
+ const base = q.base ?? JUPITER_V6;
1481
+ const slippageBps = q.slippageBps ?? 100;
1482
+ const maxAccounts = q.maxAccounts ?? 28;
1483
+ const quoteUrl = `${base}/quote?inputMint=${q.inputMint.toBase58()}&outputMint=${q.outputMint.toBase58()}&amount=${q.amount.toString()}&slippageBps=${slippageBps}&onlyDirectRoutes=false&maxAccounts=${maxAccounts}` + (q.dexes ? `&dexes=${encodeURIComponent(q.dexes)}` : "");
1484
+ const quoteRes = await fetchFn(quoteUrl);
1485
+ if (!quoteRes.ok) throw new Error(`Jupiter quote failed: ${quoteRes.status} ${await quoteRes.text()}`);
1486
+ const quote = await quoteRes.json();
1487
+ const swapRes = await fetchFn(`${base}/swap-instructions`, {
1488
+ method: "POST",
1489
+ headers: { "Content-Type": "application/json" },
1490
+ body: JSON.stringify({ quoteResponse: quote, userPublicKey: vaultAuthority.toBase58(), wrapAndUnwrapSol: false })
1491
+ });
1492
+ if (!swapRes.ok) throw new Error(`Jupiter swap-instructions failed: ${swapRes.status} ${await swapRes.text()}`);
1493
+ const swap = await swapRes.json();
1494
+ if (!swap.swapInstruction) throw new Error("Jupiter returned no swapInstruction");
1495
+ const computeBudgetIxs = (swap.computeBudgetInstructions ?? []).map(jsonToIx);
1496
+ const setupIxs = (swap.setupInstructions ?? []).map(jsonToIx);
1497
+ return {
1498
+ swapIx: jsonToIx(swap.swapInstruction),
1499
+ inAmount: BigInt(quote.inAmount),
1500
+ minOut: BigInt(quote.otherAmountThreshold),
1501
+ // Jupiter's slippage-adjusted floor
1502
+ routeLabels: (quote.routePlan ?? []).map((r) => r?.swapInfo?.label).filter(Boolean),
1503
+ // The lookup tables this route needs to fit a v0 transaction. trade() includes these when it builds
1504
+ // the v0 tx (the legacy path only works for routes whose full account list fits 1232 bytes).
1505
+ addressLookupTables: (swap.addressLookupTableAddresses ?? []).map((a) => new anchor2.web3.PublicKey(a)),
1506
+ computeBudgetIxs,
1507
+ setupIxs
1508
+ };
1509
+ }
1510
+
1511
+ // src/executor.ts
1512
+ import * as anchor3 from "@anchor-lang/core";
1513
+ var DEFAULT_WSOL = new anchor3.web3.PublicKey("So11111111111111111111111111111111111111112");
1514
+ var LAMPORTS_PER_SOL = 1e9;
1515
+ function jupiterRouteSource(opts = {}) {
1516
+ return {
1517
+ async quote(p, vaultAuthority) {
1518
+ const r = await jupiterSwapInstruction({ ...p, base: opts.base }, vaultAuthority, opts.fetchFn ?? fetch);
1519
+ return { swapIx: r.swapIx, inAmount: r.inAmount, minOut: r.minOut, addressLookupTables: r.addressLookupTables, computeBudgetIxs: r.computeBudgetIxs };
1520
+ }
1521
+ };
1522
+ }
1523
+ function makeVaultExecutor(o) {
1524
+ const route = o.route ?? jupiterRouteSource();
1525
+ const wsol = o.wsolMint ?? DEFAULT_WSOL;
1526
+ const vault = o.client.vaultPda(o.owner, Buffer.from(o.agentSeed));
1527
+ return {
1528
+ async execute(intent, vi) {
1529
+ if (intent.kind !== "buy" && intent.kind !== "sell") throw new Error(`unsupported intent kind: ${intent.kind}`);
1530
+ if (!intent.token) throw new Error("intent.token (mint) is required");
1531
+ const token = new anchor3.web3.PublicKey(intent.token);
1532
+ const slippageBps = intent.maxSlippageBps ?? 100;
1533
+ const inputMint = intent.kind === "buy" ? wsol : token;
1534
+ const outputMint = intent.kind === "buy" ? token : wsol;
1535
+ const amount = intent.kind === "buy" ? BigInt(Math.round((intent.sizeSol ?? 0) * LAMPORTS_PER_SOL)) : BigInt(Math.trunc(intent.amount ?? 0));
1536
+ if (amount <= 0n) throw new Error("trade amount must be > 0 (buy needs sizeSol, sell needs amount)");
1537
+ const q = await route.quote({ inputMint, outputMint, amount, slippageBps }, vault);
1538
+ const inAta = o.ataFor(inputMint);
1539
+ const outAta = o.ataFor(outputMint);
1540
+ if (vi && !o.attest) throw new Error("verified intent requires an `attest` builder to produce the oracle attestation");
1541
+ const oracleIx = vi ? o.attest(vi) : void 0;
1542
+ const signature = await o.client.trade({
1543
+ owner: o.owner,
1544
+ agentSeed: o.agentSeed,
1545
+ delegate: o.delegate,
1546
+ vaultInput: inAta.account,
1547
+ vaultOutput: outAta.account,
1548
+ amountIn: q.inAmount,
1549
+ minOut: q.minOut,
1550
+ swapIx: q.swapIx,
1551
+ tokenProgram: inAta.tokenProgram ?? TOKEN_PROGRAM_ID,
1552
+ oracleIx,
1553
+ addressLookupTables: q.addressLookupTables,
1554
+ // real Jupiter routes → v0 tx with ALTs
1555
+ preInstructions: q.computeBudgetIxs
1556
+ // raise the CU limit for the swap
1557
+ });
1558
+ const solValue = intent.kind === "buy" ? Number(q.inAmount) / LAMPORTS_PER_SOL : Number(q.minOut) / LAMPORTS_PER_SOL;
1559
+ return { signature, solValue };
1560
+ }
1561
+ };
1562
+ }
1563
+
1564
+ // src/index.ts
1565
+ function loadVaultProgram(connection, wallet) {
1566
+ const provider = new anchor4.AnchorProvider(connection, wallet, { commitment: "confirmed", preflightCommitment: "confirmed" });
1567
+ return new anchor4.Program(idl_default, provider);
1568
+ }
1569
+ export {
1570
+ TOKEN_2022_PROGRAM_ID,
1571
+ TOKEN_PROGRAM_ID,
1572
+ VaultClient,
1573
+ jupiterRouteSource,
1574
+ jupiterSwapInstruction,
1575
+ loadVaultProgram,
1576
+ makeVaultExecutor
1577
+ };