@pushchain/core 6.0.27-alpha.3 → 6.0.27-alpha.4

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 (90) hide show
  1. package/AGW.md +27 -6
  2. package/CHANGELOG.md +7 -0
  3. package/MARKETPLACE.md +206 -0
  4. package/package.json +2 -1
  5. package/src/lib/agentic/codec/rules.js +74 -69
  6. package/src/lib/agentic/codec/universal.js +15 -3
  7. package/src/lib/agentic/constants.d.ts +36 -1
  8. package/src/lib/agentic/constants.js +14 -1
  9. package/src/lib/agentic/contracts/reader.d.ts +21 -0
  10. package/src/lib/agentic/contracts/reader.js +3 -0
  11. package/src/lib/agentic/error-messages.d.ts +3 -0
  12. package/src/lib/agentic/error-messages.js +125 -0
  13. package/src/lib/agentic/errors.d.ts +12 -3
  14. package/src/lib/agentic/errors.js +76 -0
  15. package/src/lib/agentic/management/common.js +6 -0
  16. package/src/lib/agentic/management/destination.d.ts +5 -0
  17. package/src/lib/agentic/management/destination.js +32 -0
  18. package/src/lib/agentic/management/prepare.js +80 -55
  19. package/src/lib/agentic/management/svm-public.js +13 -4
  20. package/src/lib/agentic/presets/index.js +7 -8
  21. package/src/lib/agentic/presets/routes.d.ts +1 -1
  22. package/src/lib/agentic/presets/routes.js +6 -7
  23. package/src/lib/agentic/presets/types.d.ts +1 -6
  24. package/src/lib/agentic/public-rule.js +13 -2
  25. package/src/lib/constants/index.d.ts +35 -0
  26. package/src/lib/index.d.ts +4 -0
  27. package/src/lib/index.js +6 -2
  28. package/src/lib/job/job.d.ts +35 -0
  29. package/src/lib/job/job.js +382 -0
  30. package/src/lib/job/types.d.ts +94 -0
  31. package/src/lib/job/types.js +3 -0
  32. package/src/lib/job/watch.d.ts +3 -0
  33. package/src/lib/job/watch.js +169 -0
  34. package/src/lib/job-spec/codec.d.ts +18 -0
  35. package/src/lib/job-spec/codec.js +348 -0
  36. package/src/lib/job-spec/constants.d.ts +32 -0
  37. package/src/lib/job-spec/constants.js +36 -0
  38. package/src/lib/job-spec/helpers.d.ts +19 -0
  39. package/src/lib/job-spec/helpers.js +138 -0
  40. package/src/lib/job-spec/index.d.ts +14 -0
  41. package/src/lib/job-spec/index.js +17 -0
  42. package/src/lib/job-spec/preview.d.ts +8 -0
  43. package/src/lib/job-spec/preview.js +298 -0
  44. package/src/lib/job-spec/read.d.ts +20 -0
  45. package/src/lib/job-spec/read.js +224 -0
  46. package/src/lib/job-spec/schema.d.ts +290 -0
  47. package/src/lib/job-spec/schema.js +70 -0
  48. package/src/lib/job-spec/types.d.ts +139 -0
  49. package/src/lib/job-spec/types.js +3 -0
  50. package/src/lib/market/contracts/AgenticCommerce.d.ts +1026 -0
  51. package/src/lib/market/contracts/AgenticCommerce.js +1317 -0
  52. package/src/lib/market/contracts/RulesBindingHook.d.ts +235 -0
  53. package/src/lib/market/contracts/RulesBindingHook.js +314 -0
  54. package/src/lib/market/contracts/UniversalMarketplace.d.ts +1770 -0
  55. package/src/lib/market/contracts/UniversalMarketplace.js +2295 -0
  56. package/src/lib/market/contracts/UniversalMarketplaceErrors.d.ts +309 -0
  57. package/src/lib/market/contracts/UniversalMarketplaceErrors.js +416 -0
  58. package/src/lib/market/contracts/UniversalMarketplaceRules.d.ts +241 -0
  59. package/src/lib/market/contracts/UniversalMarketplaceRules.js +323 -0
  60. package/src/lib/market/data.d.ts +8 -0
  61. package/src/lib/market/data.js +60 -0
  62. package/src/lib/market/deployment.d.ts +14 -0
  63. package/src/lib/market/deployment.js +23 -0
  64. package/src/lib/market/deposit.d.ts +24 -0
  65. package/src/lib/market/deposit.js +271 -0
  66. package/src/lib/market/errors.d.ts +13 -0
  67. package/src/lib/market/errors.js +81 -0
  68. package/src/lib/market/history.d.ts +6 -0
  69. package/src/lib/market/history.js +83 -0
  70. package/src/lib/market/index.d.ts +4 -0
  71. package/src/lib/market/index.js +12 -0
  72. package/src/lib/market/kernel-wire.d.ts +15 -0
  73. package/src/lib/market/kernel-wire.js +41 -0
  74. package/src/lib/market/market.d.ts +55 -0
  75. package/src/lib/market/market.js +635 -0
  76. package/src/lib/market/rules.d.ts +106 -0
  77. package/src/lib/market/rules.js +293 -0
  78. package/src/lib/market/runtime.d.ts +35 -0
  79. package/src/lib/market/runtime.js +130 -0
  80. package/src/lib/market/types.d.ts +180 -0
  81. package/src/lib/market/types.js +3 -0
  82. package/src/lib/orchestrator/internals/errors.d.ts +9 -2
  83. package/src/lib/orchestrator/internals/errors.js +9 -2
  84. package/src/lib/orchestrator/internals/push-chain-tx.js +17 -3
  85. package/src/lib/push-chain/push-chain.d.ts +44 -1
  86. package/src/lib/push-chain/push-chain.js +23 -3
  87. package/src/lib/read-state/read-params.d.ts +9 -0
  88. package/src/lib/read-state/read-params.js +5 -1
  89. package/src/lib/utils.d.ts +15 -0
  90. package/src/lib/utils.js +4 -0
