@ottochain/sdk 2.2.4 → 2.2.5

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.
@@ -3,41 +3,32 @@
3
3
  * Normalize OttoChain Messages for Signing
4
4
  *
5
5
  * Converts OttoChain message objects to the wire format expected by the
6
- * Scala metagraph. Metakit's JsonBinaryCodec (used by OttoChain for data
7
- * transaction signing) canonicalizes JSON with dropNullValues = true.
6
+ * Scala metagraph. Specifically, ensures all `Option[A]=None` fields are
7
+ * present as explicit `null` values, matching what circe's magnolia encoder
8
+ * produces on the Scala side.
8
9
  *
9
- * NOTE: This is Metakit's codec, NOT tessellation's JsonSerializer (which
10
- * uses Brotli compression for snapshots/consensus a different layer).
11
- * Different layers use different byte-sequence encoders.
10
+ * This is necessary because metakit's `JsonBinaryCodec.deriveDataUpdate`
11
+ * (rc.8) canonicalizes the circe-encoded JSON **including null fields**.
12
+ * If the TypeScript client omits optional fields (undefined), the canonical
13
+ * JSON won't match and signature verification will fail.
12
14
  *
13
- * Because Metakit drops null fields during canonicalization, the canonical
14
- * JSON used for signature verification **omits** null fields entirely.
15
- * If the TypeScript client includes explicit nulls (e.g., `"metadata": null`),
16
- * the canonical form won't match and signature verification will fail.
17
- *
18
- * Schema mapping (Scala → TypeScript wire format):
19
- * - `Option[A] = None` → field OMITTED (not null, not undefined)
15
+ * Schema mapping (Scala TypeScript):
16
+ * - `Option[A] = None` `null` (must be explicit, not undefined/absent)
20
17
  * - `Option[A] = Some(v)` → `v`
21
- * - `List.empty` / `Set.empty` → `[]`
18
+ * - `List.empty` → `[]`
22
19
  * - `Map.empty` → `{}`
23
- * - `Boolean = false` → `false` (always include, not a null/Option)
24
20
  */
25
21
  Object.defineProperty(exports, "__esModule", { value: true });
26
22
  exports.normalizeMessage = exports.normalizeArchiveStateMachine = exports.normalizeTransitionStateMachine = exports.normalizeCreateStateMachine = void 0;
27
23
  /**
28
- * Normalize a State object for wire format.
29
- * State: id (required), isFinal (default false), metadata (Option = None)
30
- * Omit metadata when null/undefined (dropNullValues).
24
+ * Normalize a State object for wire format
31
25
  */
