cesr-ts 0.4.0 → 0.6.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 (204) hide show
  1. package/esm/src/adapters/async-iterable.js +8 -0
  2. package/esm/src/adapters/effection.js +6 -0
  3. package/esm/src/annotate/annotator.js +12 -0
  4. package/esm/src/annotate/cli.js +12 -0
  5. package/esm/src/annotate/comments.js +5 -1
  6. package/esm/src/annotate/denot.js +6 -0
  7. package/esm/src/annotate/render.js +15 -3
  8. package/esm/src/core/bytes.js +9 -0
  9. package/esm/src/core/errors.js +3 -0
  10. package/esm/src/core/parser-engine.js +1 -1
  11. package/esm/src/core/parser-frame-parser.js +22 -18
  12. package/esm/src/core/vocabulary.js +47 -0
  13. package/esm/src/index.js +5 -0
  14. package/esm/src/parser/attachment-parser.js +4 -0
  15. package/esm/src/parser/cold-start.js +6 -0
  16. package/esm/src/parser/group-dispatch.js +2 -2
  17. package/esm/src/primitives/aggor.js +374 -30
  18. package/esm/src/primitives/bexter.js +2 -3
  19. package/esm/src/primitives/blinder.js +6 -0
  20. package/esm/src/primitives/byte-like.js +19 -0
  21. package/esm/src/primitives/cigar.js +17 -3
  22. package/esm/src/primitives/cipher.js +91 -6
  23. package/esm/src/primitives/codex.js +39 -6
  24. package/esm/src/primitives/compactor.js +307 -3
  25. package/esm/src/primitives/counter.js +6 -2
  26. package/esm/src/primitives/dater.js +1 -2
  27. package/esm/src/primitives/decimer.js +7 -11
  28. package/esm/src/primitives/decrypter.js +123 -7
  29. package/esm/src/primitives/diger.js +57 -3
  30. package/esm/src/primitives/disclosure.js +300 -0
  31. package/esm/src/primitives/encrypter.js +130 -7
  32. package/esm/src/primitives/hydrate.js +49 -0
  33. package/esm/src/primitives/ilker.js +2 -3
  34. package/esm/src/primitives/indexer.js +21 -4
  35. package/esm/src/primitives/labeler.js +1 -2
  36. package/esm/src/primitives/mapper.js +612 -35
  37. package/esm/src/primitives/matter.js +133 -3
  38. package/esm/src/primitives/mediar.js +6 -0
  39. package/esm/src/primitives/noncer.js +2 -3
  40. package/esm/src/primitives/number.js +1 -2
  41. package/esm/src/primitives/pather.js +102 -5
  42. package/esm/src/primitives/prefixer.js +1 -2
  43. package/esm/src/primitives/primitive.js +14 -0
  44. package/esm/src/primitives/registry.js +2 -0
  45. package/esm/src/primitives/saider.js +80 -3
  46. package/esm/src/primitives/salter.js +96 -2
  47. package/esm/src/primitives/sealed-box.js +41 -0
  48. package/esm/src/primitives/seqner.js +1 -2
  49. package/esm/src/primitives/siger.js +58 -3
  50. package/esm/src/primitives/signer.js +243 -9
  51. package/esm/src/primitives/streamer.js +28 -0
  52. package/esm/src/primitives/structing.js +727 -0
  53. package/esm/src/primitives/structor.js +20 -0
  54. package/esm/src/primitives/tagger.js +1 -2
  55. package/esm/src/primitives/texter.js +1 -2
  56. package/esm/src/primitives/tholder.js +552 -10
  57. package/esm/src/primitives/traitor.js +2 -3
  58. package/esm/src/primitives/verfer.js +50 -6
  59. package/esm/src/primitives/verser.js +16 -6
  60. package/esm/src/router/router-stub.js +1 -0
  61. package/esm/src/serder/native.js +1326 -0
  62. package/esm/src/serder/serder.js +1558 -59
  63. package/esm/src/serder/serdery.js +92 -7
  64. package/esm/src/serder/smell.js +26 -1
  65. package/esm/src/tables/codex-utils.js +2 -0
  66. package/esm/src/tables/counter-codex.js +2 -0
  67. package/esm/src/tables/counter-groups.js +6 -0
  68. package/esm/src/tables/versions.js +4 -0
  69. package/esm/src/version.js +5 -2
  70. package/package.json +5 -2
  71. package/types/src/adapters/async-iterable.d.ts +8 -0
  72. package/types/src/adapters/async-iterable.d.ts.map +1 -1
  73. package/types/src/adapters/effection.d.ts +7 -0
  74. package/types/src/adapters/effection.d.ts.map +1 -1
  75. package/types/src/annotate/annotator.d.ts +12 -0
  76. package/types/src/annotate/annotator.d.ts.map +1 -1
  77. package/types/src/annotate/cli.d.ts +13 -0
  78. package/types/src/annotate/cli.d.ts.map +1 -1
  79. package/types/src/annotate/comments.d.ts +4 -0
  80. package/types/src/annotate/comments.d.ts.map +1 -1
  81. package/types/src/annotate/denot.d.ts +6 -0
  82. package/types/src/annotate/denot.d.ts.map +1 -1
  83. package/types/src/annotate/render.d.ts.map +1 -1
  84. package/types/src/annotate/types.d.ts +2 -0
  85. package/types/src/annotate/types.d.ts.map +1 -1
  86. package/types/src/bench/parser-benchmark.d.ts +3 -0
  87. package/types/src/bench/parser-benchmark.d.ts.map +1 -1
  88. package/types/src/core/bytes.d.ts +9 -0
  89. package/types/src/core/bytes.d.ts.map +1 -1
  90. package/types/src/core/errors.d.ts +3 -0
  91. package/types/src/core/errors.d.ts.map +1 -1
  92. package/types/src/core/parser-engine.d.ts +4 -0
  93. package/types/src/core/parser-engine.d.ts.map +1 -1
  94. package/types/src/core/parser-frame-parser.d.ts.map +1 -1
  95. package/types/src/core/types.d.ts +2 -0
  96. package/types/src/core/types.d.ts.map +1 -1
  97. package/types/src/core/vocabulary.d.ts +48 -0
  98. package/types/src/core/vocabulary.d.ts.map +1 -0
  99. package/types/src/index.d.ts +5 -0
  100. package/types/src/index.d.ts.map +1 -1
  101. package/types/src/parser/attachment-parser.d.ts +4 -0
  102. package/types/src/parser/attachment-parser.d.ts.map +1 -1
  103. package/types/src/parser/cold-start.d.ts +6 -0
  104. package/types/src/parser/cold-start.d.ts.map +1 -1
  105. package/types/src/parser/group-dispatch.d.ts.map +1 -1
  106. package/types/src/primitives/aggor.d.ts +100 -13
  107. package/types/src/primitives/aggor.d.ts.map +1 -1
  108. package/types/src/primitives/bexter.d.ts.map +1 -1
  109. package/types/src/primitives/blinder.d.ts +6 -0
  110. package/types/src/primitives/blinder.d.ts.map +1 -1
  111. package/types/src/primitives/byte-like.d.ts +7 -0
  112. package/types/src/primitives/byte-like.d.ts.map +1 -0
  113. package/types/src/primitives/cigar.d.ts +11 -1
  114. package/types/src/primitives/cigar.d.ts.map +1 -1
  115. package/types/src/primitives/cipher.d.ts +73 -2
  116. package/types/src/primitives/cipher.d.ts.map +1 -1
  117. package/types/src/primitives/codex.d.ts +34 -4
  118. package/types/src/primitives/codex.d.ts.map +1 -1
  119. package/types/src/primitives/compactor.d.ts +94 -2
  120. package/types/src/primitives/compactor.d.ts.map +1 -1
  121. package/types/src/primitives/counter.d.ts.map +1 -1
  122. package/types/src/primitives/dater.d.ts.map +1 -1
  123. package/types/src/primitives/decimer.d.ts.map +1 -1
  124. package/types/src/primitives/decrypter.d.ts +64 -3
  125. package/types/src/primitives/decrypter.d.ts.map +1 -1
  126. package/types/src/primitives/diger.d.ts +16 -0
  127. package/types/src/primitives/diger.d.ts.map +1 -1
  128. package/types/src/primitives/disclosure.d.ts +201 -0
  129. package/types/src/primitives/disclosure.d.ts.map +1 -0
  130. package/types/src/primitives/encrypter.d.ts +66 -4
  131. package/types/src/primitives/encrypter.d.ts.map +1 -1
  132. package/types/src/primitives/hydrate.d.ts +20 -0
  133. package/types/src/primitives/hydrate.d.ts.map +1 -0
  134. package/types/src/primitives/ilker.d.ts.map +1 -1
  135. package/types/src/primitives/indexer.d.ts.map +1 -1
  136. package/types/src/primitives/labeler.d.ts.map +1 -1
  137. package/types/src/primitives/mapper.d.ts +132 -11
  138. package/types/src/primitives/mapper.d.ts.map +1 -1
  139. package/types/src/primitives/matter.d.ts +33 -1
  140. package/types/src/primitives/matter.d.ts.map +1 -1
  141. package/types/src/primitives/mediar.d.ts +6 -0
  142. package/types/src/primitives/mediar.d.ts.map +1 -1
  143. package/types/src/primitives/noncer.d.ts.map +1 -1
  144. package/types/src/primitives/number.d.ts.map +1 -1
  145. package/types/src/primitives/pather.d.ts +21 -0
  146. package/types/src/primitives/pather.d.ts.map +1 -1
  147. package/types/src/primitives/prefixer.d.ts.map +1 -1
  148. package/types/src/primitives/primitive.d.ts +26 -0
  149. package/types/src/primitives/primitive.d.ts.map +1 -1
  150. package/types/src/primitives/registry.d.ts +3 -0
  151. package/types/src/primitives/registry.d.ts.map +1 -1
  152. package/types/src/primitives/saider.d.ts +41 -0
  153. package/types/src/primitives/saider.d.ts.map +1 -1
  154. package/types/src/primitives/salter.d.ts +56 -1
  155. package/types/src/primitives/salter.d.ts.map +1 -1
  156. package/types/src/primitives/sealed-box.d.ts +29 -0
  157. package/types/src/primitives/sealed-box.d.ts.map +1 -0
  158. package/types/src/primitives/seqner.d.ts.map +1 -1
  159. package/types/src/primitives/siger.d.ts +14 -0
  160. package/types/src/primitives/siger.d.ts.map +1 -1
  161. package/types/src/primitives/signer.d.ts +80 -4
  162. package/types/src/primitives/signer.d.ts.map +1 -1
  163. package/types/src/primitives/streamer.d.ts +31 -0
  164. package/types/src/primitives/streamer.d.ts.map +1 -0
  165. package/types/src/primitives/structing.d.ts +4114 -0
  166. package/types/src/primitives/structing.d.ts.map +1 -0
  167. package/types/src/primitives/structor.d.ts +6 -0
  168. package/types/src/primitives/structor.d.ts.map +1 -1
  169. package/types/src/primitives/tagger.d.ts.map +1 -1
  170. package/types/src/primitives/texter.d.ts.map +1 -1
  171. package/types/src/primitives/tholder.d.ts +150 -5
  172. package/types/src/primitives/tholder.d.ts.map +1 -1
  173. package/types/src/primitives/traitor.d.ts.map +1 -1
  174. package/types/src/primitives/unknown.d.ts +1 -0
  175. package/types/src/primitives/unknown.d.ts.map +1 -1
  176. package/types/src/primitives/verfer.d.ts +12 -0
  177. package/types/src/primitives/verfer.d.ts.map +1 -1
  178. package/types/src/primitives/verser.d.ts +14 -3
  179. package/types/src/primitives/verser.d.ts.map +1 -1
  180. package/types/src/router/router-stub.d.ts +3 -0
  181. package/types/src/router/router-stub.d.ts.map +1 -1
  182. package/types/src/serder/native.d.ts +115 -0
  183. package/types/src/serder/native.d.ts.map +1 -0
  184. package/types/src/serder/serder.d.ts +187 -9
  185. package/types/src/serder/serder.d.ts.map +1 -1
  186. package/types/src/serder/serdery.d.ts +42 -0
  187. package/types/src/serder/serdery.d.ts.map +1 -1
  188. package/types/src/serder/smell.d.ts +22 -0
  189. package/types/src/serder/smell.d.ts.map +1 -1
  190. package/types/src/tables/codex-utils.d.ts +3 -0
  191. package/types/src/tables/codex-utils.d.ts.map +1 -1
  192. package/types/src/tables/counter-codex.d.ts +4 -0
  193. package/types/src/tables/counter-codex.d.ts.map +1 -1
  194. package/types/src/tables/counter-groups.d.ts +6 -0
  195. package/types/src/tables/counter-groups.d.ts.map +1 -1
  196. package/types/src/tables/counter.tables.generated.d.ts.map +1 -1
  197. package/types/src/tables/indexer.codex.generated.d.ts.map +1 -1
  198. package/types/src/tables/matter.codex.generated.d.ts.map +1 -1
  199. package/types/src/tables/table-types.d.ts +6 -0
  200. package/types/src/tables/table-types.d.ts.map +1 -1
  201. package/types/src/tables/versions.d.ts +6 -0
  202. package/types/src/tables/versions.d.ts.map +1 -1
  203. package/types/src/version.d.ts +5 -2
  204. package/types/src/version.d.ts.map +1 -1
