Skip to content

Commit

Permalink
Properly replace bigints when passed as single primitive type when
Browse files Browse the repository at this point in the history
format = 'string'
  • Loading branch information
soerenbf committed Nov 10, 2023
1 parent 527f4d1 commit 21af1cf
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
28 changes: 20 additions & 8 deletions packages/sdk/src/types/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,11 @@ export function jsonStringify(
* This should be used if you want to manually deserialize the inner property values, as the serialization is irreversible.
*
* @param value A JavaScript value, usually an object or array, to be converted.
* @param bigintFormat Determines how to handle bigints.
* Can be set to either 'number' (uses 'json-bigint to safely serialize), 'string', or undefined (must be taken care of in replacer function)
* @param bigintFormat Determines how to handle bigints. Can be set to either:
* - `'number'`: uses 'json-bigint to safely serialize,
* - `'string'`: converts `bigint` to strings
* - `undefined`: must be taken care of manually, e.g. in replacer function.
* Defaults to 'number'
* @param replacer A function that transforms the results.
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
Expand All @@ -239,21 +242,30 @@ export function jsonUnwrapStringify(
replacer?: ReplacerFun,
space?: string | number
): string {
function replacerFunction(this: any, key: string, value: any) {
let transformedValue = ccdUnwrapReplacer.call(this, key, value);

function replaceBigintValue(value: any): any {
switch (bigintFormat) {
case 'string':
if (typeof value === 'bigint') {
transformedValue = value.toString();
return value.toString();
}
default:
break;
return value;
}
}

function replacerFunction(this: any, key: string, value: any) {
let transformedValue = ccdUnwrapReplacer.call(this, key, value);
transformedValue = replaceBigintValue(transformedValue);
return replacer?.call(this, key, transformedValue) ?? transformedValue;
}

let replaced = input;

if (typeof input !== 'object') {
replaced = replaceBigintValue(replaced);
}

const stringify =
bigintFormat === 'number' ? JSONBig.stringify : JSON.stringify;
return stringify(input, replacerFunction, space);
return stringify(replaced, replacerFunction, space);
}
46 changes: 46 additions & 0 deletions packages/sdk/test/ci/types/json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,43 @@ describe('jsonStringify', () => {
});
});

describe(jsonUnwrapStringify, () => {
test('Serializes bigint values as expected', () => {
const t = 100n;
expect(jsonUnwrapStringify(t)).toEqual('100');
expect(jsonUnwrapStringify(t, 'string')).toEqual('"100"');
expect(
jsonUnwrapStringify(t, undefined, (_, v) =>
typeof v === 'bigint' ? -v : v
)
).toEqual('-100');
});

test('Serializes nested bigint (arrays) values as expected', () => {
const t = [100n, 200n];
expect(jsonUnwrapStringify(t)).toEqual('[100,200]');
expect(jsonUnwrapStringify(t, 'string')).toEqual('["100","200"]');
expect(
jsonUnwrapStringify(t, undefined, (_, v) =>
typeof v === 'bigint' ? -v : v
)
).toEqual('[-100,-200]');
});

test('Serializes nested bigint (objects) values as expected', () => {
const t = { a: 100n, b: 200n };
expect(jsonUnwrapStringify(t)).toEqual('{"a":100,"b":200}');
expect(jsonUnwrapStringify(t, 'string')).toEqual(
'{"a":"100","b":"200"}'
);
expect(
jsonUnwrapStringify(t, undefined, (_, v) =>
typeof v === 'bigint' ? -v : v
)
).toEqual('{"a":-100,"b":-200}');
});
});

describe('ContractName', () => {
test('Unwraps as expected', () => {
const t = ContractName.fromString('some-name');
Expand Down Expand Up @@ -151,6 +188,12 @@ describe('SequenceNumber', () => {
let t = SequenceNumber.create(300);
let e = '300';
expect(jsonUnwrapStringify(t)).toEqual(e);
expect(jsonUnwrapStringify(t, 'string')).toEqual(`"${e}"`);
expect(
jsonUnwrapStringify(t, undefined, (_, v) =>
typeof v === 'bigint' ? -v : v
)
).toEqual('-300');

// Test for numbers bigger than Number.MAX_SAFE_INTEGER
t = SequenceNumber.create(9007199254740997n);
Expand Down Expand Up @@ -204,6 +247,9 @@ describe('ContractAddress', () => {
let t = ContractAddress.create(100, 10);
let e = '{"index":100,"subindex":10}';
expect(jsonUnwrapStringify(t)).toEqual(e);
expect(jsonUnwrapStringify(t, 'string')).toEqual(
'{"index":"100","subindex":"10"}'
);

// Test for numbers bigger than Number.MAX_SAFE_INTEGER
t = ContractAddress.create(9007199254740997n, 10);
Expand Down

0 comments on commit 21af1cf

Please sign in to comment.