32
26
  function normalizeState(state) {
33
- const result = {
27
+ return {
34
28
  id: state.id,
35
29
  isFinal: state.isFinal ?? false,
30
+ metadata: state.metadata ?? null,
36
31
  };
37
- if (state.metadata != null) {
38
- result.metadata = state.metadata;
39
- }
40
- return result;
41
32
  }
42
33
  /**
43
34
  * Normalize a Transition object for wire format
@@ -89,54 +80,41 @@ function normalizeDefinition(def) {
89
80
  }
90
81
  const transitions = def.transitions ?? [];
91
82
  // Strip FiberAppMetadata if present — it's TypeScript-only, not part of wire format.
92
- // Omit metadata entirely when null/FiberAppMetadata (dropNullValues = true on Scala side).
93
- const wireMetadata = isFiberAppMetadata(def.metadata) ? undefined : def.metadata;
94
- const result = {
83
+ // The Scala schema has `metadata: Option[Json] = None`, so use null for wire format.
84
+ const wireMetadata = isFiberAppMetadata(def.metadata) ? null : (def.metadata ?? null);
85
+ return {
95
86
  states: normalizedStates,
96
87
  initialState: def.initialState,
97
88
  transitions: transitions.map(normalizeTransition),
89
+ metadata: wireMetadata,
98
90
  };
99
- if (wireMetadata != null) {
100
- result.metadata = wireMetadata;
101
- }
102
- return result;
103
91
  }
104
92
  /**
105
93
  * Normalize a CreateStateMachine message for wire format
106
94
  *
107
- * Metakit's JsonBinaryCodec uses dropNullValues = true for canonicalization.
108
- * Optional fields at their defaults must be OMITTED (not set to null)
109
- * to match the canonical JSON used for signature verification.
110
- *
111
- * - definition.metadataOMITTED when absent/FiberAppMetadata
112
- * - definition.states[*].metadata → OMITTED when absent
113
- * - definition.transitions[*].dependencies → [] (Set.empty default, always included)
114
- * - parentFiberId → OMITTED when absent (Option[UUID] = None)
115
- * - participants → OMITTED when absent (Option[Set[Address]] = None)
95
+ * Ensures all Option/default fields are explicit in wire format:
96
+ * - definition.metadata null when absent
97
+ * - definition.states[*].metadata null when absent
98
+ * - definition.transitions[*].dependencies → [] when absent
99
+ * - parentFiberIdnull when absent
116
100
  *
117
101
  * @example
118
102
  * ```typescript
119
103
  * const message = normalizeCreateStateMachine({
120
104
  * fiberId: '...',
121
- * definition: { states: { INIT: { id: 'INIT', isFinal: false } }, ... },
105
+ * definition: { states: { INIT: { id: { value: 'INIT' }, isFinal: false } }, ... },
122
106
  * initialData: {}
123
107
  * });
124
- * // Optional fields are absent (not null): no parentFiberId, no metadata, etc.
108
+ * // message now has parentFiberId: null, definition.metadata: null, etc.
125
109
  * ```
126
110
  */
127
111
  function normalizeCreateStateMachine(msg) {
128
- const result = {
112
+ return {
129
113
  fiberId: msg.fiberId,
130
114
  definition: normalizeDefinition(msg.definition),
131
115
  initialData: msg.initialData ?? {},
116
+ parentFiberId: msg.parentFiberId ?? null,
132
117
  };
133
- if (msg.parentFiberId != null) {
134
- result.parentFiberId = msg.parentFiberId;
135
- }
136
- if (msg.participants != null) {
137
- result.participants = msg.participants;
138
- }
139
- return result;
140
118
  }
141
119
  exports.normalizeCreateStateMachine = normalizeCreateStateMachine;
142
120
  /**
@@ -2,39 +2,30 @@
2
2
  * Normalize OttoChain Messages for Signing
3
3
  *
4
4
  * Converts OttoChain message objects to the wire format expected by the
5
- * Scala metagraph. Metakit's JsonBinaryCodec (used by OttoChain for data
6
- * transaction signing) canonicalizes JSON with dropNullValues = true.
5
+ * Scala metagraph. Specifically, ensures all `Option[A]=None` fields are
6
+ * present as explicit `null` values, matching what circe's magnolia encoder
7
+ * produces on the Scala side.
7
8
  *
8
- * NOTE: This is Metakit's codec, NOT tessellation's JsonSerializer (which
9
- * uses Brotli compression for snapshots/consensus a different layer).
10
- * Different layers use different byte-sequence encoders.
9
+ * This is necessary because metakit's `JsonBinaryCodec.deriveDataUpdate`
10
+ * (rc.8) canonicalizes the circe-encoded JSON **including null fields**.
11
+ * If the TypeScript client omits optional fields (undefined), the canonical
12
+ * JSON won't match and signature verification will fail.
11
13
  *
12
- * Because Metakit drops null fields during canonicalization, the canonical
13
- * JSON used for signature verification **omits** null fields entirely.
14
- * If the TypeScript client includes explicit nulls (e.g., `"metadata": null`),
15
- * the canonical form won't match and signature verification will fail.
16
- *
17
- * Schema mapping (Scala → TypeScript wire format):
18
- * - `Option[A] = None` → field OMITTED (not null, not undefined)
14
+ * Schema mapping (Scala TypeScript):
15
+ * - `Option[A] = None` `null` (must be explicit, not undefined/absent)
19
16
  * - `Option[A] = Some(v)` → `v`
20
- * - `List.empty` / `Set.empty` → `[]`
17
+ * - `List.empty` → `[]`
21
18
  * - `Map.empty` → `{}`
22
- * - `Boolean = false` → `false` (always include, not a null/Option)
23
19
  */
24
20
  /**
25
- * Normalize a State object for wire format.
26
- * State: id (required), isFinal (default false), metadata (Option = None)
27
- * Omit metadata when null/undefined (dropNullValues).
21
+ * Normalize a State object for wire format
28
22
  */
29
23
  function normalizeState(state) {
30
- const result = {
24
+ return {
31
25
  id: state.id,
32
26
  isFinal: state.isFinal ?? false,
27
+ metadata: state.metadata ?? null,
33
28
  };
34
- if (state.metadata != null) {
35
- result.metadata = state.metadata;
36
- }
37
- return result;
38
29
  }
39
30
  /**
40
31
  * Normalize a Transition object for wire format
@@ -86,54 +77,41 @@ function normalizeDefinition(def) {
86
77
  }
87
78
  const transitions = def.transitions ?? [];
88
79
  // Strip FiberAppMetadata if present — it's TypeScript-only, not part of wire format.
89
- // Omit metadata entirely when null/FiberAppMetadata (dropNullValues = true on Scala side).
90
- const wireMetadata = isFiberAppMetadata(def.metadata) ? undefined : def.metadata;
91
- const result = {
80
+ // The Scala schema has `metadata: Option[Json] = None`, so use null for wire format.
81
+ const wireMetadata = isFiberAppMetadata(def.metadata) ? null : (def.metadata ?? null);
82
+ return {
92
83
  states: normalizedStates,
93
84
  initialState: def.initialState,
94
85
  transitions: transitions.map(normalizeTransition),
86
+ metadata: wireMetadata,
95
87
  };
96
- if (wireMetadata != null) {
97
- result.metadata = wireMetadata;
98
- }
99
- return result;
100
88
  }
101
89
  /**
102
90
  * Normalize a CreateStateMachine message for wire format
103
91
  *
104
- * Metakit's JsonBinaryCodec uses dropNullValues = true for canonicalization.
105
- * Optional fields at their defaults must be OMITTED (not set to null)
106
- * to match the canonical JSON used for signature verification.
107
- *
108
- * - definition.metadataOMITTED when absent/FiberAppMetadata
109
- * - definition.states[*].metadata → OMITTED when absent
110
- * - definition.transitions[*].dependencies → [] (Set.empty default, always included)
111
- * - parentFiberId → OMITTED when absent (Option[UUID] = None)
112
- * - participants → OMITTED when absent (Option[Set[Address]] = None)
92
+ * Ensures all Option/default fields are explicit in wire format:
93
+ * - definition.metadata null when absent
94
+ * - definition.states[*].metadata null when absent
95
+ * - definition.transitions[*].dependencies → [] when absent
96
+ * - parentFiberIdnull when absent
113
97
  *
114
98
  * @example
115
99
  * ```typescript
116
100
  * const message = normalizeCreateStateMachine({
117
101
  * fiberId: '...',
118
- * definition: { states: { INIT: { id: 'INIT', isFinal: false } }, ... },
102
+ * definition: { states: { INIT: { id: { value: 'INIT' }, isFinal: false } }, ... },
119
103
  * initialData: {}
120
104
  * });
121
- * // Optional fields are absent (not null): no parentFiberId, no metadata, etc.
105
+ * // message now has parentFiberId: null, definition.metadata: null, etc.
122
106
  * ```
123
107
  */
124
108
  export function normalizeCreateStateMachine(msg) {
125
- const result = {
109
+ return {
126
110
  fiberId: msg.fiberId,
127
111
  definition: normalizeDefinition(msg.definition),
128
112
  initialData: msg.initialData ?? {},
113
+ parentFiberId: msg.parentFiberId ?? null,
129
114
  };
130
- if (msg.parentFiberId != null) {
131
- result.parentFiberId = msg.parentFiberId;
132
- }
133
- if (msg.participants != null) {
134
- result.participants = msg.participants;
135
- }
136
- return result;
137
115
  }
138
116
  /**
139
117
  * Normalize a TransitionStateMachine message for wire format
@@ -2,46 +2,38 @@
2
2
  * Normalize OttoChain Messages for Signing
3
3
  *
4
4
  * Converts OttoChain message objects to the wire format expected by the
5
- * Scala metagraph. Metakit's JsonBinaryCodec (used by OttoChain for data
6
- * transaction signing) canonicalizes JSON with dropNullValues = true.
5
+ * Scala metagraph. Specifically, ensures all `Option[A]=None` fields are
6
+ * present as explicit `null` values, matching what circe's magnolia encoder
7
+ * produces on the Scala side.
7
8
  *
8
- * NOTE: This is Metakit's codec, NOT tessellation's JsonSerializer (which
9
- * uses Brotli compression for snapshots/consensus a different layer).
10
- * Different layers use different byte-sequence encoders.
9
+ * This is necessary because metakit's `JsonBinaryCodec.deriveDataUpdate`
10
+ * (rc.8) canonicalizes the circe-encoded JSON **including null fields**.
11
+ * If the TypeScript client omits optional fields (undefined), the canonical
12
+ * JSON won't match and signature verification will fail.
11
13
  *
12
- * Because Metakit drops null fields during canonicalization, the canonical
13
- * JSON used for signature verification **omits** null fields entirely.
14
- * If the TypeScript client includes explicit nulls (e.g., `"metadata": null`),
15
- * the canonical form won't match and signature verification will fail.
16
- *
17
- * Schema mapping (Scala → TypeScript wire format):
18
- * - `Option[A] = None` → field OMITTED (not null, not undefined)
14
+ * Schema mapping (Scala TypeScript):
15
+ * - `Option[A] = None` `null` (must be explicit, not undefined/absent)
19
16
  * - `Option[A] = Some(v)` → `v`
20
- * - `List.empty` / `Set.empty` → `[]`
17
+ * - `List.empty` → `[]`
21
18
  * - `Map.empty` → `{}`
22
- * - `Boolean = false` → `false` (always include, not a null/Option)
23
19
  */
24
20
  /**
25
21
  * Normalize a CreateStateMachine message for wire format
26
22
  *
27
- * Metakit's JsonBinaryCodec uses dropNullValues = true for canonicalization.
28
- * Optional fields at their defaults must be OMITTED (not set to null)
29
- * to match the canonical JSON used for signature verification.
30
- *
31
- * - definition.metadataOMITTED when absent/FiberAppMetadata
32
- * - definition.states[*].metadata → OMITTED when absent
33
- * - definition.transitions[*].dependencies → [] (Set.empty default, always included)
34
- * - parentFiberId → OMITTED when absent (Option[UUID] = None)
35
- * - participants → OMITTED when absent (Option[Set[Address]] = None)
23
+ * Ensures all Option/default fields are explicit in wire format:
24
+ * - definition.metadata null when absent
25
+ * - definition.states[*].metadata null when absent
26
+ * - definition.transitions[*].dependencies → [] when absent
27
+ * - parentFiberIdnull when absent
36
28
  *
37
29
  * @example
38
30
  * ```typescript
39
31
  * const message = normalizeCreateStateMachine({
40
32
  * fiberId: '...',
41
- * definition: { states: { INIT: { id: 'INIT', isFinal: false } }, ... },
33
+ * definition: { states: { INIT: { id: { value: 'INIT' }, isFinal: false } }, ... },
42
34
  * initialData: {}
43
35
  * });
44
- * // Optional fields are absent (not null): no parentFiberId, no metadata, etc.
36
+ * // message now has parentFiberId: null, definition.metadata: null, etc.
45
37
  * ```
46
38
  */
47
39
  export declare function normalizeCreateStateMachine(msg: Record<string, unknown>): Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottochain/sdk",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "TypeScript SDK for ottochain metagraph operations - signing, encoding, and network interactions",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",