@totemsdk/omnia-vtxo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Totem SDK Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # `@totemsdk/omnia-vtxo`
2
+
3
+ Virtual UTXO (vTXO) / payment-pool claim layer for the Totem Edge ecosystem.
4
+
5
+ ## What is Omnia VTXO?
6
+
7
+ `@totemsdk/omnia-vtxo` is a **cash-like off-chain balance primitive** that gives Totem Edge applications a way to hold, transfer, split, merge, and exit token balances without requiring a live Minima node for every operation. Each VTXO (Virtual Transaction Output) is a claim on a pool of on-chain capacity, backed by a deterministic Merkle commitment tree.
8
+
9
+ Think of it as a bearer note inside a shared liquidity pool. The pool operator holds the on-chain UTXO; the holder holds the VTXO proof.
10
+
11
+ ### How it differs from Statechains
12
+
13
+ | | Statechain | Omnia VTXO |
14
+ |---|---|---|
15
+ | Ownership transfer | Blind SE co-signature | Pure functional, no live signing needed |
16
+ | Privacy model | Blind Mercury SE | Local commitment root |
17
+ | Splitting | Not supported | Supported natively |
18
+ | Merging | Not supported | Supported natively |
19
+ | Exit model | On-chain UTXO handoff | Pool epoch settlement |
20
+ | Use case | Privacy UTXO custody | Merchant receipts, credits, pool liquidity |
21
+
22
+ ### Relation to other `@totemsdk` packages
23
+
24
+ ```
25
+ @totemsdk/omnia ← L2 channel layer (eltoo state machine)
26
+ @totemsdk/omnia-factory ← N-of-N funding factory
27
+ @totemsdk/omnia-vtxo ← Virtual UTXO claim layer (this package)
28
+ @totemsdk/statechain ← Mercury off-chain ownership records
29
+ ```
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pnpm add @totemsdk/omnia-vtxo @noble/hashes
35
+ ```
36
+
37
+ ## Import
38
+
39
+ ```ts
40
+ import {
41
+ createPool,
42
+ mintVtxo,
43
+ transferVtxo,
44
+ splitVtxo,
45
+ mergeVtxos,
46
+ refreshVtxo,
47
+ createExitDraft,
48
+ verifyVtxo,
49
+ verifyConservation,
50
+ MemoryOmniaVtxoStore,
51
+ serializeVtxo,
52
+ deserializeVtxo,
53
+ } from '@totemsdk/omnia-vtxo';
54
+ ```
55
+
56
+ ## Full Lifecycle Example
57
+
58
+ ```ts
59
+ import {
60
+ createPool,
61
+ mintVtxo,
62
+ transferVtxo,
63
+ splitVtxo,
64
+ mergeVtxos,
65
+ refreshVtxo,
66
+ createExitDraft,
67
+ markExiting,
68
+ markExited,
69
+ verifyVtxo,
70
+ verifyConservation,
71
+ MemoryOmniaVtxoStore,
72
+ } from '@totemsdk/omnia-vtxo';
73
+
74
+ const NOW = Date.now();
75
+
76
+ // 1. Create a pool (deterministic — poolId derived from operator + tokenId + nonce)
77
+ const pool = createPool({
78
+ operator: 'MxOperatorAddress',
79
+ tokenId: '0x00', // Minima native token
80
+ totalCapacity: BigInt(1_000_000_000),
81
+ nonce: 'pool-genesis-v1',
82
+ }, NOW);
83
+
84
+ // 2. Mint a VTXO (reduces pool.availableCapacity)
85
+ const { pool: p1, vtxo: note, receipt: mintReceipt } = mintVtxo(
86
+ pool,
87
+ { owner: 'MxAlice', amount: BigInt(100_000), nonce: 'note-1' },
88
+ NOW,
89
+ );
90
+
91
+ // 3. Transfer the note to Bob (full transfer: note → transferred, bobNote → active)
92
+ const { input: spentNote, output: bobNote, transfer } = transferVtxo(
93
+ note,
94
+ { recipient: 'MxBob', amount: BigInt(100_000), nonce: 'tx-1' },
95
+ NOW + 1,
96
+ );
97
+
98
+ // 4. Split Bob's note into two pieces
99
+ const { input: splitInput, outputs: [piece1, piece2] } = splitVtxo(
100
+ bobNote,
101
+ { amounts: [BigInt(60_000), BigInt(40_000)], nonces: ['sp-1', 'sp-2'] },
102
+ NOW + 2,
103
+ );
104
+
105
+ // 5. Merge the two pieces back together
106
+ const { output: mergedNote } = mergeVtxos(
107
+ [piece1, piece2],
108
+ { nonce: 'mg-1', owner: 'MxBob' },
109
+ NOW + 3,
110
+ );
111
+
112
+ // 6. Refresh the note to a new epoch (re-anchor against pool epoch)
113
+ const { old: staleNote, refreshed: freshNote } = refreshVtxo(
114
+ mergedNote,
115
+ { newEpoch: 1, nonce: 'ref-1' },
116
+ NOW + 4,
117
+ );
118
+
119
+ // 7. Create a mock exit draft
120
+ const { draft, receipt: exitReceipt } = createExitDraft(freshNote, NOW + 5);
121
+ console.log('Exit draft type:', draft.draftType); // 'mock-exit'
122
+
123
+ // 8. Verify proofs and conservation
124
+ const vtxoCheck = verifyVtxo(freshNote);
125
+ console.log('VTXO valid:', vtxoCheck.valid);
126
+
127
+ const conservation = verifyConservation({
128
+ inputs: [note],
129
+ outputs: [spentNote], // full transfer: input sum must equal output sum
130
+ });
131
+
132
+ // 9. Persist with MemoryOmniaVtxoStore
133
+ const store = new MemoryOmniaVtxoStore();
134
+ await store.savePool(p1);
135
+ await store.saveVtxo(freshNote);
136
+ const loaded = await store.getVtxo(freshNote.vtxoId);
137
+ ```
138
+
139
+ ## API Reference
140
+
141
+ ### Pool
142
+
143
+ | Function | Description |
144
+ |---|---|
145
+ | `createPool(params, now)` | Creates a new VTXO pool. `poolId` is deterministic from `operator + tokenId + nonce`. Never calls `Date.now()` internally. |
146
+ | `assertPoolCanMint(pool, amount)` | Validates capacity and policy. Throws `VtxoPoolCapacityError` or `VtxoPolicyError`. |
147
+ | `updatePoolRoot(pool, root)` | Returns a new pool with an updated commitment root (immutable). |
148
+ | `advancePoolEpoch(pool, newEpoch)` | Advances epoch; throws if `newEpoch <= pool.epoch`. |
149
+
150
+ ### VTXO Lifecycle
151
+
152
+ | Function | Status transition | Notes |
153
+ |---|---|---|
154
+ | `mintVtxo(pool, params, now)` | — → `active` | Reduces `pool.availableCapacity`. |
155
+ | `transferVtxo(vtxo, params, now)` | `active` → `transferred`/`split` | Full: input `transferred`, output `active`. Partial: input `split`, output+change `active`. |
156
+ | `splitVtxo(vtxo, params, now)` | `active` → `split` | Outputs `active`. Sum must equal input amount. |
157
+ | `mergeVtxos(vtxos, params, now)` | `active[]` → `merged` | Output `active`. Rejects duplicate IDs. Same pool+token required. |
158
+ | `refreshVtxo(vtxo, params, now)` | `active` → `refreshed` | New VTXO `active` with higher epoch. |
159
+ | `markExiting(vtxo, now)` | `active` → `exiting` | Initiates unilateral exit. |
160
+ | `markExited(vtxo, now)` | `exiting` → `exited` | Finalises exit. |
161
+ | `createExitDraft(vtxo, now)` | — | Returns `draftType: 'mock-exit'` and a receipt. |
162
+ | `markVtxoSpent(vtxo, now)` | `active` → `spent` | Direct spend (used by operator settlement). |
163
+
164
+ ### Verification & Conservation
165
+
166
+ ```ts
167
+ verifyVtxo(vtxo) // validate fields + proof
168
+ verifyVtxoProof(vtxo, proof) // verify Merkle path
169
+ verifyVtxoTransfer(input, output, tx) // validate transfer struct
170
+ verifyConservation({ inputs, outputs }) // sum(inputs) must equal sum(outputs)
171
+ ```
172
+
173
+ ### Serialization (BigInt-safe)
174
+
175
+ ```ts
176
+ serializeVtxo(vtxo) // → JSON string (BigInt serialized as "__bigint__:<value>")
177
+ deserializeVtxo(json) // → OmniaVtxo (BigInt restored)
178
+ serializePool(pool) // → JSON string
179
+ deserializePool(json) // → OmniaVtxoPool
180
+ ```
181
+
182
+ ### Store Interface
183
+
184
+ `OmniaVtxoStore` is a simple async interface:
185
+
186
+ ```ts
187
+ interface OmniaVtxoStore {
188
+ savePool(pool): Promise<void>;
189
+ getPool(poolId): Promise<OmniaVtxoPool | undefined>;
190
+ saveVtxo(vtxo): Promise<void>;
191
+ getVtxo(vtxoId): Promise<OmniaVtxo | undefined>;
192
+ listVtxos(poolId?): Promise<OmniaVtxo[]>;
193
+ markVtxoSpent(vtxoId, now?): Promise<void>;
194
+ }
195
+ ```
196
+
197
+ `MemoryOmniaVtxoStore` ships as the in-memory MVP implementation.
198
+
199
+ ### Policy Helpers
200
+
201
+ ```ts
202
+ buildVtxoTransferIntent(vtxo, recipient, amount, nonce, changeNonce?)
203
+ buildVtxoExitIntent(vtxo)
204
+ ```
205
+
206
+ ## VtxoStatus State Machine
207
+
208
+ ```
209
+ ┌──────── mint ────────┐
210
+ ▼ │
211
+ active ──transfer──► transferred
212
+ │
213
+ ├─ partial-transfer ──► split (input)
214
+ │ │
215
+ ├─ split ────────────► split (input)
216
+ │
217
+ ├─ merge ────────────► merged (inputs)
218
+ │
219
+ ├─ refresh ──────────► refreshed (old)
220
+ │
221
+ ├─ exit_initiated ───► exiting
222
+ │ │
223
+ │ exited
224
+ └─ spent ──────────── spent
225
+ ```
226
+
227
+ ## Error Hierarchy
228
+
229
+ ```
230
+ OmniaVtxoError
231
+ ├── VtxoAmountError — invalid amounts (zero, overflow, sum mismatch)
232
+ ├── VtxoStatusError — wrong status for the requested operation
233
+ ├── VtxoOwnershipError — owner mismatch
234
+ ├── VtxoProofError — Merkle proof verification failure
235
+ ├── VtxoPoolCapacityError — insufficient pool capacity
236
+ ├── VtxoPolicyError — policy violation (min/max amounts, epoch ordering)
237
+ ├── VtxoMergeError — merge precondition failure (cross-pool, duplicates)
238
+ ├── VtxoSplitError — split precondition failure
239
+ └── VtxoExitError — exit precondition failure
240
+ ```
241
+
242
+ ## Security Notes
243
+
244
+ > **This is an MVP SDK — not a production Ark implementation.**
245
+
246
+ The current implementation provides deterministic, locally-verifiable commitment proofs, but several critical components are stubs:
247
+
248
+ - **Operator receipts** are signed with `MOCK_OPERATOR_SIGNATURE`. In production, the operator signs over the commitment root using a real WOTS or Schnorr key, and clients must verify against the operator's published public key.
249
+ - **Commitment roots** are single-batch local roots, not pool-wide epoch roots. A full deployment requires the operator to broadcast a pool-wide commitment root across all live VTXOs each epoch, giving every holder a verifiable place in the pool's state tree.
250
+ - **Exit scripts** use `draftType: 'mock-exit'`. Real exits require audited KISSVM covenant exit scripts, a watchtower monitoring the on-chain dispute window, and Omnia factory settlement logic.
251
+ - **No watchtower / dispute monitoring.** Operator equivocation (signing two conflicting pool roots) is not detected. A production system needs an independent watchtower service.
252
+ - **No replay protection beyond nonce uniqueness.** Nonces must be globally unique per pool. Implementations must enforce this.
253
+
254
+ ## Future Roadmap
255
+
256
+ - **Real Omnia factory backing** — Pool funds held in an N-of-N Omnia factory UTXO, with batch settlement on exit.
257
+ - **Batch refresh rounds** — Operator posts a new commitment root; all live VTXOs are refreshed in a single Minima transaction.
258
+ - **Operator signing** — Real WOTS receipts replacing `MOCK_OPERATOR_SIGNATURE`, with client-side signature verification.
259
+ - **Wallet integration** — Direct integration with Totem Wallet's coin selection and WOTS signing infrastructure.
260
+ - **Connect API methods** — `totem_mintVtxo`, `totem_transferVtxo`, `totem_listVtxos` exposed via the TOTEM_CONNECT dApp API.
261
+ - **Persistence adapters** — PostgreSQL and IndexedDB adapters for `OmniaVtxoStore`.
262
+ - **KISSVM exit script** — Audited on-chain exit covenant for unilateral exit with timelock enforcement.
263
+
264
+ ## Canary Scenario
265
+
266
+ ```ts
267
+ // Create pool → mint note → transfer → split → merge → refresh → exit → verify
268
+
269
+ const pool = createPool({ operator, tokenId, totalCapacity, nonce }, NOW);
270
+ const { pool: p1, vtxo: note } = mintVtxo(pool, { owner, amount, nonce: 'n1' }, NOW);
271
+ const { output: received } = transferVtxo(note, { recipient: 'MxBob', amount, nonce: 'n2' }, NOW + 1);
272
+ const { outputs: [a, b] } = splitVtxo(received, { amounts: [amount / 2n, amount / 2n], nonces: ['n3', 'n4'] }, NOW + 2);
273
+ const { output: merged } = mergeVtxos([a, b], { nonce: 'n5', owner: 'MxBob' }, NOW + 3);
274
+ const { refreshed } = refreshVtxo(merged, { newEpoch: 1, nonce: 'n6' }, NOW + 4);
275
+ const { draft } = createExitDraft(refreshed, NOW + 5);
276
+
277
+ const check = verifyVtxo(refreshed);
278
+ const conservation = verifyConservation({ inputs: [note], outputs: [received] });
279
+
280
+ console.assert(check.valid, 'VTXO proof must be valid');
281
+ console.assert(conservation.valid, 'Conservation must hold');
282
+ console.assert(draft.draftType === 'mock-exit', 'Exit draft type must be mock-exit');
283
+ ```
284
+
285
+ ## Runtime Compatibility
286
+
287
+ This package is **runtime-neutral** and compatible with Bare/Pear-style Totem Edge deployments. It does not import `node:crypto`, `fs`, `path`, `net`, `http`, `child_process`, DOM APIs, `window`, `document`, or `localStorage`. All deterministic functions accept injected `now` and `nonce` parameters — no hidden `Date.now()` or `randomUUID()` calls inside pure logic.
288
+
289
+ The only runtime dependency is `@noble/hashes` (SHA3-256), which is itself runtime-neutral and browser/Bare-compatible.
290
+
291
+ ## License
292
+
293
+ MIT
@@ -0,0 +1,28 @@
1
+ import { OmniaVtxo, VtxoId, VtxoProof } from './types.js';
2
+ export declare function computeVtxoLeaf(vtxo: OmniaVtxo): string;
3
+ export interface ComputeVtxoIdParams {
4
+ poolId: string;
5
+ owner: string;
6
+ amount: bigint;
7
+ tokenId: string;
8
+ nonce: string;
9
+ }
10
+ export declare function computeVtxoId(params: ComputeVtxoIdParams): string;
11
+ export interface ComputePoolIdParams {
12
+ operator: string;
13
+ tokenId: string;
14
+ nonce: string;
15
+ }
16
+ export declare function computePoolId(params: ComputePoolIdParams): string;
17
+ export declare function computeCommitmentRoot(leaves: string[]): string;
18
+ export interface MerkleProofNode {
19
+ sibling: string;
20
+ position: 'left' | 'right';
21
+ }
22
+ export declare function verifyMerkleProof(leaf: string, proof: MerkleProofNode[], root: string): boolean;
23
+ export interface VtxoProofSet {
24
+ root: string;
25
+ proofs: Record<VtxoId, VtxoProof>;
26
+ }
27
+ export declare function buildVtxoProofSet(vtxos: OmniaVtxo[]): VtxoProofSet;
28
+ export declare function computeReceiptId(poolId: string, op: string, inputIds: string[], outputIds: string[], at: number): string;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeVtxoLeaf = computeVtxoLeaf;
4
+ exports.computeVtxoId = computeVtxoId;
5
+ exports.computePoolId = computePoolId;
6
+ exports.computeCommitmentRoot = computeCommitmentRoot;
7
+ exports.verifyMerkleProof = verifyMerkleProof;
8
+ exports.buildVtxoProofSet = buildVtxoProofSet;
9
+ exports.computeReceiptId = computeReceiptId;
10
+ const sha3_1 = require("@noble/hashes/sha3");
11
+ const utils_1 = require("@noble/hashes/utils");
12
+ const constants_js_1 = require("./constants.js");
13
+ function sha3hex(input) {
14
+ const bytes = new TextEncoder().encode(input);
15
+ return (0, utils_1.bytesToHex)((0, sha3_1.sha3_256)(bytes));
16
+ }
17
+ function hashPair(a, b) {
18
+ const [left, right] = a <= b ? [a, b] : [b, a];
19
+ const combined = left + right;
20
+ const bytes = (0, utils_1.hexToBytes)(combined);
21
+ return (0, utils_1.bytesToHex)((0, sha3_1.sha3_256)(bytes));
22
+ }
23
+ function computeVtxoLeaf(vtxo) {
24
+ const input = [
25
+ vtxo.vtxoId,
26
+ vtxo.owner,
27
+ vtxo.amount.toString(),
28
+ vtxo.tokenId,
29
+ vtxo.epoch.toString(),
30
+ vtxo.poolId,
31
+ ].join(':');
32
+ return sha3hex(input);
33
+ }
34
+ function computeVtxoId(params) {
35
+ const input = [
36
+ 'vtxo',
37
+ params.poolId,
38
+ params.owner,
39
+ params.amount.toString(),
40
+ params.tokenId,
41
+ params.nonce,
42
+ ].join(':');
43
+ return sha3hex(input);
44
+ }
45
+ function computePoolId(params) {
46
+ const input = [
47
+ 'pool',
48
+ params.operator,
49
+ params.tokenId,
50
+ params.nonce,
51
+ ].join(':');
52
+ return sha3hex(input);
53
+ }
54
+ function nextPowerOfTwo(n) {
55
+ if (n <= 1)
56
+ return 1;
57
+ let p = 1;
58
+ while (p < n)
59
+ p <<= 1;
60
+ return p;
61
+ }
62
+ function computeCommitmentRoot(leaves) {
63
+ if (leaves.length === 0)
64
+ return constants_js_1.EMPTY_LEAF;
65
+ const size = nextPowerOfTwo(leaves.length);
66
+ const level = new Array(size).fill(constants_js_1.EMPTY_LEAF);
67
+ for (let i = 0; i < leaves.length; i++) {
68
+ level[i] = leaves[i];
69
+ }
70
+ let current = level;
71
+ while (current.length > 1) {
72
+ const next = [];
73
+ for (let i = 0; i < current.length; i += 2) {
74
+ next.push(hashPair(current[i], current[i + 1]));
75
+ }
76
+ current = next;
77
+ }
78
+ return current[0];
79
+ }
80
+ function verifyMerkleProof(leaf, proof, root) {
81
+ let current = leaf;
82
+ for (const node of proof) {
83
+ if (node.position === 'left') {
84
+ current = hashPair(node.sibling, current);
85
+ }
86
+ else {
87
+ current = hashPair(current, node.sibling);
88
+ }
89
+ }
90
+ return current === root;
91
+ }
92
+ function buildVtxoProofSet(vtxos) {
93
+ if (vtxos.length === 0) {
94
+ return { root: constants_js_1.EMPTY_LEAF, proofs: {} };
95
+ }
96
+ const sorted = [...vtxos].sort((a, b) => a.vtxoId < b.vtxoId ? -1 : a.vtxoId > b.vtxoId ? 1 : 0);
97
+ const leafMap = new Map();
98
+ const leaves = sorted.map(v => {
99
+ const leaf = computeVtxoLeaf(v);
100
+ leafMap.set(v.vtxoId, leaf);
101
+ return leaf;
102
+ });
103
+ const size = nextPowerOfTwo(leaves.length);
104
+ const paddedLeaves = [...leaves];
105
+ while (paddedLeaves.length < size)
106
+ paddedLeaves.push(constants_js_1.EMPTY_LEAF);
107
+ const levels = [paddedLeaves];
108
+ let current = paddedLeaves;
109
+ while (current.length > 1) {
110
+ const next = [];
111
+ for (let i = 0; i < current.length; i += 2) {
112
+ next.push(hashPair(current[i], current[i + 1]));
113
+ }
114
+ levels.push(next);
115
+ current = next;
116
+ }
117
+ const root = current[0];
118
+ const proofs = {};
119
+ sorted.forEach((vtxo, idx) => {
120
+ const siblings = [];
121
+ const positions = [];
122
+ let pos = idx;
123
+ for (let lvl = 0; lvl < levels.length - 1; lvl++) {
124
+ const isLeft = pos % 2 === 0;
125
+ const siblingIdx = isLeft ? pos + 1 : pos - 1;
126
+ const sibling = levels[lvl][siblingIdx] ?? constants_js_1.EMPTY_LEAF;
127
+ siblings.push(sibling);
128
+ positions.push(isLeft ? 'right' : 'left');
129
+ pos = Math.floor(pos / 2);
130
+ }
131
+ const leaf = leafMap.get(vtxo.vtxoId);
132
+ proofs[vtxo.vtxoId] = {
133
+ leaf,
134
+ root,
135
+ siblings,
136
+ positions,
137
+ epoch: vtxo.epoch,
138
+ batchId: constants_js_1.MOCK_BATCH_ID,
139
+ };
140
+ });
141
+ return { root, proofs };
142
+ }
143
+ function computeReceiptId(poolId, op, inputIds, outputIds, at) {
144
+ const input = [
145
+ 'receipt',
146
+ poolId,
147
+ op,
148
+ inputIds.sort().join(','),
149
+ outputIds.sort().join(','),
150
+ at.toString(),
151
+ ].join(':');
152
+ return sha3hex(input);
153
+ }
@@ -0,0 +1,12 @@
1
+ export declare const EMPTY_LEAF = "0000000000000000000000000000000000000000000000000000000000000000";
2
+ export declare const EMPTY_TREE_ROOT = "0000000000000000000000000000000000000000000000000000000000000000";
3
+ export declare const EPOCH_ZERO = 0;
4
+ export declare const DEFAULT_POLICY: {
5
+ readonly minAmount: bigint;
6
+ readonly maxAmount: bigint;
7
+ readonly maxMergeInputs: 8;
8
+ readonly maxSplitOutputs: 8;
9
+ readonly exitTimelockSeconds: 86400;
10
+ };
11
+ export declare const MOCK_OPERATOR_SIGNATURE = "mock-operator-sig-v0";
12
+ export declare const MOCK_BATCH_ID = "batch-local-mvp";
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MOCK_BATCH_ID = exports.MOCK_OPERATOR_SIGNATURE = exports.DEFAULT_POLICY = exports.EPOCH_ZERO = exports.EMPTY_TREE_ROOT = exports.EMPTY_LEAF = void 0;
4
+ exports.EMPTY_LEAF = '0000000000000000000000000000000000000000000000000000000000000000';
5
+ exports.EMPTY_TREE_ROOT = '0000000000000000000000000000000000000000000000000000000000000000';
6
+ exports.EPOCH_ZERO = 0;
7
+ exports.DEFAULT_POLICY = {
8
+ minAmount: BigInt(1),
9
+ maxAmount: BigInt(1000000000000000),
10
+ maxMergeInputs: 8,
11
+ maxSplitOutputs: 8,
12
+ exitTimelockSeconds: 86400,
13
+ };
14
+ exports.MOCK_OPERATOR_SIGNATURE = 'mock-operator-sig-v0';
15
+ exports.MOCK_BATCH_ID = 'batch-local-mvp';
@@ -0,0 +1,33 @@
1
+ export declare class OmniaVtxoError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class VtxoAmountError extends OmniaVtxoError {
5
+ constructor(message: string);
6
+ }
7
+ export declare class VtxoStatusError extends OmniaVtxoError {
8
+ readonly currentStatus: string;
9
+ constructor(message: string, currentStatus: string);
10
+ }
11
+ export declare class VtxoOwnershipError extends OmniaVtxoError {
12
+ constructor(message: string);
13
+ }
14
+ export declare class VtxoProofError extends OmniaVtxoError {
15
+ constructor(message: string);
16
+ }
17
+ export declare class VtxoPoolCapacityError extends OmniaVtxoError {
18
+ readonly requested: bigint;
19
+ readonly available: bigint;
20
+ constructor(message: string, requested: bigint, available: bigint);
21
+ }
22
+ export declare class VtxoPolicyError extends OmniaVtxoError {
23
+ constructor(message: string);
24
+ }
25
+ export declare class VtxoMergeError extends OmniaVtxoError {
26
+ constructor(message: string);
27
+ }
28
+ export declare class VtxoSplitError extends OmniaVtxoError {
29
+ constructor(message: string);
30
+ }
31
+ export declare class VtxoExitError extends OmniaVtxoError {
32
+ constructor(message: string);
33
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VtxoExitError = exports.VtxoSplitError = exports.VtxoMergeError = exports.VtxoPolicyError = exports.VtxoPoolCapacityError = exports.VtxoProofError = exports.VtxoOwnershipError = exports.VtxoStatusError = exports.VtxoAmountError = exports.OmniaVtxoError = void 0;
4
+ class OmniaVtxoError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'OmniaVtxoError';
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
11
+ exports.OmniaVtxoError = OmniaVtxoError;
12
+ class VtxoAmountError extends OmniaVtxoError {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = 'VtxoAmountError';
16
+ }
17
+ }
18
+ exports.VtxoAmountError = VtxoAmountError;
19
+ class VtxoStatusError extends OmniaVtxoError {
20
+ constructor(message, currentStatus) {
21
+ super(message);
22
+ this.name = 'VtxoStatusError';
23
+ this.currentStatus = currentStatus;
24
+ }
25
+ }
26
+ exports.VtxoStatusError = VtxoStatusError;
27
+ class VtxoOwnershipError extends OmniaVtxoError {
28
+ constructor(message) {
29
+ super(message);
30
+ this.name = 'VtxoOwnershipError';
31
+ }
32
+ }
33
+ exports.VtxoOwnershipError = VtxoOwnershipError;
34
+ class VtxoProofError extends OmniaVtxoError {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = 'VtxoProofError';
38
+ }
39
+ }
40
+ exports.VtxoProofError = VtxoProofError;
41
+ class VtxoPoolCapacityError extends OmniaVtxoError {
42
+ constructor(message, requested, available) {
43
+ super(message);
44
+ this.name = 'VtxoPoolCapacityError';
45
+ this.requested = requested;
46
+ this.available = available;
47
+ }
48
+ }
49
+ exports.VtxoPoolCapacityError = VtxoPoolCapacityError;
50
+ class VtxoPolicyError extends OmniaVtxoError {
51
+ constructor(message) {
52
+ super(message);
53
+ this.name = 'VtxoPolicyError';
54
+ }
55
+ }
56
+ exports.VtxoPolicyError = VtxoPolicyError;
57
+ class VtxoMergeError extends OmniaVtxoError {
58
+ constructor(message) {
59
+ super(message);
60
+ this.name = 'VtxoMergeError';
61
+ }
62
+ }
63
+ exports.VtxoMergeError = VtxoMergeError;
64
+ class VtxoSplitError extends OmniaVtxoError {
65
+ constructor(message) {
66
+ super(message);
67
+ this.name = 'VtxoSplitError';
68
+ }
69
+ }
70
+ exports.VtxoSplitError = VtxoSplitError;
71
+ class VtxoExitError extends OmniaVtxoError {
72
+ constructor(message) {
73
+ super(message);
74
+ this.name = 'VtxoExitError';
75
+ }
76
+ }
77
+ exports.VtxoExitError = VtxoExitError;
package/dist/exit.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { OmniaVtxo, ExitDraft, VtxoOperatorReceipt } from './types.js';
2
+ /**
3
+ * Transitions an active VTXO to 'exiting' status.
4
+ * @param now - Timestamp in ms. Defaults to Date.now() if omitted — pass explicitly for determinism.
5
+ */
6
+ export declare function markExiting(vtxo: OmniaVtxo, now?: number): OmniaVtxo;
7
+ /**
8
+ * Transitions an exiting VTXO to 'exited' status.
9
+ * @param now - Timestamp in ms. Defaults to Date.now() if omitted — pass explicitly for determinism.
10
+ */
11
+ export declare function markExited(vtxo: OmniaVtxo, now?: number): OmniaVtxo;
12
+ /**
13
+ * Creates a mock exit draft for a VTXO. Validates the proof leaf before drafting.
14
+ * @param now - Timestamp in ms. Defaults to Date.now() if omitted — pass explicitly for determinism.
15
+ */
16
+ export declare function createExitDraft(vtxo: OmniaVtxo, now?: number): {
17
+ draft: ExitDraft;
18
+ receipt: VtxoOperatorReceipt;
19
+ };