@ottochain/sdk 2.3.0 → 2.4.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 (209) hide show
  1. package/dist/cjs/apps/contracts/index.js +15 -8
  2. package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +35 -40
  3. package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +80 -37
  4. package/dist/cjs/apps/contracts/state-machines/contract-universal.js +4 -4
  5. package/dist/cjs/apps/corporate/index.js +2 -2
  6. package/dist/cjs/apps/corporate/state-machines/corp-board.js +169 -59
  7. package/dist/cjs/apps/corporate/state-machines/corp-entity.js +245 -47
  8. package/dist/cjs/apps/corporate/state-machines/corp-securities.js +407 -99
  9. package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +151 -37
  10. package/dist/cjs/apps/governance/index.js +14 -14
  11. package/dist/cjs/apps/governance/state-machines/dao-multisig.js +58 -40
  12. package/dist/cjs/apps/governance/state-machines/dao-reputation.js +46 -40
  13. package/dist/cjs/apps/governance/state-machines/dao-single.js +28 -11
  14. package/dist/cjs/apps/governance/state-machines/dao-token.js +67 -41
  15. package/dist/cjs/apps/governance/state-machines/governance-simple.js +93 -61
  16. package/dist/cjs/apps/governance/state-machines/governance-universal.js +2 -2
  17. package/dist/cjs/apps/identity/constants.js +55 -14
  18. package/dist/cjs/apps/identity/index.js +27 -11
  19. package/dist/cjs/apps/identity/state-machines/identity-agent.js +3 -3
  20. package/dist/cjs/apps/identity/state-machines/identity-oracle.js +25 -22
  21. package/dist/cjs/apps/identity/state-machines/identity-registry.js +288 -0
  22. package/dist/cjs/apps/identity/state-machines/identity-universal.js +3 -3
  23. package/dist/cjs/apps/identity/state-machines/index.js +3 -1
  24. package/dist/cjs/apps/index.js +19 -8
  25. package/dist/cjs/apps/lending/assets.js +223 -0
  26. package/dist/cjs/apps/lending/credit-scoring.js +87 -0
  27. package/dist/cjs/apps/lending/eligibility.js +121 -0
  28. package/dist/cjs/apps/lending/index.js +91 -0
  29. package/dist/cjs/apps/lending/state-machines/index.js +9 -0
  30. package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +412 -0
  31. package/dist/cjs/apps/markets/index.js +21 -11
  32. package/dist/cjs/apps/markets/state-machines/market-auction.js +14 -13
  33. package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +29 -24
  34. package/dist/cjs/apps/markets/state-machines/market-group-buy.js +24 -26
  35. package/dist/cjs/apps/markets/state-machines/market-prediction.js +80 -53
  36. package/dist/cjs/apps/markets/state-machines/market-universal.js +5 -5
  37. package/dist/cjs/apps/oracles/index.js +2 -2
  38. package/dist/cjs/errors.js +3 -3
  39. package/dist/cjs/generated/google/protobuf/struct.js +4 -4
  40. package/dist/cjs/generated/index.js +11 -7
  41. package/dist/cjs/generated/openapi.js +6 -0
  42. package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +50 -50
  43. package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +19 -20
  44. package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +13 -13
  45. package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +4 -4
  46. package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +124 -130
  47. package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +107 -107
  48. package/dist/cjs/generated/ottochain/v1/common.js +4 -4
  49. package/dist/cjs/generated/ottochain/v1/fiber.js +4 -4
  50. package/dist/cjs/index.js +41 -7
  51. package/dist/cjs/openapi.js +2 -0
  52. package/dist/cjs/ottochain/drop-nulls.js +1 -2
  53. package/dist/cjs/ottochain/genesis-manifest.js +11 -11
  54. package/dist/cjs/ottochain/index.js +23 -13
  55. package/dist/cjs/ottochain/metagraph-client.js +65 -8
  56. package/dist/cjs/ottochain/snapshot.js +11 -12
  57. package/dist/cjs/ottochain/transaction.js +57 -14
  58. package/dist/cjs/ottochain/types.js +16 -2
  59. package/dist/cjs/privacy/index.js +14 -0
  60. package/dist/cjs/privacy/sealed-bid.js +210 -0
  61. package/dist/cjs/privacy/shield-app.js +131 -0
  62. package/dist/cjs/schema/effects.js +40 -0
  63. package/dist/cjs/schema/fiber-app.js +19 -13
  64. package/dist/cjs/schema/guard-lint.js +352 -0
  65. package/dist/cjs/schema/guards.js +246 -0
  66. package/dist/cjs/signing.js +80 -0
  67. package/dist/cjs/types.js +2 -3
  68. package/dist/cjs/validation.js +8 -8
  69. package/dist/cjs/verify.js +9 -4
  70. package/dist/cjs/zk/commit.js +53 -0
  71. package/dist/cjs/zk/guard.js +107 -0
  72. package/dist/cjs/zk/index.js +48 -0
  73. package/dist/cjs/zk/preimage.js +37 -0
  74. package/dist/cjs/zk/prover.js +87 -0
  75. package/dist/cjs/zk/registry.js +62 -0
  76. package/dist/cjs/zk/types.js +28 -0
  77. package/dist/cjs/zk/witness.js +19 -0
  78. package/dist/esm/apps/contracts/index.js +7 -3
  79. package/dist/esm/apps/contracts/state-machines/contract-agreement.js +35 -40
  80. package/dist/esm/apps/contracts/state-machines/contract-escrow.js +80 -37
  81. package/dist/esm/apps/contracts/state-machines/contract-universal.js +4 -4
  82. package/dist/esm/apps/corporate/state-machines/corp-board.js +169 -59
  83. package/dist/esm/apps/corporate/state-machines/corp-entity.js +245 -47
  84. package/dist/esm/apps/corporate/state-machines/corp-securities.js +407 -99
  85. package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +151 -37
  86. package/dist/esm/apps/governance/state-machines/dao-multisig.js +58 -40
  87. package/dist/esm/apps/governance/state-machines/dao-reputation.js +46 -40
  88. package/dist/esm/apps/governance/state-machines/dao-single.js +28 -11
  89. package/dist/esm/apps/governance/state-machines/dao-token.js +67 -41
  90. package/dist/esm/apps/governance/state-machines/governance-simple.js +93 -61
  91. package/dist/esm/apps/governance/state-machines/governance-universal.js +2 -2
  92. package/dist/esm/apps/identity/constants.js +51 -12
  93. package/dist/esm/apps/identity/index.js +12 -7
  94. package/dist/esm/apps/identity/state-machines/identity-agent.js +3 -3
  95. package/dist/esm/apps/identity/state-machines/identity-oracle.js +25 -22
  96. package/dist/esm/apps/identity/state-machines/identity-registry.js +285 -0
  97. package/dist/esm/apps/identity/state-machines/identity-universal.js +3 -3
  98. package/dist/esm/apps/identity/state-machines/index.js +1 -0
  99. package/dist/esm/apps/index.js +1 -0
  100. package/dist/esm/apps/lending/assets.js +207 -0
  101. package/dist/esm/apps/lending/credit-scoring.js +81 -0
  102. package/dist/esm/apps/lending/eligibility.js +115 -0
  103. package/dist/esm/apps/lending/index.js +69 -0
  104. package/dist/esm/apps/lending/state-machines/index.js +5 -0
  105. package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +409 -0
  106. package/dist/esm/apps/markets/index.js +8 -4
  107. package/dist/esm/apps/markets/state-machines/market-auction.js +14 -13
  108. package/dist/esm/apps/markets/state-machines/market-crowdfund.js +29 -24
  109. package/dist/esm/apps/markets/state-machines/market-group-buy.js +24 -26
  110. package/dist/esm/apps/markets/state-machines/market-prediction.js +80 -53
  111. package/dist/esm/apps/markets/state-machines/market-universal.js +5 -5
  112. package/dist/esm/generated/index.js +9 -5
  113. package/dist/esm/generated/openapi.js +5 -0
  114. package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +46 -46
  115. package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +114 -120
  116. package/dist/esm/generated/ottochain/apps/markets/v1/market.js +100 -100
  117. package/dist/esm/index.js +21 -2
  118. package/dist/esm/openapi.js +1 -0
  119. package/dist/esm/ottochain/genesis-manifest.js +9 -9
  120. package/dist/esm/ottochain/index.js +2 -3
  121. package/dist/esm/ottochain/metagraph-client.js +65 -8
  122. package/dist/esm/ottochain/snapshot.js +4 -4
  123. package/dist/esm/ottochain/transaction.js +43 -3
  124. package/dist/esm/ottochain/types.js +15 -1
  125. package/dist/esm/privacy/index.js +6 -0
  126. package/dist/esm/privacy/sealed-bid.js +206 -0
  127. package/dist/esm/privacy/shield-app.js +127 -0
  128. package/dist/esm/schema/effects.js +35 -0
  129. package/dist/esm/schema/fiber-app.js +13 -6
  130. package/dist/esm/schema/guard-lint.js +346 -0
  131. package/dist/esm/schema/guards.js +229 -0
  132. package/dist/esm/signing.js +74 -0
  133. package/dist/esm/verify.js +8 -2
  134. package/dist/esm/zk/commit.js +44 -0
  135. package/dist/esm/zk/guard.js +99 -0
  136. package/dist/esm/zk/index.js +19 -0
  137. package/dist/esm/zk/preimage.js +30 -0
  138. package/dist/esm/zk/prover.js +82 -0
  139. package/dist/esm/zk/registry.js +55 -0
  140. package/dist/esm/zk/types.js +25 -0
  141. package/dist/esm/zk/witness.js +15 -0
  142. package/dist/types/apps/contracts/index.d.ts +69 -209
  143. package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +20 -95
  144. package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +46 -112
  145. package/dist/types/apps/corporate/index.d.ts +1040 -304
  146. package/dist/types/apps/corporate/state-machines/corp-board.d.ts +188 -52
  147. package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +267 -62
  148. package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +355 -131
  149. package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +225 -53
  150. package/dist/types/apps/governance/index.d.ts +296 -398
  151. package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +77 -92
  152. package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +42 -66
  153. package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
  154. package/dist/types/apps/governance/state-machines/dao-token.d.ts +60 -49
  155. package/dist/types/apps/governance/state-machines/governance-simple.d.ts +87 -117
  156. package/dist/types/apps/governance/state-machines/governance-universal.d.ts +2 -2
  157. package/dist/types/apps/identity/constants.d.ts +32 -4
  158. package/dist/types/apps/identity/index.d.ts +378 -94
  159. package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +16 -87
  160. package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
  161. package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
  162. package/dist/types/apps/index.d.ts +1 -0
  163. package/dist/types/apps/lending/assets.d.ts +258 -0
  164. package/dist/types/apps/lending/credit-scoring.d.ts +80 -0
  165. package/dist/types/apps/lending/eligibility.d.ts +83 -0
  166. package/dist/types/apps/lending/index.d.ts +548 -0
  167. package/dist/types/apps/lending/state-machines/index.d.ts +5 -0
  168. package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +528 -0
  169. package/dist/types/apps/markets/index.d.ts +108 -203
  170. package/dist/types/apps/markets/state-machines/market-auction.d.ts +13 -37
  171. package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +16 -34
  172. package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +17 -43
  173. package/dist/types/apps/markets/state-machines/market-prediction.d.ts +51 -72
  174. package/dist/types/apps/markets/state-machines/market-universal.d.ts +5 -5
  175. package/dist/types/generated/index.d.ts +5 -5
  176. package/dist/types/generated/openapi.d.ts +1257 -0
  177. package/dist/types/generated/ottochain/apps/contracts/v1/contract.d.ts +5 -5
  178. package/dist/types/generated/ottochain/apps/identity/v1/identity.d.ts +12 -12
  179. package/dist/types/generated/ottochain/apps/markets/v1/market.d.ts +11 -11
  180. package/dist/types/index.d.ts +6 -2
  181. package/dist/types/openapi.d.ts +22 -0
  182. package/dist/types/ottochain/genesis-manifest.d.ts +5 -5
  183. package/dist/types/ottochain/index.d.ts +5 -6
  184. package/dist/types/ottochain/metagraph-client.d.ts +49 -7
  185. package/dist/types/ottochain/snapshot.d.ts +6 -6
  186. package/dist/types/ottochain/transaction.d.ts +33 -1
  187. package/dist/types/ottochain/types.d.ts +335 -30
  188. package/dist/types/privacy/index.d.ts +6 -0
  189. package/dist/types/privacy/sealed-bid.d.ts +348 -0
  190. package/dist/types/privacy/shield-app.d.ts +48 -0
  191. package/dist/types/schema/effects.d.ts +34 -0
  192. package/dist/types/schema/fiber-app.d.ts +1 -2
  193. package/dist/types/schema/guard-lint.d.ts +111 -0
  194. package/dist/types/schema/guards.d.ts +134 -0
  195. package/dist/types/signing.d.ts +45 -0
  196. package/dist/types/validation.d.ts +22 -217
  197. package/dist/types/verify.d.ts +4 -0
  198. package/dist/types/zk/commit.d.ts +28 -0
  199. package/dist/types/zk/guard.d.ts +46 -0
  200. package/dist/types/zk/index.d.ts +19 -0
  201. package/dist/types/zk/preimage.d.ts +10 -0
  202. package/dist/types/zk/prover.d.ts +34 -0
  203. package/dist/types/zk/registry.d.ts +34 -0
  204. package/dist/types/zk/types.d.ts +33 -0
  205. package/dist/types/zk/witness.d.ts +40 -0
  206. package/package.json +27 -13
  207. package/dist/cjs/ottochain/normalize.js +0 -186
  208. package/dist/esm/ottochain/normalize.js +0 -179
  209. package/dist/types/ottochain/normalize.d.ts +0 -79
