@sparkdreamnft/sparkdreamjs 0.0.46 → 0.0.48

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 (92) hide show
  1. package/amino-schema.d.ts +5741 -0
  2. package/amino-schema.js +8 -0
  3. package/chain-amino.d.ts +61 -0
  4. package/chain-amino.js +670 -0
  5. package/esm/amino-schema.js +5 -0
  6. package/esm/chain-amino.js +665 -0
  7. package/esm/nested-amino.js +7 -1
  8. package/esm/sparkdream/artifact/v1/query.js +125 -0
  9. package/esm/sparkdream/artifact/v1/query.lcd.js +7 -0
  10. package/esm/sparkdream/artifact/v1/query.rpc.Query.js +12 -1
  11. package/esm/sparkdream/artifact/v1/tx.amino.js +12 -473
  12. package/esm/sparkdream/artifact/v1/tx.js +13 -1
  13. package/esm/sparkdream/blog/v1/tx.amino.js +15 -135
  14. package/esm/sparkdream/collect/v1/tx.amino.js +15 -254
  15. package/esm/sparkdream/commons/v1/tx.amino.js +12 -258
  16. package/esm/sparkdream/ecosystem/v1/tx.amino.js +15 -26
  17. package/esm/sparkdream/federation/v1/tx.amino.js +12 -174
  18. package/esm/sparkdream/forum/v1/tx.amino.js +15 -231
  19. package/esm/sparkdream/futarchy/v1/tx.amino.js +16 -38
  20. package/esm/sparkdream/guardian/v1/tx.amino.js +12 -33
  21. package/esm/sparkdream/name/v1/tx.amino.js +16 -63
  22. package/esm/sparkdream/rep/v1/query.js +304 -1
  23. package/esm/sparkdream/rep/v1/query.lcd.js +19 -0
  24. package/esm/sparkdream/rep/v1/query.rpc.Query.js +22 -1
  25. package/esm/sparkdream/rep/v1/tx.amino.js +12 -484
  26. package/esm/sparkdream/reveal/v1/tx.amino.js +15 -73
  27. package/esm/sparkdream/season/v1/tx.amino.js +12 -276
  28. package/esm/sparkdream/service/v1/tx.amino.js +16 -78
  29. package/esm/sparkdream/session/v1/tx.amino.js +16 -271
  30. package/esm/sparkdream/shield/v1/tx.amino.js +15 -80
  31. package/esm/sparkdream/sparkdream/v1/tx.amino.js +16 -8
  32. package/esm/sparkdream/split/v1/tx.amino.js +16 -8
  33. package/esm/sparkdream/vault/v1/tx.amino.js +12 -105
  34. package/nested-amino.d.ts +5 -1
  35. package/nested-amino.js +8 -1
  36. package/package.json +1 -1
  37. package/sparkdream/artifact/v1/query.d.ts +86 -0
  38. package/sparkdream/artifact/v1/query.js +126 -1
  39. package/sparkdream/artifact/v1/query.lcd.d.ts +2 -1
  40. package/sparkdream/artifact/v1/query.lcd.js +7 -0
  41. package/sparkdream/artifact/v1/query.rpc.Query.d.ts +9 -1
  42. package/sparkdream/artifact/v1/query.rpc.Query.js +11 -0
  43. package/sparkdream/artifact/v1/tx.amino.d.ts +1 -353
  44. package/sparkdream/artifact/v1/tx.amino.js +47 -475
  45. package/sparkdream/artifact/v1/tx.d.ts +14 -0
  46. package/sparkdream/artifact/v1/tx.js +13 -1
  47. package/sparkdream/blog/v1/tx.amino.d.ts +1 -103
  48. package/sparkdream/blog/v1/tx.amino.js +50 -137
  49. package/sparkdream/bundle.d.ts +97 -2047
  50. package/sparkdream/client.d.ts +1 -2009
  51. package/sparkdream/collect/v1/tx.amino.d.ts +1 -153
  52. package/sparkdream/collect/v1/tx.amino.js +50 -256
  53. package/sparkdream/commons/v1/tx.amino.d.ts +1 -123
  54. package/sparkdream/commons/v1/tx.amino.js +49 -262
  55. package/sparkdream/ecosystem/v1/tx.amino.d.ts +1 -13
  56. package/sparkdream/ecosystem/v1/tx.amino.js +50 -28
  57. package/sparkdream/federation/v1/tx.amino.d.ts +1 -128
  58. package/sparkdream/federation/v1/tx.amino.js +47 -176
  59. package/sparkdream/forum/v1/tx.amino.d.ts +1 -203
  60. package/sparkdream/forum/v1/tx.amino.js +50 -233
  61. package/sparkdream/futarchy/v1/tx.amino.d.ts +1 -38
  62. package/sparkdream/futarchy/v1/tx.amino.js +49 -38
  63. package/sparkdream/guardian/v1/tx.amino.d.ts +1 -7
  64. package/sparkdream/guardian/v1/tx.amino.js +49 -37
  65. package/sparkdream/name/v1/tx.amino.d.ts +1 -63
  66. package/sparkdream/name/v1/tx.amino.js +49 -63
  67. package/sparkdream/rep/v1/query.d.ts +187 -1
  68. package/sparkdream/rep/v1/query.js +304 -1
  69. package/sparkdream/rep/v1/query.lcd.d.ts +3 -1
  70. package/sparkdream/rep/v1/query.lcd.js +19 -0
  71. package/sparkdream/rep/v1/query.rpc.Query.d.ts +16 -1
  72. package/sparkdream/rep/v1/query.rpc.Query.js +21 -0
  73. package/sparkdream/rep/v1/tx.amino.d.ts +1 -353
  74. package/sparkdream/rep/v1/tx.amino.js +47 -486
  75. package/sparkdream/reveal/v1/tx.amino.d.ts +1 -53
  76. package/sparkdream/reveal/v1/tx.amino.js +50 -75
  77. package/sparkdream/rpc.query.d.ts +3 -0
  78. package/sparkdream/season/v1/tx.amino.d.ts +1 -218
  79. package/sparkdream/season/v1/tx.amino.js +47 -278
  80. package/sparkdream/service/v1/tx.amino.d.ts +1 -78
  81. package/sparkdream/service/v1/tx.amino.js +49 -78
  82. package/sparkdream/session/v1/tx.amino.d.ts +1 -93
  83. package/sparkdream/session/v1/tx.amino.js +48 -270
  84. package/sparkdream/shield/v1/tx.amino.d.ts +1 -28
  85. package/sparkdream/shield/v1/tx.amino.js +50 -82
  86. package/sparkdream/sparkdream/v1/tx.amino.d.ts +1 -8
  87. package/sparkdream/sparkdream/v1/tx.amino.js +49 -8
  88. package/sparkdream/split/v1/tx.amino.d.ts +1 -8
  89. package/sparkdream/split/v1/tx.amino.js +49 -8
  90. package/sparkdream/vault/v1/tx.amino.d.ts +1 -43
  91. package/sparkdream/vault/v1/tx.amino.js +49 -109
  92. package/varint.d.ts +1 -1
