@telaro/sacp 1.0.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.
Files changed (75) hide show
  1. package/INTEGRATION.md +238 -0
  2. package/README.md +253 -0
  3. package/dist/codec.d.ts +35 -0
  4. package/dist/codec.d.ts.map +1 -0
  5. package/dist/codec.js +63 -0
  6. package/dist/codec.js.map +1 -0
  7. package/dist/constants.d.ts +50 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +50 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/dispatcher.d.ts +87 -0
  12. package/dist/dispatcher.d.ts.map +1 -0
  13. package/dist/dispatcher.js +175 -0
  14. package/dist/dispatcher.js.map +1 -0
  15. package/dist/events.d.ts +93 -0
  16. package/dist/events.d.ts.map +1 -0
  17. package/dist/events.js +142 -0
  18. package/dist/events.js.map +1 -0
  19. package/dist/index.d.ts +38 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +39 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/job.d.ts +99 -0
  24. package/dist/job.d.ts.map +1 -0
  25. package/dist/job.js +297 -0
  26. package/dist/job.js.map +1 -0
  27. package/dist/lst.d.ts +52 -0
  28. package/dist/lst.d.ts.map +1 -0
  29. package/dist/lst.js +58 -0
  30. package/dist/lst.js.map +1 -0
  31. package/dist/negotiation.d.ts +66 -0
  32. package/dist/negotiation.d.ts.map +1 -0
  33. package/dist/negotiation.js +184 -0
  34. package/dist/negotiation.js.map +1 -0
  35. package/dist/offering.d.ts +65 -0
  36. package/dist/offering.d.ts.map +1 -0
  37. package/dist/offering.js +190 -0
  38. package/dist/offering.js.map +1 -0
  39. package/dist/pdas.d.ts +44 -0
  40. package/dist/pdas.d.ts.map +1 -0
  41. package/dist/pdas.js +95 -0
  42. package/dist/pdas.js.map +1 -0
  43. package/dist/runtime.d.ts +244 -0
  44. package/dist/runtime.d.ts.map +1 -0
  45. package/dist/runtime.js +481 -0
  46. package/dist/runtime.js.map +1 -0
  47. package/dist/signer.d.ts +107 -0
  48. package/dist/signer.d.ts.map +1 -0
  49. package/dist/signer.js +94 -0
  50. package/dist/signer.js.map +1 -0
  51. package/dist/take_rate.d.ts +44 -0
  52. package/dist/take_rate.d.ts.map +1 -0
  53. package/dist/take_rate.js +141 -0
  54. package/dist/take_rate.js.map +1 -0
  55. package/dist/timeout.d.ts +35 -0
  56. package/dist/timeout.d.ts.map +1 -0
  57. package/dist/timeout.js +113 -0
  58. package/dist/timeout.js.map +1 -0
  59. package/dist/types.d.ts +39 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +13 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/validation.d.ts +133 -0
  64. package/dist/validation.d.ts.map +1 -0
  65. package/dist/validation.js +315 -0
  66. package/dist/validation.js.map +1 -0
  67. package/dist/watcher.d.ts +67 -0
  68. package/dist/watcher.d.ts.map +1 -0
  69. package/dist/watcher.js +176 -0
  70. package/dist/watcher.js.map +1 -0
  71. package/dist/wormhole.d.ts +88 -0
  72. package/dist/wormhole.d.ts.map +1 -0
  73. package/dist/wormhole.js +152 -0
  74. package/dist/wormhole.js.map +1 -0
  75. package/package.json +138 -0
