Skip to content

Commit

Permalink
feat: add cvToJSON
Browse files Browse the repository at this point in the history
  • Loading branch information
friedger authored and yknl committed Dec 9, 2020
1 parent 7fa1453 commit 36e2138
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 5 deletions.
49 changes: 47 additions & 2 deletions packages/transactions/src/clarity/clarityValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,51 @@ export function cvToString(val: ClarityValue, encoding: 'tryAscii' | 'hex' = 'he
}
}

export function cvToValue(val: ClarityValue): any {
switch (val.type) {
case ClarityType.BoolTrue:
return true;
case ClarityType.BoolFalse:
return false;
case ClarityType.Int:
return val.value.fromTwos(CLARITY_INT_SIZE).toNumber();
case ClarityType.UInt:
return val.value.toNumber();
case ClarityType.Buffer:
return `0x${val.buffer.toString('hex')}`;
case ClarityType.OptionalNone:
return null;
case ClarityType.OptionalSome:
return cvToJSON(val.value);
case ClarityType.ResponseErr:
return cvToJSON(val.value);
case ClarityType.ResponseOk:
return cvToJSON(val.value);
case ClarityType.PrincipalStandard:
case ClarityType.PrincipalContract:
return principalToString(val);
case ClarityType.List:
return val.list.map(v => cvToJSON(v));
case ClarityType.Tuple:
return Object.keys(val.data).map(key => cvToJSON(val.data[key], key));
case ClarityType.StringASCII:
return val.data;
case ClarityType.StringUTF8:
return val.data;
}
}

export function cvToJSON(val: ClarityValue, name?: string): any {
switch (val.type) {
case ClarityType.ResponseErr:
return { name, type: getCVTypeString(val), value: cvToValue(val), success: false };
case ClarityType.ResponseOk:
return { name, type: getCVTypeString(val), value: cvToValue(val), success: true };
default:
return { name, type: getCVTypeString(val), value: cvToValue(val) };
}
}

export function getCVTypeString(val: ClarityValue): string {
switch (val.type) {
case ClarityType.BoolTrue:
Expand All @@ -112,9 +157,9 @@ export function getCVTypeString(val: ClarityValue): string {
case ClarityType.OptionalSome:
return `(optional ${getCVTypeString(val.value)})`;
case ClarityType.ResponseErr:
return `(responseError ${getCVTypeString(val.value)})`;
return `(response UnknownType ${getCVTypeString(val.value)})`;
case ClarityType.ResponseOk:
return `(responseOk ${getCVTypeString(val.value)})`;
return `(response ${getCVTypeString(val.value)} UnknownType)`;
case ClarityType.PrincipalStandard:
case ClarityType.PrincipalContract:
return 'principal';
Expand Down
66 changes: 63 additions & 3 deletions packages/transactions/tests/clarity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
StringUtf8CV,
} from '../src/clarity';
import { BufferReader } from '../src/bufferReader';
import { cvToString } from '../src/clarity/clarityValue';
import { cvToString, cvToJSON } from '../src/clarity/clarityValue';

const ADDRESS = 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B';

Expand Down Expand Up @@ -291,7 +291,7 @@ describe('Clarity Types', () => {
test('Ascii String Escaped Length', () => {
const strings = [
stringAsciiCV('\\'),
stringAsciiCV('\"'),
stringAsciiCV('"'),
stringAsciiCV('\n'),
stringAsciiCV('\t'),
stringAsciiCV('\r'),
Expand All @@ -303,7 +303,7 @@ describe('Clarity Types', () => {
const serializedStringLenByte = reader.readBuffer(5)[4];
expect(serializedStringLenByte).toEqual(1);
expect(ser.length).toEqual(6);
})
});
});

test('Utf8 String Vector', () => {
Expand Down Expand Up @@ -363,4 +363,64 @@ describe('Clarity Types', () => {
expect(cvToString(bufferCV(Buffer.from([127])))).toEqual('0x7f');
});
});

describe('Clarity value to JSON', () => {
test('Complex Tuple', () => {
const tuple = tupleCV({
a: intCV(-1),
b: uintCV(1),
c: bufferCV(Buffer.from('test')),
d: trueCV(),
e: someCV(trueCV()),
f: noneCV(),
g: standardPrincipalCV(ADDRESS),
h: contractPrincipalCV(ADDRESS, 'test'),
i: responseOkCV(trueCV()),
j: responseErrorCV(falseCV()),
k: listCV([trueCV(), falseCV()]),
l: tupleCV({
a: trueCV(),
b: falseCV(),
}),
m: stringAsciiCV('hello world'),
n: stringUtf8CV('hello \u{1234}'),
});

const tupleString = JSON.stringify(cvToJSON(tuple));

expect(tupleString).toEqual(
oneLineTrim`
{"type":"(tuple (a int) (b uint) (c (buff 4)) (d bool) (e (optional bool))
(f (optional none)) (g principal) (h principal) (i (response bool UnknownType))
(j (response UnknownType bool)) (k (list 2 bool)) (l (tuple (a bool) (b bool)))
(m (string-ascii 11)) (n (string-utf8 9)))",
"value":[
{"name":"a","type":"int","value":-1},
{"name":"b","type":"uint","value":1},
{"name":"c","type":"(buff 4)","value":"0x74657374"},
{"name":"d","type":"bool","value":true},
{"name":"e","type":"(optional bool)","value":{"type":"bool","value":true}},
{"name":"f","type":"(optional none)","value":null},
{"name":"g","type":"principal","value":"SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B"},
{"name":"h","type":"principal","value":"SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B.test"},
{"name":"i","type":"(response bool UnknownType)","value":{"type":"bool","value":true},"success":true},
{"name":"j","type":"(response UnknownType bool)","value":{"type":"bool","value":false},"success":false},
{"name":"k","type":"(list 2 bool)","value":[{"type":"bool","value":true},{"type":"bool","value":false}]},
{"name":"l","type":"(tuple (a bool) (b bool))",
"value":[{"name":"a","type":"bool","value":true},{"name":"b","type":"bool","value":false}]},
{"name":"m","type":"(string-ascii 11)","value":"hello world"},
{"name":"n","type":"(string-utf8 9)","value":"hello \u{1234}"}]
}`
);
});

test('Hex Buffer', () => {
expect(JSON.stringify(cvToJSON(bufferCV(Buffer.from('\n', 'ascii'))))).toEqual(
oneLineTrim`
{"type":"(buff 1)",
"value":"0x0a"}
`
);
});
});
});

0 comments on commit 36e2138

Please sign in to comment.