@fleet-sdk/serializer 0.8.2 → 0.8.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.
package/dist/index.mjs CHANGED
@@ -1,21 +1,21 @@
1
- import { ensureBigInt, _0n, _128n, isEmpty, assert, first, last, isDefined, some, isUndefined, byteSizeOf, _7n, _1n, _127n, _63n } from '@fleet-sdk/common';
2
- import { ensureBytes, hex, blake2b256 } from '@fleet-sdk/crypto';
1
+ import { FEE_CONTRACT, isEmpty, startsWith, assert, first, last, _0n, _128n, _1n, ensureBigInt, isDefined, _7n, ergoTreeHeaderFlags, _127n, _63n, isUndefined, byteSizeOf } from '@fleet-sdk/common';
2
+ import { hex, ensureBytes, blake2b256, validateEcPoint } from '@fleet-sdk/crypto';
3
3
 
4
4
  // src/coders/sigmaByteReader.ts
5
- function hexToBigInt(hex6) {
6
- const value = BigInt(hex6.length % 2 ? `0x0${hex6}` : `0x${hex6}`);
7
- const highByte = Number.parseInt(hex6.slice(0, 2), 16);
5
+ function hexToBigInt(hex8) {
6
+ const value = BigInt(hex8.length % 2 ? `0x0${hex8}` : `0x${hex8}`);
7
+ const highByte = Number.parseInt(hex8.slice(0, 2), 16);
8
8
  if (128 & highByte) return -negateAndMask(value);
9
9
  return value;
10
10
  }
11
11
  function bigIntToHex(value) {
12
12
  const positive = value >= _0n;
13
- let hex6 = (positive ? value : negateAndMask(value)).toString(16);
14
- if (hex6.length % 2) hex6 = `0${hex6}`;
15
- if (positive && 128 & Number.parseInt(hex6.slice(0, 2), 16)) {
16
- return `00${hex6}`;
13
+ let hex8 = (positive ? value : negateAndMask(value)).toString(16);
14
+ if (hex8.length % 2) hex8 = `0${hex8}`;
15
+ if (positive && 128 & Number.parseInt(hex8.slice(0, 2), 16)) {
16
+ return `00${hex8}`;
17
17
  }
18
- return hex6;
18
+ return hex8;
19
19
  }
20
20
  function negateAndMask(value) {
21
21
  let val = value;
@@ -148,12 +148,26 @@ var SigmaByteReader = class {
148
148
  #bytes;
149
149
  #cursor;
150
150
  get isEmpty() {
151
- return isEmpty(this.#bytes);
151
+ return this.#bytes.length === this.#cursor;
152
+ }
153
+ get bytes() {
154
+ return this.#bytes;
155
+ }
156
+ get cursor() {
157
+ return this.#cursor;
152
158
  }
153
159
  constructor(bytes) {
154
160
  this.#bytes = ensureBytes(bytes);
155
161
  this.#cursor = 0;
156
162
  }
163
+ readArray(readFn) {
164
+ const length = this.readUInt();
165
+ const items = new Array(length);
166
+ for (let i = 0; i < length; i++) {
167
+ items[i] = readFn(this, i);
168
+ }
169
+ return items;
170
+ }
157
171
  readBool() {
158
172
  return this.readByte() === 1;
159
173
  }
@@ -177,9 +191,12 @@ var SigmaByteReader = class {
177
191
  readBytes(length) {
178
192
  return this.#bytes.subarray(this.#cursor, this.#cursor += length);
179
193
  }
180
- readVlq() {
194
+ readUInt() {
181
195
  return readVLQ(this);
182
196
  }
197
+ readBigUInt() {
198
+ return readBigVLQ(this);
199
+ }
183
200
  readI8() {
184
201
  const byte = this.readByte();
185
202
  return byte > MAX_I8 ? byte - (MAX_U8 + 1) : byte;
@@ -197,6 +214,19 @@ var SigmaByteReader = class {
197
214
  const len = readVLQ(this);
198
215
  return hexToBigInt(hex.encode(this.readBytes(len)));
199
216
  }
217
+ /**
218
+ * Returns bytes without advancing the cursor.
219
+ */
220
+ peek(count, offset = 0) {
221
+ const begin = this.#cursor + offset;
222
+ return this.#bytes.subarray(begin, begin + count);
223
+ }
224
+ /**
225
+ * Checks if the current position in the byte array starts with the given bytes.
226
+ */
227
+ match(bytes, offset = 0) {
228
+ return startsWith(this.#bytes, bytes, this.#cursor + offset);
229
+ }
200
230
  };
201
231
  var SigmaByteWriter = class {
202
232
  #bytes;
@@ -212,37 +242,37 @@ var SigmaByteWriter = class {
212
242
  this.write(value === true ? 1 : 0);
213
243
  return this;
214
244
  }
215
- writeVLQ(value) {
245
+ writeUInt(value) {
216
246
  return writeVLQ(this, value);
217
247
  }
218
- writeBigVLQ(value) {
248
+ writeBigUInt(value) {
219
249
  return writeBigVLQ(this, value);
220
250
  }
221
251
  writeI16(value) {
222
252
  if (value < MIN_I16 || value > MAX_I16) {
223
253
  throw new RangeError(`Value ${value} is out of range for a 16-bit integer`);
224
254
  }
225
- this.writeBigVLQ(zigZag32.encode(value));
255
+ this.writeBigUInt(zigZag32.encode(value));
226
256
  return this;
227
257
  }
228
258
  writeI32(value) {
229
259
  if (value < MIN_I32 || value > MAX_I32) {
230
260
  throw new RangeError(`Value ${value} is out of range for a 32-bit integer`);
231
261
  }
232
- return this.writeBigVLQ(zigZag32.encode(value));
262
+ return this.writeBigUInt(zigZag32.encode(value));
233
263
  }
234
264
  writeI64(value) {
235
265
  if (value < MIN_I64 || value > MAX_I64) {
236
266
  throw new RangeError(`Value ${value} is out of range for a 64-bit integer`);
237
267
  }
238
- return this.writeBigVLQ(zigZag64.encode(value));
268
+ return this.writeBigUInt(zigZag64.encode(value));
239
269
  }
240
270
  writeI256(value) {
241
271
  if (value < MIN_I256 || value > MAX_I256) {
242
272
  throw new RangeError(`Value ${value} is out of range for a 256-bit integer`);
243
273
  }
244
- const hex6 = bigIntToHex(value);
245
- return this.writeVLQ(hex6.length / 2).writeHex(hex6);
274
+ const hex8 = bigIntToHex(value);
275
+ return this.writeUInt(hex8.length / 2).writeHex(hex8);
246
276
  }
247
277
  write(byte) {
248
278
  this.#bytes[this.#cursor++] = byte;
@@ -276,6 +306,23 @@ var SigmaByteWriter = class {
276
306
  const hash = hashFn(this.toBytes());
277
307
  return this.writeBytes(length ? hash.subarray(0, length) : hash);
278
308
  }
309
+ /**
310
+ * Writes a length-delimited array of items to the byte stream using a provided
311
+ * serializer function.
312
+ *
313
+ * @typeParam T - The type of items in the array.
314
+ * @param items - The array of items to serialize and write.
315
+ * @param serializer - A function that serializes each item and writes it using the provided SigmaByteWriter.
316
+ * @returns The current instance of SigmaByteWriter for method chaining.
317
+ */
318
+ writeArray(items, serializer) {
319
+ this.writeUInt(items.length);
320
+ if (items.length === 0) return this;
321
+ for (const item of items) {
322
+ serializer(item, this);
323
+ }
324
+ return this;
325
+ }
279
326
  encode(coder) {
280
327
  return coder.encode(this.toBytes());
281
328
  }
@@ -397,6 +444,14 @@ var SUnitType = class extends SMonomorphicType {
397
444
  return "SUnit";
398
445
  }
399
446
  };
447
+ var SBoxType = class extends SMonomorphicType {
448
+ get code() {
449
+ return 99;
450
+ }
451
+ toString() {
452
+ return "SBox";
453
+ }
454
+ };
400
455
 
401
456
  // src/types/descriptors.ts
402
457
  var constructorCode = Object.freeze({
@@ -439,6 +494,7 @@ var descriptors = {
439
494
  groupElement: new SGroupElementType(),
440
495
  sigmaProp: new SSigmaPropType(),
441
496
  unit: new SUnitType(),
497
+ box: new SBoxType(),
442
498
  coll: collDescriptor,
443
499
  tuple: tupleDescriptor
444
500
  };
@@ -535,7 +591,8 @@ var SSigmaProp = monoProxy(
535
591
  SSigmaPropType,
536
592
  descriptors.sigmaProp
537
593
  );
538
- var SUnit = monoProxy(SUnitType, undefined, true);
594
+ var SUnit = monoProxy(SUnitType, void 0, true);
595
+ var SBox = monoProxy(SBoxType, void 0, true);
539
596
  var SColl = genericProxy(SCollType, (target, _, args) => {
540
597
  const [type, elements] = args;
541
598
  const elementsType = type();
@@ -552,6 +609,143 @@ var SPair = genericProxy(STupleType, (target, _, args) => {
552
609
  }
553
610
  throw new Error("Invalid tuple declaration.");
554
611
  });
612
+ var MAX_UINT16_VALUE = 65535;
613
+ var FEE_CONTRACT_BYTES = hex.decode(FEE_CONTRACT);
614
+ var P2PK_CONTRACT_PREFIX = hex.decode("0008cd");
615
+ var COMPRESSED_PK_LENGTH = 33;
616
+ var P2PK_CONTRACT_LENGTH = P2PK_CONTRACT_PREFIX.length + COMPRESSED_PK_LENGTH;
617
+ function serializeBox(box, writer = new SigmaByteWriter(4096), distinctTokenIds) {
618
+ writer.writeBigUInt(ensureBigInt(box.value)).writeHex(box.ergoTree).writeUInt(box.creationHeight);
619
+ writeTokens(writer, box.assets, distinctTokenIds);
620
+ writeRegisters(writer, box.additionalRegisters);
621
+ if (isDefined(distinctTokenIds)) return writer;
622
+ if (!isBox(box)) throw new Error("Invalid box type.");
623
+ return writer.writeHex(box.transactionId).writeUInt(box.index);
624
+ }
625
+ function isBox(box) {
626
+ const castedBox = box;
627
+ return isDefined(castedBox.transactionId) && isDefined(castedBox.index);
628
+ }
629
+ function writeTokens(writer, tokens, tokenIds) {
630
+ if (tokenIds) {
631
+ writer.writeArray(
632
+ tokens,
633
+ (token, w) => w.writeUInt(tokenIds.indexOf(token.tokenId)).writeBigUInt(ensureBigInt(token.amount))
634
+ );
635
+ } else {
636
+ writer.writeArray(
637
+ tokens,
638
+ (token, w) => w.writeHex(token.tokenId).writeBigUInt(ensureBigInt(token.amount))
639
+ );
640
+ }
641
+ }
642
+ function writeRegisters(writer, registers) {
643
+ const keys = Object.keys(registers).sort();
644
+ const values = [];
645
+ for (const key of keys) {
646
+ const value = registers[key];
647
+ if (!value) continue;
648
+ values.push(value);
649
+ }
650
+ writer.writeArray(values, (value, w) => w.writeHex(value));
651
+ }
652
+ function estimateBoxSize(box, withValue) {
653
+ if (isUndefined(box.creationHeight)) {
654
+ throw new Error("Box size estimation error: creation height is undefined.");
655
+ }
656
+ let size = 0;
657
+ size += estimateVLQSize(isDefined(withValue) ? withValue : box.value);
658
+ size += byteSizeOf(box.ergoTree);
659
+ size += estimateVLQSize(box.creationHeight);
660
+ size += estimateVLQSize(box.assets.length);
661
+ for (const asset of box.assets) {
662
+ size += byteSizeOf(asset.tokenId) + estimateVLQSize(asset.amount);
663
+ }
664
+ let registersLength = 0;
665
+ for (const key in box.additionalRegisters) {
666
+ const register = box.additionalRegisters[key];
667
+ if (register) {
668
+ size += byteSizeOf(register);
669
+ registersLength++;
670
+ }
671
+ }
672
+ size += estimateVLQSize(registersLength);
673
+ size += 32;
674
+ size += estimateVLQSize(isBox(box) ? box.index : MAX_UINT16_VALUE);
675
+ return size;
676
+ }
677
+ function deserializeEmbeddedBox(reader, distinctTokenIds, transactionId, index) {
678
+ let begin = reader.cursor;
679
+ const value = reader.readBigUInt();
680
+ const ergoTree = hex.encode(readErgoTree(reader));
681
+ const creationHeight = reader.readUInt();
682
+ const boxIdWriter = new SigmaByteWriter(4096).writeBytes(reader.bytes.subarray(begin, reader.cursor));
683
+ const assets = readTokens(reader, distinctTokenIds);
684
+ boxIdWriter.writeUInt(assets.length);
685
+ for (const asset of assets) {
686
+ boxIdWriter.writeHex(asset.tokenId).writeBigUInt(asset.amount);
687
+ }
688
+ begin = reader.cursor;
689
+ const additionalRegisters = readRegisters(reader);
690
+ boxIdWriter.writeBytes(reader.bytes.subarray(begin, reader.cursor)).writeHex(transactionId).writeUInt(index);
691
+ return {
692
+ boxId: hex.encode(blake2b256(boxIdWriter.toBytes())),
693
+ value,
694
+ ergoTree,
695
+ creationHeight,
696
+ assets,
697
+ additionalRegisters,
698
+ transactionId,
699
+ index
700
+ };
701
+ }
702
+ function deserializeBox(input) {
703
+ const reader = input instanceof SigmaByteReader ? input : new SigmaByteReader(input);
704
+ const begin = reader.cursor;
705
+ const box = {
706
+ boxId: "",
707
+ // placeholder, will be calculated later
708
+ value: reader.readBigUInt(),
709
+ ergoTree: hex.encode(readErgoTree(reader)),
710
+ creationHeight: reader.readUInt(),
711
+ assets: readTokens(reader),
712
+ additionalRegisters: readRegisters(reader),
713
+ transactionId: hex.encode(reader.readBytes(32)),
714
+ index: reader.readUInt()
715
+ };
716
+ box.boxId = hex.encode(blake2b256(reader.bytes.subarray(begin, reader.cursor)));
717
+ return box;
718
+ }
719
+ function readErgoTree(reader) {
720
+ if (reader.match(FEE_CONTRACT_BYTES)) {
721
+ return reader.readBytes(FEE_CONTRACT_BYTES.length);
722
+ }
723
+ if (reader.match(P2PK_CONTRACT_PREFIX) && validateEcPoint(reader.peek(COMPRESSED_PK_LENGTH, P2PK_CONTRACT_PREFIX.length))) {
724
+ return reader.readBytes(P2PK_CONTRACT_LENGTH);
725
+ }
726
+ const header = reader.readByte();
727
+ const hasSize = (header & ergoTreeHeaderFlags.sizeInclusion) !== 0;
728
+ if (!hasSize) {
729
+ throw new Error("ErgoTree parsing without the size flag is not supported.");
730
+ }
731
+ const size = reader.readUInt();
732
+ return new SigmaByteWriter(1 + 4 + size).write(header).writeUInt(size).writeBytes(reader.readBytes(size)).toBytes();
733
+ }
734
+ function readTokens(reader, tokenIds) {
735
+ return reader.readArray((r) => ({
736
+ tokenId: tokenIds ? tokenIds[r.readUInt()] : hex.encode(r.readBytes(32)),
737
+ amount: r.readBigUInt()
738
+ }));
739
+ }
740
+ function readRegisters(reader) {
741
+ const registers = {};
742
+ const count = reader.readUInt();
743
+ for (let i = 0; i < count; i++) {
744
+ const value = SConstant.from(reader).toHex();
745
+ registers[`R${(i + 4).toString()}`] = value;
746
+ }
747
+ return registers;
748
+ }
555
749
 
556
750
  // src/serializers/dataSerializer.ts
557
751
  var GROUP_ELEMENT_LENGTH = 33;
@@ -593,7 +787,7 @@ var dataSerializer = {
593
787
  } else {
594
788
  assert(Array.isArray(data), `SColl expected an array, got ${typeof data}.`);
595
789
  }
596
- writer.writeVLQ(data.length);
790
+ writer.writeUInt(data.length);
597
791
  switch (type.elementsType.code) {
598
792
  case descriptors.bool.code: {
599
793
  return writer.writeBits(data);
@@ -621,6 +815,7 @@ var dataSerializer = {
621
815
  return writer;
622
816
  }
623
817
  if (type.code === descriptors.unit.code) return writer;
818
+ if (type.code === descriptors.box.code) return serializeBox(data, writer);
624
819
  throw Error(
625
820
  `Serialization error: '0x${type.code.toString(16)}' type not implemented.`
626
821
  );
@@ -652,7 +847,7 @@ var dataSerializer = {
652
847
  } else {
653
848
  switch (type.code) {
654
849
  case descriptors.coll.code: {
655
- const length = reader.readVlq();
850
+ const length = reader.readUInt();
656
851
  const embeddedType = type.elementsType;
657
852
  switch (embeddedType.code) {
658
853
  case descriptors.bool.code:
@@ -674,7 +869,9 @@ var dataSerializer = {
674
869
  );
675
870
  }
676
871
  case descriptors.unit.code:
677
- return undefined;
872
+ return void 0;
873
+ case descriptors.box.code:
874
+ return deserializeBox(reader);
678
875
  }
679
876
  }
680
877
  throw new Error(`Parsing error: '0x${type.code.toString(16)}' type not implemented.`);
@@ -686,6 +883,8 @@ var typeSerializer = {
686
883
  writer.write(type.code);
687
884
  } else if (type.code === descriptors.unit.code) {
688
885
  writer.write(type.code);
886
+ } else if (type.code === descriptors.box.code) {
887
+ writer.write(type.code);
689
888
  } else if (isColl(type)) {
690
889
  if (type.elementsType.embeddable) {
691
890
  writer.write(descriptors.coll.simpleCollTypeCode + type.elementsType.code);
@@ -738,7 +937,7 @@ var typeSerializer = {
738
937
  "Invalid type: tuples must have between 2 and 255 items."
739
938
  );
740
939
  writer.write(descriptors.tuple.genericTupleTypeCode);
741
- writer.writeVLQ(len);
940
+ writer.writeUInt(len);
742
941
  }
743
942
  }
744
943
  for (let i = 0; i < type.elementsType.length; i++) {
@@ -786,16 +985,17 @@ var typeSerializer = {
786
985
  }
787
986
  switch (byte) {
788
987
  case descriptors.tuple.genericTupleTypeCode: {
789
- const len = r.readVlq();
988
+ const len = r.readUInt();
790
989
  const wrapped = new Array(len);
791
990
  for (let i = 0; i < len; i++) {
792
991
  wrapped[i] = this.deserialize(r);
793
992
  }
794
993
  return new STupleType(wrapped);
795
994
  }
796
- case descriptors.unit.code: {
995
+ case descriptors.unit.code:
797
996
  return descriptors.unit;
798
- }
997
+ case descriptors.box.code:
998
+ return descriptors.box;
799
999
  }
800
1000
  throw new Error("Not implemented.");
801
1001
  }
@@ -811,8 +1011,8 @@ var SConstant = class _SConstant {
811
1011
  this.#data = type.coerce(data);
812
1012
  }
813
1013
  static from(bytes) {
814
- assert(bytes.length > 0, "Empty constant bytes.");
815
- const reader = new SigmaByteReader(bytes);
1014
+ const reader = bytes instanceof SigmaByteReader ? bytes : new SigmaByteReader(bytes);
1015
+ if (reader.isEmpty) throw new Error("Empty constant bytes.");
816
1016
  const type = typeSerializer.deserialize(reader);
817
1017
  const data = dataSerializer.deserialize(type, reader);
818
1018
  return new _SConstant(type, data);
@@ -834,7 +1034,7 @@ var SConstant = class _SConstant {
834
1034
  }
835
1035
  };
836
1036
  function decode(value) {
837
- if (value === undefined) return;
1037
+ if (value === void 0) return;
838
1038
  try {
839
1039
  return SConstant.from(value);
840
1040
  } catch {
@@ -858,114 +1058,93 @@ function parse(constant, mode = "strict") {
858
1058
  return;
859
1059
  }
860
1060
  }
861
- var MAX_UINT16_VALUE = 65535;
862
- function serializeBox(box, writer = new SigmaByteWriter(4096), distinctTokenIds) {
863
- writer.writeBigVLQ(ensureBigInt(box.value));
864
- writer.writeHex(box.ergoTree);
865
- writer.writeVLQ(box.creationHeight);
866
- writeTokens(writer, box.assets, distinctTokenIds);
867
- writeRegisters(writer, box.additionalRegisters);
868
- if (isDefined(distinctTokenIds)) return writer;
869
- if (!isBox(box)) throw new Error("Invalid box type.");
870
- return writer.writeHex(box.transactionId).writeVLQ(box.index);
871
- }
872
- function isBox(box) {
873
- const castedBox = box;
874
- return isDefined(castedBox.transactionId) && isDefined(castedBox.index);
1061
+ function serializeTransaction(transaction) {
1062
+ const tokenIds = getDistinctTokenIds(transaction.outputs);
1063
+ return new SigmaByteWriter(1e5).writeArray(transaction.inputs, (input, w) => writeInput(w, input)).writeArray(transaction.dataInputs, (dataInput, w) => w.writeHex(dataInput.boxId)).writeArray(tokenIds, (tokenId, w) => w.writeHex(tokenId)).writeArray(transaction.outputs, (output, w) => serializeBox(output, w, tokenIds));
875
1064
  }
876
- function writeTokens(writer, tokens, tokenIds) {
877
- if (isEmpty(tokens)) {
878
- writer.write(0);
1065
+ function writeInput(writer, input) {
1066
+ if (isSignedInput(input)) {
1067
+ writeSignedInput(writer, input);
879
1068
  return;
880
1069
  }
881
- writer.writeVLQ(tokens.length);
882
- if (some(tokenIds)) {
883
- tokens.map(
884
- (token) => writer.writeVLQ(tokenIds.indexOf(token.tokenId)).writeBigVLQ(ensureBigInt(token.amount))
885
- );
886
- } else {
887
- tokens.map(
888
- (token) => writer.writeHex(token.tokenId).writeBigVLQ(ensureBigInt(token.amount))
889
- );
890
- }
1070
+ writeUnsignedInput(writer, input);
891
1071
  }
892
- function writeRegisters(writer, registers) {
893
- const keys = Object.keys(registers).sort();
894
- let length = 0;
895
- for (const key of keys) {
896
- if (registers[key]) length++;
897
- }
898
- writer.writeVLQ(length);
899
- if (length === 0) return;
900
- for (const key of keys) {
901
- const register = registers[key];
902
- if (isDefined(register)) writer.writeHex(register);
903
- }
1072
+ function writeSignedInput(writer, input) {
1073
+ writer.writeHex(input.boxId);
1074
+ writeProof(writer, input.spendingProof?.proofBytes);
1075
+ writeExtension(writer, input.spendingProof?.extension);
904
1076
  }
905
- function estimateBoxSize(box, withValue) {
906
- if (isUndefined(box.creationHeight)) {
907
- throw new Error("Box size estimation error: creation height is undefined.");
908
- }
909
- let size = 0;
910
- size += estimateVLQSize(isDefined(withValue) ? withValue : box.value);
911
- size += byteSizeOf(box.ergoTree);
912
- size += estimateVLQSize(box.creationHeight);
913
- size += estimateVLQSize(box.assets.length);
914
- for (const asset of box.assets) {
915
- size += byteSizeOf(asset.tokenId) + estimateVLQSize(asset.amount);
916
- }
917
- let registersLength = 0;
918
- for (const key in box.additionalRegisters) {
919
- const register = box.additionalRegisters[key];
920
- if (register) {
921
- size += byteSizeOf(register);
922
- registersLength++;
923
- }
924
- }
925
- size += estimateVLQSize(registersLength);
926
- size += 32;
927
- size += estimateVLQSize(isBox(box) ? box.index : MAX_UINT16_VALUE);
928
- return size;
1077
+ function writeUnsignedInput(writer, input) {
1078
+ writer.writeHex(input.boxId);
1079
+ writeProof(writer, null);
1080
+ writeExtension(
1081
+ writer,
1082
+ isSignedInput(input) ? input.spendingProof?.extension : input.extension
1083
+ );
929
1084
  }
930
- function serializeTransaction(transaction) {
931
- const writer = new SigmaByteWriter(1e5);
932
- writer.writeVLQ(transaction.inputs.length);
933
- transaction.inputs.map((input) => writeInput(writer, input));
934
- writer.writeVLQ(transaction.dataInputs.length);
935
- transaction.dataInputs.map((dataInput) => writer.writeHex(dataInput.boxId));
936
- const distinctTokenIds = getDistinctTokenIds(transaction.outputs);
937
- writer.writeVLQ(distinctTokenIds.length);
938
- distinctTokenIds.map((tokenId) => writer.writeHex(tokenId));
939
- writer.writeVLQ(transaction.outputs.length);
940
- transaction.outputs.map((output) => serializeBox(output, writer, distinctTokenIds));
941
- return writer;
1085
+ function isSignedInput(input) {
1086
+ return input.spendingProof !== void 0;
942
1087
  }
943
- function writeInput(writer, input) {
944
- writer.writeHex(input.boxId);
945
- writer.write(0);
946
- writeExtension(writer, input.extension);
1088
+ function writeProof(writer, proof) {
1089
+ if (!proof) {
1090
+ writer.write(0);
1091
+ return;
1092
+ }
1093
+ const bytes = hex.decode(proof);
1094
+ writer.writeUInt(bytes.length).writeBytes(bytes);
947
1095
  }
948
1096
  function writeExtension(writer, extension) {
949
- const keys = Object.keys(extension);
950
- let length = 0;
951
- for (const key of keys) {
952
- if (isDefined(extension[key])) length++;
1097
+ if (!extension) {
1098
+ writer.write(0);
1099
+ return;
953
1100
  }
954
- writer.writeVLQ(length);
955
- if (length === 0) return;
1101
+ const keys = Object.keys(extension);
1102
+ const values = [];
956
1103
  for (const key of keys) {
957
- const val = extension[key];
958
- if (isDefined(val)) {
959
- writer.writeVLQ(Number(key)).writeHex(val);
960
- }
961
- }
1104
+ const value = extension[key];
1105
+ if (!value) continue;
1106
+ values.push([key, value]);
1107
+ }
1108
+ writer.writeArray(
1109
+ values,
1110
+ ([key, value], w) => w.writeUInt(Number(key)).writeHex(value)
1111
+ );
962
1112
  }
963
1113
  function getDistinctTokenIds(outputs) {
964
1114
  const tokenIds = /* @__PURE__ */ new Set();
965
1115
  outputs.flatMap((output) => output.assets.map((asset) => tokenIds.add(asset.tokenId)));
966
1116
  return Array.from(tokenIds);
967
1117
  }
1118
+ function deserializeTransaction(input) {
1119
+ const reader = new SigmaByteReader(input);
1120
+ const inputs = reader.readArray(readInput);
1121
+ const id = computeId(reader, inputs);
1122
+ const dataInputs = reader.readArray((r) => ({ boxId: hex.encode(r.readBytes(32)) }));
1123
+ const tokenIds = reader.readArray((r) => hex.encode(r.readBytes(32)));
1124
+ const outputs = reader.readArray((r, i) => deserializeEmbeddedBox(r, tokenIds, id, i));
1125
+ return {
1126
+ id,
1127
+ inputs,
1128
+ dataInputs,
1129
+ outputs
1130
+ };
1131
+ }
1132
+ function readInput(reader) {
1133
+ const boxId = hex.encode(reader.readBytes(32));
1134
+ const proofLength = reader.readUInt();
1135
+ const proofBytes = proofLength > 0 ? hex.encode(reader.readBytes(proofLength)) : null;
1136
+ const extensionLength = reader.readUInt();
1137
+ const extension = {};
1138
+ for (let i = 0; i < extensionLength; i++) {
1139
+ extension[reader.readUInt()] = SConstant.from(reader).toHex();
1140
+ }
1141
+ return proofBytes ? { boxId, spendingProof: { proofBytes, extension } } : { boxId, extension };
1142
+ }
1143
+ function computeId(reader, inputs) {
1144
+ const bytes = new SigmaByteWriter(reader.bytes.length).writeArray(inputs, (input, writer) => writeUnsignedInput(writer, input)).writeBytes(reader.bytes.subarray(reader.cursor)).toBytes();
1145
+ return hex.encode(blake2b256(bytes));
1146
+ }
968
1147
 
969
- export { SBigInt, SBigIntType, SBool, SBoolType, SByte, SByteType, SColl, SCollType, SConstant, SGenericType, SGroupElement, SGroupElementType, SInt, SIntType, SLong, SLongType, SMonomorphicType, SPair, SPrimitiveType, SShort, SShortType, SSigmaProp, SSigmaPropType, STupleType, SType, SUnit, SUnitType, SigmaByteReader, SigmaByteWriter, dataSerializer, decode, estimateBoxSize, estimateVLQSize, isColl, isTuple, parse, serializeBox, serializeTransaction, stypeof, typeSerializer };
1148
+ export { SBigInt, SBigIntType, SBool, SBoolType, SBox, SBoxType, SByte, SByteType, SColl, SCollType, SConstant, SGenericType, SGroupElement, SGroupElementType, SInt, SIntType, SLong, SLongType, SMonomorphicType, SPair, SPrimitiveType, SShort, SShortType, SSigmaProp, SSigmaPropType, STupleType, SType, SUnit, SUnitType, SigmaByteReader, SigmaByteWriter, dataSerializer, decode, deserializeBox, deserializeEmbeddedBox, deserializeTransaction, estimateBoxSize, estimateVLQSize, isColl, isTuple, parse, serializeBox, serializeTransaction, stypeof, typeSerializer };
970
1149
  //# sourceMappingURL=index.mjs.map
971
1150
  //# sourceMappingURL=index.mjs.map