@occa/sdk 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1627 @@
1
+ {
2
+ "address": "occaxyVLnurdjedWCBPrvDCCto8wGYadtTZ3nAmcVzh",
3
+ "metadata": {
4
+ "name": "treasury",
5
+ "version": "0.1.0",
6
+ "spec": "0.1.0",
7
+ "description": "OCCA Treasury — TreasuryAccount, PolicyAccount, OperationsAccount, ProtocolFeeAccount on Solana"
8
+ },
9
+ "instructions": [
10
+ {
11
+ "name": "close_operations",
12
+ "docs": [
13
+ "Close a revoked OperationsAccount and refund rent to the controlling",
14
+ "authority. Must be revoked first (terminal-state precondition makes",
15
+ "the rotation flow explicit + auditable)."
16
+ ],
17
+ "discriminator": [
18
+ 2,
19
+ 52,
20
+ 136,
21
+ 225,
22
+ 80,
23
+ 230,
24
+ 222,
25
+ 120
26
+ ],
27
+ "accounts": [
28
+ {
29
+ "name": "company",
30
+ "docs": [
31
+ "`controlling_authority` signer check happens in handler."
32
+ ]
33
+ },
34
+ {
35
+ "name": "controlling_authority",
36
+ "docs": [
37
+ "Receives rent refund."
38
+ ],
39
+ "writable": true,
40
+ "signer": true
41
+ },
42
+ {
43
+ "name": "operations",
44
+ "writable": true
45
+ }
46
+ ],
47
+ "args": []
48
+ },
49
+ {
50
+ "name": "disburse_discretionary",
51
+ "docs": [
52
+ "Discretionary-class disbursement to an agent's receiving address.",
53
+ "Signed by controlling authority (= company.owner). Used for ad-hoc",
54
+ "agent payouts outside of recurring routine flow.",
55
+ "",
56
+ "Same validation as routine except: no operations account, no rate",
57
+ "limit, no whitelist check. Budget check uses `discretionary_*`",
58
+ "counters. Fee always applies (intra-company agent destination)."
59
+ ],
60
+ "discriminator": [
61
+ 102,
62
+ 176,
63
+ 14,
64
+ 127,
65
+ 210,
66
+ 4,
67
+ 96,
68
+ 175
69
+ ],
70
+ "accounts": [
71
+ {
72
+ "name": "company"
73
+ },
74
+ {
75
+ "name": "controlling_authority",
76
+ "signer": true
77
+ },
78
+ {
79
+ "name": "treasury",
80
+ "writable": true,
81
+ "pda": {
82
+ "seeds": [
83
+ {
84
+ "kind": "const",
85
+ "value": [
86
+ 116,
87
+ 114,
88
+ 101,
89
+ 97,
90
+ 115,
91
+ 117,
92
+ 114,
93
+ 121
94
+ ]
95
+ },
96
+ {
97
+ "kind": "account",
98
+ "path": "company"
99
+ }
100
+ ]
101
+ }
102
+ },
103
+ {
104
+ "name": "policy",
105
+ "writable": true,
106
+ "pda": {
107
+ "seeds": [
108
+ {
109
+ "kind": "const",
110
+ "value": [
111
+ 112,
112
+ 111,
113
+ 108,
114
+ 105,
115
+ 99,
116
+ 121
117
+ ]
118
+ },
119
+ {
120
+ "kind": "account",
121
+ "path": "company"
122
+ }
123
+ ]
124
+ }
125
+ },
126
+ {
127
+ "name": "deployment"
128
+ },
129
+ {
130
+ "name": "destination",
131
+ "writable": true
132
+ },
133
+ {
134
+ "name": "protocol_fee_account",
135
+ "writable": true,
136
+ "pda": {
137
+ "seeds": [
138
+ {
139
+ "kind": "const",
140
+ "value": [
141
+ 112,
142
+ 114,
143
+ 111,
144
+ 116,
145
+ 111,
146
+ 99,
147
+ 111,
148
+ 108,
149
+ 95,
150
+ 102,
151
+ 101,
152
+ 101,
153
+ 115
154
+ ]
155
+ }
156
+ ]
157
+ }
158
+ }
159
+ ],
160
+ "args": [
161
+ {
162
+ "name": "mint",
163
+ "type": "pubkey"
164
+ },
165
+ {
166
+ "name": "amount",
167
+ "type": "u64"
168
+ }
169
+ ]
170
+ },
171
+ {
172
+ "name": "disburse_privileged",
173
+ "docs": [
174
+ "Privileged-class disbursement. Destination unrestricted: may be an",
175
+ "agent receiving address (fee applies) or any external pubkey (no fee).",
176
+ "Signed by controlling authority. Above-threshold amounts additionally",
177
+ "require the secondary signer registered in policy.",
178
+ "",
179
+ "`is_agent_destination`: if `true`, caller MUST pass the agent's",
180
+ "`Deployment` as `deployment` and the destination must equal",
181
+ "`deployment.receiving_address`. Fee deducted per §11.1.",
182
+ "If `false`, `deployment` should be omitted; no fee applies.",
183
+ "",
184
+ "No budget check — privileged class is unbudgeted by design (§3.2 has",
185
+ "no privileged_budget field)."
186
+ ],
187
+ "discriminator": [
188
+ 173,
189
+ 78,
190
+ 248,
191
+ 158,
192
+ 76,
193
+ 46,
194
+ 88,
195
+ 167
196
+ ],
197
+ "accounts": [
198
+ {
199
+ "name": "company"
200
+ },
201
+ {
202
+ "name": "controlling_authority",
203
+ "signer": true
204
+ },
205
+ {
206
+ "name": "secondary_signer",
207
+ "docs": [
208
+ "Required only when `amount > policy.privileged_threshold_lamports`",
209
+ "AND a `secondary_signer` is registered. Pass `None` for below-threshold",
210
+ "disbursements. Pubkey verified against `policy.secondary_signer` in handler."
211
+ ],
212
+ "signer": true,
213
+ "optional": true
214
+ },
215
+ {
216
+ "name": "treasury",
217
+ "writable": true,
218
+ "pda": {
219
+ "seeds": [
220
+ {
221
+ "kind": "const",
222
+ "value": [
223
+ 116,
224
+ 114,
225
+ 101,
226
+ 97,
227
+ 115,
228
+ 117,
229
+ 114,
230
+ 121
231
+ ]
232
+ },
233
+ {
234
+ "kind": "account",
235
+ "path": "company"
236
+ }
237
+ ]
238
+ }
239
+ },
240
+ {
241
+ "name": "policy",
242
+ "pda": {
243
+ "seeds": [
244
+ {
245
+ "kind": "const",
246
+ "value": [
247
+ 112,
248
+ 111,
249
+ 108,
250
+ 105,
251
+ 99,
252
+ 121
253
+ ]
254
+ },
255
+ {
256
+ "kind": "account",
257
+ "path": "company"
258
+ }
259
+ ]
260
+ }
261
+ },
262
+ {
263
+ "name": "deployment",
264
+ "docs": [
265
+ "Pass `Some(deployment_account)` when `is_agent_destination = true`.",
266
+ "Pass `None` for external destinations."
267
+ ],
268
+ "optional": true
269
+ },
270
+ {
271
+ "name": "destination",
272
+ "docs": [
273
+ "`deployment.receiving_address` only when `is_agent_destination = true`."
274
+ ],
275
+ "writable": true
276
+ },
277
+ {
278
+ "name": "protocol_fee_account",
279
+ "writable": true,
280
+ "pda": {
281
+ "seeds": [
282
+ {
283
+ "kind": "const",
284
+ "value": [
285
+ 112,
286
+ 114,
287
+ 111,
288
+ 116,
289
+ 111,
290
+ 99,
291
+ 111,
292
+ 108,
293
+ 95,
294
+ 102,
295
+ 101,
296
+ 101,
297
+ 115
298
+ ]
299
+ }
300
+ ]
301
+ }
302
+ }
303
+ ],
304
+ "args": [
305
+ {
306
+ "name": "mint",
307
+ "type": "pubkey"
308
+ },
309
+ {
310
+ "name": "amount",
311
+ "type": "u64"
312
+ },
313
+ {
314
+ "name": "is_agent_destination",
315
+ "type": "bool"
316
+ }
317
+ ]
318
+ },
319
+ {
320
+ "name": "disburse_routine",
321
+ "docs": [
322
+ "Routine-class disbursement to an agent's receiving address.",
323
+ "Signed by `OperationsAccount[Disbursement].signer` (operator-held key,",
324
+ "OCCA never holds the privkey). Per design §2, the FE constructs a",
325
+ "batched tx of multiple `disburse_routine` ixs (one per agent) and",
326
+ "the operator signs it manually each pay period.",
327
+ "",
328
+ "Validation pipeline (§4.4 row 1 + §7):",
329
+ "1. Mint is in `treasury.accepted_assets`.",
330
+ "2. Phase 1: mint == `SOL_PSEUDO_MINT` (SPL deferred per §2).",
331
+ "3. Destination matches `Deployment.receiving_address` and the",
332
+ "Deployment belongs to the same company.",
333
+ "4. OperationsAccount is not revoked, not expired.",
334
+ "5. This ix's discriminator is in `ops.action_whitelist`.",
335
+ "6. Lazy-rollover both `policy.current_period_anchor` and",
336
+ "`ops.current_period_anchor` to current month start.",
337
+ "7. `ops.signatures_this_period < ops.rate_limit_per_period`.",
338
+ "8. `routine_budget_per_month[mint] - routine_spent_this_period[mint] >= amount + fee`.",
339
+ "",
340
+ "Fee: always applies (intra-company agent destination per §11.1).",
341
+ "`fee = amount * agent_operating_fee_bps / 10_000`.",
342
+ "`gross = amount + fee` debited from treasury; `amount` to destination,",
343
+ "`fee` to ProtocolFeeAccount."
344
+ ],
345
+ "discriminator": [
346
+ 45,
347
+ 152,
348
+ 225,
349
+ 130,
350
+ 133,
351
+ 73,
352
+ 62,
353
+ 202
354
+ ],
355
+ "accounts": [
356
+ {
357
+ "name": "company"
358
+ },
359
+ {
360
+ "name": "treasury",
361
+ "writable": true,
362
+ "pda": {
363
+ "seeds": [
364
+ {
365
+ "kind": "const",
366
+ "value": [
367
+ 116,
368
+ 114,
369
+ 101,
370
+ 97,
371
+ 115,
372
+ 117,
373
+ 114,
374
+ 121
375
+ ]
376
+ },
377
+ {
378
+ "kind": "account",
379
+ "path": "company"
380
+ }
381
+ ]
382
+ }
383
+ },
384
+ {
385
+ "name": "policy",
386
+ "writable": true,
387
+ "pda": {
388
+ "seeds": [
389
+ {
390
+ "kind": "const",
391
+ "value": [
392
+ 112,
393
+ 111,
394
+ 108,
395
+ 105,
396
+ 99,
397
+ 121
398
+ ]
399
+ },
400
+ {
401
+ "kind": "account",
402
+ "path": "company"
403
+ }
404
+ ]
405
+ }
406
+ },
407
+ {
408
+ "name": "operations",
409
+ "writable": true
410
+ },
411
+ {
412
+ "name": "operations_signer",
413
+ "docs": [
414
+ "Disbursement Wallet — operator-held only. Pubkey verified via the",
415
+ "`operations.signer == operations_signer.key()` constraint above."
416
+ ],
417
+ "signer": true
418
+ },
419
+ {
420
+ "name": "deployment",
421
+ "docs": [
422
+ "Registry-owned Deployment whose `receiving_address` must equal",
423
+ "`destination.key()`. Field decoding done in handler."
424
+ ]
425
+ },
426
+ {
427
+ "name": "destination",
428
+ "docs": [
429
+ "Net amount lands here. Marked `mut` so its lamports balance can be",
430
+ "updated by direct manipulation (treasury PDA is owned by this program,",
431
+ "not System, so we can't use SystemProgram::transfer)."
432
+ ],
433
+ "writable": true
434
+ },
435
+ {
436
+ "name": "protocol_fee_account",
437
+ "writable": true,
438
+ "pda": {
439
+ "seeds": [
440
+ {
441
+ "kind": "const",
442
+ "value": [
443
+ 112,
444
+ 114,
445
+ 111,
446
+ 116,
447
+ 111,
448
+ 99,
449
+ 111,
450
+ 108,
451
+ 95,
452
+ 102,
453
+ 101,
454
+ 101,
455
+ 115
456
+ ]
457
+ }
458
+ ]
459
+ }
460
+ }
461
+ ],
462
+ "args": [
463
+ {
464
+ "name": "mint",
465
+ "type": "pubkey"
466
+ },
467
+ {
468
+ "name": "amount",
469
+ "type": "u64"
470
+ }
471
+ ]
472
+ },
473
+ {
474
+ "name": "init_protocol_fee_account",
475
+ "docs": [
476
+ "One-time singleton init for the protocol-wide fee accumulator. Called",
477
+ "once at program deployment by the upgrade authority. The `governance`",
478
+ "pubkey passed in is the long-lived withdrawal authority (e.g. a",
479
+ "multisig / DAO key) — it may differ from the deployer's upgrade key.",
480
+ "",
481
+ "Seeds: `[\"protocol_fees\"]` — singleton.",
482
+ "",
483
+ "Authorization: signer must equal the program's upgrade authority,",
484
+ "verified by reading the program's ProgramData PDA",
485
+ "(`upgrade_authority_address`). Prevents anyone from calling this ix",
486
+ "and pinning their own governance key on a fresh deploy."
487
+ ],
488
+ "discriminator": [
489
+ 214,
490
+ 27,
491
+ 184,
492
+ 174,
493
+ 155,
494
+ 79,
495
+ 141,
496
+ 114
497
+ ],
498
+ "accounts": [
499
+ {
500
+ "name": "protocol_fee_account",
501
+ "writable": true,
502
+ "pda": {
503
+ "seeds": [
504
+ {
505
+ "kind": "const",
506
+ "value": [
507
+ 112,
508
+ 114,
509
+ 111,
510
+ 116,
511
+ 111,
512
+ 99,
513
+ 111,
514
+ 108,
515
+ 95,
516
+ 102,
517
+ 101,
518
+ 101,
519
+ 115
520
+ ]
521
+ }
522
+ ]
523
+ }
524
+ },
525
+ {
526
+ "name": "authority",
527
+ "docs": [
528
+ "Upgrade authority of this program. Pays rent + signs."
529
+ ],
530
+ "writable": true,
531
+ "signer": true
532
+ },
533
+ {
534
+ "name": "program",
535
+ "docs": [
536
+ "This program's executable account — used to derive ProgramData PDA."
537
+ ],
538
+ "address": "occaxyVLnurdjedWCBPrvDCCto8wGYadtTZ3nAmcVzh"
539
+ },
540
+ {
541
+ "name": "program_data",
542
+ "docs": [
543
+ "ProgramData PDA — verifies `authority` is the actual upgrade authority."
544
+ ]
545
+ },
546
+ {
547
+ "name": "system_program",
548
+ "address": "11111111111111111111111111111111"
549
+ }
550
+ ],
551
+ "args": [
552
+ {
553
+ "name": "governance",
554
+ "type": "pubkey"
555
+ }
556
+ ]
557
+ },
558
+ {
559
+ "name": "init_treasury",
560
+ "docs": [
561
+ "Atomically create the TreasuryAccount + PolicyAccount PDA pair bound",
562
+ "to a CompanyAccount. Per design doc §6, both accounts are initialized",
563
+ "together so a company never exists in a state where treasury is set",
564
+ "but policy is not (or vice versa).",
565
+ "",
566
+ "Seeds:",
567
+ "• treasury: `[\"treasury\", company_pda]`",
568
+ "• policy: `[\"policy\", company_pda]`",
569
+ "",
570
+ "Phase 1 defaults (per §2 + §3.2):",
571
+ "• treasury.accepted_assets = `[SOL_PSEUDO_MINT]` — SPL mints added",
572
+ "later via Privileged-class `set_policy`.",
573
+ "• policy budgets = empty (nothing disbursable until operator calls",
574
+ "`set_policy`).",
575
+ "• policy.privileged_threshold_lamports = `u64::MAX` — secondary",
576
+ "signer never required by default.",
577
+ "• policy.agent_operating_fee_bps = `DEFAULT_AGENT_OPERATING_FEE_BPS`",
578
+ "(300 bps = 3%).",
579
+ "• policy.current_period_anchor = 0 — lazy-initialized on first",
580
+ "disbursement.",
581
+ "",
582
+ "Authorization model (M5): canonical invocation is via CPI from",
583
+ "`registry::create_company`. Direct calls remain technically allowed",
584
+ "— there is no controlling-authority check here because Anchor does",
585
+ "not flush `Account<T>` mutations to the underlying data buffer until",
586
+ "handler exit, so reading `company.owner` mid-CPI returns stale bytes.",
587
+ "The omitted check is *safe* because:",
588
+ "1. Defaults written by this ix are identical regardless of caller.",
589
+ "2. PDA seeds pin treasury+policy to the company; re-init is impossible.",
590
+ "3. All subsequent operations (`set_policy`, `disburse_*`,",
591
+ "`register_*`) verify controlling_authority against `company.owner`.",
592
+ "The worst an attacker can do is burn rent (~0.005 SOL) to pre-init a",
593
+ "stranger's treasury with the same defaults the legitimate owner would",
594
+ "have gotten anyway."
595
+ ],
596
+ "discriminator": [
597
+ 105,
598
+ 152,
599
+ 173,
600
+ 51,
601
+ 158,
602
+ 151,
603
+ 49,
604
+ 14
605
+ ],
606
+ "accounts": [
607
+ {
608
+ "name": "company",
609
+ "docs": [
610
+ "CompanyAccount this treasury+policy bind to. Program-owner match",
611
+ "enforced — must be a real Registry-owned account, not a forgery."
612
+ ]
613
+ },
614
+ {
615
+ "name": "treasury",
616
+ "writable": true,
617
+ "pda": {
618
+ "seeds": [
619
+ {
620
+ "kind": "const",
621
+ "value": [
622
+ 116,
623
+ 114,
624
+ 101,
625
+ 97,
626
+ 115,
627
+ 117,
628
+ 114,
629
+ 121
630
+ ]
631
+ },
632
+ {
633
+ "kind": "account",
634
+ "path": "company"
635
+ }
636
+ ]
637
+ }
638
+ },
639
+ {
640
+ "name": "policy",
641
+ "writable": true,
642
+ "pda": {
643
+ "seeds": [
644
+ {
645
+ "kind": "const",
646
+ "value": [
647
+ 112,
648
+ 111,
649
+ 108,
650
+ 105,
651
+ 99,
652
+ 121
653
+ ]
654
+ },
655
+ {
656
+ "kind": "account",
657
+ "path": "company"
658
+ }
659
+ ]
660
+ }
661
+ },
662
+ {
663
+ "name": "payer",
664
+ "docs": [
665
+ "Pays rent for both PDAs. Direct call: operator hot wallet. CPI from",
666
+ "`registry::create_company`: the same `payer` account from registry's",
667
+ "outer ix is forwarded through."
668
+ ],
669
+ "writable": true,
670
+ "signer": true
671
+ },
672
+ {
673
+ "name": "system_program",
674
+ "address": "11111111111111111111111111111111"
675
+ }
676
+ ],
677
+ "args": []
678
+ },
679
+ {
680
+ "name": "register_company_operations",
681
+ "docs": [
682
+ "Register a company-scoped operations key (Disbursement | Anchor).",
683
+ "Privileged class — signed by controlling authority (= company.owner).",
684
+ "",
685
+ "Seeds: `[\"operations\", company_pda, &[kind.as_byte()]]`.",
686
+ "Up to 2 per company: one Disbursement, one Anchor (§3.3).",
687
+ "",
688
+ "Phase 1 scope: company-scoped only. `register_agent_operations` is",
689
+ "deferred to Phase 2+ per design §2 — per-agent operations keys are",
690
+ "not needed until marketplace settlement.",
691
+ "",
692
+ "`action_whitelist`: 8-byte Anchor instruction discriminators allowed",
693
+ "to be signed by this key. Caller is responsible for computing them",
694
+ "off-chain (e.g. `sha256(\"global:disburse_routine\")[0..8]`). Expected",
695
+ "values per design §3.3:",
696
+ "• Disbursement: `[disburse_routine]`",
697
+ "• Anchor: `[commit_daily_anchor]` (lives in Registry program)",
698
+ "",
699
+ "`expiry_unix`: `0` for no expiry, otherwise must be in the future.",
700
+ "`rate_limit_per_period`: max signatures per calendar month (lazily",
701
+ "rolled over inside the ix being signed, in M4+)."
702
+ ],
703
+ "discriminator": [
704
+ 212,
705
+ 173,
706
+ 142,
707
+ 23,
708
+ 28,
709
+ 221,
710
+ 55,
711
+ 99
712
+ ],
713
+ "accounts": [
714
+ {
715
+ "name": "company",
716
+ "docs": [
717
+ "`controlling_authority` signer check happens in handler."
718
+ ]
719
+ },
720
+ {
721
+ "name": "controlling_authority",
722
+ "docs": [
723
+ "Controlling Authority — must equal `CompanyAccount.owner`."
724
+ ],
725
+ "signer": true
726
+ },
727
+ {
728
+ "name": "operations",
729
+ "writable": true
730
+ },
731
+ {
732
+ "name": "payer",
733
+ "docs": [
734
+ "Pays rent. Typically the operator hot wallet."
735
+ ],
736
+ "writable": true,
737
+ "signer": true
738
+ },
739
+ {
740
+ "name": "system_program",
741
+ "address": "11111111111111111111111111111111"
742
+ }
743
+ ],
744
+ "args": [
745
+ {
746
+ "name": "kind",
747
+ "type": {
748
+ "defined": {
749
+ "name": "OperationsKind"
750
+ }
751
+ }
752
+ },
753
+ {
754
+ "name": "signer",
755
+ "type": "pubkey"
756
+ },
757
+ {
758
+ "name": "action_whitelist",
759
+ "type": {
760
+ "vec": {
761
+ "array": [
762
+ "u8",
763
+ 8
764
+ ]
765
+ }
766
+ }
767
+ },
768
+ {
769
+ "name": "rate_limit_per_period",
770
+ "type": "u32"
771
+ },
772
+ {
773
+ "name": "expiry_unix",
774
+ "type": "i64"
775
+ }
776
+ ]
777
+ },
778
+ {
779
+ "name": "revoke_operations",
780
+ "docs": [
781
+ "Mark an OperationsAccount revoked. Terminal flag — once set, no",
782
+ "further signatures via this account are accepted (M4+ disburse",
783
+ "handlers reject `ops.revoked == true`). Privileged class.",
784
+ "",
785
+ "Rotation flow: `revoke_operations` → `close_operations` (refunds",
786
+ "rent) → `register_company_operations` with the new signer pubkey."
787
+ ],
788
+ "discriminator": [
789
+ 141,
790
+ 196,
791
+ 241,
792
+ 103,
793
+ 182,
794
+ 146,
795
+ 117,
796
+ 183
797
+ ],
798
+ "accounts": [
799
+ {
800
+ "name": "company",
801
+ "docs": [
802
+ "`controlling_authority` signer check happens in handler."
803
+ ]
804
+ },
805
+ {
806
+ "name": "controlling_authority",
807
+ "signer": true
808
+ },
809
+ {
810
+ "name": "operations",
811
+ "writable": true
812
+ }
813
+ ],
814
+ "args": []
815
+ },
816
+ {
817
+ "name": "set_policy",
818
+ "docs": [
819
+ "Update policy fields and/or treasury's accepted-asset list.",
820
+ "Privileged class (§4.2 + §7) — signed by controlling authority.",
821
+ "",
822
+ "Each field in `params` is `Option<T>`: `None` = no change, `Some(v)`",
823
+ "= set. `secondary_signer` is `Option<Option<Pubkey>>` so the caller",
824
+ "can distinguish \"leave unchanged\" (outer `None`), \"clear\" (outer",
825
+ "`Some(None)`), and \"set\" (outer `Some(Some(pk))`).",
826
+ "",
827
+ "Validation: fee bps ≤ 10_000; vec lengths ≤ MAX_*; mint uniqueness",
828
+ "inside any single vec. Period rollover is NOT performed here — spent",
829
+ "counters are only touched by disbursement instructions (M4+)."
830
+ ],
831
+ "discriminator": [
832
+ 40,
833
+ 133,
834
+ 12,
835
+ 157,
836
+ 235,
837
+ 202,
838
+ 2,
839
+ 132
840
+ ],
841
+ "accounts": [
842
+ {
843
+ "name": "company",
844
+ "docs": [
845
+ "CompanyAccount this policy/treasury belong to."
846
+ ]
847
+ },
848
+ {
849
+ "name": "controlling_authority",
850
+ "docs": [
851
+ "Controlling Authority — must equal `CompanyAccount.owner`."
852
+ ],
853
+ "signer": true
854
+ },
855
+ {
856
+ "name": "treasury",
857
+ "writable": true,
858
+ "pda": {
859
+ "seeds": [
860
+ {
861
+ "kind": "const",
862
+ "value": [
863
+ 116,
864
+ 114,
865
+ 101,
866
+ 97,
867
+ 115,
868
+ 117,
869
+ 114,
870
+ 121
871
+ ]
872
+ },
873
+ {
874
+ "kind": "account",
875
+ "path": "company"
876
+ }
877
+ ]
878
+ }
879
+ },
880
+ {
881
+ "name": "policy",
882
+ "writable": true,
883
+ "pda": {
884
+ "seeds": [
885
+ {
886
+ "kind": "const",
887
+ "value": [
888
+ 112,
889
+ 111,
890
+ 108,
891
+ 105,
892
+ 99,
893
+ 121
894
+ ]
895
+ },
896
+ {
897
+ "kind": "account",
898
+ "path": "company"
899
+ }
900
+ ]
901
+ }
902
+ }
903
+ ],
904
+ "args": [
905
+ {
906
+ "name": "params",
907
+ "type": {
908
+ "defined": {
909
+ "name": "SetPolicyParams"
910
+ }
911
+ }
912
+ }
913
+ ]
914
+ },
915
+ {
916
+ "name": "update_operations_capability",
917
+ "docs": [
918
+ "Modify an OperationsAccount's whitelist / rate limit / expiry without",
919
+ "rotating the signer pubkey. Privileged class.",
920
+ "",
921
+ "Each field of `params` is `Option<T>`: `None` = leave unchanged.",
922
+ "To rotate the `signer` pubkey, the operator must `revoke_operations`",
923
+ "→ `close_operations` → `register_company_operations` with the new",
924
+ "pubkey. This forces an audit trail across pubkey rotation events.",
925
+ "",
926
+ "Allowed on expired ops (operator can extend expiry to revive).",
927
+ "Rejected on revoked ops (terminal state — must close + recreate)."
928
+ ],
929
+ "discriminator": [
930
+ 21,
931
+ 13,
932
+ 197,
933
+ 41,
934
+ 92,
935
+ 229,
936
+ 142,
937
+ 202
938
+ ],
939
+ "accounts": [
940
+ {
941
+ "name": "company",
942
+ "docs": [
943
+ "`controlling_authority` signer check happens in handler."
944
+ ]
945
+ },
946
+ {
947
+ "name": "controlling_authority",
948
+ "signer": true
949
+ },
950
+ {
951
+ "name": "operations",
952
+ "writable": true
953
+ }
954
+ ],
955
+ "args": [
956
+ {
957
+ "name": "params",
958
+ "type": {
959
+ "defined": {
960
+ "name": "UpdateOperationsCapabilityParams"
961
+ }
962
+ }
963
+ }
964
+ ]
965
+ }
966
+ ],
967
+ "accounts": [
968
+ {
969
+ "name": "OperationsAccount",
970
+ "discriminator": [
971
+ 185,
972
+ 55,
973
+ 148,
974
+ 90,
975
+ 151,
976
+ 227,
977
+ 104,
978
+ 158
979
+ ]
980
+ },
981
+ {
982
+ "name": "PolicyAccount",
983
+ "discriminator": [
984
+ 218,
985
+ 201,
986
+ 183,
987
+ 164,
988
+ 156,
989
+ 127,
990
+ 81,
991
+ 175
992
+ ]
993
+ },
994
+ {
995
+ "name": "ProtocolFeeAccount",
996
+ "discriminator": [
997
+ 5,
998
+ 171,
999
+ 24,
1000
+ 9,
1001
+ 150,
1002
+ 135,
1003
+ 135,
1004
+ 201
1005
+ ]
1006
+ },
1007
+ {
1008
+ "name": "TreasuryAccount",
1009
+ "discriminator": [
1010
+ 204,
1011
+ 140,
1012
+ 18,
1013
+ 173,
1014
+ 90,
1015
+ 152,
1016
+ 134,
1017
+ 123
1018
+ ]
1019
+ }
1020
+ ],
1021
+ "errors": [
1022
+ {
1023
+ "code": 6000,
1024
+ "name": "CompanyOwnerMismatch",
1025
+ "msg": "company account is not owned by the Registry program"
1026
+ },
1027
+ {
1028
+ "code": 6001,
1029
+ "name": "InvalidCompanyAccount",
1030
+ "msg": "company account data is malformed or too short"
1031
+ },
1032
+ {
1033
+ "code": 6002,
1034
+ "name": "IncompatibleCompanyVersion",
1035
+ "msg": "company account version is not supported by this program"
1036
+ },
1037
+ {
1038
+ "code": 6003,
1039
+ "name": "InvalidProgramData",
1040
+ "msg": "ProgramData account does not match this program"
1041
+ },
1042
+ {
1043
+ "code": 6004,
1044
+ "name": "NotUpgradeAuthority",
1045
+ "msg": "signer is not the program's upgrade authority"
1046
+ },
1047
+ {
1048
+ "code": 6005,
1049
+ "name": "UnauthorizedSigner",
1050
+ "msg": "signer is not authorized for this instruction"
1051
+ },
1052
+ {
1053
+ "code": 6006,
1054
+ "name": "PolicyMismatch",
1055
+ "msg": "policy/treasury does not match company"
1056
+ },
1057
+ {
1058
+ "code": 6007,
1059
+ "name": "TooManyEntries",
1060
+ "msg": "vector exceeds maximum length"
1061
+ },
1062
+ {
1063
+ "code": 6008,
1064
+ "name": "DuplicateMint",
1065
+ "msg": "duplicate mint in vector"
1066
+ },
1067
+ {
1068
+ "code": 6009,
1069
+ "name": "InvalidFeeBps",
1070
+ "msg": "fee bps exceeds 10000 (100%)"
1071
+ },
1072
+ {
1073
+ "code": 6010,
1074
+ "name": "InvalidSigner",
1075
+ "msg": "operations account signer cannot be the default pubkey"
1076
+ },
1077
+ {
1078
+ "code": 6011,
1079
+ "name": "EmptyWhitelist",
1080
+ "msg": "operations account requires at least one whitelisted action"
1081
+ },
1082
+ {
1083
+ "code": 6012,
1084
+ "name": "ExpiryInPast",
1085
+ "msg": "expiry timestamp must be in the future or zero"
1086
+ },
1087
+ {
1088
+ "code": 6013,
1089
+ "name": "OperationsRevoked",
1090
+ "msg": "operations account is revoked"
1091
+ },
1092
+ {
1093
+ "code": 6014,
1094
+ "name": "AlreadyRevoked",
1095
+ "msg": "operations account is already revoked"
1096
+ },
1097
+ {
1098
+ "code": 6015,
1099
+ "name": "NotRevoked",
1100
+ "msg": "operations account must be revoked before closing"
1101
+ },
1102
+ {
1103
+ "code": 6016,
1104
+ "name": "WrongOperationsKind",
1105
+ "msg": "operations account kind does not match instruction expectation"
1106
+ },
1107
+ {
1108
+ "code": 6017,
1109
+ "name": "OperationsExpired",
1110
+ "msg": "operations account is past its expiry"
1111
+ },
1112
+ {
1113
+ "code": 6018,
1114
+ "name": "DiscriminatorNotWhitelisted",
1115
+ "msg": "instruction discriminator is not whitelisted on operations account"
1116
+ },
1117
+ {
1118
+ "code": 6019,
1119
+ "name": "RateLimitExceeded",
1120
+ "msg": "rate limit for operations account is exhausted this period"
1121
+ },
1122
+ {
1123
+ "code": 6020,
1124
+ "name": "ZeroAmount",
1125
+ "msg": "disbursement amount must be greater than zero"
1126
+ },
1127
+ {
1128
+ "code": 6021,
1129
+ "name": "SplNotSupported",
1130
+ "msg": "SPL token disbursement is not yet supported (Phase 1 SOL only)"
1131
+ },
1132
+ {
1133
+ "code": 6022,
1134
+ "name": "AssetNotAllowListed",
1135
+ "msg": "mint is not in treasury accepted_assets list"
1136
+ },
1137
+ {
1138
+ "code": 6023,
1139
+ "name": "AssetNotBudgeted",
1140
+ "msg": "no budget configured for this asset"
1141
+ },
1142
+ {
1143
+ "code": 6024,
1144
+ "name": "BudgetExceeded",
1145
+ "msg": "budget remaining is insufficient for this disbursement"
1146
+ },
1147
+ {
1148
+ "code": 6025,
1149
+ "name": "InsufficientFunds",
1150
+ "msg": "treasury balance is insufficient (rent-exempt minimum protected)"
1151
+ },
1152
+ {
1153
+ "code": 6026,
1154
+ "name": "ArithmeticOverflow",
1155
+ "msg": "arithmetic overflow"
1156
+ },
1157
+ {
1158
+ "code": 6027,
1159
+ "name": "InvalidDeploymentAccount",
1160
+ "msg": "deployment account data is malformed or too short"
1161
+ },
1162
+ {
1163
+ "code": 6028,
1164
+ "name": "IncompatibleDeploymentVersion",
1165
+ "msg": "deployment account version is not supported by this program"
1166
+ },
1167
+ {
1168
+ "code": 6029,
1169
+ "name": "DeploymentCompanyMismatch",
1170
+ "msg": "deployment does not belong to this company"
1171
+ },
1172
+ {
1173
+ "code": 6030,
1174
+ "name": "DestinationMismatch",
1175
+ "msg": "destination does not match deployment.receiving_address"
1176
+ },
1177
+ {
1178
+ "code": 6031,
1179
+ "name": "ReceivingAddressUnset",
1180
+ "msg": "deployment.receiving_address has not been set"
1181
+ },
1182
+ {
1183
+ "code": 6032,
1184
+ "name": "SecondarySignerRequired",
1185
+ "msg": "disbursement above threshold requires secondary signer"
1186
+ },
1187
+ {
1188
+ "code": 6033,
1189
+ "name": "SecondarySignerMismatch",
1190
+ "msg": "provided secondary signer does not match policy.secondary_signer"
1191
+ },
1192
+ {
1193
+ "code": 6034,
1194
+ "name": "MissingDeploymentForAgentDestination",
1195
+ "msg": "agent destination flag set but no deployment account provided"
1196
+ }
1197
+ ],
1198
+ "types": [
1199
+ {
1200
+ "name": "AssetBudget",
1201
+ "type": {
1202
+ "kind": "struct",
1203
+ "fields": [
1204
+ {
1205
+ "name": "mint",
1206
+ "docs": [
1207
+ "SPL mint pubkey — `SOL_PSEUDO_MINT` for SOL."
1208
+ ],
1209
+ "type": "pubkey"
1210
+ },
1211
+ {
1212
+ "name": "amount",
1213
+ "docs": [
1214
+ "Amount in lamports (SOL) or base units (SPL)."
1215
+ ],
1216
+ "type": "u64"
1217
+ }
1218
+ ]
1219
+ }
1220
+ },
1221
+ {
1222
+ "name": "OperationsAccount",
1223
+ "type": {
1224
+ "kind": "struct",
1225
+ "fields": [
1226
+ {
1227
+ "name": "version",
1228
+ "type": "u8"
1229
+ },
1230
+ {
1231
+ "name": "company",
1232
+ "type": "pubkey"
1233
+ },
1234
+ {
1235
+ "name": "kind",
1236
+ "docs": [
1237
+ "What kind of operations key this is (Disbursement | Anchor).",
1238
+ "Also encoded into the PDA seed so each company can host one of each."
1239
+ ],
1240
+ "type": {
1241
+ "defined": {
1242
+ "name": "OperationsKind"
1243
+ }
1244
+ }
1245
+ },
1246
+ {
1247
+ "name": "signer",
1248
+ "docs": [
1249
+ "Pubkey of the registered wallet:",
1250
+ "• Disbursement: operator-held only — OCCA never holds the privkey.",
1251
+ "• Anchor: shared session key — operator + OCCA both hold privkey,",
1252
+ "either can sign `commit_daily_anchor` (capability-scoped)."
1253
+ ],
1254
+ "type": "pubkey"
1255
+ },
1256
+ {
1257
+ "name": "action_whitelist",
1258
+ "docs": [
1259
+ "Whitelist of allowed instruction discriminators (8-byte Anchor",
1260
+ "discriminators). Defaults set at registration:",
1261
+ "• Disbursement: `[disburse_routine]`",
1262
+ "• Anchor: `[commit_daily_anchor]` (lives in Registry program)"
1263
+ ],
1264
+ "type": {
1265
+ "vec": {
1266
+ "array": [
1267
+ "u8",
1268
+ 8
1269
+ ]
1270
+ }
1271
+ }
1272
+ },
1273
+ {
1274
+ "name": "rate_limit_per_period",
1275
+ "type": "u32"
1276
+ },
1277
+ {
1278
+ "name": "signatures_this_period",
1279
+ "type": "u32"
1280
+ },
1281
+ {
1282
+ "name": "current_period_anchor",
1283
+ "docs": [
1284
+ "Unix timestamp of start-of-current-month UTC. `0` = uninitialized."
1285
+ ],
1286
+ "type": "i64"
1287
+ },
1288
+ {
1289
+ "name": "expiry_unix",
1290
+ "docs": [
1291
+ "Hard expiry (unix timestamp). `0` = no expiry."
1292
+ ],
1293
+ "type": "i64"
1294
+ },
1295
+ {
1296
+ "name": "revoked",
1297
+ "docs": [
1298
+ "Once true, all future signatures via this account are rejected.",
1299
+ "Rotation flow: revoke → close → re-create with new `signer`."
1300
+ ],
1301
+ "type": "bool"
1302
+ },
1303
+ {
1304
+ "name": "bump",
1305
+ "type": "u8"
1306
+ }
1307
+ ]
1308
+ }
1309
+ },
1310
+ {
1311
+ "name": "OperationsKind",
1312
+ "type": {
1313
+ "kind": "enum",
1314
+ "variants": [
1315
+ {
1316
+ "name": "Disbursement"
1317
+ },
1318
+ {
1319
+ "name": "Anchor"
1320
+ }
1321
+ ]
1322
+ }
1323
+ },
1324
+ {
1325
+ "name": "PolicyAccount",
1326
+ "type": {
1327
+ "kind": "struct",
1328
+ "fields": [
1329
+ {
1330
+ "name": "version",
1331
+ "type": "u8"
1332
+ },
1333
+ {
1334
+ "name": "company",
1335
+ "type": "pubkey"
1336
+ },
1337
+ {
1338
+ "name": "routine_budget_per_month",
1339
+ "docs": [
1340
+ "Max disbursable per calendar month via Routine class (auto-signed by",
1341
+ "OperationsAccount[Disbursement])."
1342
+ ],
1343
+ "type": {
1344
+ "vec": {
1345
+ "defined": {
1346
+ "name": "AssetBudget"
1347
+ }
1348
+ }
1349
+ }
1350
+ },
1351
+ {
1352
+ "name": "discretionary_budget_per_month",
1353
+ "docs": [
1354
+ "Max disbursable per calendar month via Discretionary class",
1355
+ "(operator-signed, e.g. ad-hoc agent payouts)."
1356
+ ],
1357
+ "type": {
1358
+ "vec": {
1359
+ "defined": {
1360
+ "name": "AssetBudget"
1361
+ }
1362
+ }
1363
+ }
1364
+ },
1365
+ {
1366
+ "name": "privileged_threshold_lamports",
1367
+ "docs": [
1368
+ "Privileged disbursements above this lamport amount require both",
1369
+ "controlling authority + secondary signer. Default `u64::MAX` (no",
1370
+ "threshold trip until operator opts in)."
1371
+ ],
1372
+ "type": "u64"
1373
+ },
1374
+ {
1375
+ "name": "privileged_threshold_per_token",
1376
+ "docs": [
1377
+ "Per-SPL-token equivalent of `privileged_threshold_lamports`. Empty",
1378
+ "vec = no per-token threshold configured."
1379
+ ],
1380
+ "type": {
1381
+ "vec": {
1382
+ "defined": {
1383
+ "name": "AssetBudget"
1384
+ }
1385
+ }
1386
+ }
1387
+ },
1388
+ {
1389
+ "name": "secondary_signer",
1390
+ "docs": [
1391
+ "Secondary signer pubkey. `None` = unconfigured; any threshold-crossing",
1392
+ "privileged ix will reject until set."
1393
+ ],
1394
+ "type": {
1395
+ "option": "pubkey"
1396
+ }
1397
+ },
1398
+ {
1399
+ "name": "agent_operating_fee_bps",
1400
+ "docs": [
1401
+ "Fee in basis points (300 = 3%). Mutable via `set_policy`. Routes to",
1402
+ "`ProtocolFeeAccount` when destination is a `Deployment.receiving_address`",
1403
+ "under the same company."
1404
+ ],
1405
+ "type": "u16"
1406
+ },
1407
+ {
1408
+ "name": "current_period_anchor",
1409
+ "docs": [
1410
+ "Unix timestamp of start-of-current-month UTC. `0` = uninitialized;",
1411
+ "first disbursement after init lazy-rolls to current month start."
1412
+ ],
1413
+ "type": "i64"
1414
+ },
1415
+ {
1416
+ "name": "routine_spent_this_period",
1417
+ "type": {
1418
+ "vec": {
1419
+ "defined": {
1420
+ "name": "AssetBudget"
1421
+ }
1422
+ }
1423
+ }
1424
+ },
1425
+ {
1426
+ "name": "discretionary_spent_this_period",
1427
+ "type": {
1428
+ "vec": {
1429
+ "defined": {
1430
+ "name": "AssetBudget"
1431
+ }
1432
+ }
1433
+ }
1434
+ },
1435
+ {
1436
+ "name": "bump",
1437
+ "type": "u8"
1438
+ }
1439
+ ]
1440
+ }
1441
+ },
1442
+ {
1443
+ "name": "ProtocolFeeAccount",
1444
+ "type": {
1445
+ "kind": "struct",
1446
+ "fields": [
1447
+ {
1448
+ "name": "version",
1449
+ "type": "u8"
1450
+ },
1451
+ {
1452
+ "name": "governance",
1453
+ "docs": [
1454
+ "Long-lived withdrawal authority — typically a DAO / multisig key,",
1455
+ "distinct from the program's upgrade authority. Settable only at init."
1456
+ ],
1457
+ "type": "pubkey"
1458
+ },
1459
+ {
1460
+ "name": "balances",
1461
+ "docs": [
1462
+ "Per-asset accumulated fee balances."
1463
+ ],
1464
+ "type": {
1465
+ "vec": {
1466
+ "defined": {
1467
+ "name": "AssetBudget"
1468
+ }
1469
+ }
1470
+ }
1471
+ },
1472
+ {
1473
+ "name": "bump",
1474
+ "type": "u8"
1475
+ }
1476
+ ]
1477
+ }
1478
+ },
1479
+ {
1480
+ "name": "SetPolicyParams",
1481
+ "docs": [
1482
+ "Parameter bag for `set_policy`. Each field is `Option<T>`: `None` =",
1483
+ "\"leave unchanged\", `Some(v)` = \"set to v\". `secondary_signer` is doubly",
1484
+ "optional (outer = include in update; inner = new value, with `None` =",
1485
+ "clear and `Some(pk)` = set)."
1486
+ ],
1487
+ "type": {
1488
+ "kind": "struct",
1489
+ "fields": [
1490
+ {
1491
+ "name": "routine_budget_per_month",
1492
+ "type": {
1493
+ "option": {
1494
+ "vec": {
1495
+ "defined": {
1496
+ "name": "AssetBudget"
1497
+ }
1498
+ }
1499
+ }
1500
+ }
1501
+ },
1502
+ {
1503
+ "name": "discretionary_budget_per_month",
1504
+ "type": {
1505
+ "option": {
1506
+ "vec": {
1507
+ "defined": {
1508
+ "name": "AssetBudget"
1509
+ }
1510
+ }
1511
+ }
1512
+ }
1513
+ },
1514
+ {
1515
+ "name": "privileged_threshold_lamports",
1516
+ "type": {
1517
+ "option": "u64"
1518
+ }
1519
+ },
1520
+ {
1521
+ "name": "privileged_threshold_per_token",
1522
+ "type": {
1523
+ "option": {
1524
+ "vec": {
1525
+ "defined": {
1526
+ "name": "AssetBudget"
1527
+ }
1528
+ }
1529
+ }
1530
+ }
1531
+ },
1532
+ {
1533
+ "name": "secondary_signer",
1534
+ "type": {
1535
+ "option": {
1536
+ "option": "pubkey"
1537
+ }
1538
+ }
1539
+ },
1540
+ {
1541
+ "name": "agent_operating_fee_bps",
1542
+ "type": {
1543
+ "option": "u16"
1544
+ }
1545
+ },
1546
+ {
1547
+ "name": "accepted_assets",
1548
+ "type": {
1549
+ "option": {
1550
+ "vec": "pubkey"
1551
+ }
1552
+ }
1553
+ }
1554
+ ]
1555
+ }
1556
+ },
1557
+ {
1558
+ "name": "TreasuryAccount",
1559
+ "type": {
1560
+ "kind": "struct",
1561
+ "fields": [
1562
+ {
1563
+ "name": "version",
1564
+ "type": "u8"
1565
+ },
1566
+ {
1567
+ "name": "company",
1568
+ "type": "pubkey"
1569
+ },
1570
+ {
1571
+ "name": "accepted_assets",
1572
+ "docs": [
1573
+ "Token mints allow-listed for inflow/outflow accounting. SOL is",
1574
+ "represented as `SOL_PSEUDO_MINT` (lamports custodied directly on this",
1575
+ "PDA). SPL mints are custodied via per-mint Associated Token Accounts",
1576
+ "authored by this PDA."
1577
+ ],
1578
+ "type": {
1579
+ "vec": "pubkey"
1580
+ }
1581
+ },
1582
+ {
1583
+ "name": "bump",
1584
+ "type": "u8"
1585
+ }
1586
+ ]
1587
+ }
1588
+ },
1589
+ {
1590
+ "name": "UpdateOperationsCapabilityParams",
1591
+ "docs": [
1592
+ "Parameter bag for `update_operations_capability`. `None` = leave field",
1593
+ "unchanged. To set `expiry_unix` to \"no expiry\", pass `Some(0)` (sentinel)."
1594
+ ],
1595
+ "type": {
1596
+ "kind": "struct",
1597
+ "fields": [
1598
+ {
1599
+ "name": "action_whitelist",
1600
+ "type": {
1601
+ "option": {
1602
+ "vec": {
1603
+ "array": [
1604
+ "u8",
1605
+ 8
1606
+ ]
1607
+ }
1608
+ }
1609
+ }
1610
+ },
1611
+ {
1612
+ "name": "rate_limit_per_period",
1613
+ "type": {
1614
+ "option": "u32"
1615
+ }
1616
+ },
1617
+ {
1618
+ "name": "expiry_unix",
1619
+ "type": {
1620
+ "option": "i64"
1621
+ }
1622
+ }
1623
+ ]
1624
+ }
1625
+ }
1626
+ ]
1627
+ }