@@ -4,7 +4,7 @@
4
4
  * Client for interacting with ottochain ML0 custom routes (/v1 prefix)
5
5
  * and framework snapshot endpoints.
6
6
  *
7
- * @see modules/l0/src/main/scala/xyz/kd5ujc/metagraph_l0/ML0CustomRoutes.scala
7
+ * @see modules/l0/src/main/scala/xyz/kd5ujc/metagraph_l0/ML0Routes.scala
8
8
  * @see modules/data_l1/src/main/scala/xyz/kd5ujc/data_l1/DataL1CustomRoutes.scala
9
9
  * @packageDocumentation
10
10
  */
@@ -28,7 +28,7 @@ import { extractOnChainState } from './snapshot.js';
28
28
  * const onChain = await client.getOnChain();
29
29
  *
30
30
  * // Get all active state machines
31
- * const machines = await client.getStateMachines('Active');
31
+ * const machines = await client.getStateMachines('ACTIVE');
32
32
  *
33
33
  * // Get event receipts for a fiber
34
34
  * const events = await client.getStateMachineEvents(fiberId);
@@ -87,18 +87,18 @@ export class MetagraphClient {
87
87
  return this.ml0.get(`/data-application/v1/state-machines/${fiberId}/events`);
88
88
  }
89
89
  /**
90
- * Get all script oracles, optionally filtered by status.
90
+ * Get all scripts, optionally filtered by status.
91
91
  */
