Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement isClarityType #1597

Merged
merged 3 commits into from Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 40 additions & 0 deletions packages/transactions/src/clarity/clarityValue.ts
Expand Up @@ -13,6 +13,8 @@ import {
StringUtf8CV,
NoneCV,
SomeCV,
TrueCV,
FalseCV,
} from '.';

import { principalToString } from './types/principalCV';
Expand Down Expand Up @@ -169,3 +171,41 @@ export function getCVTypeString(val: ClarityValue): string {
return `(string-utf8 ${utf8ToBytes(val.data).length})`;
}
}

type ClarityTypetoValue = {
[ClarityType.OptionalNone]: NoneCV;
[ClarityType.OptionalSome]: SomeCV;
[ClarityType.ResponseOk]: ResponseOkCV;
[ClarityType.ResponseErr]: ResponseErrorCV;
[ClarityType.BoolTrue]: TrueCV;
[ClarityType.BoolFalse]: FalseCV;
[ClarityType.Int]: IntCV;
[ClarityType.UInt]: UIntCV;
[ClarityType.StringASCII]: StringAsciiCV;
[ClarityType.StringUTF8]: StringUtf8CV;
[ClarityType.PrincipalStandard]: StandardPrincipalCV;
[ClarityType.PrincipalContract]: ContractPrincipalCV;
[ClarityType.List]: ListCV;
[ClarityType.Tuple]: TupleCV;
[ClarityType.Buffer]: BufferCV;
};

/**
* @description narrow down the type of a generic ClarityValue
hugocaillard marked this conversation as resolved.
Show resolved Hide resolved
* @example
* ```ts
* // some functions can return a generic `ClarityValue` type
* let value = callReadOnlyFunction();
* // ^ ClarityValue
* // use `isClarityType` to narrow down the type
* assert(isClarityType(value, ClarityType.Int))
* console.log(value)
* // ^ IntCV
* ```
*/
export function isClarityType<T extends ClarityType>(
input: ClarityValue,
withType: T
): input is ClarityTypetoValue[T] {
return input.type === withType;
}
10 changes: 9 additions & 1 deletion packages/transactions/src/clarity/index.ts
@@ -1,4 +1,11 @@
import { ClarityValue, getCVTypeString, cvToString, cvToJSON, cvToValue } from './clarityValue';
import {
ClarityValue,
getCVTypeString,
cvToString,
cvToJSON,
cvToValue,
isClarityType,
} from './clarityValue';
import { ClarityType } from './constants';
import { BooleanCV, TrueCV, FalseCV, trueCV, falseCV, boolCV } from './types/booleanCV';
import { IntCV, UIntCV, intCV, uintCV } from './types/intCV';
Expand Down Expand Up @@ -91,6 +98,7 @@ export {
stringAsciiCV,
stringUtf8CV,
getCVTypeString,
isClarityType,
};

// Serialization
Expand Down
36 changes: 33 additions & 3 deletions packages/transactions/tests/clarity.test.ts
Expand Up @@ -10,6 +10,7 @@ import { BytesReader } from '../src/bytesReader';
import {
bufferCV,
BufferCV,
ClarityType,
ClarityValue,
contractPrincipalCV,
contractPrincipalCVFromStandard,
Expand Down Expand Up @@ -38,9 +39,17 @@ import {
uintCV,
UIntCV,
} from '../src/clarity';
import { cvToJSON, cvToString, cvToValue, getCVTypeString } from '../src/clarity/clarityValue';
import { Cl } from '../src';
import {
cvToJSON,
cvToString,
cvToValue,
getCVTypeString,
isClarityType,
} from '../src/clarity/clarityValue';
import { addressToString } from '../src/common';
import { deserializeAddress } from '../src/types';
import assert from 'assert';

const ADDRESS = 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B';

Expand Down Expand Up @@ -423,9 +432,8 @@ describe('Clarity Types', () => {

// Test lexicographic ordering of tuple keys (to match Node Buffer compare)
const lexicographic = Object.keys(tuple.data).sort((a, b) => {
// eslint-disable-next-line node/prefer-global/buffer
const bufA = Buffer.from(a);
// eslint-disable-next-line node/prefer-global/buffer

const bufB = Buffer.from(b);
return bufA.compare(bufB);
});
Expand Down Expand Up @@ -678,4 +686,26 @@ describe('Clarity Types', () => {
);
});
});

describe('Clarity type narrowing', () => {
it('can narrow strings', () => {
const vUint = Cl.uint(1) as ClarityValue;
expect(isClarityType(vUint, ClarityType.UInt)).toBeTruthy();
expect(isClarityType(vUint, ClarityType.Int)).toBeFalsy();

const vInt = Cl.int(1) as ClarityValue;
expect(isClarityType(vInt, ClarityType.Int)).toBeTruthy();
expect(isClarityType(vInt, ClarityType.UInt)).toBeFalsy();
janniks marked this conversation as resolved.
Show resolved Hide resolved

// test the type assertion

assert(isClarityType(vUint, ClarityType.UInt));
const uintTest: UIntCV = vUint;
uintTest; // avoid the "value is never read warning"

assert(isClarityType(vInt, ClarityType.Int));
const intTest: IntCV = vInt;
intTest; // avoid the "value is never read warning"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

});
});
});