@@ -0,0 +1,1326 @@
1
+ import { b, codeB2ToB64, intToB64, t } from "../core/bytes.js";
2
+ import { DeserializeError, SerializeError } from "../core/errors.js";
3
+ import { Ilks } from "../core/vocabulary.js";
4
+ import { parseAttachmentDispatch } from "../parser/group-dispatch.js";
5
+ import { Aggor, isAggorListCode, isAggorMapCode, parseAggor } from "../primitives/aggor.js";
6
+ import { Bexter } from "../primitives/bexter.js";
7
+ import { BEXTER_CODES, DATER_CODES, DIGEST_CODES, LabelDex, MtrDex, NON_DIGEST_PREFIX_CODES, NONCE_CODES, NUMBER_CODES, PREFIX_CODES, TAG_CODES, } from "../primitives/codex.js";
8
+ import { Counter, parseCounter } from "../primitives/counter.js";
9
+ import { Dater } from "../primitives/dater.js";
10
+ import { parseIlker } from "../primitives/ilker.js";
11
+ import { Labeler, parseLabeler } from "../primitives/labeler.js";
12
+ import { Mapper } from "../primitives/mapper.js";
13
+ import { parseMatter } from "../primitives/matter.js";
14
+ import { parseNoncer } from "../primitives/noncer.js";
15
+ import { NumberPrimitive } from "../primitives/number.js";
16
+ import { makePather, parsePather } from "../primitives/pather.js";
17
+ import { isCounterGroupLike, isPrimitiveTuple } from "../primitives/primitive.js";
18
+ import { Structor } from "../primitives/structor.js";
19
+ import { Texter } from "../primitives/texter.js";
20
+ import { Tholder } from "../primitives/tholder.js";
21
+ import { parseTraitor } from "../primitives/traitor.js";
22
+ import { parseVerser } from "../primitives/verser.js";
23
+ import { CtrDexV2 } from "../tables/counter-codex.js";
24
+ import { Kinds, Protocols, Vrsn_2_0 } from "../tables/versions.js";
25
+ import { versify } from "./smell.js";
26
+ /**
27
+ * CESR-native serder helper layer.
28
+ *
29
+ * This module exists to keep native inhale/exhale logic in one shared place so
30
+ * `Serder`, `Serdery`, and parser hydration all agree on the same rules. The
31
+ * current implementation is intentionally a staged parity port: it handles the
32
+ * real KERI native flows needed by runtime integration first, while broader
33
+ * KERI/ACDC native parity and compactification continue to expand here.
34
+ *
35
+ * Mental model:
36
+ * - non-native KERI/ACDC bodies are self-describing field maps (`JSON`,
37
+ * `CBOR`, `MGPK`) that `smell()` can recognize directly from the embedded
38
+ * version string
39
+ * - CESR-native bodies are instead "counter + compact CESR fields", so the
40
+ * parser must first identify the body-group frame before the serder layer can
41
+ * reconstruct a SAD
42
+ * - this module bridges that gap by converting native bodies into the same
43
+ * semantic `ked` shape that non-native serders use
44
+ *
45
+ * Text-domain native example, segmented for humans:
46
+ *
47
+ * ```text
48
+ * -FA5 | 0OKERICAACA | Xicp | EFaYE2... | DNG2ar... | MAAA | MAAB | -JAL...
49
+ * ^ ^ ^ ^ ^ ^ ^ ^
50
+ * body verser ilk said `d` prefix `i` `s` `kt` list/group payloads
51
+ * ctr
52
+ * ```
53
+ *
54
+ * The same message may also arrive in qb2/binary form. In that case the bytes
55
+ * are not human-readable, so this module canonicalizes them back to the qb64
56
+ * text form above before decoding semantics. That is why many helpers talk
57
+ * about "text-domain canonical form" even when their input may have started as
58
+ * raw qb2 bytes.
59
+ */
60
+ const TAG_CODES_BY_LENGTH = new Map([
61
+ [1, LabelDex.Tag1],
62
+ [2, LabelDex.Tag2],
63
+ [3, LabelDex.Tag3],
64
+ [4, LabelDex.Tag4],
65
+ [5, LabelDex.Tag5],
66
+ [6, LabelDex.Tag6],
67
+ [7, LabelDex.Tag7],
68
+ [8, LabelDex.Tag8],
69
+ [9, LabelDex.Tag9],
70
+ [10, LabelDex.Tag10],
71
+ [11, LabelDex.Tag11],
72
+ ]);
73
+ const NUMBER_CAPACITIES = [
74
+ { code: "M", rawSize: 2 },
75
+ { code: "0H", rawSize: 4 },
76
+ { code: "R", rawSize: 5 },
77
+ { code: "N", rawSize: 8 },
78
+ { code: "S", rawSize: 11 },
79
+ { code: "T", rawSize: 14 },
80
+ { code: "0A", rawSize: 16 },
81
+ { code: "U", rawSize: 17 },
82
+ ];
83
+ /** Native text bodies always begin with a counter hard code `-`. */
84
+ function isTextDomain(raw) {
85
+ return raw.length > 0 && raw[0] === "-".charCodeAt(0);
86
+ }
87
+ /**
88
+ * Resolve the canonical qb64 span of one native body-group token.
89
+ *
90
+ * Even when the input is qb2, the body counter still declares the payload in
91
+ * qb64 quadlets, so this helper always returns the text-domain width.
92
+ */
93
+ function nativeQb64Size(raw, version) {
94
+ const cold = isTextDomain(raw) ? "txt" : "bny";
95
+ const counter = parseCounter(raw, version, cold);
96
+ return counter.fullSize + counter.count * 4;
97
+ }
98
+ /**
99
+ * Convert native input into the canonical qb64 text-domain form used by the
100
+ * rest of this module.
101
+ *
102
+ * If `raw` is already text-domain, it is returned unchanged. If `raw` is qb2,
103
+ * the function converts exactly one native body-group span back into its qb64
104
+ * ASCII form.
105
+ *
106
+ * Example:
107
+ *
108
+ * ```ts
109
+ * const txt = canonicalizeCesrNativeRaw(qb2Bytes, { major: 2, minor: 0 });
110
+ * // new TextDecoder().decode(txt) starts with "-F..." or "-G..."
111
+ * ```
112
+ */
113
+ export function canonicalizeCesrNativeRaw(raw, version) {
114
+ if (isTextDomain(raw)) {
115
+ return raw;
116
+ }
117
+ return b(codeB2ToB64(raw, nativeQb64Size(raw, version)));
118
+ }
119
+ /** Emit the narrowest fixed-width tag family that can carry `text`. */
120
+ function encodeTag(text) {
121
+ const code = TAG_CODES_BY_LENGTH.get(text.length);
122
+ if (!code) {
123
+ throw new SerializeError(`Unsupported tag length=${text.length}`);
124
+ }
125
+ const pad = code === LabelDex.Tag1 || code === LabelDex.Tag5 || code === LabelDex.Tag9
126
+ ? "_"
127
+ : "";
128
+ return `${code}${pad}${text}`;
129
+ }
130
+ /** Emit base64-safe text through the StrB64/Bexter family. */
131
+ function encodeBext(text) {
132
+ const rem = text.length % 4;
133
+ const code = rem === 0
134
+ ? LabelDex.StrB64_L0
135
+ : rem === 1
136
+ ? LabelDex.StrB64_L1
137
+ : LabelDex.StrB64_L2;
138
+ return new Bexter({ code, raw: Bexter.rawify(text) }).qb64;
139
+ }
140
+ /** Emit arbitrary UTF-8 text through the bytes label family. */
141
+ function encodeBytes(text) {
142
+ const raw = b(text);
143
+ const rem = raw.length % 3;
144
+ const code = rem === 0
145
+ ? LabelDex.Bytes_L0
146
+ : rem === 1
147
+ ? LabelDex.Bytes_L1
148
+ : LabelDex.Bytes_L2;
149
+ return new Texter({ code, raw }).qb64;
150
+ }
151
+ /**
152
+ * Choose the most compact supported native label/text encoding for `text`.
153
+ *
154
+ * Decision order mirrors the intended CESR-native compactness ladder:
155
+ * tag first, then StrB64, then generic bytes.
156
+ */
157
+ function encodeLabel(text) {
158
+ if (text.length === 0) {
159
+ return LabelDex.Empty;
160
+ }
161
+ if (/^[A-Za-z0-9_-]{1,11}$/.test(text)) {
162
+ return encodeTag(text);
163
+ }
164
+ if (/^[A-Za-z0-9_-]+$/.test(text)) {
165
+ return encodeBext(text);
166
+ }
167
+ return encodeBytes(text);
168
+ }
169
+ /** Encode protocol + version metadata into one native verser token. */
170
+ function encodeVerser(proto, pvrsn, gvrsn) {
171
+ const payload = `${proto}${intToB64(pvrsn.major, 1)}${intToB64(pvrsn.minor, 2)}${gvrsn ? `${intToB64(gvrsn.major, 1)}${intToB64(gvrsn.minor, 2)}` : ""}`;
172
+ return encodeTag(payload);
173
+ }
174
+ /** Big-endian integer helper used by native numeric families. */
175
+ function bigintToBytes(value) {
176
+ if (value < 0n) {
177
+ throw new SerializeError(`Negative CESR number=${value}`);
178
+ }
179
+ if (value === 0n) {
180
+ return new Uint8Array([0]);
181
+ }
182
+ const bytes = [];
183
+ let working = value;
184
+ while (working > 0n) {
185
+ bytes.unshift(Number(working & 0xffn));
186
+ working >>= 8n;
187
+ }
188
+ return new Uint8Array(bytes);
189
+ }
190
+ /**
191
+ * Emit one CESR numeric primitive from a semantic integer/hex-string value.
192
+ *
193
+ * Maintainer rule: when native number-family parity broadens, extend
194
+ * `NUMBER_CAPACITIES` instead of growing special cases in callers.
195
+ */
196
+ function encodeNumber(value) {
197
+ const bigint = typeof value === "bigint"
198
+ ? value
199
+ : typeof value === "number"
200
+ ? BigInt(value)
201
+ : BigInt(`0x${value || "0"}`);
202
+ const raw = bigintToBytes(bigint);
203
+ const entry = NUMBER_CAPACITIES.find(({ rawSize }) => raw.length <= rawSize);
204
+ if (!entry) {
205
+ throw new SerializeError(`Unsupported number width=${raw.length}`);
206
+ }
207
+ const padded = new Uint8Array(entry.rawSize);
208
+ padded.set(raw, entry.rawSize - raw.length);
209
+ return new NumberPrimitive({ code: entry.code, raw: padded }).qb64;
210
+ }
211
+ /** KERI thresholds are either numeric hex strings or weighted clause expressions. */
212
+ function encodeThreshold(value) {
213
+ try {
214
+ return new Tholder({ sith: value }).qb64;
215
+ }
216
+ catch (error) {
217
+ throw new SerializeError(`Unsupported CESR threshold=${JSON.stringify(value)}`, undefined, error instanceof Error ? error.message : undefined);
218
+ }
219
+ }
220
+ /** CESR-native datetimes substitute base64-safe glyphs for RFC3339 punctuation. */
221
+ function encodeDate(iso8601) {
222
+ return `${MtrDex.DateTime}${iso8601.replaceAll(":", "c").replaceAll(".", "d").replaceAll("+", "p")}`;
223
+ }
224
+ /**
225
+ * Encode semantic route/path strings using the same Pather rules as KERIpy.
226
+ *
227
+ * Important nuance:
228
+ * KERI route fields are not generic labels. Even when the semantic value is a
229
+ * simple string like `ksn`, KERIpy encodes it through `Pather(..., relative=True,
230
+ * pathive=False)` so the result may be a compact StrB64 path token such as
231
+ * `4AABAksn` instead of a labeler/text token.
232
+ */
233
+ function encodePath(path) {
234
+ return makePather(path, { relative: true, pathive: false }).qb64;
235
+ }
236
+ /** Enclose already-encoded members inside one native generic-list group. */
237
+ function encodeList(entries, gvrsn) {
238
+ const frame = entries.join("");
239
+ const count = frame.length / 4;
240
+ const code = count < 64 ** 2
241
+ ? CtrDexV2.GenericListGroup
242
+ : CtrDexV2.BigGenericListGroup;
243
+ return `${new Counter({ code, count, version: gvrsn ?? Vrsn_2_0 }).qb64}${frame}`;
244
+ }
245
+ /**
246
+ * Enclose one semantic field map inside either a top-level body-group or a
247
+ * nested generic map-group.
248
+ */
249
+ function encodeMap(map, gvrsn, topLevel = false) {
250
+ let frame = "";
251
+ for (const [label, value] of Object.entries(map)) {
252
+ frame += encodeLabel(label);
253
+ frame += encodeValue(value, gvrsn, label);
254
+ }
255
+ const count = frame.length / 4;
256
+ const code = topLevel
257
+ ? count < 64 ** 2 ? CtrDexV2.MapBodyGroup : CtrDexV2.BigMapBodyGroup
258
+ : count < 64 ** 2
259
+ ? CtrDexV2.GenericMapGroup
260
+ : CtrDexV2.BigGenericMapGroup;
261
+ return `${new Counter({ code, count, version: gvrsn ?? Vrsn_2_0 }).qb64}${frame}`;
262
+ }
263
+ /**
264
+ * Best-effort native emit for one semantic field value.
265
+ *
266
+ * Decision order matters:
267
+ * 1. preserve already-qualified CESR primitives when present
268
+ * 2. apply field-specific semantic encoders
269
+ * 3. fall back to generic scalar/list/map encoders
270
+ */
271
+ function encodeValue(value, gvrsn, label) {
272
+ if (typeof value === "string") {
273
+ if (value.length === 0 && label && ["u", "rd", "td"].includes(label)) {
274
+ return LabelDex.Empty;
275
+ }
276
+ try {
277
+ const primitive = parseMatter(b(value), "txt");
278
+ if (DIGEST_CODES.has(primitive.code)
279
+ || PREFIX_CODES.has(primitive.code)
280
+ || NON_DIGEST_PREFIX_CODES.has(primitive.code)
281
+ || NONCE_CODES.has(primitive.code)
282
+ || BEXTER_CODES.has(primitive.code)
283
+ || TAG_CODES.has(primitive.code)
284
+ || DATER_CODES.has(primitive.code)) {
285
+ return primitive.qb64;
286
+ }
287
+ }
288
+ catch {
289
+ // fall through to semantic encoding
290
+ }
291
+ if (label === "dt") {
292
+ return encodeDate(value);
293
+ }
294
+ if (label === "r" || label === "rr") {
295
+ return encodePath(value);
296
+ }
297
+ if (label === "ts") {
298
+ return encodeLabel(value);
299
+ }
300
+ if (/^[A-Za-z0-9_-]{1,11}$/.test(value)) {
301
+ return encodeTag(value);
302
+ }
303
+ if (/^[A-Za-z0-9_-]+$/.test(value)) {
304
+ return encodeBext(value);
305
+ }
306
+ return encodeBytes(value);
307
+ }
308
+ if (typeof value === "number" || typeof value === "bigint") {
309
+ return encodeNumber(value);
310
+ }
311
+ if (Array.isArray(value)) {
312
+ const entries = value.map((entry) => encodeValue(entry, gvrsn));
313
+ return encodeList(entries, gvrsn);
314
+ }
315
+ if (value && typeof value === "object") {
316
+ return encodeMap(value, gvrsn);
317
+ }
318
+ throw new SerializeError(`Unsupported native value=${String(value)}`);
319
+ }
320
+ /**
321
+ * Decode one parser graph entry back into a semantic SAD value.
322
+ *
323
+ * This stays parser-graph aware on purpose so native deserialization reuses the
324
+ * existing group dispatch machinery instead of maintaining a separate
325
+ * attachment/group decoder.
326
+ */
327
+ function decodeEntry(entry, gvrsn) {
328
+ if (isPrimitiveTuple(entry)) {
329
+ return entry.map((item) => decodeEntry(item, gvrsn));
330
+ }
331
+ if (isCounterGroupLike(entry)) {
332
+ if (isAggorListCode(entry.code)) {
333
+ return entry.items.map((item) => decodeEntry(item, gvrsn));
334
+ }
335
+ if (isAggorMapCode(entry.code)) {
336
+ const aggor = parseAggor(b(Structor.fromGroup(entry).qb64g), gvrsn, "txt");
337
+ const fields = aggor.mapFields ?? [];
338
+ return Object.fromEntries(fields.map((field) => [field.label ?? "", decodeMapperField(field, gvrsn)]));
339
+ }
340
+ return Structor.fromGroup(entry).qb64g;
341
+ }
342
+ const matter = entry;
343
+ if (DIGEST_CODES.has(matter.code)
344
+ || PREFIX_CODES.has(matter.code)
345
+ || NON_DIGEST_PREFIX_CODES.has(matter.code)) {
346
+ return matter.qb64;
347
+ }
348
+ if (NONCE_CODES.has(matter.code)) {
349
+ return parseNoncer(b(matter.qb64), "txt").nonce;
350
+ }
351
+ if (NUMBER_CODES.has(matter.code)) {
352
+ return new NumberPrimitive(matter).numh;
353
+ }
354
+ if (DATER_CODES.has(matter.code)) {
355
+ return new Dater(matter).iso8601;
356
+ }
357
+ if (matter.code === MtrDex.DateTime) {
358
+ return new Dater(matter).iso8601;
359
+ }
360
+ if (TAG_CODES.has(matter.code)) {
361
+ if (matter.code === MtrDex.Tag3) {
362
+ return parseIlker(b(matter.qb64), "txt").ilk;
363
+ }
364
+ return new Labeler(matter).text;
365
+ }
366
+ if (BEXTER_CODES.has(matter.code)) {
367
+ return parsePather(b(matter.qb64), "txt").path;
368
+ }
369
+ return matter.qb64;
370
+ }
371
+ /** Recursively convert parsed mapper fields into nested JS map/list/scalar values. */
372
+ function decodeMapperField(field, gvrsn) {
373
+ if (field.children) {
374
+ return Object.fromEntries(field.children.map((child) => [child.label ?? "", decodeMapperField(child, gvrsn)]));
375
+ }
376
+ return decodeEntry(field.primitive, gvrsn);
377
+ }
378
+ /**
379
+ * Decode one native generic-list group.
380
+ *
381
+ * Items may be plain primitives or nested counted groups, so we probe group
382
+ * dispatch first and fall back to `Matter` only when no valid group starts at
383
+ * the current offset.
384
+ */
385
+ function decodeList(raw, gvrsn) {
386
+ const counter = parseCounter(raw, gvrsn, "txt");
387
+ if (counter.code !== CtrDexV2.GenericListGroup
388
+ && counter.code !== CtrDexV2.BigGenericListGroup) {
389
+ throw new DeserializeError(`Expected list group, got ${counter.code}`);
390
+ }
391
+ const payload = t(raw.slice(counter.fullSize, counter.fullSize + counter.count * 4));
392
+ const out = [];
393
+ let offset = 0;
394
+ while (offset < payload.length) {
395
+ const chunk = b(payload.slice(offset));
396
+ try {
397
+ const parsed = parseAttachmentDispatch(chunk, gvrsn, "txt");
398
+ out.push(decodeEntry(parsed.group, gvrsn));
399
+ offset += parsed.consumed;
400
+ continue;
401
+ }
402
+ catch {
403
+ const matter = parseMatter(chunk, "txt");
404
+ out.push(decodeEntry(matter, gvrsn));
405
+ offset += matter.fullSize;
406
+ }
407
+ }
408
+ return out;
409
+ }
410
+ /**
411
+ * Decode one native field that is already carried as a complete qb64 CESR
412
+ * primitive.
413
+ *
414
+ * Typical KERI fixed-body examples:
415
+ * - `d`: top-level SAID such as `EFaYE2LTv8dItUgQzIHKRA9FaHDrHtIHNs-m5DJKWXRN`
416
+ * - `i`: identifier prefix such as `DNG2arBDtHK_JyHRAq-emRdC6UM-yIpCAeJIWDiXp4Hx`
417
+ *
418
+ * In these cases the semantic value is the qb64 text itself, so the helper
419
+ * simply parses one `Matter` and returns its canonical qb64 string.
420
+ */
421
+ function parseQb64Field(raw, offset) {
422
+ const matter = parseMatter(raw.slice(offset), "txt");
423
+ return {
424
+ value: matter.qb64,
425
+ nextOffset: offset + matter.fullSize,
426
+ };
427
+ }
428
+ /**
429
+ * Decode one native numeric field that KERI exposes as a hex string in the SAD.
430
+ *
431
+ * Typical KERI fixed-body examples:
432
+ * - `s`: sequence number, where native `MAAA` becomes semantic `"0"`
433
+ * - `bt`: witness threshold/count field, where native `MAAA` also becomes `"0"`
434
+ *
435
+ * Native CESR uses compact numeric primitives, but KERI SADs conventionally
436
+ * expose these values as lowercase hex strings, so this helper performs that
437
+ * projection.
438
+ */
439
+ function parseNumericHexField(raw, offset) {
440
+ const matter = new NumberPrimitive({ qb64b: raw.slice(offset) });
441
+ return {
442
+ value: matter.numh,
443
+ nextOffset: offset + matter.fullSize,
444
+ };
445
+ }
446
+ /**
447
+ * Decode one native signing-threshold field into its SAD `sith` representation.
448
+ *
449
+ * Typical KERI fixed-body examples:
450
+ * - `kt`: current signing threshold, e.g. native `MAAB` -> semantic `"1"`
451
+ * - `nt`: next signing threshold, also commonly `MAAB` -> semantic `"1"`
452
+ *
453
+ * The native bytes are parsed through `Tholder`, which understands both simple
454
+ * numeric thresholds and the more complex weighted threshold encodings.
455
+ */
456
+ function parseThresholdSithField(raw, offset) {
457
+ const matter = new Tholder({ qb64b: raw.slice(offset) });
458
+ return {
459
+ value: matter.sith,
460
+ nextOffset: offset + matter.fullSize,
461
+ };
462
+ }
463
+ /**
464
+ * Decode one native list field whose members are ordinary qb64 CESR primitives.
465
+ *
466
+ * Typical KERI fixed-body examples:
467
+ * - `k`: current key list
468
+ * - `n`: next-digest list
469
+ * - `b`: backer/witness prefix list
470
+ *
471
+ * Wire shape:
472
+ * `GenericListGroup counter` + `member1 qb64` + `member2 qb64` + ...
473
+ */
474
+ function parseQb64ListField(raw, offset, gvrsn) {
475
+ const listCounter = parseCounter(raw.slice(offset), gvrsn, "txt");
476
+ const total = listCounter.fullSize + listCounter.count * 4;
477
+ const payload = t(raw.slice(offset + listCounter.fullSize, offset + total));
478
+ const items = [];
479
+ let inner = 0;
480
+ while (inner < payload.length) {
481
+ const matter = parseMatter(b(payload.slice(inner)), "txt");
482
+ items.push(matter.qb64);
483
+ inner += matter.fullSize;
484
+ }
485
+ return {
486
+ value: items,
487
+ nextOffset: offset + total,
488
+ };
489
+ }
490
+ /**
491
+ * Decode one native trait/config list.
492
+ *
493
+ * Typical KERI fixed-body example:
494
+ * - `c`: configuration trait list such as `EO`, `NB`, etc.
495
+ *
496
+ * This looks list-shaped like `k`/`n`/`b`, but each element is a `Traitor`
497
+ * token whose semantic value is the compact trait string, not a generic qb64
498
+ * primitive string.
499
+ */
500
+ function parseTraitListField(raw, offset, gvrsn) {
501
+ const listCounter = parseCounter(raw.slice(offset), gvrsn, "txt");
502
+ const total = listCounter.fullSize + listCounter.count * 4;
503
+ const payload = t(raw.slice(offset + listCounter.fullSize, offset + total));
504
+ const items = [];
505
+ let inner = 0;
506
+ while (inner < payload.length) {
507
+ const trait = parseTraitor(b(payload.slice(inner)), "txt");
508
+ items.push(trait.trait);
509
+ inner += trait.fullSize;
510
+ }
511
+ return {
512
+ value: items,
513
+ nextOffset: offset + total,
514
+ };
515
+ }
516
+ /**
517
+ * Decode one native list field whose members may themselves be nested groups.
518
+ *
519
+ * Typical KERI fixed-body example:
520
+ * - `a`: seal/data list in inception/rotation/interact-style messages
521
+ *
522
+ * Unlike `k`/`n`/`b`, the `a` field may contain grouped or structured payloads,
523
+ * so we reuse `decodeList()` instead of assuming each member is one plain
524
+ * `Matter`.
525
+ */
526
+ function parseNestedSealOrDataListField(raw, offset, gvrsn) {
527
+ const listCounter = parseCounter(raw.slice(offset), gvrsn, "txt");
528
+ const total = listCounter.fullSize + listCounter.count * 4;
529
+ return {
530
+ value: listCounter.count === 0
531
+ ? []
532
+ : decodeList(raw.slice(offset, offset + total), gvrsn),
533
+ nextOffset: offset + total,
534
+ };
535
+ }
536
+ /**
537
+ * Decode one native field-map block into semantic JS map form.
538
+ *
539
+ * `strict=false` is mainly for ACDC schema sections, which may carry `$id`
540
+ * instead of the usual `d` saidive label.
541
+ */
542
+ function parseMapperField(raw, offset, gvrsn, strict = true) {
543
+ const mapper = new Mapper({
544
+ raw: raw.slice(offset),
545
+ version: gvrsn,
546
+ kind: "CESR",
547
+ verify: false,
548
+ strict,
549
+ });
550
+ return {
551
+ value: mapper.mad,
552
+ nextOffset: offset + mapper.raw.length,
553
+ };
554
+ }
555
+ function nativeLayoutKey(proto, version, ilk) {
556
+ return `${proto}:${version.major}.${version.minor}:${ilk ?? "<none>"}`;
557
+ }
558
+ function withKinds(proto, shape, labels, families, options = {}) {
559
+ return {
560
+ proto,
561
+ shape,
562
+ labels,
563
+ fields: Object.fromEntries(labels.map((label) => [
564
+ label,
565
+ {
566
+ kind: families[label],
567
+ ...(options[label] ?? {}),
568
+ },
569
+ ])),
570
+ };
571
+ }
572
+ const KERI_NATIVE_FAMILIES = {
573
+ d: "said",
574
+ p: "said",
575
+ x: "said",
576
+ u: "noncer",
577
+ i: "aid",
578
+ di: "aid",
579
+ ri: "aid",
580
+ s: "number",
581
+ bt: "number",
582
+ kt: "threshold",
583
+ nt: "threshold",
584
+ k: "primitive-list",
585
+ n: "primitive-list",
586
+ b: "primitive-list",
587
+ ba: "primitive-list",
588
+ br: "primitive-list",
589
+ dt: "datetime",
590
+ r: "route",
591
+ rr: "route",
592
+ rp: "route",
593
+ c: "trait-list",
594
+ a: "seal-list-or-mapper",
595
+ e: "mapper",
596
+ q: "mapper",
597
+ };
598
+ const ACDC_NATIVE_FAMILIES = {
599
+ d: "said",
600
+ p: "said",
601
+ b: "said",
602
+ u: "nonce-or-empty",
603
+ i: "aid",
604
+ ri: "said",
605
+ rd: "nonce-or-empty",
606
+ n: "number",
607
+ dt: "datetime",
608
+ td: "nonce-or-empty",
609
+ ts: "label-text",
610
+ s: "said-or-mapper",
611
+ a: "said-or-mapper",
612
+ e: "said-or-mapper",
613
+ r: "said-or-mapper",
614
+ A: "agid-or-aggor",
615
+ };
616
+ const NATIVE_LAYOUTS = new Map([
617
+ [
618
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.icp),
619
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s", "kt", "k", "nt", "n", "bt", "b", "c", "a"], KERI_NATIVE_FAMILIES),
620
+ ],
621
+ [
622
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.rot),
623
+ withKinds(Protocols.keri, "fixed", [
624
+ "d",
625
+ "i",
626
+ "s",
627
+ "p",
628
+ "kt",
629
+ "k",
630
+ "nt",
631
+ "n",
632
+ "bt",
633
+ "br",
634
+ "ba",
635
+ "a",
636
+ ], KERI_NATIVE_FAMILIES),
637
+ ],
638
+ [
639
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.ixn),
640
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s", "p", "a"], KERI_NATIVE_FAMILIES),
641
+ ],
642
+ [
643
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.dip),
644
+ withKinds(Protocols.keri, "fixed", [
645
+ "d",
646
+ "i",
647
+ "s",
648
+ "kt",
649
+ "k",
650
+ "nt",
651
+ "n",
652
+ "bt",
653
+ "b",
654
+ "c",
655
+ "a",
656
+ "di",
657
+ ], KERI_NATIVE_FAMILIES),
658
+ ],
659
+ [
660
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.drt),
661
+ withKinds(Protocols.keri, "fixed", [
662
+ "d",
663
+ "i",
664
+ "s",
665
+ "p",
666
+ "kt",
667
+ "k",
668
+ "nt",
669
+ "n",
670
+ "bt",
671
+ "br",
672
+ "ba",
673
+ "a",
674
+ ], KERI_NATIVE_FAMILIES),
675
+ ],
676
+ [
677
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.rct),
678
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s"], KERI_NATIVE_FAMILIES),
679
+ ],
680
+ [
681
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.qry),
682
+ withKinds(Protocols.keri, "fixed", ["d", "dt", "r", "rr", "q"], KERI_NATIVE_FAMILIES),
683
+ ],
684
+ [
685
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.rpy),
686
+ withKinds(Protocols.keri, "fixed", ["d", "dt", "r", "a"], KERI_NATIVE_FAMILIES),
687
+ ],
688
+ [
689
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.pro),
690
+ withKinds(Protocols.keri, "fixed", ["d", "dt", "r", "rr", "q"], KERI_NATIVE_FAMILIES),
691
+ ],
692
+ [
693
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.bar),
694
+ withKinds(Protocols.keri, "fixed", ["d", "dt", "r", "a"], KERI_NATIVE_FAMILIES),
695
+ ],
696
+ [
697
+ nativeLayoutKey(Protocols.keri, { major: 1, minor: 0 }, Ilks.exn),
698
+ withKinds(Protocols.keri, "fixed", ["d", "i", "rp", "p", "dt", "r", "q", "a", "e"], KERI_NATIVE_FAMILIES),
699
+ ],
700
+ [
701
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.icp),
702
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s", "kt", "k", "nt", "n", "bt", "b", "c", "a"], KERI_NATIVE_FAMILIES),
703
+ ],
704
+ [
705
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.rot),
706
+ withKinds(Protocols.keri, "fixed", [
707
+ "d",
708
+ "i",
709
+ "s",
710
+ "p",
711
+ "kt",
712
+ "k",
713
+ "nt",
714
+ "n",
715
+ "bt",
716
+ "br",
717
+ "ba",
718
+ "c",
719
+ "a",
720
+ ], KERI_NATIVE_FAMILIES),
721
+ ],
722
+ [
723
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.ixn),
724
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s", "p", "a"], KERI_NATIVE_FAMILIES),
725
+ ],
726
+ [
727
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.dip),
728
+ withKinds(Protocols.keri, "fixed", [
729
+ "d",
730
+ "i",
731
+ "s",
732
+ "kt",
733
+ "k",
734
+ "nt",
735
+ "n",
736
+ "bt",
737
+ "b",
738
+ "c",
739
+ "a",
740
+ "di",
741
+ ], KERI_NATIVE_FAMILIES),
742
+ ],
743
+ [
744
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.drt),
745
+ withKinds(Protocols.keri, "fixed", [
746
+ "d",
747
+ "i",
748
+ "s",
749
+ "p",
750
+ "kt",
751
+ "k",
752
+ "nt",
753
+ "n",
754
+ "bt",
755
+ "br",
756
+ "ba",
757
+ "c",
758
+ "a",
759
+ ], KERI_NATIVE_FAMILIES),
760
+ ],
761
+ [
762
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.rct),
763
+ withKinds(Protocols.keri, "fixed", ["d", "i", "s"], KERI_NATIVE_FAMILIES),
764
+ ],
765
+ [
766
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.qry),
767
+ withKinds(Protocols.keri, "fixed", ["d", "i", "dt", "r", "rr", "q"], KERI_NATIVE_FAMILIES),
768
+ ],
769
+ [
770
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.rpy),
771
+ withKinds(Protocols.keri, "fixed", ["d", "i", "dt", "r", "a"], KERI_NATIVE_FAMILIES),
772
+ ],
773
+ [
774
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.pro),
775
+ withKinds(Protocols.keri, "fixed", ["d", "i", "dt", "r", "rr", "q"], KERI_NATIVE_FAMILIES),
776
+ ],
777
+ [
778
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.bar),
779
+ withKinds(Protocols.keri, "fixed", ["d", "i", "dt", "r", "a"], KERI_NATIVE_FAMILIES),
780
+ ],
781
+ [
782
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.xip),
783
+ withKinds(Protocols.keri, "fixed", ["d", "u", "i", "ri", "dt", "r", "q", "a"], KERI_NATIVE_FAMILIES),
784
+ ],
785
+ [
786
+ nativeLayoutKey(Protocols.keri, { major: 2, minor: 0 }, Ilks.exn),
787
+ withKinds(Protocols.keri, "fixed", ["d", "i", "ri", "x", "p", "dt", "r", "q", "a"], KERI_NATIVE_FAMILIES),
788
+ ],
789
+ [
790
+ nativeLayoutKey(Protocols.acdc, { major: 1, minor: 0 }, null),
791
+ withKinds(Protocols.acdc, "map", ["v", "d", "u", "i", "ri", "s", "a", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
792
+ s: { strict: false },
793
+ }),
794
+ ],
795
+ [
796
+ nativeLayoutKey(Protocols.acdc, { major: 1, minor: 0 }, Ilks.ace),
797
+ withKinds(Protocols.acdc, "map", ["v", "t", "d", "u", "i", "ri", "s", "a", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
798
+ s: { strict: false },
799
+ }),
800
+ ],
801
+ [
802
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, null),
803
+ withKinds(Protocols.acdc, "map", ["v", "d", "u", "i", "rd", "s", "a", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
804
+ s: { strict: false },
805
+ }),
806
+ ],
807
+ [
808
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.acm),
809
+ withKinds(Protocols.acdc, "map", ["v", "t", "d", "u", "i", "rd", "s", "a", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
810
+ s: { strict: false },
811
+ }),
812
+ ],
813
+ [
814
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.ace),
815
+ withKinds(Protocols.acdc, "map", ["v", "t", "d", "u", "i", "ri", "s", "a", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
816
+ s: { strict: false },
817
+ }),
818
+ ],
819
+ [
820
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.act),
821
+ withKinds(Protocols.acdc, "fixed", ["d", "u", "i", "rd", "s", "a", "e", "r"], ACDC_NATIVE_FAMILIES, {
822
+ s: { strict: false },
823
+ }),
824
+ ],
825
+ [
826
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.acg),
827
+ withKinds(Protocols.acdc, "fixed", ["d", "u", "i", "rd", "s", "A", "e", "r"], ACDC_NATIVE_FAMILIES, {
828
+ s: { strict: false },
829
+ }),
830
+ ],
831
+ [
832
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.sch),
833
+ withKinds(Protocols.acdc, "fixed", ["d", "s"], ACDC_NATIVE_FAMILIES, {
834
+ s: { strict: false },
835
+ }),
836
+ ],
837
+ [
838
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.att),
839
+ withKinds(Protocols.acdc, "fixed", ["d", "a"], ACDC_NATIVE_FAMILIES),
840
+ ],
841
+ [
842
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.agg),
843
+ withKinds(Protocols.acdc, "fixed", ["d", "A"], ACDC_NATIVE_FAMILIES),
844
+ ],
845
+ [
846
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.edg),
847
+ withKinds(Protocols.acdc, "fixed", ["d", "e"], ACDC_NATIVE_FAMILIES),
848
+ ],
849
+ [
850
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.rul),
851
+ withKinds(Protocols.acdc, "fixed", ["d", "r"], ACDC_NATIVE_FAMILIES),
852
+ ],
853
+ [
854
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.rip),
855
+ withKinds(Protocols.acdc, "fixed", ["d", "u", "i", "n", "dt"], ACDC_NATIVE_FAMILIES),
856
+ ],
857
+ [
858
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.bup),
859
+ withKinds(Protocols.acdc, "fixed", ["d", "rd", "n", "p", "dt", "b"], ACDC_NATIVE_FAMILIES),
860
+ ],
861
+ [
862
+ nativeLayoutKey(Protocols.acdc, { major: 2, minor: 0 }, Ilks.upd),
863
+ withKinds(Protocols.acdc, "fixed", ["d", "rd", "n", "p", "dt", "td", "ts"], ACDC_NATIVE_FAMILIES),
864
+ ],
865
+ ]);
866
+ /** Resolve the protocol/version/ilk entry from the shared CESR-native support matrix. */
867
+ function getNativeLayout(proto, version, ilk) {
868
+ const layout = NATIVE_LAYOUTS.get(nativeLayoutKey(proto, version, ilk));
869
+ if (!layout) {
870
+ throw new DeserializeError(`Unsupported ${proto} native ilk=${String(ilk)} version=${version.major}.${version.minor}`);
871
+ }
872
+ return layout;
873
+ }
874
+ /**
875
+ * Decode one native field according to the field-family declared in the
876
+ * support matrix.
877
+ */
878
+ function parseNativeField(raw, offset, label, spec, gvrsn) {
879
+ if (spec.kind === "said" || spec.kind === "aid") {
880
+ return parseQb64Field(raw, offset);
881
+ }
882
+ if (spec.kind === "noncer") {
883
+ const nonce = parseNoncer(raw.slice(offset), "txt");
884
+ return {
885
+ value: nonce.qb64,
886
+ nextOffset: offset + nonce.fullSize,
887
+ };
888
+ }
889
+ if (spec.kind === "nonce-or-empty") {
890
+ const nonce = parseNoncer(raw.slice(offset), "txt");
891
+ return {
892
+ value: nonce.nonce,
893
+ nextOffset: offset + nonce.fullSize,
894
+ };
895
+ }
896
+ if (spec.kind === "number") {
897
+ return parseNumericHexField(raw, offset);
898
+ }
899
+ if (spec.kind === "threshold") {
900
+ return parseThresholdSithField(raw, offset);
901
+ }
902
+ if (spec.kind === "primitive-list") {
903
+ return parseQb64ListField(raw, offset, gvrsn);
904
+ }
905
+ if (spec.kind === "trait-list") {
906
+ return parseTraitListField(raw, offset, gvrsn);
907
+ }
908
+ if (spec.kind === "datetime") {
909
+ const date = new Dater({ qb64b: raw.slice(offset) });
910
+ return {
911
+ value: date.iso8601,
912
+ nextOffset: offset + date.fullSize,
913
+ };
914
+ }
915
+ if (spec.kind === "route") {
916
+ // Route fields use Pather semantics, not generic labels. That means a
917
+ // native token like `4AAEcredential-issue` must round-trip back to the
918
+ // slash-delimited semantic route `credential/issue`.
919
+ const pather = parsePather(raw.slice(offset), "txt");
920
+ return {
921
+ value: pather.path,
922
+ nextOffset: offset + pather.fullSize,
923
+ };
924
+ }
925
+ if (spec.kind === "mapper") {
926
+ return parseMapperField(raw, offset, gvrsn, spec.strict ?? true);
927
+ }
928
+ if (spec.kind === "seal-list-or-mapper") {
929
+ const counter = parseCounter(raw.slice(offset), gvrsn, "txt");
930
+ if (counter.code === CtrDexV2.GenericMapGroup
931
+ || counter.code === CtrDexV2.BigGenericMapGroup) {
932
+ return parseMapperField(raw, offset, gvrsn, spec.strict ?? true);
933
+ }
934
+ if (counter.code === CtrDexV2.GenericListGroup
935
+ || counter.code === CtrDexV2.BigGenericListGroup) {
936
+ return parseNestedSealOrDataListField(raw, offset, gvrsn);
937
+ }
938
+ throw new DeserializeError(`Expected native list/map group for field ${label}, got ${counter.code}`);
939
+ }
940
+ if (spec.kind === "said-or-mapper") {
941
+ if (raw[offset] === "-".charCodeAt(0)) {
942
+ return parseMapperField(raw, offset, gvrsn, spec.strict ?? true);
943
+ }
944
+ return parseQb64Field(raw, offset);
945
+ }
946
+ if (spec.kind === "agid-or-aggor") {
947
+ if (raw[offset] === "-".charCodeAt(0)) {
948
+ const aggor = new Aggor({
949
+ raw: raw.slice(offset),
950
+ version: gvrsn,
951
+ kind: "CESR",
952
+ verify: false,
953
+ });
954
+ return {
955
+ value: aggor.ael,
956
+ nextOffset: offset + aggor.serialized.length,
957
+ };
958
+ }
959
+ return parseQb64Field(raw, offset);
960
+ }
961
+ if (spec.kind === "label-text") {
962
+ const text = parseLabeler(raw.slice(offset), "txt");
963
+ return {
964
+ value: text.text,
965
+ nextOffset: offset + text.fullSize,
966
+ };
967
+ }
968
+ throw new DeserializeError(`Unsupported native field label=${label}`);
969
+ }
970
+ /**
971
+ * Encode one semantic SAD field back into the native field-family form
972
+ * declared in the support matrix.
973
+ */
974
+ function encodeNativeFieldValue(value, label, spec, gvrsn) {
975
+ if (spec.kind === "said" || spec.kind === "aid" || spec.kind === "noncer") {
976
+ if (typeof value !== "string" || value.length === 0) {
977
+ throw new SerializeError(`Expected non-empty qb64 value for native field ${label}`);
978
+ }
979
+ return value;
980
+ }
981
+ if (spec.kind === "nonce-or-empty") {
982
+ if (typeof value !== "string") {
983
+ throw new SerializeError(`Expected string nonce value for native field ${label}`);
984
+ }
985
+ return value.length === 0 ? LabelDex.Empty : value;
986
+ }
987
+ if (spec.kind === "number") {
988
+ if (typeof value !== "string"
989
+ && typeof value !== "number"
990
+ && typeof value !== "bigint") {
991
+ throw new SerializeError(`Expected numeric value for native field ${label}`);
992
+ }
993
+ return encodeNumber(value);
994
+ }
995
+ if (spec.kind === "threshold") {
996
+ if (typeof value !== "string"
997
+ && typeof value !== "number"
998
+ && typeof value !== "bigint"
999
+ && !Array.isArray(value)) {
1000
+ throw new SerializeError(`Expected threshold value for native field ${label}`);
1001
+ }
1002
+ return encodeThreshold(value);
1003
+ }
1004
+ if (spec.kind === "primitive-list") {
1005
+ if (!Array.isArray(value)) {
1006
+ throw new SerializeError(`Expected primitive list for native field ${label}`);
1007
+ }
1008
+ return encodeList(value.map((entry) => {
1009
+ if (typeof entry !== "string" || entry.length === 0) {
1010
+ throw new SerializeError(`Expected qb64 list member for native field ${label}`);
1011
+ }
1012
+ return entry;
1013
+ }), gvrsn);
1014
+ }
1015
+ if (spec.kind === "trait-list") {
1016
+ if (!Array.isArray(value)) {
1017
+ throw new SerializeError(`Expected trait list for native field ${label}`);
1018
+ }
1019
+ return encodeList(value.map((entry) => encodeTag(String(entry))), gvrsn);
1020
+ }
1021
+ if (spec.kind === "datetime") {
1022
+ if (typeof value !== "string") {
1023
+ throw new SerializeError(`Expected ISO-8601 string for native field ${label}`);
1024
+ }
1025
+ return encodeDate(value);
1026
+ }
1027
+ if (spec.kind === "route") {
1028
+ if (typeof value !== "string") {
1029
+ throw new SerializeError(`Expected route/path string for native field ${label}`);
1030
+ }
1031
+ return encodePath(value);
1032
+ }
1033
+ if (spec.kind === "mapper") {
1034
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1035
+ return Mapper.fromSad(value, {
1036
+ strict: spec.strict ?? true,
1037
+ kind: "CESR",
1038
+ verify: false,
1039
+ saidive: false,
1040
+ }).qb64;
1041
+ }
1042
+ throw new SerializeError(`Expected map value for native field ${label}`);
1043
+ }
1044
+ if (spec.kind === "seal-list-or-mapper") {
1045
+ if (Array.isArray(value)) {
1046
+ return encodeList(value.map((entry) => encodeValue(entry, gvrsn)), gvrsn);
1047
+ }
1048
+ if (value && typeof value === "object") {
1049
+ return Mapper.fromSad(value, {
1050
+ strict: spec.strict ?? true,
1051
+ kind: "CESR",
1052
+ verify: false,
1053
+ saidive: false,
1054
+ }).qb64;
1055
+ }
1056
+ throw new SerializeError(`Expected list or map for native field ${label}`);
1057
+ }
1058
+ if (spec.kind === "said-or-mapper") {
1059
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1060
+ return Mapper.fromSad(value, {
1061
+ strict: spec.strict ?? true,
1062
+ kind: "CESR",
1063
+ verify: false,
1064
+ saidive: false,
1065
+ }).qb64;
1066
+ }
1067
+ if (typeof value !== "string" || value.length === 0) {
1068
+ throw new SerializeError(`Expected qb64 or map for native field ${label}`);
1069
+ }
1070
+ return value;
1071
+ }
1072
+ if (spec.kind === "agid-or-aggor") {
1073
+ if (Array.isArray(value)) {
1074
+ return new Aggor({
1075
+ ael: value,
1076
+ kind: "CESR",
1077
+ makify: false,
1078
+ verify: false,
1079
+ }).qb64g;
1080
+ }
1081
+ if (typeof value !== "string" || value.length === 0) {
1082
+ throw new SerializeError(`Expected agid string or aggregate list for native field ${label}`);
1083
+ }
1084
+ return value;
1085
+ }
1086
+ if (spec.kind === "label-text") {
1087
+ if (typeof value !== "string") {
1088
+ throw new SerializeError(`Expected text string for native field ${label}`);
1089
+ }
1090
+ return encodeLabel(value);
1091
+ }
1092
+ throw new SerializeError(`Unsupported native field kind for ${label}`);
1093
+ }
1094
+ /**
1095
+ * Decode one CESR-native body into a semantic SAD plus core serder projections.
1096
+ *
1097
+ * Current intent is narrow but real: hydrate actual native message bodies into
1098
+ * something `Serder` can verify and expose through its normal accessor surface.
1099
+ * Broader KERI/ACDC ilk parity should continue extending this function rather
1100
+ * than introducing sidecar native decoders elsewhere in the stack.
1101
+ *
1102
+ * Inputs:
1103
+ * - `raw`: full native body-group bytes, either qb64 text or qb2 binary
1104
+ * - `smellage`: protocol/version metadata already derived by `Serdery` or a
1105
+ * parser-side native pre-read
1106
+ *
1107
+ * Output:
1108
+ * - `ked`: semantic SAD reconstructed from compact CESR fields
1109
+ * - `ilk`: top-level message type when present
1110
+ * - `said`: top-level `d` SAID when present
1111
+ *
1112
+ * High-level flow:
1113
+ * 1. canonicalize qb2 to qb64 text if needed
1114
+ * 2. parse the body-group counter (`-F...` or `-G...`)
1115
+ * 3. consume version metadata (`Verser`) and then protocol-specific fields
1116
+ * 4. rebuild normal SAD strings/lists/maps so `Serder` verification can run on
1117
+ * the same shape used by JSON/CBOR/MGPK bodies
1118
+ *
1119
+ * Maintainer rule:
1120
+ * top-level KERI native messages are fixed-field bodies. A top-level
1121
+ * `MapBodyGroup` may still be meaningful for lower-level CESR-native mapping
1122
+ * surfaces or ACDC, but it is not a valid KERI native message body and should
1123
+ * be rejected here.
1124
+ *
1125
+ * Example:
1126
+ *
1127
+ * ```ts
1128
+ * const { ked } = parseCesrNativeKed(
1129
+ * new TextEncoder().encode("-FA50OKERICAACAXicp..."),
1130
+ * { proto: "KERI", pvrsn: { major: 2, minor: 0 }, gvrsn: { major: 2, minor: 0 }, kind: "CESR", size: 188 },
1131
+ * );
1132
+ * // ked.t === "icp"
1133
+ * // ked.d === "EFaYE2LTv8dItUgQzIHKRA9FaHDrHtIHNs-m5DJKWXRN"
1134
+ * ```
1135
+ */
1136
+ export function parseCesrNativeKed(raw, smellage) {
1137
+ const gvrsn = smellage.gvrsn ?? smellage.pvrsn;
1138
+ const textRaw = canonicalizeCesrNativeRaw(raw, gvrsn);
1139
+ const counter = parseCounter(textRaw, gvrsn, "txt");
1140
+ let offset = counter.fullSize;
1141
+ const fixed = counter.code === CtrDexV2.FixBodyGroup
1142
+ || counter.code === CtrDexV2.BigFixBodyGroup;
1143
+ if (!fixed) {
1144
+ const versionLabel = parseLabeler(textRaw.slice(offset), "txt");
1145
+ if (versionLabel.label !== "v") {
1146
+ throw new DeserializeError(`Expected native version label 'v', got ${versionLabel.label}`);
1147
+ }
1148
+ offset += versionLabel.fullSize;
1149
+ }
1150
+ const verser = parseVerser(textRaw.slice(offset), "txt");
1151
+ offset += verser.fullSize;
1152
+ const ked = {
1153
+ v: versify({
1154
+ proto: verser.proto,
1155
+ pvrsn: verser.pvrsn,
1156
+ gvrsn: verser.gvrsn,
1157
+ kind: Kinds.cesr,
1158
+ size: textRaw.length,
1159
+ }),
1160
+ };
1161
+ if (smellage.proto === Protocols.keri && !fixed) {
1162
+ throw new DeserializeError("KERI CESR-native top-level messages must use FixBodyGroup, not MapBodyGroup");
1163
+ }
1164
+ let ilk = fixed ? parseIlker(textRaw.slice(offset), "txt").ilk : null;
1165
+ if (fixed && ilk !== null) {
1166
+ const ilker = parseIlker(textRaw.slice(offset), "txt");
1167
+ offset += ilker.fullSize;
1168
+ ked.t = ilker.ilk;
1169
+ ilk = ilker.ilk;
1170
+ }
1171
+ let layout = getNativeLayout(smellage.proto, smellage.pvrsn, ilk);
1172
+ if ((fixed && layout.shape !== "fixed") || (!fixed && layout.shape !== "map")) {
1173
+ throw new DeserializeError(`${smellage.proto} CESR-native ilk=${String(ilk)} requires ${layout.shape} body shape`);
1174
+ }
1175
+ if (fixed) {
1176
+ for (const label of layout.labels) {
1177
+ const parsed = parseNativeField(textRaw, offset, label, layout.fields[label], gvrsn);
1178
+ ked[label] = parsed.value;
1179
+ offset = parsed.nextOffset;
1180
+ }
1181
+ return {
1182
+ ked,
1183
+ ilk,
1184
+ said: typeof ked.d === "string" ? ked.d : null,
1185
+ };
1186
+ }
1187
+ while (offset < textRaw.length) {
1188
+ const labeler = parseLabeler(textRaw.slice(offset), "txt");
1189
+ const label = labeler.label;
1190
+ offset += labeler.fullSize;
1191
+ if (!label) {
1192
+ break;
1193
+ }
1194
+ if (label === "t") {
1195
+ const ilker = parseIlker(textRaw.slice(offset), "txt");
1196
+ ked.t = ilker.ilk;
1197
+ ilk = ilker.ilk;
1198
+ layout = getNativeLayout(smellage.proto, smellage.pvrsn, ilk);
1199
+ offset += ilker.fullSize;
1200
+ continue;
1201
+ }
1202
+ const spec = layout.fields[label];
1203
+ if (!spec) {
1204
+ throw new DeserializeError(`Unsupported ${smellage.proto} native label=${label} for ilk=${String(ilk)}`);
1205
+ }
1206
+ const parsed = parseNativeField(textRaw, offset, label, spec, gvrsn);
1207
+ ked[label] = parsed.value;
1208
+ offset = parsed.nextOffset;
1209
+ }
1210
+ return {
1211
+ ked,
1212
+ ilk,
1213
+ said: typeof ked.d === "string" ? ked.d : null,
1214
+ };
1215
+ }
1216
+ /**
1217
+ * Serialize one semantic SAD into CESR-native qb64 text-domain bytes.
1218
+ *
1219
+ * Callers that start from qb2 should still route through this text-domain emit
1220
+ * path; qb2 is derived from qb64 later, matching the canonicalization path used
1221
+ * during native inhale.
1222
+ *
1223
+ * Inputs:
1224
+ * - one semantic SAD in the same shape used by non-native serders
1225
+ *
1226
+ * Output:
1227
+ * - qb64 text-domain bytes for a CESR-native body group
1228
+ *
1229
+ * High-level flow:
1230
+ * 1. derive protocol/version context from the SAD's `v`
1231
+ * 2. emit compact CESR primitives for each field (`Verser`, `Ilker`, `Matter`,
1232
+ * grouped lists/maps, etc.)
1233
+ * 3. wrap the payload in `FixBodyGroup` or `MapBodyGroup`
1234
+ *
1235
+ * ASCII shape of the result for a KERI fixed-body message:
1236
+ *
1237
+ * ```text
1238
+ * -F... <verser> <ilk> <d> <i> <s> <kt> <k-list> <nt> <n-list> ...
1239
+ * ```
1240
+ *
1241
+ * Example:
1242
+ *
1243
+ * ```ts
1244
+ * const raw = dumpCesrNativeSad({
1245
+ * v: "KERICAACAACESRAAC8.",
1246
+ * t: "icp",
1247
+ * d: "EFaYE2LTv8dItUgQzIHKRA9FaHDrHtIHNs-m5DJKWXRN",
1248
+ * i: "DNG2arBDtHK_JyHRAq-emRdC6UM-yIpCAeJIWDiXp4Hx",
1249
+ * s: "0",
1250
+ * kt: "1",
1251
+ * k: ["DNG2arBDtHK_JyHRAq-emRdC6UM-yIpCAeJIWDiXp4Hx"],
1252
+ * nt: "1",
1253
+ * n: ["EFXIx7URwmw7AVQTBcMxPXfOOJ2YYA1SJAam69DXV8D2"],
1254
+ * bt: "0",
1255
+ * b: [],
1256
+ * c: [],
1257
+ * a: [],
1258
+ * });
1259
+ * ```
1260
+ */
1261
+ export function dumpCesrNativeSad(sad) {
1262
+ if (typeof sad.v !== "string") {
1263
+ throw new SerializeError("Missing version string for CESR native dump");
1264
+ }
1265
+ const pvrsn = sad.v[4] === "1"
1266
+ ? { major: 1, minor: Number.parseInt(sad.v[5], 16) }
1267
+ : { major: 2, minor: 0 };
1268
+ const gvrsn = sad.v.includes("CESR") && sad.v.length >= 19
1269
+ ? { major: 2, minor: 0 }
1270
+ : null;
1271
+ const smellage = {
1272
+ proto: sad.v.slice(0, 4),
1273
+ pvrsn,
1274
+ gvrsn,
1275
+ };
1276
+ const ilk = typeof sad.t === "string" ? sad.t : null;
1277
+ const layout = getNativeLayout(smellage.proto, smellage.pvrsn, ilk);
1278
+ const version = smellage.gvrsn ?? Vrsn_2_0;
1279
+ const body = layout.shape === "map"
1280
+ ? (() => {
1281
+ let frame = "";
1282
+ for (const label of layout.labels) {
1283
+ if (!(label in sad)) {
1284
+ continue;
1285
+ }
1286
+ if (label === "v") {
1287
+ frame += encodeLabel("v");
1288
+ frame += encodeVerser(smellage.proto, smellage.pvrsn, smellage.gvrsn);
1289
+ continue;
1290
+ }
1291
+ if (label === "t") {
1292
+ frame += encodeLabel("t");
1293
+ frame += encodeTag(String(sad.t));
1294
+ continue;
1295
+ }
1296
+ const spec = layout.fields[label];
1297
+ if (!spec) {
1298
+ throw new SerializeError(`Unsupported native field ${label} for ilk=${String(ilk)}`);
1299
+ }
1300
+ frame += encodeLabel(label);
1301
+ frame += encodeNativeFieldValue(sad[label], label, spec, version);
1302
+ }
1303
+ const code = frame.length / 4 < 64 ** 2
1304
+ ? CtrDexV2.MapBodyGroup
1305
+ : CtrDexV2.BigMapBodyGroup;
1306
+ return `${new Counter({ code, count: frame.length / 4, version }).qb64}${frame}`;
1307
+ })()
1308
+ : (() => {
1309
+ if (!ilk) {
1310
+ throw new SerializeError(`Missing ilk for fixed-body native ${smellage.proto} message`);
1311
+ }
1312
+ let frame = `${encodeVerser(smellage.proto, smellage.pvrsn, smellage.gvrsn)}${encodeTag(ilk)}`;
1313
+ for (const label of layout.labels) {
1314
+ const spec = layout.fields[label];
1315
+ if (!spec) {
1316
+ throw new SerializeError(`Unsupported native field ${label} for ilk=${String(ilk)}`);
1317
+ }
1318
+ frame += encodeNativeFieldValue(sad[label], label, spec, version);
1319
+ }
1320
+ const code = frame.length / 4 < 64 ** 2
1321
+ ? CtrDexV2.FixBodyGroup
1322
+ : CtrDexV2.BigFixBodyGroup;
1323
+ return `${new Counter({ code, count: frame.length / 4, version }).qb64}${frame}`;
1324
+ })();
1325
+ return b(body);
1326
+ }