@occa/sdk 0.4.0 → 0.5.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/CHANGELOG.md +29 -0
- package/dist/{chunk-YCSBYRSH.js → chunk-BR62YC5F.js} +17 -3
- package/dist/chunk-BR62YC5F.js.map +1 -0
- package/dist/{chunk-X6FBCGHU.js → chunk-QZSQEGLT.js} +15 -3
- package/dist/chunk-QZSQEGLT.js.map +1 -0
- package/dist/{chunk-N7LNBSDD.js → chunk-YC33EXHO.js} +82 -5
- package/dist/chunk-YC33EXHO.js.map +1 -0
- package/dist/constants.cjs +20 -2
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +13 -2
- package/dist/constants.d.ts +13 -2
- package/dist/constants.js +9 -1
- package/dist/index.cjs +109 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +17 -3
- package/dist/instructions.cjs +92 -2
- package/dist/instructions.cjs.map +1 -1
- package/dist/instructions.d.cts +66 -1
- package/dist/instructions.d.ts +66 -1
- package/dist/instructions.js +7 -3
- package/dist/pda.cjs +15 -1
- package/dist/pda.cjs.map +1 -1
- package/dist/pda.d.cts +15 -1
- package/dist/pda.d.ts +15 -1
- package/dist/pda.js +4 -2
- package/package.json +1 -1
- package/src/constants.ts +17 -1
- package/src/idl/registry.json +389 -5
- package/src/instructions.ts +149 -0
- package/src/pda.ts +25 -0
- package/dist/chunk-N7LNBSDD.js.map +0 -1
- package/dist/chunk-X6FBCGHU.js.map +0 -1
- package/dist/chunk-YCSBYRSH.js.map +0 -1
package/src/idl/registry.json
CHANGED
|
@@ -140,6 +140,162 @@
|
|
|
140
140
|
}
|
|
141
141
|
]
|
|
142
142
|
},
|
|
143
|
+
{
|
|
144
|
+
"name": "commit_trace",
|
|
145
|
+
"docs": [
|
|
146
|
+
"Anchor a single completed, verified deliverable on-chain — per-task",
|
|
147
|
+
"provenance. Where `commit_daily_anchor` commits one Merkle root over",
|
|
148
|
+
"a day's task stream, this records ONE deliverable: a link to the",
|
|
149
|
+
"result, the content hash that locks it, and the verification verdict",
|
|
150
|
+
"+ quality score.",
|
|
151
|
+
"",
|
|
152
|
+
"Only deliverables that PASSED the off-chain verification gate are",
|
|
153
|
+
"anchored (policy: keep unverified / spam output off the chain).",
|
|
154
|
+
"`verdict` is therefore always written `TRACE_VERDICT_PASSED`; failed",
|
|
155
|
+
"work is simply never committed through this ix.",
|
|
156
|
+
"",
|
|
157
|
+
"Per Whitepaper §2 trace architecture: the deliverable itself stays",
|
|
158
|
+
"off-chain. `content_hash` makes the result tamper-evident and",
|
|
159
|
+
"`evidence_hash` locks the off-chain verification report. Anyone can",
|
|
160
|
+
"re-hash the artifact + report and verify against these. The on-chain",
|
|
161
|
+
"`quality_score` + `rubric_version` make the quality signal itself",
|
|
162
|
+
"tamper-evident — the agent cannot self-assert it.",
|
|
163
|
+
"",
|
|
164
|
+
"Seeds: `[\"trace\", task_id]`. PDA collision = at most one anchor per",
|
|
165
|
+
"task. Re-attempts on the same `task_id` fail naturally (Anchor `init`",
|
|
166
|
+
"rejects).",
|
|
167
|
+
"",
|
|
168
|
+
"Authorization: identical model to `commit_daily_anchor` — signed by",
|
|
169
|
+
"the Anchor Wallet registered as `OperationsAccount[Anchor]`; this",
|
|
170
|
+
"ix's discriminator must be whitelisted on that account. Resolved via",
|
|
171
|
+
"cross-program PDA lookup (`seeds::program = treasury::ID`).",
|
|
172
|
+
"",
|
|
173
|
+
"Phase 1 rate limit: NOT enforced (same constraint as",
|
|
174
|
+
"`commit_daily_anchor` — registry cannot mutate the treasury-owned",
|
|
175
|
+
"ops counter without an extra CPI). PDA-per-task dedup + rent burn",
|
|
176
|
+
"cap griefing."
|
|
177
|
+
],
|
|
178
|
+
"discriminator": [
|
|
179
|
+
58,
|
|
180
|
+
140,
|
|
181
|
+
230,
|
|
182
|
+
51,
|
|
183
|
+
170,
|
|
184
|
+
109,
|
|
185
|
+
228,
|
|
186
|
+
125
|
|
187
|
+
],
|
|
188
|
+
"accounts": [
|
|
189
|
+
{
|
|
190
|
+
"name": "deployment",
|
|
191
|
+
"docs": [
|
|
192
|
+
"Deployment that produced this deliverable."
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"name": "company",
|
|
197
|
+
"docs": [
|
|
198
|
+
"CompanyAccount referenced by deployment. Verified via",
|
|
199
|
+
"`deployment.company == company.key()` in the handler so we can also",
|
|
200
|
+
"resolve the OperationsAccount[Anchor] PDA from it."
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "anchor_signer",
|
|
205
|
+
"docs": [
|
|
206
|
+
"Anchor Wallet — pubkey verified against `operations.signer`."
|
|
207
|
+
],
|
|
208
|
+
"signer": true
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"name": "operations",
|
|
212
|
+
"docs": [
|
|
213
|
+
"`OperationsAccount[Anchor]` from treasury program. Resolved via",
|
|
214
|
+
"cross-program PDA derivation; Anchor `Account<T>` auto-verifies",
|
|
215
|
+
"owner = treasury::ID."
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "trace_anchor",
|
|
220
|
+
"writable": true,
|
|
221
|
+
"pda": {
|
|
222
|
+
"seeds": [
|
|
223
|
+
{
|
|
224
|
+
"kind": "const",
|
|
225
|
+
"value": [
|
|
226
|
+
116,
|
|
227
|
+
114,
|
|
228
|
+
97,
|
|
229
|
+
99,
|
|
230
|
+
101
|
|
231
|
+
]
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"kind": "arg",
|
|
235
|
+
"path": "task_id"
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"name": "payer",
|
|
242
|
+
"docs": [
|
|
243
|
+
"Pays rent for the TraceAnchorAccount PDA."
|
|
244
|
+
],
|
|
245
|
+
"writable": true,
|
|
246
|
+
"signer": true
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "system_program",
|
|
250
|
+
"address": "11111111111111111111111111111111"
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
"args": [
|
|
254
|
+
{
|
|
255
|
+
"name": "task_id",
|
|
256
|
+
"type": {
|
|
257
|
+
"array": [
|
|
258
|
+
"u8",
|
|
259
|
+
32
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"name": "result_uri",
|
|
265
|
+
"type": "string"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "content_hash",
|
|
269
|
+
"type": {
|
|
270
|
+
"array": [
|
|
271
|
+
"u8",
|
|
272
|
+
32
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"name": "quality_score",
|
|
278
|
+
"type": "u8"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "rubric_version",
|
|
282
|
+
"type": "u8"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"name": "evidence_hash",
|
|
286
|
+
"type": {
|
|
287
|
+
"array": [
|
|
288
|
+
"u8",
|
|
289
|
+
32
|
|
290
|
+
]
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"name": "completed_at",
|
|
295
|
+
"type": "i64"
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
},
|
|
143
299
|
{
|
|
144
300
|
"name": "create_company",
|
|
145
301
|
"docs": [
|
|
@@ -286,23 +442,29 @@
|
|
|
286
442
|
],
|
|
287
443
|
"accounts": [
|
|
288
444
|
{
|
|
289
|
-
"name": "company"
|
|
445
|
+
"name": "company",
|
|
446
|
+
"docs": [
|
|
447
|
+
"Company the agent is being deployed into. Referenced only — the",
|
|
448
|
+
"company owner's consent to the hire is captured off-chain (the",
|
|
449
|
+
"invite), so the company owner is NOT a required signer here."
|
|
450
|
+
]
|
|
290
451
|
},
|
|
291
452
|
{
|
|
292
453
|
"name": "identity",
|
|
293
454
|
"docs": [
|
|
294
|
-
"AgentIdentity
|
|
295
|
-
"
|
|
455
|
+
"AgentIdentity being deployed. The IDENTITY owner signs — deploying",
|
|
456
|
+
"an agent (incl. into another owner's company, the marketplace case)",
|
|
457
|
+
"is authorized by the agent's owner accepting."
|
|
296
458
|
]
|
|
297
459
|
},
|
|
298
460
|
{
|
|
299
461
|
"name": "owner",
|
|
300
462
|
"docs": [
|
|
301
|
-
"
|
|
463
|
+
"Agent owner (signer) — authorizes deploying THEIR agent."
|
|
302
464
|
],
|
|
303
465
|
"signer": true,
|
|
304
466
|
"relations": [
|
|
305
|
-
"
|
|
467
|
+
"identity"
|
|
306
468
|
]
|
|
307
469
|
},
|
|
308
470
|
{
|
|
@@ -508,6 +670,44 @@
|
|
|
508
670
|
],
|
|
509
671
|
"args": []
|
|
510
672
|
},
|
|
673
|
+
{
|
|
674
|
+
"name": "set_agent_receiving_address",
|
|
675
|
+
"docs": [
|
|
676
|
+
"Set or replace the agent's PERSONAL receiving wallet — the passive",
|
|
677
|
+
"destination for funds disbursed to this agent, intrinsic to the",
|
|
678
|
+
"identity (no company/deployment required). Pass `Pubkey::default()`",
|
|
679
|
+
"to clear. Identity-owner only. NEVER a signer — it only receives."
|
|
680
|
+
],
|
|
681
|
+
"discriminator": [
|
|
682
|
+
197,
|
|
683
|
+
126,
|
|
684
|
+
122,
|
|
685
|
+
18,
|
|
686
|
+
38,
|
|
687
|
+
62,
|
|
688
|
+
179,
|
|
689
|
+
218
|
|
690
|
+
],
|
|
691
|
+
"accounts": [
|
|
692
|
+
{
|
|
693
|
+
"name": "identity",
|
|
694
|
+
"writable": true
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"name": "owner",
|
|
698
|
+
"signer": true,
|
|
699
|
+
"relations": [
|
|
700
|
+
"identity"
|
|
701
|
+
]
|
|
702
|
+
}
|
|
703
|
+
],
|
|
704
|
+
"args": [
|
|
705
|
+
{
|
|
706
|
+
"name": "new_receiving_address",
|
|
707
|
+
"type": "pubkey"
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
},
|
|
511
711
|
{
|
|
512
712
|
"name": "set_receiving_address",
|
|
513
713
|
"docs": [
|
|
@@ -822,6 +1022,19 @@
|
|
|
822
1022
|
64,
|
|
823
1023
|
178
|
|
824
1024
|
]
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
"name": "TraceAnchorAccount",
|
|
1028
|
+
"discriminator": [
|
|
1029
|
+
159,
|
|
1030
|
+
101,
|
|
1031
|
+
186,
|
|
1032
|
+
98,
|
|
1033
|
+
211,
|
|
1034
|
+
217,
|
|
1035
|
+
119,
|
|
1036
|
+
232
|
|
1037
|
+
]
|
|
825
1038
|
}
|
|
826
1039
|
],
|
|
827
1040
|
"errors": [
|
|
@@ -924,6 +1137,21 @@
|
|
|
924
1137
|
"code": 6019,
|
|
925
1138
|
"name": "InvalidDiscriminator",
|
|
926
1139
|
"msg": "could not parse instruction discriminator"
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
"code": 6020,
|
|
1143
|
+
"name": "ResultUriTooLong",
|
|
1144
|
+
"msg": "result_uri exceeds MAX_RESULT_URI_LEN"
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
"code": 6021,
|
|
1148
|
+
"name": "InvalidQualityScore",
|
|
1149
|
+
"msg": "quality_score exceeds MAX_QUALITY_SCORE (0-100)"
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
"code": 6022,
|
|
1153
|
+
"name": "InvalidCompletedAt",
|
|
1154
|
+
"msg": "completed_at must be > 0 and not in the future"
|
|
927
1155
|
}
|
|
928
1156
|
],
|
|
929
1157
|
"types": [
|
|
@@ -953,6 +1181,18 @@
|
|
|
953
1181
|
],
|
|
954
1182
|
"type": "pubkey"
|
|
955
1183
|
},
|
|
1184
|
+
{
|
|
1185
|
+
"name": "receiving_address",
|
|
1186
|
+
"docs": [
|
|
1187
|
+
"The agent's PERSONAL receiving wallet — a passive destination for",
|
|
1188
|
+
"funds disbursed to this agent, intrinsic to the identity (like a",
|
|
1189
|
+
"person's bank account). Owner-set anytime via",
|
|
1190
|
+
"`set_agent_receiving_address`, independent of any company/deployment.",
|
|
1191
|
+
"At `create_deployment` the deployment's `receiving_address` defaults",
|
|
1192
|
+
"to this. `Pubkey::default()` = unset. NEVER a signer."
|
|
1193
|
+
],
|
|
1194
|
+
"type": "pubkey"
|
|
1195
|
+
},
|
|
956
1196
|
{
|
|
957
1197
|
"name": "created_at",
|
|
958
1198
|
"docs": [
|
|
@@ -1410,6 +1650,150 @@
|
|
|
1410
1650
|
}
|
|
1411
1651
|
]
|
|
1412
1652
|
}
|
|
1653
|
+
},
|
|
1654
|
+
{
|
|
1655
|
+
"name": "TraceAnchorAccount",
|
|
1656
|
+
"docs": [
|
|
1657
|
+
"Per-deliverable provenance record. One per completed, verified task.",
|
|
1658
|
+
"The deliverable content lives off-chain; this account locks its",
|
|
1659
|
+
"identity, content hash, and verified quality so it is tamper-evident",
|
|
1660
|
+
"and attributable. Reputation views are derived off-chain by folding",
|
|
1661
|
+
"over these accounts per `agent`."
|
|
1662
|
+
],
|
|
1663
|
+
"type": {
|
|
1664
|
+
"kind": "struct",
|
|
1665
|
+
"fields": [
|
|
1666
|
+
{
|
|
1667
|
+
"name": "version",
|
|
1668
|
+
"docs": [
|
|
1669
|
+
"Schema version."
|
|
1670
|
+
],
|
|
1671
|
+
"type": "u8"
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
"name": "task_id",
|
|
1675
|
+
"docs": [
|
|
1676
|
+
"Hash of task creation params — globally unique task id, also baked",
|
|
1677
|
+
"into the PDA seed."
|
|
1678
|
+
],
|
|
1679
|
+
"type": {
|
|
1680
|
+
"array": [
|
|
1681
|
+
"u8",
|
|
1682
|
+
32
|
|
1683
|
+
]
|
|
1684
|
+
}
|
|
1685
|
+
},
|
|
1686
|
+
{
|
|
1687
|
+
"name": "company",
|
|
1688
|
+
"docs": [
|
|
1689
|
+
"CompanyAccount the work was produced in (denormalized for indexing)."
|
|
1690
|
+
],
|
|
1691
|
+
"type": "pubkey"
|
|
1692
|
+
},
|
|
1693
|
+
{
|
|
1694
|
+
"name": "agent",
|
|
1695
|
+
"docs": [
|
|
1696
|
+
"AgentIdentity PDA that produced the deliverable. Reputation",
|
|
1697
|
+
"aggregates against this (stable across redeployments), NOT the",
|
|
1698
|
+
"per-company deployment."
|
|
1699
|
+
],
|
|
1700
|
+
"type": "pubkey"
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
"name": "deployment",
|
|
1704
|
+
"docs": [
|
|
1705
|
+
"Deployment PDA active when the work was produced (company context)."
|
|
1706
|
+
],
|
|
1707
|
+
"type": "pubkey"
|
|
1708
|
+
},
|
|
1709
|
+
{
|
|
1710
|
+
"name": "result_uri",
|
|
1711
|
+
"docs": [
|
|
1712
|
+
"Link to the deliverable (article URL, PR, etc). Off-chain pointer."
|
|
1713
|
+
],
|
|
1714
|
+
"type": "string"
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
"name": "content_hash",
|
|
1718
|
+
"docs": [
|
|
1719
|
+
"SHA-256 of the deliverable content at completion — tamper-evidence",
|
|
1720
|
+
"for the result behind `result_uri`."
|
|
1721
|
+
],
|
|
1722
|
+
"type": {
|
|
1723
|
+
"array": [
|
|
1724
|
+
"u8",
|
|
1725
|
+
32
|
|
1726
|
+
]
|
|
1727
|
+
}
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
"name": "verdict",
|
|
1731
|
+
"docs": [
|
|
1732
|
+
"Verification verdict. Always `TRACE_VERDICT_PASSED` — only passed",
|
|
1733
|
+
"deliverables are anchored."
|
|
1734
|
+
],
|
|
1735
|
+
"type": "u8"
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
"name": "quality_score",
|
|
1739
|
+
"docs": [
|
|
1740
|
+
"Rubric quality score 0-100 (see `MAX_QUALITY_SCORE`). Tamper-evident",
|
|
1741
|
+
"quality signal, produced by the deterministic gate, not the agent."
|
|
1742
|
+
],
|
|
1743
|
+
"type": "u8"
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
"name": "rubric_version",
|
|
1747
|
+
"docs": [
|
|
1748
|
+
"Version of the scoring rubric that produced `quality_score`. Scores",
|
|
1749
|
+
"are only comparable within the same rubric version."
|
|
1750
|
+
],
|
|
1751
|
+
"type": "u8"
|
|
1752
|
+
},
|
|
1753
|
+
{
|
|
1754
|
+
"name": "evidence_hash",
|
|
1755
|
+
"docs": [
|
|
1756
|
+
"SHA-256 of the off-chain verification report (claims checked +",
|
|
1757
|
+
"sources). Lets anyone audit WHY the verdict/score was assigned."
|
|
1758
|
+
],
|
|
1759
|
+
"type": {
|
|
1760
|
+
"array": [
|
|
1761
|
+
"u8",
|
|
1762
|
+
32
|
|
1763
|
+
]
|
|
1764
|
+
}
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
"name": "completed_at",
|
|
1768
|
+
"docs": [
|
|
1769
|
+
"Unix timestamp the deliverable was completed off-chain."
|
|
1770
|
+
],
|
|
1771
|
+
"type": "i64"
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
"name": "committed_at",
|
|
1775
|
+
"docs": [
|
|
1776
|
+
"Unix timestamp this commit landed on-chain."
|
|
1777
|
+
],
|
|
1778
|
+
"type": "i64"
|
|
1779
|
+
},
|
|
1780
|
+
{
|
|
1781
|
+
"name": "committed_by",
|
|
1782
|
+
"docs": [
|
|
1783
|
+
"Anchor Wallet pubkey that signed the commit. Mirror of",
|
|
1784
|
+
"`OperationsAccount[Anchor].signer` at commit time."
|
|
1785
|
+
],
|
|
1786
|
+
"type": "pubkey"
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
"name": "bump",
|
|
1790
|
+
"docs": [
|
|
1791
|
+
"Bump for PDA verification."
|
|
1792
|
+
],
|
|
1793
|
+
"type": "u8"
|
|
1794
|
+
}
|
|
1795
|
+
]
|
|
1796
|
+
}
|
|
1413
1797
|
}
|
|
1414
1798
|
]
|
|
1415
1799
|
}
|
package/src/instructions.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
TransactionInstruction,
|
|
5
5
|
} from "@solana/web3.js";
|
|
6
6
|
import {
|
|
7
|
+
MAX_QUALITY_SCORE,
|
|
8
|
+
MAX_RESULT_URI_LEN,
|
|
7
9
|
OPERATIONS_KIND,
|
|
8
10
|
REGISTRY_PROGRAM_ID,
|
|
9
11
|
SOL_PSEUDO_MINT,
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
deriveOperationsPda,
|
|
19
21
|
derivePolicyPda,
|
|
20
22
|
deriveProtocolFeePda,
|
|
23
|
+
deriveTraceAnchorPda,
|
|
21
24
|
deriveTreasuryPda,
|
|
22
25
|
u32LeBytes,
|
|
23
26
|
} from "./pda";
|
|
@@ -42,7 +45,9 @@ export const INSTRUCTION_DISCRIMINATOR = {
|
|
|
42
45
|
updateDeploymentStatus: Buffer.from([225, 195, 150, 254, 178, 203, 53, 147]),
|
|
43
46
|
retireDeployment: Buffer.from([45, 188, 162, 197, 136, 180, 202, 153]),
|
|
44
47
|
setReceivingAddress: Buffer.from([70, 63, 44, 87, 16, 6, 156, 200]),
|
|
48
|
+
setAgentReceivingAddress: Buffer.from([197, 126, 122, 18, 38, 62, 179, 218]),
|
|
45
49
|
commitDailyAnchor: Buffer.from([18, 7, 3, 65, 58, 148, 164, 0]),
|
|
50
|
+
commitTrace: Buffer.from([58, 140, 230, 51, 170, 109, 228, 125]),
|
|
46
51
|
} as const;
|
|
47
52
|
|
|
48
53
|
// ── Borsh primitives ────────────────────────────────────────────────────────
|
|
@@ -461,6 +466,40 @@ export function buildSetReceivingAddressInstruction(
|
|
|
461
466
|
return { instruction };
|
|
462
467
|
}
|
|
463
468
|
|
|
469
|
+
export interface SetAgentReceivingAddressParams {
|
|
470
|
+
/** AgentIdentity PDA whose personal receiving wallet is being set. */
|
|
471
|
+
identityPda: PublicKey;
|
|
472
|
+
/** User wallet — must equal `identity.owner`. */
|
|
473
|
+
owner: PublicKey;
|
|
474
|
+
/** New personal receiving address (passive destination for funds
|
|
475
|
+
* disbursed to this agent). Pass `PublicKey.default` to clear. NEVER a
|
|
476
|
+
* signer — it never authorizes any on-chain action. */
|
|
477
|
+
newReceivingAddress: PublicKey;
|
|
478
|
+
programId?: PublicKey;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Sets the agent's PERSONAL receiving wallet on the AgentIdentity itself —
|
|
482
|
+
// independent of any company/deployment (Phase 4 marketplace). The deployment
|
|
483
|
+
// receiving_address defaults from this at create_deployment.
|
|
484
|
+
export function buildSetAgentReceivingAddressInstruction(
|
|
485
|
+
params: SetAgentReceivingAddressParams,
|
|
486
|
+
): { instruction: TransactionInstruction } {
|
|
487
|
+
const programId = params.programId ?? REGISTRY_PROGRAM_ID;
|
|
488
|
+
const data = Buffer.concat([
|
|
489
|
+
INSTRUCTION_DISCRIMINATOR.setAgentReceivingAddress,
|
|
490
|
+
encodePubkey(params.newReceivingAddress),
|
|
491
|
+
]);
|
|
492
|
+
const instruction = new TransactionInstruction({
|
|
493
|
+
programId,
|
|
494
|
+
keys: [
|
|
495
|
+
{ pubkey: params.identityPda, isSigner: false, isWritable: true },
|
|
496
|
+
{ pubkey: params.owner, isSigner: true, isWritable: false },
|
|
497
|
+
],
|
|
498
|
+
data,
|
|
499
|
+
});
|
|
500
|
+
return { instruction };
|
|
501
|
+
}
|
|
502
|
+
|
|
464
503
|
// ── Treasury program ────────────────────────────────────────────────────────
|
|
465
504
|
//
|
|
466
505
|
// The treasury program is a SEPARATE program from registry — these
|
|
@@ -1169,3 +1208,113 @@ export function buildCommitDailyAnchorInstruction(
|
|
|
1169
1208
|
});
|
|
1170
1209
|
return { instruction };
|
|
1171
1210
|
}
|
|
1211
|
+
|
|
1212
|
+
export interface CommitTraceParams {
|
|
1213
|
+
deploymentPda: PublicKey;
|
|
1214
|
+
companyPda: PublicKey;
|
|
1215
|
+
/** Anchor Wallet — must equal `operations.signer` (kind=Anchor). */
|
|
1216
|
+
anchorSigner: PublicKey;
|
|
1217
|
+
/** Anchor-kind OperationsAccount for this company (in TREASURY program,
|
|
1218
|
+
* read-only here). Caller derives via `deriveOperationsPda(company,
|
|
1219
|
+
* OPERATIONS_KIND.Anchor)`. */
|
|
1220
|
+
operationsPda: PublicKey;
|
|
1221
|
+
/** 32-byte hash of the task creation params — globally unique, becomes
|
|
1222
|
+
* part of the TraceAnchor PDA seed. */
|
|
1223
|
+
taskId: Uint8Array | Buffer;
|
|
1224
|
+
/** Link to the deliverable (article URL, PR, etc). Max
|
|
1225
|
+
* `MAX_RESULT_URI_LEN` bytes. */
|
|
1226
|
+
resultUri: string;
|
|
1227
|
+
/** SHA-256 of the deliverable content at completion (32 bytes). */
|
|
1228
|
+
contentHash: Uint8Array | Buffer;
|
|
1229
|
+
/** Rubric quality score, 0..=`MAX_QUALITY_SCORE`. */
|
|
1230
|
+
qualityScore: number;
|
|
1231
|
+
/** Version of the scoring rubric that produced `qualityScore`. */
|
|
1232
|
+
rubricVersion: number;
|
|
1233
|
+
/** SHA-256 of the off-chain verification report (32 bytes). */
|
|
1234
|
+
evidenceHash: Uint8Array | Buffer;
|
|
1235
|
+
/** Unix seconds the deliverable was completed off-chain. Must be > 0 and
|
|
1236
|
+
* not in the future. */
|
|
1237
|
+
completedAt: bigint;
|
|
1238
|
+
/** Rent payer (typically the operator hot wallet). */
|
|
1239
|
+
payer: PublicKey;
|
|
1240
|
+
programId?: PublicKey;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* Build a `commit_trace` instruction — Anchor-class single-tx commit of one
|
|
1245
|
+
* completed, VERIFIED deliverable. Signed by the Anchor Wallet bound to the
|
|
1246
|
+
* company's Anchor-kind OperationsAccount (same authority as
|
|
1247
|
+
* `commit_daily_anchor`).
|
|
1248
|
+
*
|
|
1249
|
+
* Only deliverables that passed the off-chain verification gate should be
|
|
1250
|
+
* committed — the on-chain `verdict` is always Passed. Caller is
|
|
1251
|
+
* responsible for:
|
|
1252
|
+
* 1. Computing `contentHash` (SHA-256 of the deliverable)
|
|
1253
|
+
* 2. Running the verification gate + scoring rubric off-chain
|
|
1254
|
+
* 3. Computing `evidenceHash` (SHA-256 of the verification report)
|
|
1255
|
+
*
|
|
1256
|
+
* The verdict byte is fixed on-chain; it is not a caller arg.
|
|
1257
|
+
*/
|
|
1258
|
+
export function buildCommitTraceInstruction(params: CommitTraceParams): {
|
|
1259
|
+
instruction: TransactionInstruction;
|
|
1260
|
+
traceAnchorPda: PublicKey;
|
|
1261
|
+
} {
|
|
1262
|
+
const programId = params.programId ?? REGISTRY_PROGRAM_ID;
|
|
1263
|
+
if (params.taskId.length !== 32) {
|
|
1264
|
+
throw new RangeError(`taskId must be 32 bytes, got ${params.taskId.length}`);
|
|
1265
|
+
}
|
|
1266
|
+
if (params.contentHash.length !== 32) {
|
|
1267
|
+
throw new RangeError(
|
|
1268
|
+
`contentHash must be 32 bytes, got ${params.contentHash.length}`,
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
if (params.evidenceHash.length !== 32) {
|
|
1272
|
+
throw new RangeError(
|
|
1273
|
+
`evidenceHash must be 32 bytes, got ${params.evidenceHash.length}`,
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
if (Buffer.from(params.resultUri, "utf8").length > MAX_RESULT_URI_LEN) {
|
|
1277
|
+
throw new RangeError(
|
|
1278
|
+
`resultUri exceeds MAX_RESULT_URI_LEN (${MAX_RESULT_URI_LEN} bytes)`,
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
if (params.qualityScore < 0 || params.qualityScore > MAX_QUALITY_SCORE) {
|
|
1282
|
+
throw new RangeError(
|
|
1283
|
+
`qualityScore out of range 0..=${MAX_QUALITY_SCORE}: ${params.qualityScore}`,
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
const taskId = Buffer.from(params.taskId);
|
|
1288
|
+
const { pda: traceAnchorPda } = deriveTraceAnchorPda(taskId, programId);
|
|
1289
|
+
|
|
1290
|
+
// Wire arg order must match the Rust handler: task_id, result_uri,
|
|
1291
|
+
// content_hash, quality_score, rubric_version, evidence_hash,
|
|
1292
|
+
// completed_at. verdict is NOT a wire arg (fixed Passed on-chain).
|
|
1293
|
+
const data = Buffer.concat([
|
|
1294
|
+
INSTRUCTION_DISCRIMINATOR.commitTrace,
|
|
1295
|
+
taskId,
|
|
1296
|
+
encodeString(params.resultUri),
|
|
1297
|
+
Buffer.from(params.contentHash),
|
|
1298
|
+
encodeU8(params.qualityScore),
|
|
1299
|
+
encodeU8(params.rubricVersion),
|
|
1300
|
+
Buffer.from(params.evidenceHash),
|
|
1301
|
+
encodeI64(params.completedAt),
|
|
1302
|
+
]);
|
|
1303
|
+
|
|
1304
|
+
const instruction = new TransactionInstruction({
|
|
1305
|
+
programId,
|
|
1306
|
+
// Order: deployment, company, anchor_signer, operations, trace_anchor,
|
|
1307
|
+
// payer, system_program.
|
|
1308
|
+
keys: [
|
|
1309
|
+
{ pubkey: params.deploymentPda, isSigner: false, isWritable: false },
|
|
1310
|
+
{ pubkey: params.companyPda, isSigner: false, isWritable: false },
|
|
1311
|
+
{ pubkey: params.anchorSigner, isSigner: true, isWritable: false },
|
|
1312
|
+
{ pubkey: params.operationsPda, isSigner: false, isWritable: false },
|
|
1313
|
+
{ pubkey: traceAnchorPda, isSigner: false, isWritable: true },
|
|
1314
|
+
{ pubkey: params.payer, isSigner: true, isWritable: true },
|
|
1315
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
1316
|
+
],
|
|
1317
|
+
data,
|
|
1318
|
+
});
|
|
1319
|
+
return { instruction, traceAnchorPda };
|
|
1320
|
+
}
|
package/src/pda.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
POLICY_SEED,
|
|
9
9
|
PROTOCOL_FEES_SEED,
|
|
10
10
|
REGISTRY_PROGRAM_ID,
|
|
11
|
+
TRACE_SEED,
|
|
11
12
|
TREASURY_PROGRAM_ID,
|
|
12
13
|
TREASURY_SEED,
|
|
13
14
|
type OperationsKind,
|
|
@@ -197,3 +198,27 @@ export function deriveDailyAnchorPda(
|
|
|
197
198
|
);
|
|
198
199
|
return { pda, bump };
|
|
199
200
|
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* TraceAnchorAccount PDA — owned by Registry program. One per completed,
|
|
204
|
+
* verified deliverable (article, PR, etc).
|
|
205
|
+
*
|
|
206
|
+
* seeds = ["trace", task_id_32bytes]
|
|
207
|
+
*
|
|
208
|
+
* `taskId` is a 32-byte hash of the task creation params. Collision on the
|
|
209
|
+
* same `taskId` means the task is already anchored — a re-commit fails
|
|
210
|
+
* naturally (Anchor `init` rejects).
|
|
211
|
+
*/
|
|
212
|
+
export function deriveTraceAnchorPda(
|
|
213
|
+
taskId: Uint8Array,
|
|
214
|
+
programId: PublicKey = REGISTRY_PROGRAM_ID,
|
|
215
|
+
): { pda: PublicKey; bump: number } {
|
|
216
|
+
if (taskId.length !== 32) {
|
|
217
|
+
throw new RangeError(`taskId must be 32 bytes, got ${taskId.length}`);
|
|
218
|
+
}
|
|
219
|
+
const [pda, bump] = PublicKey.findProgramAddressSync(
|
|
220
|
+
[TRACE_SEED, Buffer.from(taskId)],
|
|
221
|
+
programId,
|
|
222
|
+
);
|
|
223
|
+
return { pda, bump };
|
|
224
|
+
}
|