@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/CHANGELOG.md +20 -0
- package/dist/index.d.mts +54 -16
- package/dist/index.d.ts +54 -16
- package/dist/index.js +302 -118
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -121
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
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(
|
6
|
-
const value = BigInt(
|
7
|
-
const highByte = Number.parseInt(
|
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
|
14
|
-
if (
|
15
|
-
if (positive && 128 & Number.parseInt(
|
16
|
-
return `00${
|
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
|
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
|
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
|
-
|
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
|
-
|
245
|
+
writeUInt(value) {
|
216
246
|
return writeVLQ(this, value);
|
217
247
|
}
|
218
|
-
|
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.
|
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.
|
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.
|
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
|
245
|
-
return this.
|
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,
|
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.
|
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.
|
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
|
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.
|
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.
|
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
|
-
|
815
|
-
|
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 ===
|
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
|
-
|
862
|
-
|
863
|
-
|
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
|
877
|
-
if (
|
878
|
-
writer
|
1065
|
+
function writeInput(writer, input) {
|
1066
|
+
if (isSignedInput(input)) {
|
1067
|
+
writeSignedInput(writer, input);
|
879
1068
|
return;
|
880
1069
|
}
|
881
|
-
writer
|
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
|
893
|
-
|
894
|
-
|
895
|
-
|
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
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
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
|
931
|
-
|
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
|
944
|
-
|
945
|
-
|
946
|
-
|
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
|
-
|
950
|
-
|
951
|
-
|
952
|
-
if (isDefined(extension[key])) length++;
|
1097
|
+
if (!extension) {
|
1098
|
+
writer.write(0);
|
1099
|
+
return;
|
953
1100
|
}
|
954
|
-
|
955
|
-
|
1101
|
+
const keys = Object.keys(extension);
|
1102
|
+
const values = [];
|
956
1103
|
for (const key of keys) {
|
957
|
-
const
|
958
|
-
if (
|
959
|
-
|
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
|