92
92
  async getScripts(status) {
93
93
  const query = status ? `?status=${status}` : '';
94
- return this.ml0.get(`/data-application/v1/oracles${query}`);
94
+ return this.ml0.get(`/data-application/v1/scripts${query}`);
95
95
  }
96
96
  /**
97
- * Get a single script oracle by fiber ID.
97
+ * Get a single script by fiber ID.
98
98
  */
99
99
  async getScript(scriptId) {
100
100
  try {
101
- return await this.ml0.get(`/data-application/v1/oracles/${scriptId}`);
101
+ return await this.ml0.get(`/data-application/v1/scripts/${scriptId}`);
102
102
  }
103
103
  catch (error) {
104
104
  if (error instanceof NetworkError && error.statusCode === 404) {
@@ -108,10 +108,67 @@ export class MetagraphClient {
108
108
  }
109
109
  }
110
110
  /**
111
- * Get oracle invocations from the current ordinal's logs.
111
+ * Get script invocations from the current ordinal's logs.
112
112
  */
113
113
  async getScriptInvocations(scriptId) {
114
- return this.ml0.get(`/data-application/v1/oracles/${scriptId}/invocations`);
114
+ return this.ml0.get(`/data-application/v1/scripts/${scriptId}/invocations`);
115
+ }
116
+ // -------------------------------------------------------------------------
117
+ // Registry, audit, state-proofs, fee estimates (ML0 /data-application/v1/*)
118
+ // -------------------------------------------------------------------------
119
+ /** Get the metagraph version string. */
120
+ async getVersion() {
121
+ return this.ml0.get('/data-application/v1/version');
122
+ }
123
+ /** Get the full registry namespace, keyed by full registry name `labels.tld`. */
124
+ async getRegistry() {
125
+ return this.ml0.get('/data-application/v1/registry');
126
+ }
127
+ /** Resolve a single registry entry by full name (`labels.tld`), or null if unregistered. */
128
+ async getRegistryEntry(name) {
129
+ try {
130
+ return await this.ml0.get(`/data-application/v1/registry/${encodeURIComponent(name)}`);
131
+ }
132
+ catch (error) {
133
+ if (error instanceof NetworkError && error.statusCode === 404)
134
+ return null;
135
+ throw error;
136
+ }
137
+ }
138
+ /** Reverse-resolve a fiber UUID to its canonical registered name (#29), or null. */
139
+ async getReverseName(fiberId) {
140
+ try {
141
+ return await this.ml0.get(`/data-application/v1/registry/reverse/${fiberId}`);
142
+ }
143
+ catch (error) {
144
+ if (error instanceof NetworkError && error.statusCode === 404)
145
+ return null;
146
+ throw error;
147
+ }
148
+ }
149
+ /** Get the rendered audit-trail lines for a state-machine fiber. */
150
+ async getStateMachineAudit(fiberId) {
151
+ return this.ml0.get(`/data-application/v1/state-machines/${fiberId}/audit`);
152
+ }
153
+ /** Light-client state proof for a field of a state-machine fiber, against the committed root. */
154
+ async getStateMachineStateProof(fiberId, field) {
155
+ return this.ml0.get(`/data-application/v1/state-machines/${fiberId}/state-proof?field=${encodeURIComponent(field)}`);
156
+ }
157
+ /** Light-client state proof for a field of a script fiber. */
158
+ async getScriptStateProof(fiberId, field) {
159
+ return this.ml0.get(`/data-application/v1/scripts/${fiberId}/state-proof?field=${encodeURIComponent(field)}`);
160
+ }
161
+ /** Light-client state proof for a field of an asset instance. */
162
+ async getAssetStateProof(assetId, field) {
163
+ return this.ml0.get(`/data-application/v1/assets/${assetId}/state-proof?field=${encodeURIComponent(field)}`);
164
+ }
165
+ /** Estimate the fee/gas for a transition event on a state-machine fiber. */
166
+ async estimateTransitionFee(fiberId, eventName) {
167
+ return this.ml0.get(`/data-application/v1/state-machines/${fiberId}/estimate-fee?event=${encodeURIComponent(eventName)}`);
168
+ }
169
+ /** Estimate the fee/gas for invoking a script fiber. */
170
+ async estimateScriptFee(fiberId) {
171
+ return this.ml0.get(`/data-application/v1/scripts/${fiberId}/estimate-fee`);
115
172
  }
116
173
  // -------------------------------------------------------------------------
117
174
  // Framework snapshot endpoints (ML0 /snapshots/*)
@@ -73,7 +73,7 @@ export function getLogsForFiber(onChain, fiberId) {
73
73
  /**
74
74
  * Get EventReceipt log entries for a specific fiber.
75
75
  *
76
- * EventReceipts are distinguished from OracleInvocations by the presence
76
+ * EventReceipts are distinguished from ScriptInvocations by the presence
77
77
  * of the `eventName` field.
78
78
  *
79
79
  * @param onChain - Decoded on-chain state
@@ -85,14 +85,14 @@ export function getEventReceipts(onChain, fiberId) {
85
85
  .filter((entry) => 'eventName' in entry && 'success' in entry);
86
86
  }
87
87
  /**
88
- * Get OracleInvocation log entries for a specific fiber.
88
+ * Get ScriptInvocation log entries for a specific fiber.
89
89
  *
90
- * OracleInvocations are distinguished from EventReceipts by the presence
90
+ * ScriptInvocations are distinguished from EventReceipts by the presence
91
91
  * of the `method` field.
92
92
  *
93
93
  * @param onChain - Decoded on-chain state
94
94
  * @param fiberId - Fiber UUID to filter by
95
- * @returns Array of OracleInvocation entries
95
+ * @returns Array of ScriptInvocation entries
96
96
  */
97
97
  export function getScriptInvocations(onChain, fiberId) {
98
98
  return getLogsForFiber(onChain, fiberId)
@@ -4,10 +4,18 @@
4
4
  * These helpers create properly formatted payloads for the bridge's
5
5
  * self-signed mode, where clients sign their own transactions.
6
6
  */
7
- import { signDataUpdate, getPublicKeyId } from '@constellation-network/metagraph-sdk';
7
+ import { getPublicKeyId } from '@constellation-network/metagraph-sdk';
8
+ import { signDataUpdate } from '../signing.js';
8
9
  /**
9
10
  * Create a new state machine fiber payload.
10
11
  *
12
+ * @remarks
13
+ * `params.definition` is signed VERBATIM. Pass the output of `toProtoDefinition(def)` (the
14
+ * allowlisted wire shape) — NOT a raw `FiberAppDefinition`: extra authoring fields
15
+ * (`createSchema` / `stateSchema` / `eventSchemas` / per-transition `emits`) would be signed
16
+ * but re-encoded away by the chain, diverging the canonical → opaque `InvalidSignature`.
17
+ * See `tests/ottochain/signing-parity.test.ts`.
18
+ *
11
19
  * @param params - State machine creation parameters
12
20
  * @returns A CreateStateMachine message ready for signing
13
21
  *
@@ -94,7 +102,7 @@ export function createArchivePayload(params) {
94
102
  * },
95
103
  * },
96
104
  * initialState: { value: 0 },
97
- * accessControl: { type: 'open' },
105
+ * accessControl: { Public: {} },
98
106
  * });
99
107
  * const signed = await signTransaction(script, privateKey);
100
108
  * ```
@@ -105,7 +113,7 @@ export function createScriptPayload(params) {
105
113
  fiberId: params.fiberId,
106
114
  scriptProgram: params.scriptProgram,
107
115
  initialState: params.initialState ?? null,
108
- accessControl: params.accessControl ?? { type: 'open' },
116
+ accessControl: params.accessControl ?? { Public: {} },
109
117
  },
110
118
  };
111
119
  }
@@ -125,12 +133,41 @@ export function createInvokeScriptPayload(params) {
125
133
  },
126
134
  };
127
135
  }
136
+ // ============================================================================
137
+ // Asset Operations (asset-model.md §7)
138
+ // ============================================================================
139
+ //
140
+ // Thin typed wrappers: the chain message types ({@link CreateAssetPolicy}, etc.) already model
141
+ // every field (required vs `Option`), so these builders just apply the `{ MessageName: ... }`
142
+ // envelope, for API parity with the state-machine/script `create*Payload` helpers. Sign the result
143
+ // with {@link signTransaction} (the canonical `JCS(dropNulls)` path drops any omitted optionals).
144
+ /** Wrap a {@link CreateAssetPolicy} (publish an asset-policy package version). */
145
+ export function createAssetPolicyPayload(params) {
146
+ return { CreateAssetPolicy: params };
147
+ }
148
+ /** Wrap a {@link MintAsset} (mint a new asset instance against a resolved policy version). */
149
+ export function createMintAssetPayload(params) {
150
+ return { MintAsset: params };
151
+ }
152
+ /** Wrap an {@link ApplyMorphism} (apply a typed morphism to an asset instance). */
153
+ export function createApplyMorphismPayload(params) {
154
+ return { ApplyMorphism: params };
155
+ }
156
+ /** Wrap an {@link AuthorizeCompose} (commit half of the symmetric-compose handshake). */
157
+ export function createAuthorizeComposePayload(params) {
158
+ return { AuthorizeCompose: params };
159
+ }
128
160
  /**
129
161
  * Sign a transaction payload for self-signed mode.
130
162
  *
131
163
  * This creates a Signed<T> object with the exact format expected by the bridge's
132
164
  * `/agent/transition` endpoint when using self-signed mode.
133
165
  *
166
+ * The signature is computed over the null-dropped canonical bytes (null
167
+ * object fields removed recursively, array nulls preserved, then RFC 8785),
168
+ * matching metakit's content-hash rule. Explicit-null and absent optional
169
+ * fields therefore produce identical signatures.
170
+ *
134
171
  * @param message - The message to sign (e.g., from createTransitionPayload)
135
172
  * @param privateKey - The private key in hex format (64 characters)
136
173
  * @returns A signed object ready for submission to the bridge
@@ -199,6 +236,9 @@ export function createDataTransactionRequest(signed) {
199
236
  * Use this for multi-signature scenarios where multiple parties
200
237
  * need to sign the same transaction.
201
238
  *
239
+ * The new signature is computed over the null-dropped canonical bytes,
240
+ * matching metakit's content-hash rule (see {@link signTransaction}).
241
+ *
202
242
  * @param signed - The already-signed transaction
203
243
  * @param privateKey - Additional signer's private key
204
244
  * @returns Transaction with additional signature
@@ -7,6 +7,14 @@
7
7
  * @see modules/models/src/main/scala/xyz/kd5ujc/schema/
8
8
  * @packageDocumentation
9
9
  */
10
+ /** Bit weights for {@link TokenBehavior} (T=16, S=8, C=4, E=2, G=1). */
11
+ export const TOKEN_BEHAVIOR_BITS = {
12
+ transferable: 16,
13
+ splittable: 8,
14
+ combinable: 4,
15
+ expirable: 2,
16
+ governable: 1,
17
+ };
10
18
  /**
11
19
  * Names of all valid OttochainMessage types.
12
20
  * Use this for runtime validation (e.g., in API routes).
@@ -18,7 +26,13 @@ export const OTTOCHAIN_MESSAGE_TYPES = [
18
26
  'UpgradeFiber',
19
27
  'CreateScript',
20
28
  'InvokeScript',
21
- 'PublishVersion',
29
+ 'UpgradeScript',
30
+ 'PublishMachineVersion',
31
+ 'PublishScriptVersion',
22
32
  'SetVersionStatus',
23
33
  'RegisterAlias',
34
+ 'CreateAssetPolicy',
35
+ 'MintAsset',
36
+ 'ApplyMorphism',
37
+ 'AuthorizeCompose',
24
38
  ];
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Privacy: shield any fiber app into a zk-jlvm-shielded private-state pool.
3
+ * See docs/design/zk-private-contract-state-rfc.md.
4
+ */
5
+ export { shieldApp, SHIELDED_POOL_STATE } from "./shield-app.js";
6
+ export { sealedBidAccountDef, shieldedSealedBidDef, vickreyAuctionDef } from "./sealed-bid.js";
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Sealed-bid (Vickrey) auction — the worked example for the privacy stack.
3
+ *
4
+ * Two pieces (RFC §4):
5
+ * 1. `sealedBidAccountDef` — the PRIVATE per-bidder bid. `shieldApp` turns it into a shielded
6
+ * pool (`shieldedSealedBidDef`): a bidder commits a bid note and proves it well-formed with a
7
+ * zk-jlvm-shielded Groth16 proof, so the amount stays sealed *until the deadline*. This is the
8
+ * mechanical per-instance / single-owner case.
9
+ * 2. `vickreyAuctionDef` — the PUBLIC settlement (reveal-then-tally). After the deadline bidders
10
+ * open their notes; the combine computes winner = argmax and clearingPrice = second-highest
11
+ * (the Vickrey price). This is the one shared-state step, kept simple for v1; a zk settlement
12
+ * proof that seals losers' amounts forever is the deferred upgrade (RFC §10).
13
+ */
14
+ import { defineFiberApp } from "../schema/fiber-app.js";
15
+ import { shieldApp } from "./shield-app.js";
16
+ // ── 1. The private bid (base app, shielded by shieldApp) ──────────────────────
17
+ /** The per-bidder PRIVATE state: a bid note `{ amount, bidder, nonce }`. */
18
+ export const sealedBidAccountDef = defineFiberApp({
19
+ metadata: {
20
+ name: "SealedBidAccount",
21
+ app: "markets",
22
+ type: "sealed-bid-account",
23
+ version: "1.0.0",
24
+ description: "A single bidder's sealed bid (private amount). Shielded via shieldApp.",
25
+ },
26
+ stateSchema: {
27
+ properties: {
28
+ amount: { type: "number", description: "the (private) bid amount" },
29
+ bidder: { type: "address" },
30
+ nonce: { type: "number", description: "per-note randomness; keeps the commitment hiding" },
31
+ },
32
+ },
33
+ eventSchemas: {
34
+ place_bid: {
35
+ description: "Set the sealed bid amount",
36
+ required: ["amount"],
37
+ properties: { amount: { type: "number", minimum: 1 } },
38
+ },
39
+ },
40
+ states: {
41
+ OPEN: { id: "OPEN", isFinal: false, metadata: { label: "Open", description: "No bid yet", category: "initial" } },
42
+ BID: { id: "BID", isFinal: false, metadata: { label: "Bid", description: "Bid committed", category: "active" } },
43
+ },
44
+ initialState: "OPEN",
45
+ transitions: [
46
+ {
47
+ // This effect is what the zk-jlvm-shielded circuit runs in-zkVM; `exprHash` pins it.
48
+ from: "OPEN",
49
+ to: "BID",
50
+ eventName: "place_bid",
51
+ guard: { ">": [{ var: "event.amount" }, 0] },
52
+ effect: { merge: [{ var: "state" }, { amount: { var: "event.amount" } }] },
53
+ dependencies: [],
54
+ },
55
+ ],
56
+ });
57
+ /**
58
+ * The shielded sealed-bid pool. `vkey`/`exprHash` come from the built zk-jlvm-shielded circuit
59
+ * (these are placeholders until the circuit's program vkey + the keccak of the `place_bid` effect
60
+ * are wired in by the genesis/build step).
61
+ */
62
+ export function shieldedSealedBidDef(opts) {
63
+ return shieldApp(sealedBidAccountDef, opts);
64
+ }
65
+ // ── 2. The public Vickrey settlement ──────────────────────────────────────────
66
+ /**
67
+ * Public reveal-then-tally settlement. `reveal` appends an opened bid (in a full build the opening
68
+ * is checked against the recorded commitment in the shielded pool); `settle` computes the winner
69
+ * and the Vickrey (second-price) clearing price over the revealed bids in one reduce.
70
+ */
71
+ export const vickreyAuctionDef = defineFiberApp({
72
+ metadata: {
73
+ name: "VickreyAuction",
74
+ app: "markets",
75
+ type: "vickrey-auction",
76
+ version: "1.0.0",
77
+ description: "Sealed-bid second-price auction: public reveal-then-tally over shielded bids.",
78
+ crossReferences: { bidPool: "the ShieldedSealedBidAccount pool holding the sealed bids" },
79
+ },
80
+ createSchema: {
81
+ required: ["seller", "deadline"],
82
+ properties: {
83
+ seller: { type: "address", immutable: true },
84
+ deadline: { type: "timestamp", immutable: true },
85
+ },
86
+ },
87
+ stateSchema: {
88
+ properties: {
89
+ seller: { type: "address", immutable: true },
90
+ deadline: { type: "timestamp", immutable: true },
91
+ status: { type: "string", computed: true },
92
+ revealed: { type: "array", computed: true, description: "opened bids [{bidder, amount}]" },
93
+ winner: { type: "address", computed: true },
94
+ clearingPrice: { type: "number", computed: true, description: "second-highest bid (Vickrey)" },
95
+ },
96
+ },
97
+ eventSchemas: {
98
+ reveal: {
99
+ description: "Open a sealed bid after the deadline",
100
+ required: ["bidder", "amount"],
101
+ properties: { bidder: { type: "address" }, amount: { type: "number", minimum: 1 } },
102
+ },
103
+ settle: { description: "Tally the revealed bids (winner + second price)" },
104
+ },
105
+ states: {
106
+ OPEN: { id: "OPEN", isFinal: false, metadata: { label: "Open", description: "Bidding (sealed)", category: "initial" } },
107
+ REVEAL: { id: "REVEAL", isFinal: false, metadata: { label: "Reveal", description: "Opening bids", category: "active" } },
108
+ SETTLED: { id: "SETTLED", isFinal: true, metadata: { label: "Settled", description: "Winner + price set", category: "terminal" } },
109
+ },
110
+ initialState: "OPEN",
111
+ transitions: [
112
+ {
113
+ from: "OPEN",
114
+ to: "REVEAL",
115
+ eventName: "reveal",
116
+ guard: { ">=": [{ var: "$timestamp" }, { var: "state.deadline" }] },
117
+ effect: {
118
+ merge: [
119
+ { var: "state" },
120
+ {
121
+ status: "REVEAL",
122
+ revealed: {
123
+ cat: [
124
+ { var: "state.revealed" },
125
+ [{ bidder: { var: "event.bidder" }, amount: { var: "event.amount" } }],
126
+ ],
127
+ },
128
+ },
129
+ ],
130
+ },
131
+ dependencies: [],
132
+ },
133
+ {
134
+ from: "REVEAL",
135
+ to: "REVEAL",
136
+ eventName: "reveal",
137
+ guard: { ">=": [{ var: "$timestamp" }, { var: "state.deadline" }] },
138
+ effect: {
139
+ merge: [
140
+ { var: "state" },
141
+ {
142
+ revealed: {
143
+ cat: [
144
+ { var: "state.revealed" },
145
+ [{ bidder: { var: "event.bidder" }, amount: { var: "event.amount" } }],
146
+ ],
147
+ },
148
+ },
149
+ ],
150
+ },
151
+ dependencies: [],
152
+ },
153
+ {
154
+ // Vickrey tally: fold the revealed bids tracking (max, second, winner).
155
+ from: "REVEAL",
156
+ to: "SETTLED",
157
+ eventName: "settle",
158
+ guard: { ">": [{ reduce: [{ var: "state.revealed" }, { "+": [{ var: "accumulator" }, 1] }, 0] }, 0] },
159
+ effect: {
160
+ merge: [
161
+ { var: "state" },
162
+ {
163
+ status: "SETTLED",
164
+ settledAt: { var: "$timestamp" },
165
+ winner: {
166
+ var: [
167
+ "tally.winner",
168
+ null,
169
+ ],
170
+ },
171
+ clearingPrice: { var: ["tally.second", 0] },
172
+ // compute the tally once and expose it for the two fields above
173
+ tally: {
174
+ reduce: [
175
+ { var: "state.revealed" },
176
+ {
177
+ if: [
178
+ { ">": [{ var: "current.amount" }, { var: "accumulator.max" }] },
179
+ {
180
+ max: { var: "current.amount" },
181
+ second: { var: "accumulator.max" },
182
+ winner: { var: "current.bidder" },
183
+ },
184
+ {
185
+ if: [
186
+ { ">": [{ var: "current.amount" }, { var: "accumulator.second" }] },
187
+ {
188
+ max: { var: "accumulator.max" },
189
+ second: { var: "current.amount" },
190
+ winner: { var: "accumulator.winner" },
191
+ },
192
+ { var: "accumulator" },
193
+ ],
194
+ },
195
+ ],
196
+ },
197
+ { max: 0, second: 0, winner: null },
198
+ ],
199
+ },
200
+ },
201
+ ],
202
+ },
203
+ dependencies: [],
204
+ },
205
+ ],
206
+ });
@@ -0,0 +1,127 @@
1
+ /**
2
+ * shieldApp — turn a fiber app into a PRIVATE-state pool.
3
+ *
4
+ * Given a base {@link FiberAppDefinition} (the app whose state + transition you want to keep
5
+ * private), `shieldApp` returns a new `FiberAppDefinition` for a "shielded pool" Machine fiber.
6
+ * The pool's state is PUBLIC scaffolding only — the spent-nullifier set, the commitment log, and
7
+ * the set of valid anchors — while the app's real state lives off-chain in a note committed to
8
+ * the tree. Each app transition is carried out off-chain and attested by a single
9
+ * `zk-jlvm-shielded` Groth16 proof; the on-chain combine just verifies the proof, rejects an
10
+ * already-spent nullifier, and records the new commitment.
11
+ *
12
+ * Division of labour (see ottochain-sdk RFC docs/design/zk-private-contract-state-rfc.md):
13
+ * - the CIRCUIT proves membership ∧ authorization ∧ `jlvm-core` effect ∧ new commitment;
14
+ * - this GUARD (combine) verifies the proof, pins which app logic ran (`exprHash`), checks the
15
+ * anchor is recent, and checks the nullifier is fresh — all combiner-only (CLAUDE.md);
16
+ * - block-validity stays structural (proof / publicValues present + hex).
17
+ *
18
+ * It uses NO new metakit opcode: `groth16_verify` verifies the proof, and the four-`bytes32`
19
+ * public values (`anchor`, `nullifier`, `newCommitment`, `exprHash`) are extracted from the
20
+ * VERIFIED `publicValues` string with fixed-offset `substr` — slicing the verified bytes IS the
21
+ * binding (§8.1).
22
+ *
23
+ * NOTE on cost: the note model rehashes the whole state each transition, so proving cost is
24
+ * O(state size) (RFC §8). Keep shielded note state small (a few KB); for large keyed state use
25
+ * the auth-DB variant (RFC §3.1.1).
26
+ */
27
+ import { defineFiberApp, } from "../schema/fiber-app.js";
28
+ /**
29
+ * Field extractors over the abi-encoded `JlvmTransitionPublicValues` — four static `bytes32`
30
+ * `[anchor | nullifier | newCommitment | exprHash]`, a fixed 128-byte (256 hex char) layout with
31
+ * NO dynamic arrays. `publicValues` is the 0x-prefixed hex from the prover, so each field is 64
32
+ * hex chars starting at: anchor=2, nullifier=66, newCommitment=130, exprHash=194.
33
+ */
34
+ const pvField = (publicValues, hexOffset) => ({
35
+ substr: [publicValues, hexOffset, 64],
36
+ });
37
+ /** Standard public state every shielded pool carries (the rest of the app state is private/off-chain). */
38
+ export const SHIELDED_POOL_STATE = {
39
+ vkey: { type: "hash", immutable: true },
40
+ exprHash: { type: "hash", immutable: true },
41
+ rootWindow: { type: "integer", immutable: true },
42
+ currentRoot: { type: "hash", computed: true },
43
+ knownRoots: { type: "array", computed: true, description: "rolling window of valid anchors (hex)" },
44
+ nullifiers: { type: "array", computed: true, description: "spent set (hex); monotonic — see RFC §5.3" },
45
+ commitments: { type: "array", computed: true, description: "append-only log of output commitments (hex)" },
46
+ leafCount: { type: "integer", computed: true, default: 0 },
47
+ transitions: { type: "integer", computed: true, default: 0 },
48
+ };
49
+ /**
50
+ * Build the shielded-pool variant of `base`.
51
+ *
52
+ * @param base the app being shielded (used for naming + to document the pinned logic).
53
+ * @param opts the circuit vkey + the pinned `exprHash` + the anchor window.
54
+ */
55
+ export function shieldApp(base, opts) {
56
+ const publicValues = { var: "event.publicValues" };
57
+ const anchor = pvField(publicValues, 2);
58
+ const nullifier = pvField(publicValues, 66);
59
+ const newCommitment = pvField(publicValues, 130);
60
+ const exprHash = pvField(publicValues, 194);
61
+ // GUARD (combine): all stateful, combiner-only.
62
+ const guard = {
63
+ and: [
64
+ // 1. the proof verifies against the pool's pinned vkey over EXACTLY these public bytes
65
+ { groth16_verify: [{ var: "state.vkey" }, publicValues, { var: "event.proof" }] },
66
+ // 2. it ran the app logic this pool pins (binds which effect produced the transition)
67
+ { "===": [exprHash, { var: "state.exprHash" }] },
68
+ // 3. the spent note was proven under an anchor we still honor
69
+ { in: [anchor, { var: "state.knownRoots" }] },
70
+ // 4. inter-transfer double-spend guard: the nullifier is not already spent
71
+ { none: [{ var: "state.nullifiers" }, { "===": [{ var: "" }, nullifier] }] },
72
+ ],
73
+ };
74
+ // EFFECT (combine): spend the nullifier, record the new commitment, advance counters.
75
+ // Root advancement (turning the appended commitment into the next anchor) is wallet/Bridge-side
76
+ // per RFC §6.2 / §10; the chain records the commitment + nullifier here.
77
+ const effect = {
78
+ merge: [
79
+ { var: "state" },
80
+ {
81
+ nullifiers: { cat: [{ var: "state.nullifiers" }, [nullifier]] },
82
+ commitments: { cat: [{ var: "state.commitments" }, [newCommitment]] },
83
+ leafCount: { "+": [{ var: "state.leafCount" }, 1] },
84
+ transitions: { "+": [{ var: "state.transitions" }, 1] },
85
+ lastTransitionAt: { var: "$ordinal" },
86
+ },
87
+ ],
88
+ };
89
+ return defineFiberApp({
90
+ metadata: {
91
+ name: `Shielded${base.metadata.name}`,
92
+ app: "privacy",
93
+ type: `shielded-${base.metadata.type}`,
94
+ version: base.metadata.version,
95
+ description: `Shielded (zk-jlvm-shielded) variant of ${base.metadata.name}: private state transitions ` +
96
+ `verified by a Groth16 proof; the nullifier set + anchors are public pool state.`,
97
+ },
98
+ createSchema: {
99
+ required: ["vkey", "exprHash"],
100
+ properties: {
101
+ vkey: { type: "hash", immutable: true, default: opts.vkey },
102
+ exprHash: { type: "hash", immutable: true, default: opts.exprHash },
103
+ rootWindow: { type: "integer", immutable: true, default: opts.rootWindow ?? 64 },
104
+ },
105
+ },
106
+ stateSchema: { properties: { ...SHIELDED_POOL_STATE } },
107
+ eventSchemas: {
108
+ transition: {
109
+ description: `A private state transition of ${base.metadata.name}, attested by a zk-jlvm-shielded Groth16 proof.`,
110
+ required: ["proof", "publicValues"],
111
+ properties: {
112
+ proof: { type: "string", description: "Groth16 proof bytes (0x hex)" },
113
+ publicValues: { type: "string", description: "abi-encoded JlvmTransitionPublicValues (4×bytes32, 0x hex)" },
114
+ },
115
+ },
116
+ },
117
+ states: {
118
+ ACTIVE: {
119
+ id: "ACTIVE",
120
+ isFinal: false,
121
+ metadata: { label: "Active", description: "Pool accepts shielded transitions", category: "active" },
122
+ },
123
+ },
124
+ initialState: "ACTIVE",
125
+ transitions: [{ from: "ACTIVE", to: "ACTIVE", eventName: "transition", guard, effect, dependencies: [] }],
126
+ });
127
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Builders for the fiber-engine reserved EFFECT directives — the `_`-prefixed keys the chain extracts
3
+ * from an evaluated effect result and applies as side effects (then strips from the merged state).
4
+ *
5
+ * Place the returned fragment INSIDE the state-update map of a `merge` effect, so the directive rides in
6
+ * the evaluated result map (EffectExtractor reads it; StateMerger drops `_`-prefixed keys from state):
7
+ *
8
+ * ```ts
9
+ * effect: {
10
+ * merge: [
11
+ * { var: "state" },
12
+ * { boundAt: { var: "$ordinal" }, ...addDependency({ var: "event.registryId" }) },
13
+ * ],
14
+ * }
15
+ * ```
16
+ */
17
+ /**
18
+ * `_addDependency` (#24): add — or re-activate — a runtime DYNAMIC dependency on `fiberId`, so that
19
+ * fiber's state appears in `machines.<fiberId>` for SUBSEQUENT transitions of this fiber. `fiberId` may
20
+ * be a literal UUID string or an expression (e.g. `{ var: "event.registryId" }`, `{ var: "state.registryId" }`).
21
+ * The ledger is append-only, idempotent (one entry per fiber), and engine-bounded (active + ledger caps).
22
+ * Because the `machines` context is built BEFORE the effect runs, the bound dependency is readable only
23
+ * from the NEXT transition onward (two-phase: bind, then read).
24
+ */
25
+ export const addDependency = (fiberId) => ({
26
+ _addDependency: [{ fiberId }],
27
+ });
28
+ /**
29
+ * `_setDependencyActive` (#24): toggle a dynamic dependency's `active` flag. The entry is NEVER removed —
30
+ * deactivation simply drops it from the `machines` context (and it can be cheaply re-activated). `fiberId`
31
+ * may be a literal or an expression.
32
+ */
33
+ export const setDependencyActive = (fiberId, active) => ({
34
+ _setDependencyActive: [{ fiberId, active }],
35
+ });
@@ -68,8 +68,13 @@ export function toProtoDefinition(def) {
68
68
  eventName: t.eventName,
69
69
  guard: t.guard, // Required - Scala has no default
70
70
  effect: t.effect, // Required - Scala has no default
71
- // dependencies has default Set.empty in Scala, so omit if empty
72
- ...(t.dependencies?.length && { dependencies: [...t.dependencies] }),
71
+ // Chain `Transition.dependencies: Set[UUID]` is REQUIRED (no Scala default), and each
72
+ // element must be a fiber UUID string. A `DependencySpec` object is a build-time-only
73
+ // authoring affordance with no wire representation (concrete dependency UUIDs are per
74
+ // instance, not part of the definition template), so drop non-string entries. Always
75
+ // emit the array — omitting a no-default field diverges the canonical and the chain
76
+ // rejects the whole update (InvalidSignature / decode failure).
77
+ dependencies: (t.dependencies ?? []).filter((d) => typeof d === 'string'),
73
78
  })),
74
79
  };
75
80
  // Copy states (only id and isFinal)
@@ -79,9 +84,11 @@ export function toProtoDefinition(def) {
79
84
  isFinal: state.isFinal,
80
85
  };
81
86
  }
82
- // Pass metadata through unchanged - it's an optional unstructured object
83
- if (def.metadata) {
84
- protoDef.metadata = def.metadata;
85
- }
87
+ // NOTE: `def.metadata` is the SDK's FiberAppMetadata (name/app/type/version app-routing
88
+ // packaging info), NOT chain metadata. Projecting it onto the wire would make the on-chain
89
+ // canonical + the registry `logicHash` depend on packaging fields (changing `description` would
90
+ // change the signed digest of an otherwise-identical machine), so it is deliberately NOT emitted
91
+ // (the chain's `StateMachineDefinition.metadata` stays absent → `None`). A caller that genuinely
92
+ // needs on-chain metadata sets `ProtoStateMachineDefinition.metadata` explicitly after conversion.
86
93
  return protoDef;
87
94
  }