@@ -0,0 +1,94 @@
1
+ import type { Address, Hex } from 'viem';
2
+ import type { UniversalTxResponse } from '../orchestrator/orchestrator.types';
3
+ import type { JobSpec } from '../job-spec/types';
4
+ import type { StackProgressHook } from '../market/runtime';
5
+ export type JobStatus = 'Open' | 'Funded' | 'Submitted' | 'Completed' | 'Rejected' | 'Expired';
6
+ export interface CreateJobOptions {
7
+ provider: Address;
8
+ evaluator: Address;
9
+ hook: Address;
10
+ expiredAt: number;
11
+ paymentToken: Address;
12
+ jobSpec?: Hex;
13
+ description?: string;
14
+ progressHook?: StackProgressHook;
15
+ }
16
+ export interface Job {
17
+ jobId: bigint;
18
+ client: Address;
19
+ provider: Address;
20
+ evaluator: Address;
21
+ hook: Address;
22
+ status: JobStatus;
23
+ expiredAt: number;
24
+ budget: bigint;
25
+ paymentToken: Address;
26
+ /** Raw Solidity string bytes, which may contain a binary JobSpec rather than UTF-8. */
27
+ description: Hex;
28
+ deliverable?: Hex;
29
+ rulesId?: Hex;
30
+ jobSpec?: {
31
+ spec: JobSpec;
32
+ bytes: Hex;
33
+ /** Unavailable without a compatible evaluator. */ frozen?: boolean;
34
+ };
35
+ jobSpecDecodeError?: string;
36
+ evaluation: {
37
+ available: false;
38
+ reason: 'MANUAL_EVALUATOR' | 'UNVERIFIED_EVALUATOR';
39
+ };
40
+ }
41
+ export interface JobWriteOptions {
42
+ progressHook?: StackProgressHook;
43
+ }
44
+ export interface FundJobOptions extends JobWriteOptions {
45
+ rulesId?: Hex;
46
+ /** The price the client reviewed. Required for plain jobs or an updated card version. */
47
+ expectedBudget?: bigint;
48
+ }
49
+ export interface JobEvent {
50
+ jobId: bigint;
51
+ kind: string;
52
+ txHash?: Hex;
53
+ blockNumber?: bigint;
54
+ data?: unknown;
55
+ error?: unknown;
56
+ cursor?: JobWatchCursor;
57
+ }
58
+ /** Last delivered log; resume includes its block and excludes this log and earlier logs. */
59
+ export interface JobWatchCursor {
60
+ blockNumber: bigint;
61
+ logIndex: number;
62
+ blockHash?: Hex;
63
+ }
64
+ export interface JobWatchOptions {
65
+ fromBlock?: bigint;
66
+ cursor?: JobWatchCursor;
67
+ pollIntervalMs?: number;
68
+ }
69
+ export interface JobNamespace {
70
+ create(options: CreateJobOptions): Promise<{
71
+ jobId: bigint;
72
+ tx: UniversalTxResponse;
73
+ }>;
74
+ setBudget(jobId: bigint, amount: bigint, options?: JobWriteOptions & {
75
+ jobSpec?: Hex;
76
+ }): Promise<UniversalTxResponse>;
77
+ fund(jobId: bigint, options?: FundJobOptions): Promise<UniversalTxResponse>;
78
+ submit(jobId: bigint, options: JobWriteOptions & {
79
+ deliverable: Hex | string;
80
+ }): Promise<UniversalTxResponse>;
81
+ cancel(jobId: bigint, options?: JobWriteOptions): Promise<UniversalTxResponse>;
82
+ claimRefund(jobId: bigint, options?: JobWriteOptions): Promise<UniversalTxResponse>;
83
+ verify(jobId: bigint, options?: JobWriteOptions): Promise<never>;
84
+ status(jobId: bigint): Promise<Job>;
85
+ list(options?: {
86
+ client?: Address;
87
+ provider?: Address;
88
+ status?: JobStatus;
89
+ fromJobId?: bigint;
90
+ }): Promise<{
91
+ jobs: Job[];
92
+ }>;
93
+ watch(jobId: bigint, callback: (event: JobEvent) => void, options?: JobWatchOptions): () => void;
94
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,3 @@
1
+ import { type StackRuntime } from '../market/runtime';
2
+ import type { JobEvent, JobWatchOptions } from './types';
3
+ export declare function watchJob(rt: StackRuntime, jobId: bigint, callback: (event: JobEvent) => void, options: JobWatchOptions): () => void;
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.watchJob = watchJob;
4
+ const viem_1 = require("viem");
5
+ const AgenticCommerce_1 = require("../market/contracts/AgenticCommerce");
6
+ const runtime_1 = require("../market/runtime");
7
+ const errors_1 = require("../market/errors");
8
+ const data_1 = require("../market/data");
9
+ const names = [
10
+ 'JobCreated',
11
+ 'BudgetSet',
12
+ 'JobFunded',
13
+ 'JobSubmitted',
14
+ 'JobCompleted',
15
+ 'JobRejected',
16
+ 'JobExpired',
17
+ 'Refunded',
18
+ ];
19
+ const kinds = [
20
+ 'Created',
21
+ 'BudgetSet',
22
+ 'Funded',
23
+ 'Submitted',
24
+ 'Completed',
25
+ 'Rejected',
26
+ 'Expired',
27
+ 'Refunded',
28
+ ];
29
+ function watchJob(rt, jobId, callback, options) {
30
+ const d = (0, runtime_1.deployment)(rt);
31
+ let stopped = false;
32
+ let timer;
33
+ let cursor = options.cursor && { ...options.cursor };
34
+ let next = cursor?.blockNumber ?? options.fromBlock;
35
+ const interval = options.pollIntervalMs ?? 3000;
36
+ if (!Number.isSafeInteger(interval) ||
37
+ interval < 25 ||
38
+ (next !== undefined && (typeof next !== 'bigint' || next < BigInt(0))) ||
39
+ (cursor &&
40
+ (!Number.isSafeInteger(cursor.logIndex) ||
41
+ cursor.logIndex < 0 ||
42
+ (cursor.blockHash && !/^0x[\da-f]{64}$/i.test(cursor.blockHash)))) ||
43
+ (cursor && options.fromBlock !== undefined))
44
+ throw new errors_1.JobError('INVALID_WATCH_OPTIONS', 'Use a nonnegative block or a delivered-log cursor, and a polling interval of at least 25ms.');
45
+ const notify = (event) => {
46
+ try {
47
+ callback(event);
48
+ }
49
+ catch (error) {
50
+ if (event.kind !== 'Error' && !stopped) {
51
+ try {
52
+ callback({
53
+ jobId,
54
+ kind: 'Error',
55
+ error,
56
+ cursor: cursor && { ...cursor },
57
+ });
58
+ }
59
+ catch {
60
+ /* A consumer exception must not rewind delivery or reject an unobserved promise. */
61
+ }
62
+ }
63
+ }
64
+ };
65
+ const poll = async () => {
66
+ try {
67
+ const head = await rt.agw.reader.getBlockNumber();
68
+ if (stopped)
69
+ return;
70
+ if (cursor) {
71
+ if (head < cursor.blockNumber)
72
+ throw new errors_1.JobError('WATCH_REORG', 'The delivered cursor is ahead of the canonical head. Reload status before continuing.');
73
+ const block = rt.agw.reader.getBlock &&
74
+ (await rt.agw.reader.getBlock({ blockNumber: cursor.blockNumber }));
75
+ if (head < cursor.blockNumber ||
76
+ (cursor.blockHash &&
77
+ block?.hash &&
78
+ cursor.blockHash.toLowerCase() !== block.hash.toLowerCase()))
79
+ throw new errors_1.JobError('WATCH_REORG', 'The delivered cursor is no longer canonical. Reload job status and restart from a reviewed block.');
80
+ }
81
+ if (next === undefined)
82
+ next = head;
83
+ const end = next + BigInt(999) < head ? next + BigInt(999) : head;
84
+ if (next <= end) {
85
+ const start = next;
86
+ const groups = await Promise.all(names.map((name) => rt.agw.reader.getLogs({
87
+ address: d.kernel,
88
+ event: (0, viem_1.getAbiItem)({ abi: AgenticCommerce_1.JOB_KERNEL_ABI, name }),
89
+ args: { jobId },
90
+ fromBlock: start,
91
+ toBlock: end,
92
+ })));
93
+ if (stopped)
94
+ return;
95
+ const unique = new Map();
96
+ for (const log of groups.flat()) {
97
+ if (log.removed)
98
+ throw new errors_1.JobError('WATCH_REORG', 'The RPC returned a removed job log. Reload status before continuing.');
99
+ if ((0, viem_1.getAddress)(log.address) !== (0, viem_1.getAddress)(d.kernel) ||
100
+ log.blockNumber === null ||
101
+ log.logIndex === null ||
102
+ log.blockNumber < start ||
103
+ log.blockNumber > end)
104
+ throw new errors_1.JobError('INCONSISTENT_READ', 'The RPC returned an unmined or out-of-range job log.');
105
+ const event = (0, viem_1.decodeEventLog)({
106
+ abi: AgenticCommerce_1.JOB_KERNEL_ABI,
107
+ data: log.data,
108
+ topics: log.topics,
109
+ strict: true,
110
+ });
111
+ if (event.args.jobId !== jobId ||
112
+ !names.includes(event.eventName))
113
+ throw new errors_1.JobError('INCONSISTENT_READ', 'The RPC returned a different job or unsupported event.');
114
+ const key = `${log.blockNumber}:${log.logIndex}`;
115
+ const previous = unique.get(key);
116
+ if (previous && (0, data_1.fingerprint)(previous.log) !== (0, data_1.fingerprint)(log))
117
+ throw new errors_1.JobError('INCONSISTENT_READ', 'Two different logs occupy the same job cursor.');
118
+ unique.set(key, { log, event });
119
+ }
120
+ const ordered = [...unique.values()].sort((a, b) => Number(a.log.blockNumber - b.log.blockNumber) || a.log.logIndex - b.log.logIndex);
121
+ for (const { log, event } of ordered) {
122
+ if (stopped)
123
+ return;
124
+ const blockNumber = log.blockNumber;
125
+ const logIndex = log.logIndex;
126
+ if (cursor &&
127
+ (blockNumber < cursor.blockNumber ||
128
+ (blockNumber === cursor.blockNumber &&
129
+ logIndex <= cursor.logIndex)))
130
+ continue;
131
+ cursor = {
132
+ blockNumber,
133
+ logIndex,
134
+ ...(log.blockHash ? { blockHash: log.blockHash } : {}),
135
+ };
136
+ notify({
137
+ jobId,
138
+ kind: kinds[names.indexOf(event.eventName)],
139
+ txHash: log.transactionHash ?? undefined,
140
+ blockNumber,
141
+ data: event.args,
142
+ cursor: { ...cursor },
143
+ });
144
+ }
145
+ next = end + BigInt(1);
146
+ }
147
+ }
148
+ catch (error) {
149
+ if (stopped)
150
+ return;
151
+ if (error instanceof errors_1.JobError && error.code === 'WATCH_REORG')
152
+ stopped = true;
153
+ notify({ jobId, kind: 'Error', error, cursor: cursor && { ...cursor } });
154
+ }
155
+ finally {
156
+ if (!stopped)
157
+ timer = setTimeout(() => {
158
+ void poll();
159
+ }, interval);
160
+ }
161
+ };
162
+ void poll();
163
+ return () => {
164
+ stopped = true;
165
+ if (timer)
166
+ clearTimeout(timer);
167
+ };
168
+ }
169
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1,18 @@
1
+ import { type Hex } from 'viem';
2
+ import type { BuildJobSpecOptions, BuildJobSpecTemplateOptions, JobSpec, JobSpecTemplate, LogicTree } from './types';
3
+ interface LogicWire {
4
+ kind: number;
5
+ checks: readonly number[];
6
+ children: readonly number[];
7
+ k: number;
8
+ }
9
+ export declare function int256(value: bigint, what?: string): bigint;
10
+ export declare function flattenLogic(tree: LogicTree, checkCount: number): LogicWire[];
11
+ export declare function buildJobSpec(options: BuildJobSpecOptions): JobSpec;
12
+ export declare function buildJobSpecTemplate(options: BuildJobSpecTemplateOptions): JobSpecTemplate;
13
+ export declare function encodeJobSpec(spec: JobSpec | JobSpecTemplate): Hex;
14
+ /** Known callers pass the format; inference requires one canonical validated decode. */
15
+ export declare function decodeJobSpec(bytes: Hex, options?: {
16
+ format?: 'spec' | 'template';
17
+ }): JobSpec | JobSpecTemplate;
18
+ export {};
@@ -0,0 +1,348 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.int256 = int256;
4
+ exports.flattenLogic = flattenLogic;
5
+ exports.buildJobSpec = buildJobSpec;
6
+ exports.buildJobSpecTemplate = buildJobSpecTemplate;
7
+ exports.encodeJobSpec = encodeJobSpec;
8
+ exports.decodeJobSpec = decodeJobSpec;
9
+ const viem_1 = require("viem");
10
+ const errors_1 = require("../market/errors");
11
+ const constants_1 = require("./constants");
12
+ const schema_1 = require("./schema");
13
+ const read_1 = require("./read");
14
+ const originalLogic = new WeakMap();
15
+ const fail = (message, code = 'INVALID_JOB_SPEC') => {
16
+ throw new errors_1.JobSpecError(code, message);
17
+ };
18
+ const fingerprint = (x) => JSON.stringify(x, (_, v) => (typeof v === 'bigint' ? v.toString() : v));
19
+ function int256(value, what = 'Target') {
20
+ if (typeof value !== 'bigint' ||
21
+ value < -(BigInt(1) << BigInt(255)) ||
22
+ value >= BigInt(1) << BigInt(255))
23
+ fail(`${what} must fit int256.`);
24
+ return value;
25
+ }
26
+ function count(values, max, what, min = 1) {
27
+ if (!Array.isArray(values) || values.length < min || values.length > max)
28
+ fail(`${what} must contain ${min}..${max} entries.`, `TOO_MANY_${what.toUpperCase()}`);
29
+ }
30
+ function timestamp(n) {
31
+ if (!Number.isSafeInteger(n) || n < 0)
32
+ fail('Timestamps must be nonnegative safe integers.');
33
+ }
34
+ function enumIndex(values, value, name) {
35
+ const i = values.indexOf(value);
36
+ if (i < 0)
37
+ fail(`Unknown ${name}.`);
38
+ return i;
39
+ }
40
+ function flattenLogic(tree, checkCount) {
41
+ const nodes = [];
42
+ const active = new Set();
43
+ function visit(t) {
44
+ if (!t || active.has(t) || nodes.length >= 32)
45
+ fail('Logic is cyclic or exceeds 32 operators.', 'BAD_TREE');
46
+ active.add(t);
47
+ const index = nodes.length;
48
+ const kind = enumIndex(constants_1.LOGIC_KINDS, t.kind, 'logic kind');
49
+ if (!Array.isArray(t.of) || !t.of.length || t.of.length > 255)
50
+ fail('Logic operators need 1..255 operands.', 'BAD_TREE');
51
+ const k = t.kind === 'AT_LEAST' ? t.k ?? 0 : 0;
52
+ if (!Number.isInteger(k) ||
53
+ (t.kind === 'AT_LEAST' && (k < 1 || k > t.of.length)) ||
54
+ (t.kind !== 'AT_LEAST' && t.k !== undefined && t.k !== 0))
55
+ fail('Invalid AT_LEAST threshold.', 'BAD_TREE');
56
+ const n = { kind, checks: [], children: [], k: k };
57
+ nodes.push(n);
58
+ for (const item of t.of) {
59
+ if (typeof item === 'number') {
60
+ if (!Number.isInteger(item) ||
61
+ item < 0 ||
62
+ item >= checkCount ||
63
+ n.checks.includes(item))
64
+ fail('Dangling or duplicated check index.', 'BAD_TREE');
65
+ n.checks.push(item);
66
+ }
67
+ else
68
+ n.children.push(visit(item));
69
+ }
70
+ active.delete(t);
71
+ return index;
72
+ }
73
+ visit(tree);
74
+ const saved = originalLogic.get(tree);
75
+ return saved?.fingerprint === fingerprint(tree) ? saved.wire : nodes;
76
+ }
77
+ function nestLogic(nodes, checkCount) {
78
+ count(nodes, 32, 'logic');
79
+ const reached = new Set();
80
+ let expanded = 0;
81
+ function visit(index, depth) {
82
+ if (++expanded > 512 || depth > 32)
83
+ fail('Stored logic is too large to describe as a tree.', 'BAD_TREE');
84
+ const n = nodes[index];
85
+ if (!n || !constants_1.LOGIC_KINDS[n.kind])
86
+ fail('Unknown stored logic kind.', 'BAD_TREE');
87
+ reached.add(index);
88
+ if (n.checks.some((i) => !Number.isInteger(i) || i < 0 || i >= checkCount) ||
89
+ new Set(n.checks).size !== n.checks.length)
90
+ fail('Invalid stored check reference.', 'BAD_TREE');
91
+ if (n.children.some((i) => i <= index || i >= nodes.length) ||
92
+ new Set(n.children).size !== n.children.length)
93
+ fail('Invalid stored child reference.', 'BAD_TREE');
94
+ const t = {
95
+ kind: constants_1.LOGIC_KINDS[n.kind],
96
+ of: [...n.checks, ...n.children.map((i) => visit(i, depth + 1))],
97
+ ...(n.kind === 2 ? { k: n.k } : {}),
98
+ };
99
+ if (n.kind !== 2 && n.k !== 0)
100
+ fail('Unexpected threshold on stored logic.', 'BAD_TREE');
101
+ return t;
102
+ }
103
+ const tree = visit(0, 0);
104
+ if (reached.size !== nodes.length)
105
+ fail('Stored logic has unreachable operators.', 'BAD_TREE');
106
+ // Preserve an unchanged, valid topological order instead of rewriting signed bytes.
107
+ originalLogic.set(tree, { fingerprint: fingerprint(tree), wire: nodes });
108
+ flattenLogic(tree, checkCount);
109
+ return tree;
110
+ }
111
+ function normalizeReads(values) {
112
+ count(values, 16, 'reads');
113
+ return values.map((input) => {
114
+ const wrapper = input;
115
+ const source = 'read' in input ? wrapper.read : input;
116
+ const read = {
117
+ ...source,
118
+ field: [...(wrapper.field ?? [0])],
119
+ minConfirmations: wrapper.minConfirmations ?? 1,
120
+ ...(source.fills ? { fills: source.fills.map((f) => ({ ...f })) } : {}),
121
+ };
122
+ (0, read_1.inheritReadLabel)(source, read);
123
+ return read;
124
+ });
125
+ }
126
+ function validate(spec) {
127
+ count(spec.reads, 16, 'reads');
128
+ count(spec.checks, 16, 'checks');
129
+ enumIndex(constants_1.MUTABILITIES, spec.allowedMutability, 'allowedMutability');
130
+ const template = 'params' in spec;
131
+ if (template) {
132
+ count(spec.params, 16, 'params', 0);
133
+ for (const p of spec.params)
134
+ if (int256(p.min) > int256(p.max))
135
+ fail('Parameter minimum exceeds its maximum.');
136
+ }
137
+ else {
138
+ timestamp(spec.executeBy);
139
+ timestamp(spec.failFinalAt);
140
+ if (spec.failFinalAt <= spec.executeBy ||
141
+ !/^0x[\da-f]{64}$/i.test(spec.origin))
142
+ fail('Invalid JobSpec timing or origin.');
143
+ }
144
+ for (const r of spec.reads) {
145
+ (0, read_1.validateJobRead)(r);
146
+ if (!Number.isInteger(r.minConfirmations) ||
147
+ r.minConfirmations < 1 ||
148
+ r.minConfirmations > 65535)
149
+ fail('Read confirmations must be 1..65535.');
150
+ const words = new Set();
151
+ for (const f of r.fills ?? []) {
152
+ if (!template)
153
+ fail('A complete JobSpec cannot contain placeholders.', 'UNFILLED_PLACEHOLDER');
154
+ if (!Number.isInteger(f.word) ||
155
+ f.word < 0 ||
156
+ f.word > 255 ||
157
+ f.word * 32 + 32 > (r.args.length - 2) / 2 ||
158
+ words.has(f.word))
159
+ fail('Invalid or duplicate fill word.');
160
+ words.add(f.word);
161
+ if (!['WALLET', 'PARAM'].includes(f.source))
162
+ fail('Unknown fill source.');
163
+ if (f.source === 'PARAM' &&
164
+ (!Number.isInteger(f.param) ||
165
+ (f.param ?? -1) < 0 ||
166
+ (f.param ?? -1) >= spec.params.length))
167
+ fail('Fill parameter is out of range.');
168
+ }
169
+ }
170
+ for (const c of spec.checks) {
171
+ if (!Number.isInteger(c.read) || c.read < 0 || c.read >= spec.reads.length)
172
+ fail('Check read index is out of range.');
173
+ enumIndex(constants_1.EVALUATIONS, c.evaluation, 'evaluation');
174
+ enumIndex(constants_1.OPERATIONS, c.operation, 'operation');
175
+ if (c.evaluation === 'BOOLEAN' && c.operation !== 'EQUAL')
176
+ fail('BOOLEAN checks use EQUAL.');
177
+ if (typeof c.target === 'bigint')
178
+ int256(c.target);
179
+ else if (!template)
180
+ fail('Complete JobSpec targets must be resolved integers.', 'UNFILLED_PLACEHOLDER');
181
+ else
182
+ targetWire(c.target, spec.params.length);
183
+ }
184
+ flattenLogic(spec.logic, spec.checks.length);
185
+ }
186
+ function targetWire(target, params) {
187
+ if (typeof target === 'bigint')
188
+ return { source: 0, value: int256(target) };
189
+ if (target === constants_1.PRINCIPAL)
190
+ return { source: 1, value: BigInt(10000) };
191
+ if (target === 'agentic:wallet')
192
+ return { source: 3, value: BigInt(0) };
193
+ if (target && typeof target === 'object' && 'principalBps' in target) {
194
+ if (int256(target.principalBps) <= BigInt(0))
195
+ fail('principalBps must be positive.');
196
+ return { source: 1, value: target.principalBps };
197
+ }
198
+ if (target &&
199
+ typeof target === 'object' &&
200
+ 'param' in target &&
201
+ Number.isInteger(target.param) &&
202
+ target.param >= 0 &&
203
+ target.param < params)
204
+ return { source: 2, value: BigInt(target.param) };
205
+ return fail('Unknown or out-of-range template target.');
206
+ }
207
+ function buildJobSpec(options) {
208
+ const spec = {
209
+ reads: normalizeReads(options.reads),
210
+ checks: options.checks.map((c) => ({ ...c })),
211
+ logic: typeof options.logic === 'string'
212
+ ? { kind: options.logic, of: options.checks.map((_, i) => i) }
213
+ : options.logic,
214
+ allowedMutability: options.allowedMutability ?? 'NONE',
215
+ origin: options.origin ?? viem_1.zeroHash,
216
+ executeBy: options.executeBy,
217
+ failFinalAt: options.failFinalAt,
218
+ };
219
+ validate(spec);
220
+ if (options.expiredAt !== undefined) {
221
+ timestamp(options.expiredAt);
222
+ if (options.failFinalAt >= options.expiredAt)
223
+ fail('failFinalAt must precede job expiry.', 'FAIL_WINDOW_THIN');
224
+ }
225
+ return spec;
226
+ }
227
+ function buildJobSpecTemplate(options) {
228
+ const t = {
229
+ reads: normalizeReads(options.reads),
230
+ checks: options.checks.map((c) => ({ ...c })),
231
+ logic: typeof options.logic === 'string'
232
+ ? { kind: options.logic, of: options.checks.map((_, i) => i) }
233
+ : options.logic,
234
+ allowedMutability: options.allowedMutability ?? 'NONE',
235
+ params: (options.params ?? []).map((p) => ({ ...p })),
236
+ };
237
+ validate(t);
238
+ return t;
239
+ }
240
+ function encodeJobSpec(spec) {
241
+ validate(spec);
242
+ const base = {
243
+ reads: spec.reads.map(({ fills, ...r }) => 'params' in spec
244
+ ? {
245
+ ...r,
246
+ fills: (fills ?? []).map((f) => ({
247
+ word: f.word,
248
+ source: f.source === 'WALLET' ? 0 : 1,
249
+ param: f.param ?? 0,
250
+ })),
251
+ }
252
+ : r),
253
+ logic: flattenLogic(spec.logic, spec.checks.length),
254
+ allowedMutability: constants_1.MUTABILITIES.indexOf(spec.allowedMutability),
255
+ };
256
+ const checks = spec.checks.map((c) => ({
257
+ read: c.read,
258
+ evaluation: constants_1.EVALUATIONS.indexOf(c.evaluation),
259
+ operation: constants_1.OPERATIONS.indexOf(c.operation),
260
+ ...('params' in spec
261
+ ? targetWire(c.target, spec.params.length)
262
+ : { target: c.target }),
263
+ }));
264
+ const value = 'params' in spec
265
+ ? { ...base, checks, params: spec.params }
266
+ : {
267
+ ...base,
268
+ checks,
269
+ origin: spec.origin,
270
+ executeBy: BigInt(spec.executeBy),
271
+ failFinalAt: BigInt(spec.failFinalAt),
272
+ };
273
+ return (0, viem_1.encodeAbiParameters)([('params' in spec ? schema_1.JOB_TEMPLATE_PARAM : schema_1.JOB_SPEC_PARAM)], [value]);
274
+ }
275
+ /** Known callers pass the format; inference requires one canonical validated decode. */
276
+ function decodeJobSpec(bytes, options) {
277
+ if (!(0, viem_1.isHex)(bytes) || bytes.length > 524290)
278
+ fail('Invalid or oversized JobSpec encoding.');
279
+ const valid = [];
280
+ for (const template of options?.format
281
+ ? [options.format === 'template']
282
+ : [false, true]) {
283
+ try {
284
+ const w = (0, viem_1.decodeAbiParameters)([(template ? schema_1.JOB_TEMPLATE_PARAM : schema_1.JOB_SPEC_PARAM)], bytes)[0];
285
+ const reads = w.reads.map(({ fills: rawFills, ...r }) => ({
286
+ ...r,
287
+ ...(template
288
+ ? {
289
+ fills: (rawFills ?? []).map((f) => {
290
+ if (f.source > 1 || (f.source === 0 && f.param !== 0))
291
+ fail('Invalid stored fill.');
292
+ return {
293
+ word: f.word,
294
+ source: f.source === 0 ? 'WALLET' : 'PARAM',
295
+ ...(f.source === 1 ? { param: f.param } : {}),
296
+ };
297
+ }),
298
+ }
299
+ : {}),
300
+ }));
301
+ const checks = w.checks.map((c) => {
302
+ const common = {
303
+ read: c.read,
304
+ evaluation: constants_1.EVALUATIONS[c.evaluation],
305
+ operation: constants_1.OPERATIONS[c.operation],
306
+ };
307
+ if (!template)
308
+ return { ...common, target: c.target };
309
+ const t = c;
310
+ const target = t.source === 0
311
+ ? t.value
312
+ : t.source === 1
313
+ ? t.value === BigInt(10000)
314
+ ? constants_1.PRINCIPAL
315
+ : { principalBps: t.value }
316
+ : t.source === 2
317
+ ? { param: Number(t.value) }
318
+ : t.source === 3 && t.value === BigInt(0)
319
+ ? 'agentic:wallet'
320
+ : fail('Unknown template target.');
321
+ return { ...common, target };
322
+ });
323
+ const common = {
324
+ reads,
325
+ checks,
326
+ logic: nestLogic(w.logic, checks.length),
327
+ allowedMutability: constants_1.MUTABILITIES[w.allowedMutability],
328
+ };
329
+ const spec = (template
330
+ ? { ...common, params: w.params }
331
+ : {
332
+ ...common,
333
+ origin: w.origin,
334
+ executeBy: Number(w.executeBy),
335
+ failFinalAt: Number(w.failFinalAt),
336
+ });
337
+ if (encodeJobSpec(spec).toLowerCase() === bytes.toLowerCase())
338
+ valid.push(spec);
339
+ }
340
+ catch {
341
+ /* Wrong shape, unsupported wire, malformed enums or noncanonical bytes. */
342
+ }
343
+ }
344
+ if (valid.length !== 1)
345
+ fail('The bytes do not identify one supported canonical deployed-v2 JobSpec format.', 'UNSUPPORTED_JOB_SPEC');
346
+ return valid[0];
347
+ }
348
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1,32 @@
1
+ export declare const JOB_VOCABULARY: Readonly<{
2
+ EVALUATION: Readonly<{
3
+ readonly BOOLEAN: "BOOLEAN";
4
+ readonly COMPARE: "COMPARE";
5
+ readonly NUMBER: "NUMBER";
6
+ readonly PERCENTAGE: "PERCENTAGE";
7
+ }>;
8
+ OPERATION: Readonly<{
9
+ readonly EQUAL: "EQUAL";
10
+ readonly NOT_EQUAL: "NOT_EQUAL";
11
+ readonly GREATER_THAN: "GREATER_THAN";
12
+ readonly GREATER_OR_EQUAL: "GREATER_OR_EQUAL";
13
+ readonly LESS_THAN: "LESS_THAN";
14
+ readonly LESS_OR_EQUAL: "LESS_OR_EQUAL";
15
+ }>;
16
+ LOGIC: Readonly<{
17
+ readonly ALL: "ALL";
18
+ readonly ANY: "ANY";
19
+ readonly AT_LEAST: "AT_LEAST";
20
+ }>;
21
+ ALLOWED_MUTABILITY: Readonly<{
22
+ readonly NONE: "NONE";
23
+ readonly CLIENT: "CLIENT";
24
+ readonly PROVIDER: "PROVIDER";
25
+ readonly BOTH: "BOTH";
26
+ }>;
27
+ }>;
28
+ export declare const PRINCIPAL: "agentic:principal";
29
+ export declare const EVALUATIONS: ("BOOLEAN" | "COMPARE" | "NUMBER" | "PERCENTAGE")[];
30
+ export declare const OPERATIONS: ("EQUAL" | "NOT_EQUAL" | "GREATER_THAN" | "GREATER_OR_EQUAL" | "LESS_THAN" | "LESS_OR_EQUAL")[];
31
+ export declare const LOGIC_KINDS: ("ALL" | "ANY" | "AT_LEAST")[];
32
+ export declare const MUTABILITIES: ("NONE" | "CLIENT" | "PROVIDER" | "BOTH")[];