Skip to content

Commit fcbca0c

Browse files
authored
Merge pull request #671 from multiversx/fix-managed-decimal-nested-decoding
Fix nested decoding for managed decimal
2 parents 36e47af + c42d4ec commit fcbca0c

File tree

5 files changed

+67
-13
lines changed

5 files changed

+67
-13
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@multiversx/sdk-core",
3-
"version": "15.2.1",
3+
"version": "15.2.2",
44
"description": "MultiversX SDK for JavaScript and TypeScript",
55
"author": "MultiversX",
66
"homepage": "https://multiversx.com",

src/abi/codec/binary.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ import {
3333
I8Value,
3434
List,
3535
ListType,
36+
ManagedDecimalType,
3637
NumericalType,
3738
NumericalValue,
39+
OptionType,
3840
StringType,
3941
StringValue,
4042
Struct,
@@ -478,6 +480,30 @@ describe("test binary codec (advanced)", () => {
478480
decoded = codec.decodeTopLevel(blueEncodedTopLevel, enumType);
479481
assert.deepEqual(decoded, blue);
480482
});
483+
484+
it("should decode struct", async () => {
485+
let codec = new BinaryCodec();
486+
let fooType = new StructType("DepositEvent", [
487+
new FieldDefinition("tx_nonce", "", new U64Type()),
488+
new FieldDefinition("opt_function", "", new OptionType(new BytesType())),
489+
new FieldDefinition("opt_arguments", "", new OptionType(new ListType(new BytesType()))),
490+
new FieldDefinition("opt_gas_limit", "", new OptionType(new U64Type())),
491+
new FieldDefinition("managed_decimal", "", new ManagedDecimalType("usize")),
492+
]);
493+
494+
const encoded = Buffer.from("00000000000003db0000000000000202bc00000002", "hex");
495+
496+
let [decoded] = codec.decodeNested(encoded, fooType);
497+
498+
let plainFoo = decoded.valueOf();
499+
assert.deepEqual(plainFoo, {
500+
tx_nonce: new BigNumber(987),
501+
opt_function: null,
502+
opt_arguments: null,
503+
opt_gas_limit: null,
504+
managed_decimal: new BigNumber(7),
505+
});
506+
});
481507
});
482508

483509
function serialized(prettyHex: string): Buffer {

src/abi/codec/managedDecimal.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import BigNumber from "bignumber.js";
22
import { BigUIntType, BigUIntValue, ManagedDecimalType, ManagedDecimalValue, U32Value } from "../typesystem";
33
import { BinaryCodec } from "./binary";
4-
import { bufferToBigInt } from "./utils";
54
import { SizeOfU32 } from "./constants";
5+
import { bufferToBigInt } from "./utils";
66

77
export class ManagedDecimalCodec {
88
private readonly binaryCodec: BinaryCodec;
@@ -12,8 +12,20 @@ export class ManagedDecimalCodec {
1212
}
1313

1414
decodeNested(buffer: Buffer, type: ManagedDecimalType): [ManagedDecimalValue, number] {
15-
const length = buffer.readUInt32BE(0);
16-
const payload = buffer.slice(0, length);
15+
let payload: Buffer;
16+
let length: number;
17+
18+
if (type.isVariable()) {
19+
// read BigUInt value length
20+
const bigUintSizeBytes = buffer.slice(0, SizeOfU32);
21+
const bigUintLength = bigUintSizeBytes.readUInt32BE(0);
22+
23+
length = SizeOfU32 + bigUintLength + SizeOfU32;
24+
payload = buffer.slice(0, length);
25+
} else {
26+
length = buffer.readUInt32BE(0);
27+
payload = buffer.slice(0, length);
28+
}
1729

1830
const result = this.decodeTopLevel(payload, type);
1931
return [result, length];
@@ -29,13 +41,15 @@ export class ManagedDecimalCodec {
2941

3042
const [value] = this.binaryCodec.decodeNested(buffer.slice(0, bigUintSize), new BigUIntType());
3143
const scale = buffer.readUInt32BE(bigUintSize);
32-
return new ManagedDecimalValue(value.valueOf().shiftedBy(-scale), scale);
44+
return new ManagedDecimalValue(value.valueOf().shiftedBy(-scale), scale, true);
3345
}
3446

3547
const value = bufferToBigInt(buffer);
3648
const metadata = type.getMetadata();
49+
50+
// if this code executes, metadata is guaranteed to be a number
3751
const scale = metadata !== "usize" ? parseInt(metadata.toString()) : 0;
38-
return new ManagedDecimalValue(value.shiftedBy(-scale), scale);
52+
return new ManagedDecimalValue(value.shiftedBy(-scale), scale, false);
3953
}
4054

4155
encodeNested(value: ManagedDecimalValue): Buffer {

src/abi/codec/managedDecimalSigned.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import BigNumber from "bignumber.js";
22
import { BigIntType, BigIntValue, ManagedDecimalSignedType, ManagedDecimalSignedValue, U32Value } from "../typesystem";
33
import { BinaryCodec } from "./binary";
4-
import { bufferToBigInt } from "./utils";
54
import { SizeOfU32 } from "./constants";
5+
import { bufferToBigInt } from "./utils";
66

77
export class ManagedDecimalSignedCodec {
88
private readonly binaryCodec: BinaryCodec;
@@ -12,8 +12,20 @@ export class ManagedDecimalSignedCodec {
1212
}
1313

1414
decodeNested(buffer: Buffer, type: ManagedDecimalSignedType): [ManagedDecimalSignedValue, number] {
15-
const length = buffer.readUInt32BE(0);
16-
const payload = buffer.slice(0, length);
15+
let payload: Buffer;
16+
let length: number;
17+
18+
if (type.isVariable()) {
19+
// read BigInt value length
20+
const bigIntSizeBytes = buffer.slice(0, SizeOfU32);
21+
const bigIntLength = bigIntSizeBytes.readUInt32BE(0);
22+
23+
length = SizeOfU32 + bigIntLength + SizeOfU32;
24+
payload = buffer.slice(0, length);
25+
} else {
26+
length = buffer.readUInt32BE(0);
27+
payload = buffer.slice(0, length);
28+
}
1729

1830
const result = this.decodeTopLevel(payload, type);
1931
return [result, length];
@@ -30,13 +42,15 @@ export class ManagedDecimalSignedCodec {
3042
const [value] = this.binaryCodec.decodeNested(buffer.slice(0, bigintSize), new BigIntType());
3143
const scale = buffer.readUInt32BE(bigintSize);
3244

33-
return new ManagedDecimalSignedValue(value.valueOf().shiftedBy(-scale), scale);
45+
return new ManagedDecimalSignedValue(value.valueOf().shiftedBy(-scale), scale, true);
3446
}
3547

3648
const value = bufferToBigInt(buffer);
3749
const metadata = type.getMetadata();
50+
51+
// if this code executes, metadata is guaranteed to be a number
3852
const scale = metadata !== "usize" ? parseInt(metadata.toString()) : 0;
39-
return new ManagedDecimalSignedValue(value.shiftedBy(-scale), scale);
53+
return new ManagedDecimalSignedValue(value.shiftedBy(-scale), scale, false);
4054
}
4155

4256
encodeNested(value: ManagedDecimalSignedValue): Buffer {

0 commit comments

Comments
 (0)