package/INTEGRATION.md ADDED
@@ -0,0 +1,238 @@
1
+ # sACP Integration Guide
2
+
3
+ Concrete recipes for the four common ways teams plug into sACP.
4
+ Pick the role you play and follow the matching section.
5
+
6
+ - [Role 1. Agent framework / SDK author](#role-1--agent-framework--sdk-author) (SendAI, Eliza, Crestal, similar)
7
+ - [Role 2. DApp gating on agent commerce](#role-2--dapp-gating-on-agent-commerce) (you accept agent service and want bonded settlement)
8
+ - [Role 3. Validator operator](#role-3--validator-operator) (you stake bond and act as Evaluator across many Jobs)
9
+ - [Role 4. Reputation / indexer integrator](#role-4--reputation--indexer-integrator) (you mirror sACP state for analytics or trust scoring)
10
+
11
+ If your case isn't here, open an issue or DM
12
+ [@telaroai](https://x.com/telaroai). we'll add a recipe.
13
+
14
+ ---
15
+
16
+ ## Role 1. Agent framework / SDK author
17
+
18
+ You ship a TypeScript / Rust SDK that agent operators install. You
19
+ want your agents to be able to **place jobs** (act as Client) and
20
+ **fulfill jobs** (act as Provider) on a standard.
21
+
22
+ ### Minimum surface
23
+
24
+ 1. **Add `@telaro/sacp` as a peer dependency** of your SDK so users
25
+ already pulling your SDK get sACP for free.
26
+ 2. **Expose two methods**: `placeJob(...)` and `claimJob(...)`. Each
27
+ wraps the sACP instruction builders with your SDK's idioms
28
+ (provider client, error handling, retries).
29
+ 3. **Surface job state in your agent loop**. Agents poll `fetchJob`
30
+ on PDAs they care about and react to state changes.
31
+
32
+ ### Reference pattern
33
+
34
+ ```ts
35
+ // In your SDK
36
+ import {
37
+ buildCreateJobIx,
38
+ buildSubmitWorkIx,
39
+ fetchJob,
40
+ } from "@telaro/sacp/job";
41
+
42
+ export class MyAgent {
43
+ async placeJob(params: { provider, evaluator, workUri, amount }) {
44
+ const jobId = BigInt(Date.now()) * 1000n;
45
+ const { ix, jobPda } = buildCreateJobIx({
46
+ jobId,
47
+ roles: { client: this.wallet.publicKey, ...params },
48
+ bondMint: USDC_MINT,
49
+ amount: params.amount,
50
+ workUri: params.workUri,
51
+ });
52
+ await this.sendTx([ix]);
53
+ return { jobId, jobPda };
54
+ }
55
+
56
+ async fulfillJob(jobId, submissionUri) {
57
+ const ix = buildSubmitWorkIx(this.wallet.publicKey, jobId, submissionUri);
58
+ return this.sendTx([ix]);
59
+ }
60
+
61
+ async watchJob(jobId, onStateChange) {
62
+ let last;
63
+ while (true) {
64
+ const job = await fetchJob(this.conn, jobId);
65
+ if (job?.state !== last) {
66
+ last = job?.state;
67
+ onStateChange(job);
68
+ }
69
+ await sleep(2000);
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### Why integrate
76
+
77
+ - One standard for cross-source agent commerce on Solana
78
+ - Verifiable settlement state (no off-chain agreements)
79
+ - Built-in evaluator economy via Part B
80
+ - Cross-chain compatibility with ERC-8183 (Base, BSC)
81
+
82
+ ### Co-marketing path
83
+
84
+ If your framework ships a sACP integration, we'll co-publish:
85
+ the announcement, a worked example in our docs, and a slot on
86
+ the [sACP standard](https://sacp.dev) landing page (coming
87
+ soon). Open a PR or email build@telaro.xyz.
88
+
89
+ ---
90
+
91
+ ## Role 2. DApp gating on agent commerce
92
+
93
+ You run a DApp that accepts agent-provided services (data
94
+ analysis, content generation, custom workflows) and you want
95
+ settlement that doesn't depend on a centralized escrow.
96
+
97
+ ### Minimum surface
98
+
99
+ 1. **Use sACP as your escrow layer**. Your DApp creates the Job;
100
+ your selected agent fulfills.
101
+ 2. **Pick the Evaluator path**:
102
+ - Single signer (you settle)
103
+ - Multisig (multi-stakeholder DApp)
104
+ - Validation Registry (delegated bonded evaluators)
105
+ 3. **Surface Job state in your UI**. Users see the job moving
106
+ through the state machine in real time.
107
+
108
+ ### Reference pattern
109
+
110
+ ```ts
111
+ import { buildCreateJobIx, fetchJob } from "@telaro/sacp/job";
112
+
113
+ // User clicks "Hire agent to do X"
114
+ const { ix, jobPda } = buildCreateJobIx({
115
+ jobId,
116
+ roles: {
117
+ client: dappEscrowPda, // your DApp's PDA, signs via CPI
118
+ provider: selectedAgent,
119
+ evaluator: yourMultisigPda,
120
+ },
121
+ bondMint: USDC_MINT,
122
+ amount: jobPrice,
123
+ workUri: `ipfs://${requestSpec.cid}`,
124
+ });
125
+
126
+ // CPI from your program, or sign with your treasury wallet
127
+ await this.sendTx([ix]);
128
+ ```
129
+
130
+ ### Why integrate
131
+
132
+ - No custom escrow contract to audit
133
+ - Standardized dispute flow
134
+ - Optional validator network you don't have to operate yourself
135
+
136
+ ---
137
+
138
+ ## Role 3. Validator operator
139
+
140
+ You commit USDC bond and earn fees by serving as Evaluator
141
+ across Jobs. Bond is slashed on disputed verdicts.
142
+
143
+ ### Onboarding
144
+
145
+ 1. Generate a validator authority keypair (cold + hot recommended).
146
+ 2. `register_validator` with operator metadata URI.
147
+ 3. `stake_bond` (USDC in v0.1; JitoSOL via adapter in v0.2).
148
+ 4. Run a verdict-acceptance daemon that watches `JobDisputed`
149
+ events for Jobs that target your validator PDA.
150
+ 5. Issue verdicts. Defend against challenges within the window.
151
+
152
+ ### Reference pattern
153
+
154
+ ```ts
155
+ import {
156
+ findValidatorPda,
157
+ buildAcceptVerdictIx,
158
+ } from "@telaro/sacp/validation";
159
+
160
+ const [validatorPda] = findValidatorPda(operator.publicKey);
161
+
162
+ // In your daemon, on a Disputed Job that names validatorPda:
163
+ const ix = buildAcceptVerdictIx(jobId, "Provider"); // your decision
164
+ await sendTx([ix]);
165
+ ```
166
+
167
+ ### Reward + risk
168
+
169
+ - **Reward**: fee per verdict (set per-Job by Client; defaults TBD).
170
+ - **Slash**: 100% of bond at risk on every challenged verdict the
171
+ challenger wins. Splits 70% to challenger, 30% to public treasury.
172
+
173
+ The full validator runbook (key management, monitoring, dispute
174
+ defense playbook) ships with v0.2.
175
+
176
+ ---
177
+
178
+ ## Role 4. Reputation / indexer integrator
179
+
180
+ You aggregate on-chain state for analytics, trust scoring,
181
+ discovery (e.g. you build something like 8004scan, or you're
182
+ Telaro's own indexer extending to cover sACP).
183
+
184
+ ### Minimum surface
185
+
186
+ 1. **Subscribe to the four event types**:
187
+ `JobCreated`, `JobFunded`, `WorkSubmitted`, `JobSettled` (and the
188
+ Validation events `ValidatorRegistered`, `BondStaked`,
189
+ `ValidatorSlashed`).
190
+ 2. **Decode account state**: Job, Submission, Verdict, Validator.
191
+ Layouts are documented in
192
+ [`src/job.ts`](src/job.ts) (`fetchJob`) and
193
+ [`src/validation.ts`](src/validation.ts) (`fetchValidator`).
194
+ 3. **Materialize derived signals**: settlement rate per Provider,
195
+ slash rate per Validator, dispute frequency, average job value.
196
+
197
+ ### Reference pattern
198
+
199
+ ```ts
200
+ import {
201
+ SACP_PROGRAM_ID,
202
+ SACP_VALIDATION_PROGRAM_ID,
203
+ } from "@telaro/sacp";
204
+
205
+ // Anchor event signatures = sha256("event:<name>")[..8]
206
+ // or watch via `onLogs(programId, ...)`.
207
+ const sub = conn.onLogs(SACP_PROGRAM_ID, (log) => {
208
+ // parse log.logs for "Program data:" lines, base64-decode, dispatch.
209
+ });
210
+ ```
211
+
212
+ ### Why integrate
213
+
214
+ - Single source of truth for agent commerce state on Solana
215
+ - Composable trust signals (combine with Telaro bond, 8004 publishes,
216
+ etc.)
217
+
218
+ ---
219
+
220
+ ## Spec change cadence
221
+
222
+ - **v0.1** (now): SDK signatures and PDA seeds frozen. Implementation
223
+ details (escrow CPI, JitoSOL adapter) ship in v0.2 without
224
+ signature changes.
225
+ - **v1.0** (target Q4 2026): governance moves to public RFC process;
226
+ spec changes require RFC + 30-day comment period.
227
+
228
+ If you're worried about a signature change before v1.0, pin
229
+ `@telaro/sacp@~0.1.0`. semver minor bumps will not change PDA seeds
230
+ or instruction argument layout.
231
+
232
+ ---
233
+
234
+ ## Need help?
235
+
236
+ - Open a GitHub issue at [Telaro-Protocol](https://github.com/Telaro-Protocol/Telaro-Protocol/issues)
237
+ - Email build@telaro.xyz
238
+ - Cold DM [@telaroai](https://x.com/telaroai) on X
package/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # @telaro/sacp
2
+
3
+ **Solana Agent Commerce Protocol. TypeScript SDK.**
4
+
5
+ [![npm](https://img.shields.io/npm/v/@telaro/sacp.svg)](https://www.npmjs.com/package/@telaro/sacp)
6
+
7
+ sACP is a Solana-native protocol for AI agent commerce: bonded job
8
+ escrow, dispute resolution, and bonded-validator economy. ERC-8183
9
+ compatible at the semantic level.
10
+
11
+ - **Spec**: [`docs/srfc/sacp-v0.1.md`](https://github.com/Telaro-Protocol/Telaro-Protocol/blob/main/docs/srfc/sacp-v0.1.md)
12
+ - **Reference impl**: [Telaro Protocol](https://telaro.xyz)
13
+ - **Status v0.3**: full standard live on devnet. `record_verdict`
14
+ restores the standalone Verdict PDA from SRFC v0.1, and the
15
+ `issue_verdict` cross-program CPI bridge lets a bonded validator
16
+ settle a Job dispute in a single transaction (validator bond is
17
+ real collateral). Verified by 5 devnet smoke tests:
18
+ happy / dispute+record_verdict / reclaim / validation (slash) /
19
+ bonded-evaluator (CPI).
20
+
21
+ ---
22
+
23
+ ## What's deployed (devnet)
24
+
25
+ | Program | Program ID | Status |
26
+ |---|---|---|
27
+ | `sacp_job` (Part A. Job Lifecycle) | [`8WAQhJJUnPqiKoJ35dNMSbRWNJsdRqu1f7uVqMwLHZuF`](https://explorer.solana.com/address/8WAQhJJUnPqiKoJ35dNMSbRWNJsdRqu1f7uVqMwLHZuF?cluster=devnet) | live |
28
+ | `sacp_validation` (Part B. Validation Registry) | [`GbWzXwirzzed3WjshJaMat9hiWgVSiPR8tAUj4oJnfMC`](https://explorer.solana.com/address/GbWzXwirzzed3WjshJaMat9hiWgVSiPR8tAUj4oJnfMC?cluster=devnet) | live |
29
+
30
+ ---
31
+
32
+ ## What v0.3 ships
33
+
34
+ | Surface | v0.3 | v1.0 plan |
35
+ |---|---|---|
36
+ | Job state machine (Open → Funded → Submitted → Settled / Disputed) | ✅ devnet | mainnet |
37
+ | `create_job`, `submit_work`, `accept_work`, `dispute_work`, `submit_verdict`, `reclaim_escrow` | ✅ full SPL escrow CPI |. |
38
+ | Escrow vault PDA + rent close on settle | ✅ |. |
39
+ | Validation Registry: register / stake / withdraw / challenge / 70-30 slash | ✅ full SPL bond CPI |. |
40
+ | Standalone `Verdict` PDA via `record_verdict` | ✅ |. |
41
+ | `sacp_validation::issue_verdict` → `sacp_job::submit_verdict` CPI bridge | ✅ bonded validator path verified e2e |. |
42
+ | Cross-chain dispatch (Base → Solana via Wormhole) | informative only | normative |
43
+
44
+ The full standard. escrow settlement, bonded validator economy,
45
+ permanent verdict provenance. works on devnet today. The CPI bridge
46
+ in particular makes the validator's bond real collateral: a
47
+ `challenge_verdict` against a verdict the validator issued can slash
48
+ 70% of their bond to the challenger.
49
+
50
+ ---
51
+
52
+ ## Install
53
+
54
+ ```sh
55
+ pnpm add @telaro/sacp @solana/web3.js
56
+ # or
57
+ npm install @telaro/sacp @solana/web3.js
58
+ ```
59
+
60
+ Node ≥20.
61
+
62
+ ---
63
+
64
+ ## Quickstart. drive a Job end-to-end on devnet
65
+
66
+ This is the literal flow our smoke test runs. Copy it, run it, see
67
+ the four real transactions on Solana Explorer.
68
+
69
+ ```ts
70
+ import {
71
+ Connection,
72
+ Keypair,
73
+ PublicKey,
74
+ Transaction,
75
+ sendAndConfirmTransaction,
76
+ } from "@solana/web3.js";
77
+ import {
78
+ buildCreateJobIx,
79
+ buildFundJobIx,
80
+ buildSubmitWorkIx,
81
+ buildAcceptWorkIx,
82
+ fetchJob,
83
+ } from "@telaro/sacp/job";
84
+
85
+ const conn = new Connection("https://api.devnet.solana.com", "confirmed");
86
+
87
+ // You play Client; provider & evaluator are fresh keypairs for the demo.
88
+ const client = Keypair.generate(); // fund this with devnet SOL first
89
+ const provider = Keypair.generate();
90
+ const evaluator = Keypair.generate();
91
+ const jobId = BigInt(Date.now()) * 1000n;
92
+
93
+ const USDC_DEVNET = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");
94
+
95
+ // 1) Open the Job. initializes the escrow vault PDA.
96
+ const { ix: createIx, jobPda } = buildCreateJobIx({
97
+ jobId,
98
+ roles: {
99
+ client: client.publicKey,
100
+ provider: provider.publicKey,
101
+ evaluator: evaluator.publicKey,
102
+ },
103
+ bondMint: USDC_DEVNET,
104
+ amount: 1_000_000n, // 1 USDC (decimals = 6)
105
+ workUri: "ipfs://Qm...your work order...",
106
+ });
107
+ await sendAndConfirmTransaction(conn, new Transaction().add(createIx), [client]);
108
+
109
+ // 2) Fund. Client transfers 1 USDC → escrow vault via SPL CPI.
110
+ // Provide the Client's USDC ATA.
111
+ await sendAndConfirmTransaction(
112
+ conn,
113
+ new Transaction().add(
114
+ buildFundJobIx({
115
+ client: client.publicKey,
116
+ jobId,
117
+ amount: 1_000_000n,
118
+ clientTokenAccount: clientUsdcAta,
119
+ }),
120
+ ),
121
+ [client],
122
+ );
123
+
124
+ // 3) Provider submits work.
125
+ await sendAndConfirmTransaction(
126
+ conn,
127
+ new Transaction().add(
128
+ buildSubmitWorkIx(provider.publicKey, jobId, "ipfs://Qm...submission..."),
129
+ ),
130
+ [provider],
131
+ );
132
+
133
+ // 4) Client accepts → Settled. Vault drains to Provider's ATA + closes.
134
+ await sendAndConfirmTransaction(
135
+ conn,
136
+ new Transaction().add(
137
+ buildAcceptWorkIx({
138
+ client: client.publicKey,
139
+ provider: provider.publicKey,
140
+ jobId,
141
+ providerTokenAccount: providerUsdcAta,
142
+ }),
143
+ ),
144
+ [client],
145
+ );
146
+
147
+ // Verify on-chain state.
148
+ const job = await fetchJob(conn, jobId);
149
+ console.log(job?.state); // "Settled"
150
+ ```
151
+
152
+ Run our exact smoke test against your wallet:
153
+
154
+ ```sh
155
+ git clone https://github.com/Telaro-Protocol/Telaro-Protocol
156
+ cd Telaro-Protocol
157
+ pnpm install
158
+ pnpm --filter @telaro/sacp run smoke
159
+ ```
160
+
161
+ Output ends with four Solana Explorer links you can click through.
162
+
163
+ ### Other verified paths
164
+
165
+ The repository also ships three additional smoke tests covering every
166
+ branch of the state machine. All four pass against the devnet
167
+ deployment.
168
+
169
+ ```sh
170
+ pnpm --filter @telaro/sacp run smoke # happy path (4 tx, real SPL escrow)
171
+ pnpm --filter @telaro/sacp run smoke:dispute # dispute → verdict + record_verdict (5 tx)
172
+ pnpm --filter @telaro/sacp run smoke:reclaim # client reclaim after timeout (2 tx + deadline guard)
173
+ pnpm --filter @telaro/sacp run smoke:validation # validator register/stake/challenge/resolve, 70/30 slash (2 scenarios)
174
+ pnpm --filter @telaro/sacp run smoke:bonded # bonded validator → CPI bridge → settlement (7 tx)
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Disputes
180
+
181
+ When the Client rejects the submitted work:
182
+
183
+ ```ts
184
+ import { buildDisputeWorkIx, buildSubmitVerdictIx } from "@telaro/sacp/job";
185
+
186
+ // Instead of accept_work, Client disputes with a reason hash
187
+ // (e.g. SHA-256 of a public reason document).
188
+ const reasonHash = new Uint8Array(32); // populate with real hash
189
+ await sendAndConfirmTransaction(
190
+ conn,
191
+ new Transaction().add(buildDisputeWorkIx(client.publicKey, jobId, reasonHash)),
192
+ [client],
193
+ );
194
+
195
+ // Evaluator then settles. Winner = "Client" or "Provider".
196
+ await sendAndConfirmTransaction(
197
+ conn,
198
+ new Transaction().add(buildSubmitVerdictIx(evaluator.publicKey, jobId, "Provider")),
199
+ [evaluator],
200
+ );
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Validation Registry (Part B)
206
+
207
+ `@telaro/sacp/validation` exposes the bonded-validator surface. A
208
+ Validator PDA can be wired into a Job's `evaluator` slot, which puts
209
+ the validator's bond at risk every time it issues a verdict.
210
+
211
+ ```ts
212
+ import { findValidatorPda } from "@telaro/sacp/validation";
213
+
214
+ const operator = Keypair.generate();
215
+ const [validatorPda] = findValidatorPda(operator.publicKey);
216
+
217
+ // validatorPda can now be used as the `evaluator` in buildCreateJobIx.
218
+ ```
219
+
220
+ The full validator-side flow (register, stake, accept verdict,
221
+ respond to challenge) is in
222
+ [`src/validation.ts`](https://github.com/Telaro-Protocol/Telaro-Protocol/blob/main/packages/sacp/src/validation.ts).
223
+ See [INTEGRATION.md](https://github.com/Telaro-Protocol/Telaro-Protocol/blob/main/packages/sacp/INTEGRATION.md)
224
+ for the validator operator runbook.
225
+
226
+ ---
227
+
228
+ ## ERC-8183 compatibility
229
+
230
+ The Job state machine, role definitions, and dispute outcomes map 1:1
231
+ to ERC-8183. See the spec's
232
+ [ERC-8183 mapping table](https://github.com/Telaro-Protocol/Telaro-Protocol/blob/main/docs/srfc/sacp-v0.1.md#erc-8183-mapping).
233
+
234
+ Cross-chain dispatch (a Base-side ERC-8183 Job that addresses a
235
+ Solana-side Provider) is informative in v0.1 and normative in v0.2,
236
+ piggybacking the existing Telaro → Base Wormhole bridge.
237
+
238
+ ---
239
+
240
+ ## How to verify the SDK matches the on-chain program
241
+
242
+ The SDK does not depend on a generated Anchor IDL. Instead, it builds
243
+ instructions from raw Borsh + the standard Anchor 0.30 discriminator
244
+ (`sha256("global:<name>")[..8]`). The PDAs are derived from the same
245
+ seeds declared in the Rust source. If you want to verify the SDK and
246
+ program agree, the smoke test does exactly that. it confirms every
247
+ state transition by reading the Job account directly after each call.
248
+
249
+ ---
250
+
251
+ ## License
252
+
253
+ MIT (spec) · Apache-2.0 (this SDK).
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Low-level codec utilities for talking to the sACP Anchor programs
3
+ * without depending on a generated IDL.
4
+ *
5
+ * Anchor 0.30 instruction encoding:
6
+ * 1. 8-byte discriminator = sha256("global:<instruction_name>")[..8]
7
+ * 2. Followed by Borsh-encoded args in declaration order.
8
+ *
9
+ * We hand-roll the encoders here so the SDK has zero coupling to the
10
+ * Anchor build pipeline. That matters because Anchor 0.30 + recent
11
+ * rustc can't always emit an IDL (see anchor-syn issue with
12
+ * proc-macro2 `source_file`), and we don't want our SDK to inherit
13
+ * that fragility.
14
+ *
15
+ * All numeric encoders write little-endian, matching Solana's wire
16
+ * convention.
17
+ */
18
+ export declare function anchorDiscriminator(instructionName: string): Buffer;
19
+ export declare function encodeU8(value: number): Buffer;
20
+ export declare function encodeU64(value: bigint): Buffer;
21
+ export declare function encodeI64(value: bigint): Buffer;
22
+ /**
23
+ * Borsh string: 4-byte little-endian length followed by UTF-8 bytes.
24
+ * Spec mandates URIs ≤ 256 bytes; we enforce in the high-level builder
25
+ * rather than the codec.
26
+ */
27
+ export declare function encodeString(value: string): Buffer;
28
+ /**
29
+ * 32-byte fixed array, used for hashes. Throws if input isn't exactly
30
+ * 32 bytes — saner than silently truncating.
31
+ */
32
+ export declare function encodeBytes32(bytes: Uint8Array): Buffer;
33
+ /** Concatenate the discriminator with serialized args. */
34
+ export declare function encodeInstruction(name: string, ...args: Buffer[]): Buffer;
35
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAKvD;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAEzE"}
package/dist/codec.js ADDED
@@ -0,0 +1,63 @@
1
+ import { sha256 } from "@noble/hashes/sha256";
2
+ /**
3
+ * Low-level codec utilities for talking to the sACP Anchor programs
4
+ * without depending on a generated IDL.
5
+ *
6
+ * Anchor 0.30 instruction encoding:
7
+ * 1. 8-byte discriminator = sha256("global:<instruction_name>")[..8]
8
+ * 2. Followed by Borsh-encoded args in declaration order.
9
+ *
10
+ * We hand-roll the encoders here so the SDK has zero coupling to the
11
+ * Anchor build pipeline. That matters because Anchor 0.30 + recent
12
+ * rustc can't always emit an IDL (see anchor-syn issue with
13
+ * proc-macro2 `source_file`), and we don't want our SDK to inherit
14
+ * that fragility.
15
+ *
16
+ * All numeric encoders write little-endian, matching Solana's wire
17
+ * convention.
18
+ */
19
+ export function anchorDiscriminator(instructionName) {
20
+ const digest = sha256(new TextEncoder().encode(`global:${instructionName}`));
21
+ return Buffer.from(digest.subarray(0, 8));
22
+ }
23
+ export function encodeU8(value) {
24
+ const buf = Buffer.alloc(1);
25
+ buf.writeUInt8(value & 0xff);
26
+ return buf;
27
+ }
28
+ export function encodeU64(value) {
29
+ const buf = Buffer.alloc(8);
30
+ buf.writeBigUInt64LE(value);
31
+ return buf;
32
+ }
33
+ export function encodeI64(value) {
34
+ const buf = Buffer.alloc(8);
35
+ buf.writeBigInt64LE(value);
36
+ return buf;
37
+ }
38
+ /**
39
+ * Borsh string: 4-byte little-endian length followed by UTF-8 bytes.
40
+ * Spec mandates URIs ≤ 256 bytes; we enforce in the high-level builder
41
+ * rather than the codec.
42
+ */
43
+ export function encodeString(value) {
44
+ const utf8 = Buffer.from(value, "utf8");
45
+ const len = Buffer.alloc(4);
46
+ len.writeUInt32LE(utf8.length);
47
+ return Buffer.concat([len, utf8]);
48
+ }
49
+ /**
50
+ * 32-byte fixed array, used for hashes. Throws if input isn't exactly
51
+ * 32 bytes — saner than silently truncating.
52
+ */
53
+ export function encodeBytes32(bytes) {
54
+ if (bytes.length !== 32) {
55
+ throw new Error(`encodeBytes32: expected 32 bytes, got ${bytes.length}`);
56
+ }
57
+ return Buffer.from(bytes);
58
+ }
59
+ /** Concatenate the discriminator with serialized args. */
60
+ export function encodeInstruction(name, ...args) {
61
+ return Buffer.concat([anchorDiscriminator(name), ...args]);
62
+ }
63
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,UAAU,mBAAmB,CAAC,eAAuB;IACzD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,eAAe,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,GAAG,IAAc;IAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ /**
3
+ * sACP program IDs.
4
+ *
5
+ * v0.1 deployments live on Solana devnet. Mainnet program IDs will
6
+ * be added at v1.0; the SDK is version-locked, so a v0.1 SDK only
7
+ * talks to a v0.1 deployment.
8
+ *
9
+ * Deployed: 2026-06-04, slot 467078075 (job) / 467078115 (validation).
10
+ */
11
+ export declare const SACP_PROGRAM_ID: PublicKey;
12
+ export declare const SACP_VALIDATION_PROGRAM_ID: PublicKey;
13
+ /** Job state machine seed namespace — keeps PDAs cleanly separated. */
14
+ export declare const JOB_SEED_PREFIX = "job";
15
+ export declare const ESCROW_SEED_PREFIX = "escrow";
16
+ export declare const ESCROW_VAULT_SEED_PREFIX = "vault";
17
+ export declare const SUBMISSION_SEED_PREFIX = "submission";
18
+ export declare const VERDICT_SEED_PREFIX = "verdict";
19
+ export declare const CONFIG_SEED_PREFIX = "config";
20
+ export declare const OFFERING_SEED_PREFIX = "offering";
21
+ export declare const NEGOTIATION_SEED_PREFIX = "negotiation";
22
+ /** Validation registry seed namespace. */
23
+ export declare const VALIDATOR_SEED_PREFIX = "validator";
24
+ export declare const BOND_SEED_PREFIX = "bond";
25
+ export declare const BOND_AUTHORITY_SEED_PREFIX = "bond_authority";
26
+ export declare const BOND_VAULT_SEED_PREFIX = "bond_vault";
27
+ export declare const CHALLENGE_SEED_PREFIX = "challenge";
28
+ export declare const TREASURY_AUTHORITY_SEED_PREFIX = "treasury_authority";
29
+ export declare const TREASURY_VAULT_SEED_PREFIX = "treasury_vault";
30
+ export declare const RESOLVER_CONFIG_SEED_PREFIX = "resolver_config";
31
+ /**
32
+ * Default windows (seconds) baked into v0.1. These can be overridden
33
+ * per-job at `create_job` time; the constants are the protocol-level
34
+ * defaults that match the spec.
35
+ */
36
+ export declare const DEFAULT_SUBMIT_WINDOW_SECS: number;
37
+ export declare const DEFAULT_ACCEPT_WINDOW_SECS: number;
38
+ export declare const DEFAULT_DISPUTE_WINDOW_SECS: number;
39
+ export declare const DEFAULT_CHALLENGE_WINDOW_SECS: number;
40
+ /** Slash distribution constants (basis points). */
41
+ export declare const SLASH_TO_CHALLENGER_BPS = 7000;
42
+ export declare const SLASH_TO_TREASURY_BPS = 3000;
43
+ /** Protocol take-rate constants. Program-enforced cap; the authority
44
+ * can choose any value in [0, MAX_TAKE_RATE_BPS]. */
45
+ export declare const FEE_DENOMINATOR_BPS = 10000;
46
+ export declare const MAX_TAKE_RATE_BPS = 500;
47
+ /** Maximum fraction of the protocol fee routable to the evaluator
48
+ * (v0.7+). 10_000 bps = 100% of the fee. */
49
+ export declare const MAX_VALIDATOR_SHARE_BPS = 10000;
50
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;GAQG;AAEH,eAAO,MAAM,eAAe,WAE3B,CAAC;AAEF,eAAO,MAAM,0BAA0B,WAEtC,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,eAAO,MAAM,wBAAwB,UAAU,CAAC;AAChD,eAAO,MAAM,sBAAsB,eAAe,CAAC;AACnD,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAC7C,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAC/C,eAAO,MAAM,uBAAuB,gBAAgB,CAAC;AAErD,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC,eAAO,MAAM,0BAA0B,mBAAmB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,eAAe,CAAC;AACnD,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,8BAA8B,uBAAuB,CAAC;AACnE,eAAO,MAAM,0BAA0B,mBAAmB,CAAC;AAC3D,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,QAAe,CAAC;AACvD,eAAO,MAAM,0BAA0B,QAAe,CAAC;AACvD,eAAO,MAAM,2BAA2B,QAAmB,CAAC;AAC5D,eAAO,MAAM,6BAA6B,QAAe,CAAC;AAE1D,mDAAmD;AACnD,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAC7C,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C;qDACqD;AACrD,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAC1C,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC;4CAC4C;AAC5C,eAAO,MAAM,uBAAuB,QAAS,CAAC"}