@@ -0,0 +1,665 @@
1
+ /**
2
+ * Amino-JSON converters (the sign mode Keplr+Ledger use) for every sparkdream
3
+ * Msg, matching the chain's cosmossdk.io/x/tx@v0.14.0 signing/aminojson byte
4
+ * for byte.
5
+ *
6
+ * Instead of one hand-written converter per message (which drifted from the
7
+ * protos on every sync: missing messages, stale field sets, `[]` for empty
8
+ * lists, empty bytes as "", human-readable Dec strings, lost oneof wrappers),
9
+ * every module's AminoConverter map is built here from one schema:
10
+ *
11
+ * - toAmino encodes the message with its Telescope codec, decodes the
12
+ * protobuf bytes and renders them with aminojson's rules
13
+ * (json_marshal.go, encoder.go, any.go, time.go), as the chain does.
14
+ * - fromAmino is the exact inverse: amino JSON to protobuf bytes, decoded
15
+ * with the codec.
16
+ *
17
+ * The schema (amino-schema.ts) is exported by the chain repo
18
+ * (`go run ./cmd/aminogolden schema`): field names, kinds and the options
19
+ * aminojson acts on (dont_omitempty, cosmos_proto.scalar, amino.encoding,
20
+ * oneof names, gogoproto.nullable). __tests__/amino-golden.test.ts checks
21
+ * every Msg against the chain's own encoder.
22
+ *
23
+ * An Any whose inner type the schema does not describe (a cosmos-sdk message
24
+ * inside a proposal) is converted through the registry and AminoTypes given
25
+ * to configureNestedAminoConverter, as before.
26
+ */
27
+ import { getNestedAminoConfig } from "./nested-amino";
28
+ import { aminoSchema } from "./amino-schema";
29
+ const schema = aminoSchema;
30
+ const BUILTIN = new Set(["google.protobuf.Timestamp", "google.protobuf.Duration", "google.protobuf.Any"]);
31
+ const byAminoName = new Map();
32
+ for (const [name, md] of Object.entries(schema.messages))
33
+ if (md.a)
34
+ byAminoName.set(md.a, name);
35
+ function readVarint(buf, pos) {
36
+ let result = BigInt(0);
37
+ let shift = BigInt(0);
38
+ for (;;) {
39
+ if (pos.i >= buf.length)
40
+ throw new Error("truncated varint");
41
+ const b = buf[pos.i++];
42
+ result |= BigInt(b & 0x7f) << shift;
43
+ if ((b & 0x80) === 0)
44
+ return result;
45
+ shift += BigInt(7);
46
+ if (shift > BigInt(63))
47
+ throw new Error("varint overflow");
48
+ }
49
+ }
50
+ function readFixed(buf, pos, size) {
51
+ if (pos.i + size > buf.length)
52
+ throw new Error("truncated fixed");
53
+ let v = BigInt(0);
54
+ for (let j = size - 1; j >= 0; j--)
55
+ v = (v << BigInt(8)) | BigInt(buf[pos.i + j]);
56
+ pos.i += size;
57
+ return v;
58
+ }
59
+ function parseFields(buf) {
60
+ const out = new Map();
61
+ const pos = { i: 0 };
62
+ while (pos.i < buf.length) {
63
+ const tag = Number(readVarint(buf, pos));
64
+ const no = tag >>> 3;
65
+ const wire = tag & 7;
66
+ let v;
67
+ switch (wire) {
68
+ case 0:
69
+ v = { wire, num: readVarint(buf, pos) };
70
+ break;
71
+ case 1:
72
+ v = { wire, num: readFixed(buf, pos, 8) };
73
+ break;
74
+ case 5:
75
+ v = { wire, num: readFixed(buf, pos, 4) };
76
+ break;
77
+ case 2: {
78
+ const len = Number(readVarint(buf, pos));
79
+ if (pos.i + len > buf.length)
80
+ throw new Error("truncated bytes");
81
+ v = { wire, bytes: buf.subarray(pos.i, pos.i + len) };
82
+ pos.i += len;
83
+ break;
84
+ }
85
+ default:
86
+ throw new Error(`unsupported wire type ${wire}`);
87
+ }
88
+ const list = out.get(no);
89
+ if (list)
90
+ list.push(v);
91
+ else
92
+ out.set(no, [v]);
93
+ }
94
+ return out;
95
+ }
96
+ const VARINT_KINDS = new Set(["int32", "int64", "uint32", "uint64", "sint32", "sint64", "bool", "enum"]);
97
+ const FIXED32_KINDS = new Set(["fixed32", "sfixed32", "float"]);
98
+ const FIXED64_KINDS = new Set(["fixed64", "sfixed64", "double"]);
99
+ const NUMERIC_KINDS = new Set([...VARINT_KINDS, ...FIXED32_KINDS, ...FIXED64_KINDS]);
100
+ /** Scalar elements of a field, unpacking packed encodings. */
101
+ function scalarElements(f, values) {
102
+ const out = [];
103
+ for (const v of values) {
104
+ if (v.wire === 2 && NUMERIC_KINDS.has(f.k)) {
105
+ const pos = { i: 0 };
106
+ const b = v.bytes;
107
+ while (pos.i < b.length) {
108
+ if (VARINT_KINDS.has(f.k))
109
+ out.push(readVarint(b, pos));
110
+ else
111
+ out.push(readFixed(b, pos, FIXED32_KINDS.has(f.k) ? 4 : 8));
112
+ }
113
+ }
114
+ else {
115
+ out.push(v.num);
116
+ }
117
+ }
118
+ return out;
119
+ }
120
+ function concatBytes(parts) {
121
+ if (parts.length === 1)
122
+ return parts[0];
123
+ const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));
124
+ let o = 0;
125
+ for (const p of parts) {
126
+ out.set(p, o);
127
+ o += p.length;
128
+ }
129
+ return out;
130
+ }
131
+ // --------------------------------------------------------- wire encoding
132
+ class Writer {
133
+ parts = [];
134
+ varint(v) {
135
+ let n = BigInt.asUintN(64, v);
136
+ const bytes = [];
137
+ do {
138
+ let b = Number(n & BigInt(0x7f));
139
+ n >>= BigInt(7);
140
+ if (n > BigInt(0))
141
+ b |= 0x80;
142
+ bytes.push(b);
143
+ } while (n > BigInt(0));
144
+ this.parts.push(Uint8Array.from(bytes));
145
+ return this;
146
+ }
147
+ fixed(v, size) {
148
+ const out = new Uint8Array(size);
149
+ let n = BigInt.asUintN(size * 8, v);
150
+ for (let i = 0; i < size; i++) {
151
+ out[i] = Number(n & BigInt(0xff));
152
+ n >>= BigInt(8);
153
+ }
154
+ this.parts.push(out);
155
+ return this;
156
+ }
157
+ tag(no, wire) {
158
+ return this.varint(BigInt((no << 3) | wire));
159
+ }
160
+ bytes(no, b) {
161
+ this.tag(no, 2).varint(BigInt(b.length));
162
+ this.parts.push(b);
163
+ return this;
164
+ }
165
+ finish() {
166
+ return concatBytes(this.parts.length ? this.parts : [new Uint8Array()]);
167
+ }
168
+ }
169
+ // --------------------------------------------------------- value helpers
170
+ const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
171
+ const utf8Encoder = new TextEncoder();
172
+ function base64(bytes) {
173
+ let s = "";
174
+ for (let i = 0; i < bytes.length; i++)
175
+ s += String.fromCharCode(bytes[i]);
176
+ return btoa(s);
177
+ }
178
+ function fromBase64(s) {
179
+ const bin = atob(s);
180
+ const out = new Uint8Array(bin.length);
181
+ for (let i = 0; i < bin.length; i++)
182
+ out[i] = bin.charCodeAt(i);
183
+ return out;
184
+ }
185
+ function zigzagDecode(u, bits) {
186
+ const v = BigInt.asUintN(bits, u);
187
+ return BigInt.asIntN(bits, (v >> BigInt(1)) ^ -(v & BigInt(1)));
188
+ }
189
+ function zigzagEncode(v, bits) {
190
+ const n = BigInt.asIntN(bits, v);
191
+ return BigInt.asUintN(bits, (n << BigInt(1)) ^ (n >> BigInt(bits - 1)));
192
+ }
193
+ function scalarJson(kind, n, bytes) {
194
+ const v = n ?? BigInt(0);
195
+ switch (kind) {
196
+ case "string":
197
+ return utf8Decoder.decode(bytes ?? new Uint8Array());
198
+ case "bytes":
199
+ // encoding/json marshals a nil []byte as null, a non-nil one as base64.
200
+ return bytes && bytes.length > 0 ? base64(bytes) : null;
201
+ case "bool":
202
+ return v !== BigInt(0);
203
+ case "int32":
204
+ case "enum":
205
+ case "sfixed32":
206
+ return Number(BigInt.asIntN(32, v));
207
+ case "uint32":
208
+ case "fixed32":
209
+ return Number(BigInt.asUintN(32, v));
210
+ case "sint32":
211
+ return Number(zigzagDecode(v, 32));
212
+ // 64-bit integers are quoted.
213
+ case "int64":
214
+ case "sfixed64":
215
+ return BigInt.asIntN(64, v).toString();
216
+ case "uint64":
217
+ case "fixed64":
218
+ return BigInt.asUintN(64, v).toString();
219
+ case "sint64":
220
+ return zigzagDecode(v, 64).toString();
221
+ }
222
+ // aminojson has no case for floats (marshal returns "unknown type").
223
+ throw new Error(`amino JSON cannot encode a ${kind} field`);
224
+ }
225
+ function isZeroScalar(kind, n, bytes) {
226
+ if (kind === "string" || kind === "bytes")
227
+ return !bytes || bytes.length === 0;
228
+ return (n ?? BigInt(0)) === BigInt(0);
229
+ }
230
+ /** math.LegacyDec.String() of an 18-decimal integer representation. */
231
+ function legacyDecString(atomics) {
232
+ if (!/^-?\d+$/.test(atomics))
233
+ throw new Error(`invalid LegacyDec ${JSON.stringify(atomics)}`);
234
+ const neg = atomics.startsWith("-");
235
+ let digits = BigInt(neg ? atomics.slice(1) : atomics).toString();
236
+ if (digits === "0")
237
+ return "0.000000000000000000";
238
+ digits = digits.padStart(19, "0");
239
+ return `${neg ? "-" : ""}${digits.slice(0, -18)}.${digits.slice(-18)}`;
240
+ }
241
+ /** Inverse of legacyDecString. */
242
+ function legacyDecAtomics(dec) {
243
+ const m = /^(-?)(\d+)(?:\.(\d{1,18}))?$/.exec(dec);
244
+ if (!m)
245
+ throw new Error(`invalid Dec ${JSON.stringify(dec)}`);
246
+ const atomics = BigInt(m[2] + (m[3] ?? "").padEnd(18, "0"));
247
+ return (m[1] && atomics !== BigInt(0) ? "-" : "") + atomics.toString();
248
+ }
249
+ function sortedJson(v) {
250
+ if (Array.isArray(v))
251
+ return v.map(sortedJson);
252
+ if (v && typeof v === "object") {
253
+ const o = v;
254
+ return Object.fromEntries(Object.keys(o).sort().map((k) => [k, sortedJson(o[k])]));
255
+ }
256
+ return v;
257
+ }
258
+ function rfc3339(seconds, nanos) {
259
+ if (nanos < 0)
260
+ throw new Error("nanos must be non-negative on timestamp");
261
+ const date = new Date(Number(seconds) * 1000);
262
+ if (Number.isNaN(date.getTime()))
263
+ throw new Error("timestamp out of range");
264
+ const base = date.toISOString().slice(0, 19);
265
+ if (nanos === 0)
266
+ return `${base}Z`;
267
+ return `${base}.${String(nanos).padStart(9, "0").replace(/0+$/, "")}Z`;
268
+ }
269
+ function parseRfc3339(s) {
270
+ const m = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?Z$/.exec(s);
271
+ if (!m)
272
+ throw new Error(`invalid timestamp ${JSON.stringify(s)}`);
273
+ const ms = Date.parse(`${m[1]}Z`);
274
+ return { seconds: BigInt(Math.floor(ms / 1000)), nanos: Number((m[2] ?? "").padEnd(9, "0")) };
275
+ }
276
+ // ---------------------------------------------------------------- render
277
+ function render(typeName, bytes, isAny) {
278
+ const md = schema.messages[typeName];
279
+ const name = isAny ? md?.a ?? `/${typeName}` : md?.a;
280
+ const value = renderMessage(typeName, bytes);
281
+ return name !== undefined ? { type: name, value } : value;
282
+ }
283
+ /** protoreflect Message.Has for a dynamic proto3 message. */
284
+ function fieldHas(f, values) {
285
+ if (values.length === 0)
286
+ return false;
287
+ if (f.k === "map")
288
+ return true;
289
+ if (f.r)
290
+ return NUMERIC_KINDS.has(f.k) ? scalarElements(f, values).length > 0 : true;
291
+ if (f.k === "message" || f.o || f.pr)
292
+ return true;
293
+ const last = values[values.length - 1];
294
+ return !isZeroScalar(f.k, last.num, last.bytes);
295
+ }
296
+ function renderMessage(typeName, bytes) {
297
+ switch (typeName) {
298
+ case "google.protobuf.Timestamp": {
299
+ const w = parseFields(bytes);
300
+ return rfc3339(BigInt.asIntN(64, w.get(1)?.at(-1)?.num ?? BigInt(0)), Number(BigInt.asIntN(32, w.get(2)?.at(-1)?.num ?? BigInt(0))));
301
+ }
302
+ case "google.protobuf.Duration": {
303
+ const w = parseFields(bytes);
304
+ const seconds = BigInt.asIntN(64, w.get(1)?.at(-1)?.num ?? BigInt(0));
305
+ const nanos = BigInt.asIntN(32, w.get(2)?.at(-1)?.num ?? BigInt(0));
306
+ return (nanos + seconds * BigInt(1_000_000_000)).toString();
307
+ }
308
+ case "google.protobuf.Any":
309
+ return renderAny(bytes);
310
+ }
311
+ const md = schema.messages[typeName];
312
+ if (!md)
313
+ throw new Error(`amino schema has no message ${typeName}`);
314
+ if (md.me)
315
+ throw new Error(`amino message_encoding ${md.me} (${typeName}) is not supported`);
316
+ const wire = parseFields(bytes);
317
+ const sortName = (f) => (f.o ? f.o[0] : f.n);
318
+ const fields = [...md.f].sort((a, b) => (sortName(a) < sortName(b) ? -1 : sortName(a) > sortName(b) ? 1 : 0));
319
+ const oneofSet = new Set(md.f.filter((f) => f.o && wire.has(f.no)).map((f) => f.o[0]));
320
+ const emptyOneofWritten = new Set();
321
+ const out = {};
322
+ for (const f of fields) {
323
+ const values = wire.get(f.no) ?? [];
324
+ let name = f.n;
325
+ let writeNil = false;
326
+ if (!fieldHas(f, values)) {
327
+ if (f.o && !oneofSet.has(f.o[0]) && !emptyOneofWritten.has(f.o[0])) {
328
+ name = f.o[0];
329
+ writeNil = true;
330
+ emptyOneofWritten.add(f.o[0]);
331
+ }
332
+ else if (!f.d) {
333
+ continue;
334
+ }
335
+ else if (f.k === "message" && !f.r) {
336
+ throw new Error(`not supported: dont_omit_empty=true on invalid (nil?) message field: ${f.n}`);
337
+ }
338
+ }
339
+ let value;
340
+ const encoder = fieldEncoder(f);
341
+ if (encoder)
342
+ value = encoder(values);
343
+ else if (writeNil)
344
+ value = null;
345
+ else
346
+ value = renderValue(f, values);
347
+ if (f.o && !writeNil)
348
+ out[f.o[0]] = { type: f.o[1], value: { [name]: value } };
349
+ else
350
+ out[name] = value;
351
+ }
352
+ return out;
353
+ }
354
+ /** encoder.go getFieldEncoder: amino.encoding first, then cosmos_proto.scalar. */
355
+ function fieldEncoder(f) {
356
+ if (f.e === "legacy_coins")
357
+ return (values) => (values.length === 0 ? [] : renderList(f, values));
358
+ if (f.e === "inline_json") {
359
+ return (values) => sortedJson(JSON.parse(values.length ? utf8Decoder.decode(values[values.length - 1].bytes) : ""));
360
+ }
361
+ if (f.sc === "int" || f.sc === "dec") {
362
+ if (f.r)
363
+ throw new Error(`unsupported repeated ${f.sc} scalar ${f.n}`);
364
+ return (values) => {
365
+ const last = values[values.length - 1];
366
+ const text = last ? utf8Decoder.decode(last.bytes) : "";
367
+ if (text === "")
368
+ return "0";
369
+ if (f.sc === "dec")
370
+ return legacyDecString(text);
371
+ // cosmosIntEncoder: a string goes through as-is, bytes are parsed.
372
+ return f.k === "bytes" ? BigInt(text).toString() : text;
373
+ };
374
+ }
375
+ return undefined;
376
+ }
377
+ function renderValue(f, values) {
378
+ if (f.k === "map")
379
+ throw new Error("maps are not supported");
380
+ if (f.r)
381
+ return values.length === 0 ? null : renderList(f, values);
382
+ if (f.k === "message")
383
+ return renderMessage(f.t, concatBytes(values.map((v) => v.bytes)));
384
+ const last = values[values.length - 1];
385
+ // dont_omitempty on an unset scalar renders the zero value.
386
+ if (!last)
387
+ return scalarJson(f.k, BigInt(0), f.k === "string" ? new Uint8Array() : undefined);
388
+ return scalarJson(f.k, last.num, last.bytes);
389
+ }
390
+ function renderList(f, values) {
391
+ if (f.k === "message")
392
+ return values.map((v) => renderMessage(f.t, v.bytes));
393
+ if (f.k === "string" || f.k === "bytes")
394
+ return values.map((v) => scalarJson(f.k, undefined, v.bytes));
395
+ return scalarElements(f, values).map((n) => scalarJson(f.k, n, undefined));
396
+ }
397
+ function renderAny(bytes) {
398
+ const w = parseFields(bytes);
399
+ const typeUrl = utf8Decoder.decode(w.get(1)?.at(-1)?.bytes ?? new Uint8Array());
400
+ const value = w.get(2)?.at(-1)?.bytes ?? new Uint8Array();
401
+ if (!typeUrl.startsWith("/"))
402
+ throw new Error(`can't resolve type URL ${typeUrl}`);
403
+ const typeName = typeUrl.slice(1);
404
+ if (typeName in schema.messages)
405
+ return render(typeName, value, true);
406
+ const cfg = getNestedAminoConfig();
407
+ const codec = cfg?.registry.lookupType(typeUrl);
408
+ if (!cfg || !codec) {
409
+ throw new Error(`can't resolve type URL ${typeUrl}: call configureNestedAminoConverter({registry, aminoTypes}) ` +
410
+ "with a registry and AminoTypes that know it");
411
+ }
412
+ return cfg.aminoTypes.toAmino({ typeUrl, value: codec.decode(value) });
413
+ }
414
+ // ---------------------------------------------------------------- encode
415
+ /** Amino JSON of a message back to its protobuf bytes (the inverse of renderMessage). */
416
+ function encodeMessage(typeName, json) {
417
+ const w = new Writer();
418
+ switch (typeName) {
419
+ case "google.protobuf.Timestamp": {
420
+ const { seconds, nanos } = parseRfc3339(json);
421
+ if (seconds !== BigInt(0))
422
+ w.tag(1, 0).varint(seconds);
423
+ if (nanos !== 0)
424
+ w.tag(2, 0).varint(BigInt(nanos));
425
+ return w.finish();
426
+ }
427
+ case "google.protobuf.Duration": {
428
+ const total = BigInt(json);
429
+ const seconds = total / BigInt(1_000_000_000);
430
+ const nanos = total % BigInt(1_000_000_000);
431
+ if (seconds !== BigInt(0))
432
+ w.tag(1, 0).varint(seconds);
433
+ if (nanos !== BigInt(0))
434
+ w.tag(2, 0).varint(nanos);
435
+ return w.finish();
436
+ }
437
+ case "google.protobuf.Any": {
438
+ const { typeUrl, value } = encodeAny(json);
439
+ w.bytes(1, utf8Encoder.encode(typeUrl));
440
+ if (value.length)
441
+ w.bytes(2, value);
442
+ return w.finish();
443
+ }
444
+ }
445
+ const md = schema.messages[typeName];
446
+ if (!md)
447
+ throw new Error(`amino schema has no message ${typeName}`);
448
+ if (md.me)
449
+ throw new Error(`amino message_encoding ${md.me} (${typeName}) is not supported`);
450
+ if (json === null || typeof json !== "object")
451
+ throw new Error(`${typeName}: expected an object`);
452
+ for (const f of md.f) {
453
+ let value;
454
+ let present = false;
455
+ if (f.o) {
456
+ const wrapper = json[f.o[0]];
457
+ if (!wrapper || wrapper.type !== f.o[1] || !wrapper.value || !(f.n in wrapper.value))
458
+ continue;
459
+ value = wrapper.value[f.n];
460
+ present = true; // a set oneof member keeps its presence even at zero
461
+ }
462
+ else {
463
+ value = json[f.n];
464
+ present = !!f.pr;
465
+ }
466
+ if (value === undefined || value === null)
467
+ continue;
468
+ encodeField(w, f, value, present);
469
+ }
470
+ return w.finish();
471
+ }
472
+ function encodeField(w, f, value, present) {
473
+ if (f.k === "map")
474
+ throw new Error("maps are not supported");
475
+ if (f.r) {
476
+ if (!Array.isArray(value))
477
+ throw new Error(`${f.n}: expected a list`);
478
+ if (NUMERIC_KINDS.has(f.k)) {
479
+ if (value.length === 0)
480
+ return;
481
+ const packed = new Writer();
482
+ for (const el of value)
483
+ writeNumeric(packed, f.k, el);
484
+ w.bytes(f.no, packed.finish());
485
+ return;
486
+ }
487
+ for (const el of value) {
488
+ if (f.k === "message")
489
+ w.bytes(f.no, encodeMessage(f.t, el));
490
+ else
491
+ w.bytes(f.no, scalarBytes(f, el));
492
+ }
493
+ return;
494
+ }
495
+ if (f.k === "message") {
496
+ w.bytes(f.no, encodeMessage(f.t, value));
497
+ return;
498
+ }
499
+ if (f.k === "string" || f.k === "bytes") {
500
+ let bytes = scalarBytes(f, value);
501
+ if (f.sc === "dec" && value === "0")
502
+ bytes = new Uint8Array(); // rendered from an empty Dec
503
+ if (bytes.length > 0 || present)
504
+ w.bytes(f.no, bytes);
505
+ return;
506
+ }
507
+ const n = numericValue(f.k, value);
508
+ if (n !== BigInt(0) || present) {
509
+ w.tag(f.no, FIXED32_KINDS.has(f.k) ? 5 : FIXED64_KINDS.has(f.k) ? 1 : 0);
510
+ writeNumeric(w, f.k, value);
511
+ }
512
+ }
513
+ function scalarBytes(f, value) {
514
+ if (f.k === "bytes") {
515
+ if (f.sc === "int" || f.sc === "dec")
516
+ return utf8Encoder.encode(f.sc === "dec" ? legacyDecAtomics(value) : String(value));
517
+ return fromBase64(value);
518
+ }
519
+ if (f.sc === "dec")
520
+ return utf8Encoder.encode(value === "0" ? "" : legacyDecAtomics(value));
521
+ return utf8Encoder.encode(String(value));
522
+ }
523
+ function numericValue(kind, value) {
524
+ if (kind === "bool")
525
+ return value ? BigInt(1) : BigInt(0);
526
+ if (kind === "float" || kind === "double")
527
+ throw new Error(`amino JSON cannot encode a ${kind} field`);
528
+ return BigInt(value);
529
+ }
530
+ function writeNumeric(w, kind, value) {
531
+ const n = numericValue(kind, value);
532
+ switch (kind) {
533
+ case "sint32":
534
+ w.varint(zigzagEncode(n, 32));
535
+ return;
536
+ case "sint64":
537
+ w.varint(zigzagEncode(n, 64));
538
+ return;
539
+ case "fixed32":
540
+ case "sfixed32":
541
+ w.fixed(n, 4);
542
+ return;
543
+ case "fixed64":
544
+ case "sfixed64":
545
+ w.fixed(n, 8);
546
+ return;
547
+ default:
548
+ w.varint(n);
549
+ }
550
+ }
551
+ function encodeAny(json) {
552
+ const type = json?.type;
553
+ if (!type)
554
+ throw new Error("Any: expected {type, value}");
555
+ const typeName = byAminoName.get(type) ?? (type.startsWith("/") && type.slice(1) in schema.messages ? type.slice(1) : undefined);
556
+ if (typeName)
557
+ return { typeUrl: `/${typeName}`, value: encodeMessage(typeName, json.value ?? {}) };
558
+ const cfg = getNestedAminoConfig();
559
+ if (!cfg)
560
+ throw new Error(`can't resolve amino type ${type}: call configureNestedAminoConverter first`);
561
+ const decoded = cfg.aminoTypes.fromAmino(json);
562
+ const codec = cfg.registry.lookupType(decoded.typeUrl);
563
+ if (!codec)
564
+ throw new Error(`No proto codec registered for inner type ${decoded.typeUrl}.`);
565
+ return { typeUrl: decoded.typeUrl, value: codec.encode(codec.fromPartial(decoded.value)).finish() };
566
+ }
567
+ // ------------------------------------------------------- non-nullable fill
568
+ /**
569
+ * Returns value with every dont_omitempty embedded message present (empty
570
+ * when left out), recursively. aminojson refuses to render an absent one, and
571
+ * Go clients never send one absent (they are gogoproto.nullable = false), but
572
+ * Telescope's fromPartial leaves them undefined.
573
+ * Filled on the plain value, before fromPartial, so the codec builds proper
574
+ * defaults; a Timestamp gets the epoch.
575
+ */
576
+ export function fillNonNullable(typeName, value) {
577
+ const md = schema.messages[typeName];
578
+ if (!md || !value || typeof value !== "object")
579
+ return value;
580
+ const out = { ...value };
581
+ for (const f of md.f) {
582
+ if (f.k !== "message" || !f.j || !f.t)
583
+ continue;
584
+ const v = out[f.j];
585
+ if (f.r) {
586
+ if (Array.isArray(v) && !BUILTIN.has(f.t))
587
+ out[f.j] = v.map((el) => fillNonNullable(f.t, el));
588
+ continue;
589
+ }
590
+ if (v === undefined || v === null) {
591
+ // Only a dont_omitempty message must be present: aminojson refuses to
592
+ // render it absent. Others render the same either way, so stay untouched.
593
+ if (!f.d)
594
+ continue;
595
+ out[f.j] = f.t === "google.protobuf.Timestamp" ? new Date(0) : BUILTIN.has(f.t) ? {} : fillNonNullable(f.t, {});
596
+ continue;
597
+ }
598
+ if (!BUILTIN.has(f.t))
599
+ out[f.j] = fillNonNullable(f.t, v);
600
+ }
601
+ return out;
602
+ }
603
+ // --------------------------------------------------------- decode + prune
604
+ /**
605
+ * Telescope's decode fills every embedded message the bytes lack with a
606
+ * default (createBase): an empty Coin, which re-encodes as present, or
607
+ * `new Date()` for a Timestamp, which re-encodes as the current time. cosmjs
608
+ * builds the signed tx body by re-encoding fromAmino's result, so clear each
609
+ * embedded message the bytes did not carry, recursively: the body then
610
+ * encodes back to exactly these bytes.
611
+ */
612
+ function pruneAbsent(typeName, bytes, value) {
613
+ const md = schema.messages[typeName];
614
+ if (!md || !value || typeof value !== "object")
615
+ return value;
616
+ const wire = parseFields(bytes);
617
+ for (const f of md.f) {
618
+ if (f.k !== "message" || !f.j || !f.t)
619
+ continue;
620
+ const values = wire.get(f.no) ?? [];
621
+ if (f.r) {
622
+ const list = value[f.j];
623
+ if (Array.isArray(list) && !BUILTIN.has(f.t)) {
624
+ value[f.j] = list.map((el, i) => (values[i] ? pruneAbsent(f.t, values[i].bytes, el) : el));
625
+ }
626
+ continue;
627
+ }
628
+ if (values.length === 0)
629
+ value[f.j] = undefined;
630
+ else if (!BUILTIN.has(f.t))
631
+ value[f.j] = pruneAbsent(f.t, concatBytes(values.map((v) => v.bytes)), value[f.j]);
632
+ }
633
+ return value;
634
+ }
635
+ /**
636
+ * The AminoConverter map for every Msg of a proto package
637
+ * ("sparkdream.<module>.v1"), given the module's generated tx codecs.
638
+ */
639
+ export function chainAminoConverters(pkg, txModule) {
640
+ const out = {};
641
+ for (const typeName of schema.msgs) {
642
+ if (!typeName.startsWith(`${pkg}.`))
643
+ continue;
644
+ const aminoType = schema.messages[typeName]?.a;
645
+ const codec = txModule[typeName.slice(pkg.length + 1)];
646
+ if (!aminoType || !codec)
647
+ continue;
648
+ out[`/${typeName}`] = {
649
+ aminoType,
650
+ toAmino: (value) => {
651
+ const bytes = codec.encode(codec.fromPartial(fillNonNullable(typeName, value))).finish();
652
+ return render(typeName, bytes, false).value;
653
+ },
654
+ fromAmino: (value) => {
655
+ const bytes = encodeMessage(typeName, value ?? {});
656
+ return pruneAbsent(typeName, bytes, codec.decode(bytes));
657
+ },
658
+ };
659
+ }
660
+ return out;
661
+ }
662
+ /** Amino JSON ({type, value}) of any message the schema describes, rendered from its protobuf bytes. */
663
+ export function renderAminoJson(typeUrl, bytes) {
664
+ return render(typeUrl.replace(/^\//, ""), bytes, false);
665
+ }
@@ -3,7 +3,9 @@
3
3
  * Shared registry + helpers for amino-converting messages that embed a
4
4
  * `google.protobuf.Any` field (`MsgSubmitProposal`,
5
5
  * `MsgSubmitAnonymousProposal`, `MsgExecSession`, vault `MsgPropose`,
6
- * guardian `MsgExec`).
6
+ * guardian `MsgExec`). chain-amino.ts renders sparkdream inner messages
7
+ * itself and uses this configuration only for inner types it doesn't know
8
+ * (cosmos-sdk messages inside a proposal).
7
9
  *
8
10
  * The Telescope-generated `Any.toAmino` just emits `{type, value: Uint8Array}`,
9
11
  * which JSON.stringify turns into `{"0":N,"1":N,…}` — numeric keys that aren't
@@ -21,6 +23,10 @@ let cfg = null;
21
23
  export function configureNestedAminoConverter(next) {
22
24
  cfg = next;
23
25
  }
26
+ /** The configured registry and AminoTypes, or null before configureNestedAminoConverter. */
27
+ export function getNestedAminoConfig() {
28
+ return cfg;
29
+ }
24
30
  function requireCfg() {
25
31
  if (!cfg) {
26
32
  throw new Error("@sparkdreamnft/sparkdreamjs: configureNestedAminoConverter({registry, aminoTypes}) " +