@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/dist/signer.js ADDED
@@ -0,0 +1,94 @@
1
+ import { Transaction, sendAndConfirmTransaction, } from "@solana/web3.js";
2
+ /** Local-keypair signer. Default for SDK consumers running in-process. */
3
+ export class LocalSigner {
4
+ keypair;
5
+ constructor(keypair) {
6
+ this.keypair = keypair;
7
+ }
8
+ get publicKey() {
9
+ return this.keypair.publicKey;
10
+ }
11
+ async sendAndConfirm(connection, instructions, coSigners = []) {
12
+ const tx = new Transaction().add(...instructions);
13
+ return sendAndConfirmTransaction(connection, tx, [this.keypair, ...coSigners], { commitment: "confirmed" });
14
+ }
15
+ /** Convenience for runtimes that want raw Signer access (e.g. for
16
+ * `@solana/spl-token` helpers that demand `Signer` not just pubkey). */
17
+ asWeb3Signer() {
18
+ return this.keypair;
19
+ }
20
+ }
21
+ export class RemoteSigner {
22
+ publicKey;
23
+ transport;
24
+ constructor(publicKey, transport) {
25
+ this.publicKey = publicKey;
26
+ this.transport = transport;
27
+ }
28
+ async sendAndConfirm(connection, instructions, coSigners = []) {
29
+ const tx = new Transaction().add(...instructions);
30
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
31
+ tx.recentBlockhash = blockhash;
32
+ tx.lastValidBlockHeight = lastValidBlockHeight;
33
+ tx.feePayer = this.publicKey;
34
+ if (coSigners.length > 0)
35
+ tx.partialSign(...coSigners);
36
+ const message = tx.serializeMessage();
37
+ const signature = await this.transport.signMessage(Uint8Array.from(message));
38
+ tx.addSignature(this.publicKey, Buffer.from(signature));
39
+ const rawTx = tx.serialize();
40
+ const sig = await connection.sendRawTransaction(rawTx, {
41
+ skipPreflight: false,
42
+ preflightCommitment: "confirmed",
43
+ });
44
+ await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, "confirmed");
45
+ return sig;
46
+ }
47
+ }
48
+ /**
49
+ * Browser signer that delegates signing to a connected wallet
50
+ * (Phantom, Backpack, Solflare, anything that follows the
51
+ * `@solana/wallet-adapter-base` `WalletAdapter` interface).
52
+ *
53
+ * Typical Phantom usage:
54
+ *
55
+ * ```ts
56
+ * await window.solana.connect();
57
+ * const signer = new WalletAdapterSigner(window.solana);
58
+ * const sacp = new SacpClient({ connection });
59
+ * const session = await sacp.openJob({
60
+ * jobId,
61
+ * actors: { client: signer, provider: ..., evaluator: ... },
62
+ * });
63
+ * await session.fund();
64
+ * ```
65
+ *
66
+ * Co-signers (ephemeral keypairs) are forwarded to the wallet's
67
+ * `sendTransaction` option. Phantom + Backpack both honor it.
68
+ */
69
+ export class WalletAdapterSigner {
70
+ adapter;
71
+ constructor(adapter) {
72
+ this.adapter = adapter;
73
+ }
74
+ get publicKey() {
75
+ if (!this.adapter.publicKey) {
76
+ throw new Error("WalletAdapterSigner: wallet not connected (publicKey is null). Call adapter.connect() first.");
77
+ }
78
+ return this.adapter.publicKey;
79
+ }
80
+ async sendAndConfirm(connection, instructions, coSigners = []) {
81
+ const pk = this.publicKey; // throws if not connected
82
+ const tx = new Transaction().add(...instructions);
83
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
84
+ tx.recentBlockhash = blockhash;
85
+ tx.lastValidBlockHeight = lastValidBlockHeight;
86
+ tx.feePayer = pk;
87
+ const sig = await this.adapter.sendTransaction(tx, connection, {
88
+ signers: coSigners,
89
+ });
90
+ await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, "confirmed");
91
+ return sig;
92
+ }
93
+ }
94
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { Connection, PublicKey, TransactionInstruction } from "@solana/web3.js";
2
+ /** Compute fee from a Provider payout, matching the on-chain math:
3
+ * `floor(amount * bps / 10_000)`. JS bigint avoids the u64 → u128 cast
4
+ * the program does, but the result is identical because we floor. */
5
+ export declare function computeTakeRateFee(amount: bigint, bps: number): bigint;
6
+ /** Treasury ATA for `bondMint`, owned by the Config PDA. Must be
7
+ * pre-initialized (via `createAssociatedTokenAccountIdempotent`) before
8
+ * any Job using `bondMint` can settle on the Provider side. */
9
+ export declare function getTreasuryTokenAccount(bondMint: PublicKey): PublicKey;
10
+ export interface InitConfigParams {
11
+ payer: PublicKey;
12
+ takeRateBps: number;
13
+ authority: PublicKey;
14
+ }
15
+ export declare function buildInitConfigIx(params: InitConfigParams): TransactionInstruction;
16
+ export interface UpdateTakeRateParams {
17
+ authority: PublicKey;
18
+ newBps: number;
19
+ }
20
+ export declare function buildUpdateTakeRateIx(params: UpdateTakeRateParams): TransactionInstruction;
21
+ export interface UpdateValidatorShareParams {
22
+ authority: PublicKey;
23
+ newBps: number;
24
+ }
25
+ export declare function buildUpdateValidatorShareIx(params: UpdateValidatorShareParams): TransactionInstruction;
26
+ export interface SetConfigAuthorityParams {
27
+ authority: PublicKey;
28
+ newAuthority: PublicKey;
29
+ }
30
+ export declare function buildSetConfigAuthorityIx(params: SetConfigAuthorityParams): TransactionInstruction;
31
+ export interface WithdrawTreasuryParams {
32
+ authority: PublicKey;
33
+ bondMint: PublicKey;
34
+ destination: PublicKey;
35
+ amount: bigint;
36
+ }
37
+ export declare function buildWithdrawTreasuryIx(params: WithdrawTreasuryParams): TransactionInstruction;
38
+ export interface FetchedSacpConfig {
39
+ authority: PublicKey;
40
+ takeRateBps: number;
41
+ validatorShareBps: number;
42
+ }
43
+ export declare function fetchSacpConfig(connection: Connection): Promise<FetchedSacpConfig | null>;
44
+ //# sourceMappingURL=take_rate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"take_rate.d.ts","sourceRoot":"","sources":["../src/take_rate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,SAAS,EAET,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAiDzB;;qEAEqE;AACrE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAQtE;AAED;;+DAE+D;AAC/D,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,CAGtE;AAID,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,GACvB,sBAAsB,CAqBxB;AAID,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,GAC3B,sBAAsB,CAmBxB;AAID,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,0BAA0B,GACjC,sBAAsB,CAmBxB;AAID,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,SAAS,CAAC;CACzB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,wBAAwB,GAC/B,sBAAsB,CAcxB;AAID,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,EAAE,SAAS,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAmBxB;AAID,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAUnC"}
@@ -0,0 +1,141 @@
1
+ import { PublicKey, SystemProgram, TransactionInstruction, } from "@solana/web3.js";
2
+ import { getAssociatedTokenAddressSync } from "@solana/spl-token";
3
+ import { encodeInstruction, encodeU64, } from "./codec.js";
4
+ import { FEE_DENOMINATOR_BPS, MAX_TAKE_RATE_BPS, MAX_VALIDATOR_SHARE_BPS, SACP_PROGRAM_ID, } from "./constants.js";
5
+ import { findSacpConfigPda } from "./pdas.js";
6
+ /**
7
+ * SDK surface for the v0.6 protocol take-rate.
8
+ *
9
+ * The Job program owns one Config PDA (seeds = ["config"]) that holds:
10
+ * - authority: Pubkey that can update the rate, hand off authority,
11
+ * and withdraw from the Treasury.
12
+ * - take_rate_bps: u16 ∈ [0, MAX_TAKE_RATE_BPS] (5%). Applied on
13
+ * every Provider-winning settlement (accept_work +
14
+ * submit_verdict[winner=Provider]). Refund paths (reclaim_escrow,
15
+ * submit_verdict[winner=Client]) pay no fee.
16
+ *
17
+ * Treasury accounting is per-mint. Each accepted bond mint requires a
18
+ * Treasury ATA owned by the Config PDA before the corresponding Job
19
+ * can settle on the Provider side. The SDK exposes
20
+ * `getTreasuryTokenAccount` so callers can derive + `createIdempotent`
21
+ * the ATA in their own setup flow.
22
+ *
23
+ * Encoding follows the same hand-rolled Borsh path as the rest of the
24
+ * SDK (see `codec.ts`) so there is no IDL dependency.
25
+ */
26
+ const SPL_TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
27
+ function encodeU16(value) {
28
+ const buf = Buffer.alloc(2);
29
+ buf.writeUInt16LE(value & 0xffff);
30
+ return buf;
31
+ }
32
+ function encodePubkey(value) {
33
+ return Buffer.from(value.toBytes());
34
+ }
35
+ /** Compute fee from a Provider payout, matching the on-chain math:
36
+ * `floor(amount * bps / 10_000)`. JS bigint avoids the u64 → u128 cast
37
+ * the program does, but the result is identical because we floor. */
38
+ export function computeTakeRateFee(amount, bps) {
39
+ if (bps === 0)
40
+ return 0n;
41
+ if (bps < 0 || bps > MAX_TAKE_RATE_BPS) {
42
+ throw new Error(`take rate ${bps} bps out of range [0, ${MAX_TAKE_RATE_BPS}]`);
43
+ }
44
+ return (amount * BigInt(bps)) / BigInt(FEE_DENOMINATOR_BPS);
45
+ }
46
+ /** Treasury ATA for `bondMint`, owned by the Config PDA. Must be
47
+ * pre-initialized (via `createAssociatedTokenAccountIdempotent`) before
48
+ * any Job using `bondMint` can settle on the Provider side. */
49
+ export function getTreasuryTokenAccount(bondMint) {
50
+ const [configPda] = findSacpConfigPda();
51
+ return getAssociatedTokenAddressSync(bondMint, configPda, true);
52
+ }
53
+ export function buildInitConfigIx(params) {
54
+ if (params.takeRateBps < 0 || params.takeRateBps > MAX_TAKE_RATE_BPS) {
55
+ throw new Error(`take rate ${params.takeRateBps} bps out of range [0, ${MAX_TAKE_RATE_BPS}]`);
56
+ }
57
+ const [configPda] = findSacpConfigPda();
58
+ const data = encodeInstruction("init_config", encodeU16(params.takeRateBps), encodePubkey(params.authority));
59
+ return new TransactionInstruction({
60
+ programId: SACP_PROGRAM_ID,
61
+ keys: [
62
+ { pubkey: params.payer, isSigner: true, isWritable: true },
63
+ { pubkey: configPda, isSigner: false, isWritable: true },
64
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
65
+ ],
66
+ data,
67
+ });
68
+ }
69
+ export function buildUpdateTakeRateIx(params) {
70
+ if (params.newBps < 0 || params.newBps > MAX_TAKE_RATE_BPS) {
71
+ throw new Error(`take rate ${params.newBps} bps out of range [0, ${MAX_TAKE_RATE_BPS}]`);
72
+ }
73
+ const [configPda] = findSacpConfigPda();
74
+ const data = encodeInstruction("update_take_rate", encodeU16(params.newBps));
75
+ return new TransactionInstruction({
76
+ programId: SACP_PROGRAM_ID,
77
+ keys: [
78
+ { pubkey: params.authority, isSigner: true, isWritable: false },
79
+ { pubkey: configPda, isSigner: false, isWritable: true },
80
+ ],
81
+ data,
82
+ });
83
+ }
84
+ export function buildUpdateValidatorShareIx(params) {
85
+ if (params.newBps < 0 || params.newBps > MAX_VALIDATOR_SHARE_BPS) {
86
+ throw new Error(`validator share ${params.newBps} bps out of range [0, ${MAX_VALIDATOR_SHARE_BPS}]`);
87
+ }
88
+ const [configPda] = findSacpConfigPda();
89
+ const data = encodeInstruction("update_validator_share", encodeU16(params.newBps));
90
+ return new TransactionInstruction({
91
+ programId: SACP_PROGRAM_ID,
92
+ keys: [
93
+ { pubkey: params.authority, isSigner: true, isWritable: false },
94
+ { pubkey: configPda, isSigner: false, isWritable: true },
95
+ ],
96
+ data,
97
+ });
98
+ }
99
+ export function buildSetConfigAuthorityIx(params) {
100
+ const [configPda] = findSacpConfigPda();
101
+ const data = encodeInstruction("set_config_authority", encodePubkey(params.newAuthority));
102
+ return new TransactionInstruction({
103
+ programId: SACP_PROGRAM_ID,
104
+ keys: [
105
+ { pubkey: params.authority, isSigner: true, isWritable: false },
106
+ { pubkey: configPda, isSigner: false, isWritable: true },
107
+ ],
108
+ data,
109
+ });
110
+ }
111
+ export function buildWithdrawTreasuryIx(params) {
112
+ if (params.amount <= 0n)
113
+ throw new Error("amount must be > 0");
114
+ const [configPda] = findSacpConfigPda();
115
+ const treasuryAta = getTreasuryTokenAccount(params.bondMint);
116
+ const data = encodeInstruction("withdraw_treasury", encodeU64(params.amount));
117
+ return new TransactionInstruction({
118
+ programId: SACP_PROGRAM_ID,
119
+ keys: [
120
+ { pubkey: params.authority, isSigner: true, isWritable: false },
121
+ { pubkey: configPda, isSigner: false, isWritable: false },
122
+ { pubkey: treasuryAta, isSigner: false, isWritable: true },
123
+ { pubkey: params.destination, isSigner: false, isWritable: true },
124
+ { pubkey: SPL_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
125
+ ],
126
+ data,
127
+ });
128
+ }
129
+ export async function fetchSacpConfig(connection) {
130
+ const [configPda] = findSacpConfigPda();
131
+ const info = await connection.getAccountInfo(configPda, "confirmed");
132
+ if (!info)
133
+ return null;
134
+ const data = info.data;
135
+ // discriminator(8) | authority(32) | take_rate_bps(2) | validator_share_bps(2) | bump(1)
136
+ const authority = new PublicKey(data.subarray(8, 40));
137
+ const takeRateBps = data.readUInt16LE(40);
138
+ const validatorShareBps = data.readUInt16LE(42);
139
+ return { authority, takeRateBps, validatorShareBps };
140
+ }
141
+ //# sourceMappingURL=take_rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"take_rate.js","sourceRoot":"","sources":["../src/take_rate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type FetchedJob } from "./job.js";
2
+ import { SacpClient } from "./runtime.js";
3
+ import type { SacpSigner } from "./signer.js";
4
+ export interface ReclaimWatcherOptions {
5
+ client: SacpClient;
6
+ /** Buyer signer. Watcher only reclaims Jobs whose `client` field
7
+ * matches this pubkey. */
8
+ signer: SacpSigner;
9
+ /** Poll interval. Defaults to 30 seconds — Jobs don't usually
10
+ * expire on the second. */
11
+ pollIntervalMs?: number;
12
+ /** Optional safety margin in seconds added to `submit_deadline`
13
+ * before reclaiming, to allow for clock skew between the user's
14
+ * box and the cluster. Defaults to 30 s. */
15
+ graceSecs?: number;
16
+ /** Fired before each reclaim attempt. Throw to skip this Job (it
17
+ * stays eligible on the next tick). */
18
+ beforeReclaim?: (job: FetchedJob) => void | Promise<void>;
19
+ /** Fired after a successful reclaim tx. */
20
+ onReclaimed?: (job: FetchedJob, signature: string) => void | Promise<void>;
21
+ logger?: {
22
+ info: (m: string) => void;
23
+ error: (m: string, e?: unknown) => void;
24
+ };
25
+ }
26
+ export declare class ReclaimWatcher {
27
+ private readonly opts;
28
+ private timer;
29
+ private inFlight;
30
+ constructor(opts: ReclaimWatcherOptions);
31
+ start(): Promise<void>;
32
+ stop(): void;
33
+ private tick;
34
+ }
35
+ //# sourceMappingURL=timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAc,UAAU,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA0B9C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB;8BAC0B;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB;+BAC2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;gDAE4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;2CACuC;IACvC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,2CAA2C;IAC3C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAC1B,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KACzC,CAAC;CACH;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAGG;IACxB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,IAAI,EAAE,qBAAqB;IAQjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,IAAI,IAAI,IAAI;YAOE,IAAI;CA4BnB"}
@@ -0,0 +1,113 @@
1
+ import { SACP_PROGRAM_ID } from "./constants.js";
2
+ import { parseJobFromBuffer, buildReclaimEscrowIx, } from "./job.js";
3
+ import { getAssociatedTokenAddressSync } from "@solana/spl-token";
4
+ /**
5
+ * v0.9 Phase 5 — Timeout enforcement helper.
6
+ *
7
+ * `ReclaimWatcher` is a client-side daemon that scans for `Funded`
8
+ * Jobs whose client matches the supplied signer and whose
9
+ * `submit_deadline` has elapsed, then issues `reclaim_escrow` on
10
+ * each. It exists because forgetting to reclaim is the #1 way a
11
+ * buyer leaves money sitting in escrow.
12
+ *
13
+ * Why client-side, not a program-side crank: `reclaim_escrow`
14
+ * already gates on `client` signing, so anyone-callable auto-reclaim
15
+ * would need a program change (Phase 7+). The watcher is the cheap
16
+ * win that ships today; the program-side crank can replace it later
17
+ * without breaking this API.
18
+ *
19
+ * Offset reused from the watcher module:
20
+ * Job discriminator(8) | job_id(8) | client(32) — so the client
21
+ * pubkey sits at offset 16.
22
+ */
23
+ const CLIENT_OFFSET = 16;
24
+ export class ReclaimWatcher {
25
+ opts;
26
+ timer = null;
27
+ inFlight = new Set();
28
+ constructor(opts) {
29
+ this.opts = {
30
+ pollIntervalMs: 30_000,
31
+ graceSecs: 30,
32
+ ...opts,
33
+ };
34
+ }
35
+ async start() {
36
+ if (this.timer)
37
+ return;
38
+ await this.tick();
39
+ this.timer = setInterval(() => void this.tick(), this.opts.pollIntervalMs);
40
+ }
41
+ stop() {
42
+ if (this.timer) {
43
+ clearInterval(this.timer);
44
+ this.timer = null;
45
+ }
46
+ }
47
+ async tick() {
48
+ const { client, signer, graceSecs, beforeReclaim, onReclaimed, logger } = this.opts;
49
+ try {
50
+ const expired = await findExpiredJobsForClient(client.connection, signer.publicKey, graceSecs ?? 30);
51
+ for (const job of expired) {
52
+ const key = `${job.jobId}`;
53
+ if (this.inFlight.has(key))
54
+ continue;
55
+ this.inFlight.add(key);
56
+ try {
57
+ if (beforeReclaim)
58
+ await beforeReclaim(job);
59
+ const sig = await reclaim(client, signer, job);
60
+ if (onReclaimed)
61
+ await onReclaimed(job, sig);
62
+ logger?.info?.(`reclaimed ${job.jobId} (sig ${sig})`);
63
+ }
64
+ catch (e) {
65
+ logger?.error(`reclaim failed for job ${job.jobId}`, e);
66
+ }
67
+ finally {
68
+ this.inFlight.delete(key);
69
+ }
70
+ }
71
+ }
72
+ catch (e) {
73
+ logger?.error("ReclaimWatcher tick failed", e);
74
+ }
75
+ }
76
+ }
77
+ /** Internal: list Funded Jobs whose client matches `actor` and whose
78
+ * deadline has passed (with `graceSecs` buffer). */
79
+ async function findExpiredJobsForClient(conn, actor, graceSecs) {
80
+ const accounts = await conn.getProgramAccounts(SACP_PROGRAM_ID, {
81
+ commitment: "confirmed",
82
+ filters: [
83
+ { memcmp: { offset: CLIENT_OFFSET, bytes: actor.toBase58() } },
84
+ ],
85
+ });
86
+ const now = Math.floor(Date.now() / 1000);
87
+ const out = [];
88
+ for (const { account } of accounts) {
89
+ try {
90
+ const job = parseJobFromBuffer(account.data);
91
+ if (job.state !== "Funded")
92
+ continue;
93
+ const deadline = Number(job.submitDeadline);
94
+ if (now < deadline + graceSecs)
95
+ continue;
96
+ out.push(job);
97
+ }
98
+ catch {
99
+ // Not a Job — skip.
100
+ }
101
+ }
102
+ return out;
103
+ }
104
+ async function reclaim(client, signer, job) {
105
+ const clientAta = getAssociatedTokenAddressSync(job.bondMint, signer.publicKey);
106
+ const ix = buildReclaimEscrowIx({
107
+ client: signer.publicKey,
108
+ jobId: job.jobId,
109
+ clientTokenAccount: clientAta,
110
+ });
111
+ return signer.sendAndConfirm(client.connection, [ix]);
112
+ }
113
+ //# sourceMappingURL=timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.js","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { PublicKey } from "@solana/web3.js";
2
+ /**
3
+ * Job state machine, matching SRFC v0.1 §"Part A — State machine".
4
+ * Encoded on-chain as a u8 discriminator; the SDK exposes a string
5
+ * union for ergonomics.
6
+ */
7
+ export type JobState = "Open" | "Funded" | "Submitted" | "Disputed" | "Settled";
8
+ /** Numeric encoding used by the Anchor program. Mirrors the on-chain enum. */
9
+ export declare const JOB_STATE_NUMERIC: Record<JobState, number>;
10
+ /**
11
+ * Roles defined by sACP. `evaluator` is optional in v0.1 — if absent,
12
+ * the Job falls back to client-driven auto-settle on submit timeout.
13
+ *
14
+ * Spec note: the evaluator can be either a plain Pubkey (single signer
15
+ * or multisig PDA) or a Validator PDA from the Part B registry. Both
16
+ * resolve to a `Pubkey` from the SDK's perspective; the on-chain
17
+ * verdict path checks whether the signer matches a registered
18
+ * Validator and gates accordingly.
19
+ */
20
+ export interface JobRoles {
21
+ client: PublicKey;
22
+ provider: PublicKey;
23
+ evaluator?: PublicKey;
24
+ }
25
+ /** Verdict outcomes recorded on-chain after dispute resolution. */
26
+ export type VerdictWinner = "Client" | "Provider";
27
+ export declare const VERDICT_WINNER_NUMERIC: Record<VerdictWinner, number>;
28
+ /**
29
+ * Information returned to a caller after `create_job` succeeds. The
30
+ * Job PDA is deterministic from `(seed prefix, jobId)`, so callers
31
+ * holding `jobId` can re-derive `jobPda` later without storing it.
32
+ */
33
+ export interface CreateJobResult {
34
+ jobId: bigint;
35
+ jobPda: PublicKey;
36
+ escrowPda: PublicKey;
37
+ txSignature: string;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAEhF,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMtD,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElD,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAGhE,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB"}
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ /** Numeric encoding used by the Anchor program. Mirrors the on-chain enum. */
2
+ export const JOB_STATE_NUMERIC = {
3
+ Open: 0,
4
+ Funded: 1,
5
+ Submitted: 2,
6
+ Disputed: 3,
7
+ Settled: 4,
8
+ };
9
+ export const VERDICT_WINNER_NUMERIC = {
10
+ Client: 0,
11
+ Provider: 1,
12
+ };
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,CAAC;IACZ,QAAQ,EAAE,CAAC;IACX,OAAO,EAAE,CAAC;CACX,CAAC;AAqBF,MAAM,CAAC,MAAM,sBAAsB,GAAkC;IACnE,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;CACZ,CAAC"}
@@ -0,0 +1,133 @@
1
+ import { Connection, PublicKey, TransactionInstruction, type Signer } from "@solana/web3.js";
2
+ import { findBondAuthorityPda, findBondVaultPda, findChallengePda, findValidatorPda } from "./pdas.js";
3
+ import type { VerdictWinner } from "./types.js";
4
+ /**
5
+ * Permissionless treasury vault bootstrap (one per bond mint).
6
+ * Anyone can pay rent; the vault is owned by a program PDA so funds
7
+ * can only be moved by a future governance instruction.
8
+ */
9
+ export declare function buildInitTreasuryVaultIx(payer: PublicKey, bondMint: PublicKey): {
10
+ ix: TransactionInstruction;
11
+ treasuryVaultPda: PublicKey;
12
+ };
13
+ export interface RegisterValidatorParams {
14
+ authority: PublicKey;
15
+ /** SPL Token mint pinned to this validator. Can't be changed later. */
16
+ bondMint: PublicKey;
17
+ /** Off-chain operator info / SLA URI. */
18
+ metadataUri: string;
19
+ }
20
+ export interface RegisterValidatorBuildResult {
21
+ ix: TransactionInstruction;
22
+ validatorPda: PublicKey;
23
+ bondAuthorityPda: PublicKey;
24
+ bondVaultPda: PublicKey;
25
+ }
26
+ export declare function buildRegisterValidatorIx(params: RegisterValidatorParams): RegisterValidatorBuildResult;
27
+ export interface StakeBondParams {
28
+ authority: PublicKey;
29
+ amount: bigint;
30
+ operatorTokenAccount: PublicKey;
31
+ }
32
+ export declare function buildStakeBondIx(params: StakeBondParams): TransactionInstruction;
33
+ export declare function buildAcceptVerdictIx(authority: PublicKey, jobId: bigint, winner: VerdictWinner): TransactionInstruction;
34
+ /**
35
+ * Full CPI bridge — the Validator PDA calls sacp_job::submit_verdict
36
+ * directly. The Job must have been created with
37
+ * `evaluator = validatorPda` for the sacp_job has_one check to pass.
38
+ *
39
+ * This is the bond-collateralized verdict path. Unlike
40
+ * `buildAcceptVerdictIx` (event-only), this one actually moves money:
41
+ * escrow drains to the chosen winner in the same transaction.
42
+ */
43
+ export interface IssueVerdictParams {
44
+ authority: PublicKey;
45
+ client: PublicKey;
46
+ provider: PublicKey;
47
+ jobId: bigint;
48
+ bondMint: PublicKey;
49
+ winner: VerdictWinner;
50
+ clientTokenAccount: PublicKey;
51
+ providerTokenAccount: PublicKey;
52
+ /** v0.7+. Validator PDA's off-curve ATA on bondMint. SDK consumers
53
+ * should derive with
54
+ * `getAssociatedTokenAddressSync(bondMint, validatorPda, true)`
55
+ * and call `createAssociatedTokenAccountIdempotent` with
56
+ * `allowOwnerOffCurve=true` before any settlement. */
57
+ validatorTokenAccount: PublicKey;
58
+ }
59
+ export declare function buildIssueVerdictIx(params: IssueVerdictParams): TransactionInstruction;
60
+ export interface ChallengeVerdictParams {
61
+ challenger: PublicKey;
62
+ validatorAuthority: PublicKey;
63
+ jobId: bigint;
64
+ evidenceUri: string;
65
+ }
66
+ export declare function buildChallengeVerdictIx(params: ChallengeVerdictParams): {
67
+ ix: TransactionInstruction;
68
+ challengePda: PublicKey;
69
+ };
70
+ export interface ResolveChallengeParams {
71
+ authority: PublicKey;
72
+ validatorAuthority: PublicKey;
73
+ /** The bond mint pinned at register_validator time. */
74
+ bondMint: PublicKey;
75
+ jobId: bigint;
76
+ slash: boolean;
77
+ /** Required when slash=true; ignored otherwise. */
78
+ challengerTokenAccount: PublicKey;
79
+ }
80
+ export declare function buildResolveChallengeIx(params: ResolveChallengeParams): TransactionInstruction;
81
+ export declare function buildInitResolverConfigIx(params: {
82
+ payer: PublicKey;
83
+ authority: PublicKey;
84
+ }): TransactionInstruction;
85
+ export declare function buildSetResolverAuthorityIx(params: {
86
+ authority: PublicKey;
87
+ newAuthority: PublicKey;
88
+ }): TransactionInstruction;
89
+ export interface FetchedResolverConfig {
90
+ authority: PublicKey;
91
+ }
92
+ export declare function fetchResolverConfig(connection: Connection): Promise<FetchedResolverConfig | null>;
93
+ export interface WithdrawBondParams {
94
+ authority: PublicKey;
95
+ amount: bigint;
96
+ operatorTokenAccount: PublicKey;
97
+ }
98
+ export declare function buildWithdrawBondIx(params: WithdrawBondParams): TransactionInstruction;
99
+ export declare function registerValidator(connection: Connection, operator: Signer, params: {
100
+ bondMint: PublicKey;
101
+ metadataUri: string;
102
+ }): Promise<{
103
+ validatorPda: PublicKey;
104
+ bondVaultPda: PublicKey;
105
+ txSignature: string;
106
+ }>;
107
+ export interface FetchedValidator {
108
+ authority: PublicKey;
109
+ metadataUri: string;
110
+ bondMint: PublicKey;
111
+ bondAmount: bigint;
112
+ slashCount: number;
113
+ activeChallenges: number;
114
+ registeredAt: bigint;
115
+ /** v0.9 Phase 7 reputation counters. Defaults to 0 on pre-v0.9
116
+ * Validator accounts (which serialize shorter, so the parse stops
117
+ * before these fields and we fill in 0). */
118
+ successfulSettles: number;
119
+ failedChallenges: number;
120
+ wonChallenges: number;
121
+ }
122
+ export declare function fetchValidator(connection: Connection, authority: PublicKey): Promise<FetchedValidator | null>;
123
+ export interface FetchedChallenge {
124
+ jobId: bigint;
125
+ challenger: PublicKey;
126
+ validator: PublicKey;
127
+ evidenceUri: string;
128
+ filedAt: bigint;
129
+ resolved: boolean;
130
+ }
131
+ export declare function fetchChallenge(connection: Connection, jobId: bigint): Promise<FetchedChallenge | null>;
132
+ export { findBondAuthorityPda, findBondVaultPda, findChallengePda, findValidatorPda, };
133
+ //# sourceMappingURL=validation.d.ts.map