commit 3913aa4344171c63d69bac6c4f69780305ab8b62 Author: Kyle Fang Date: Sat Mar 26 23:58:34 2022 +0800 chore: init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..491fc35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/package.json b/package.json new file mode 100644 index 0000000..2a57457 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "clarity-codegen", + "version": "1.0.0", + "main": "./lib/index.js", + "types": "./lib/index.d.ts", + "files": [ + "lib/" + ], + "license": "MIT", + "bin": { + "clarity-codegen": "./lib/generate/cli.js" + }, + "scripts": { + "build": "rm -rf lib && tsc -p tsconfig.json" + }, + "devDependencies": { + "@types/lodash": "^4.14.180", + "@types/node": "^17.0.23", + "@types/node-fetch": "2", + "@types/yargs": "^17.0.10", + "prettier": "^2.6.1", + "typescript": "^4.6.3", + "lodash": "^4.17.21", + "node-fetch": "2", + "yargs": "^17.4.0", + "@stacks/transactions": "^3.3.0" + }, + "peerDependencies": { + "@stacks/transactions": "*" + } +} diff --git a/src/generate/cli.ts b/src/generate/cli.ts new file mode 100644 index 0000000..3794929 --- /dev/null +++ b/src/generate/cli.ts @@ -0,0 +1,26 @@ +#!/usr/bin/env node +import yargs from "yargs/yargs"; +import { generateContracts } from "./index"; + +(async () => { + const argv = await yargs(process.argv.slice(2)).options({ + apiHost: { type: "string", demandOption: true }, + principal: { type: "string", demandOption: true }, + contracts: { + type: "array", + demandOption: true, + string: true, + required: true, + }, + output: { type: "string", demandOption: true }, + name: { type: "string" }, + }).argv; + + await generateContracts( + argv.apiHost, + argv.principal, + argv.contracts, + argv.output, + argv.name ?? "Alex" + ); +})(); diff --git a/src/generate/contractAbi.ts b/src/generate/contractAbi.ts new file mode 100644 index 0000000..16a1d55 --- /dev/null +++ b/src/generate/contractAbi.ts @@ -0,0 +1,135 @@ +// From https://github.com/blockstack/stacks-blockchain-sidecar/blob/master/src/event-stream/contract-abi.ts + +export type ClarityAbiTypeBuffer = { buffer: { length: number } }; +export type ClarityAbiTypeStringAscii = { 'string-ascii': { length: number } }; +export type ClarityAbiTypeStringUtf8 = { 'string-utf8': { length: number } }; +export type ClarityAbiTypeResponse = { + response: { ok: ClarityAbiType; error: ClarityAbiType }; +}; +export type ClarityAbiTypeOptional = { optional: ClarityAbiType }; +export type ClarityAbiTypeTuple = { + tuple: { name: string; type: ClarityAbiType }[]; +}; +export type ClarityAbiTypeList = { + list: { type: ClarityAbiType; length: number }; +}; + +export type ClarityAbiTypeUInt128 = 'uint128'; +export type ClarityAbiTypeInt128 = 'int128'; +export type ClarityAbiTypeBool = 'bool'; +export type ClarityAbiTypePrincipal = 'principal'; +export type ClarityAbiTypeTraitReference = 'trait_reference'; +export type ClarityAbiTypeNone = 'none'; + +export type ClarityAbiTypePrimitive = + | ClarityAbiTypeUInt128 + | ClarityAbiTypeInt128 + | ClarityAbiTypeBool + | ClarityAbiTypePrincipal + | ClarityAbiTypeTraitReference + | ClarityAbiTypeNone; + +export type ClarityAbiType = + | ClarityAbiTypePrimitive + | ClarityAbiTypeBuffer + | ClarityAbiTypeResponse + | ClarityAbiTypeOptional + | ClarityAbiTypeTuple + | ClarityAbiTypeList + | ClarityAbiTypeStringAscii + | ClarityAbiTypeStringUtf8 + | ClarityAbiTypeTraitReference; + +export enum ClarityAbiTypeId { + ClarityAbiTypeUInt128 = 1, + ClarityAbiTypeInt128 = 2, + ClarityAbiTypeBool = 3, + ClarityAbiTypePrincipal = 4, + ClarityAbiTypeNone = 5, + ClarityAbiTypeBuffer = 6, + ClarityAbiTypeResponse = 7, + ClarityAbiTypeOptional = 8, + ClarityAbiTypeTuple = 9, + ClarityAbiTypeList = 10, + ClarityAbiTypeStringAscii = 11, + ClarityAbiTypeStringUtf8 = 12, + ClarityAbiTypeTraitReference = 13, +} + +export const isClarityAbiPrimitive = ( + val: ClarityAbiType, +): val is ClarityAbiTypePrimitive => typeof val === 'string'; +export const isClarityAbiBuffer = ( + val: ClarityAbiType, +): val is ClarityAbiTypeBuffer => + (val as ClarityAbiTypeBuffer).buffer !== undefined; +export const isClarityAbiStringAscii = ( + val: ClarityAbiType, +): val is ClarityAbiTypeStringAscii => + (val as ClarityAbiTypeStringAscii)['string-ascii'] !== undefined; +export const isClarityAbiStringUtf8 = ( + val: ClarityAbiType, +): val is ClarityAbiTypeStringUtf8 => + (val as ClarityAbiTypeStringUtf8)['string-utf8'] !== undefined; +export const isClarityAbiResponse = ( + val: ClarityAbiType, +): val is ClarityAbiTypeResponse => + (val as ClarityAbiTypeResponse).response !== undefined; +export const isClarityAbiOptional = ( + val: ClarityAbiType, +): val is ClarityAbiTypeOptional => + (val as ClarityAbiTypeOptional).optional !== undefined; +export const isClarityAbiTuple = ( + val: ClarityAbiType, +): val is ClarityAbiTypeTuple => + (val as ClarityAbiTypeTuple).tuple !== undefined; +export const isClarityAbiList = ( + val: ClarityAbiType, +): val is ClarityAbiTypeList => (val as ClarityAbiTypeList).list !== undefined; + +export interface ClarityAbiFunction { + name: string; + access: 'private' | 'public' | 'read_only'; + args: { + name: string; + type: ClarityAbiType; + }[]; + outputs: { + type: ClarityAbiType; + }; +} + +export interface ClarityAbiVariable { + name: string; + access: 'variable' | 'constant'; + type: ClarityAbiType; +} + +export interface ClarityAbiMap { + name: string; + key: { + name: string; + type: ClarityAbiType; + }[]; + value: { + name: string; + type: ClarityAbiType; + }[]; +} + +export interface ClarityAbiTypeFungibleToken { + name: string; +} + +export interface ClarityAbiTypeNonFungibleToken { + name: string; + type: ClarityAbiType; +} + +export interface ClarityAbi { + functions: ClarityAbiFunction[]; + variables: ClarityAbiVariable[]; + maps: ClarityAbiMap[]; + fungible_tokens: ClarityAbiTypeFungibleToken[]; + non_fungible_tokens: ClarityAbiTypeNonFungibleToken[]; +} diff --git a/src/generate/contractsGenerator.ts b/src/generate/contractsGenerator.ts new file mode 100644 index 0000000..a9130c1 --- /dev/null +++ b/src/generate/contractsGenerator.ts @@ -0,0 +1,298 @@ +import * as fs from "fs"; +import { camelCase } from "lodash"; +import fetch from "node-fetch"; +import path from "path"; +import { inspect } from "util"; +import { + ClarityAbiFunction, + ClarityAbiType, + isClarityAbiBuffer, + isClarityAbiList, + isClarityAbiOptional, + isClarityAbiPrimitive, + isClarityAbiResponse, + isClarityAbiStringAscii, + isClarityAbiStringUtf8, + isClarityAbiTuple, +} from "./contractAbi"; +import { assertNever, mapValues } from "../utils/helpers"; + +type TranscoderDefArgument = TranscoderDef | Record; +type TranscoderDef = [string, ...TranscoderDefArgument[]]; + +const toTranscoderDef = ({ + name, + type, +}: { + name?: string; + type: ClarityAbiType; +}): { def: TranscoderDef } => { + if (isClarityAbiPrimitive(type)) { + if (type === "uint128" || type === "int128") { + return { def: ["numberT"] }; + } else if (type === "bool") { + return { def: ["booleanT"] }; + } else if (type === "principal" || type === "trait_reference") { + return { def: ["principalT"] }; + } else if (type === "none") { + return { def: ["noneT"] }; + } else { + assertNever(type); + } + } + + if (isClarityAbiStringUtf8(type) || isClarityAbiStringAscii(type)) { + return { def: ["stringT"] }; + } + + if (isClarityAbiBuffer(type)) { + return { def: ["bufferT"] }; + } + + if (isClarityAbiOptional(type)) { + return { + def: ["optionalT", toTranscoderDef({ type: type.optional }).def], + }; + } + + if (isClarityAbiResponse(type)) { + return { + def: ["responseSimpleT", toTranscoderDef({ type: type.response.ok }).def], + }; + } + + if (isClarityAbiList(type)) { + const list = type.list; + return { + def: [`listT`, toTranscoderDef({ type: list.type }).def], + }; + } + + if (isClarityAbiTuple(type)) { + const tuple = type.tuple; + const result = tuple.reduce( + (acc, c) => ({ + ...acc, + [c.name]: toTranscoderDef({ type: c.type }).def, + }), + {} + ); + + return { + def: ["tupleT", result], + }; + } + + console.warn(`${name}: ${JSON.stringify(type)} is not a supported type`); + assertNever(type); +}; + +const walkTranscoderDef = ( + res: TranscoderDef, + callbacks: { + onTranscoderDefStart?: (result: TranscoderDef) => void; + + onTranscoderDefEnd?: (result: TranscoderDef) => void; + + /** + * return `false` to prevent walk into this rest + */ + onTranscoderDefArgumentStart?: ( + transcoderName: string, + resultRest: TranscoderDefArgument + ) => undefined | boolean; + + onTranscoderDefArgumentEnd?: ( + transcoderName: string, + resultRest: TranscoderDefArgument + ) => void; + } +): void => { + if (res.length < 1) return; + + callbacks.onTranscoderDefStart?.(res); + (res.slice(1) as TranscoderDefArgument[]).forEach((rest) => { + let walkInto: undefined | boolean = true; + + if (callbacks.onTranscoderDefArgumentStart) { + walkInto = callbacks.onTranscoderDefArgumentStart(res[0], rest); + } + + if (walkInto !== false) { + if (Array.isArray(rest)) { + walkTranscoderDef(rest, callbacks); + } else { + mapValues(rest, (result) => { + walkTranscoderDef(result, callbacks); + }); + } + } + + callbacks.onTranscoderDefArgumentEnd?.(res[0], rest); + }); + + callbacks.onTranscoderDefEnd?.(res); +}; + +const getAllTranscoderName = (resAry: TranscoderDef[]): string[] => { + const ret: string[] = []; + + resAry.forEach((res) => { + walkTranscoderDef(res, { + onTranscoderDefStart(res) { + ret.push(res[0]); + }, + }); + }); + + return Array.from(new Set(ret)); +}; + +const stringifyTranscoderDef = (res: TranscoderDef): string => { + let ret = ""; + + walkTranscoderDef(res, { + onTranscoderDefStart(res) { + if (res.length === 1) { + ret += res[0]; + } else { + ret += `${res[0]}(`; + } + }, + onTranscoderDefEnd(res) { + if (res.length !== 1) { + ret += `)`; + } + }, + onTranscoderDefArgumentStart(name, rest) { + if (!Array.isArray(rest)) { + ret += inspect( + mapValues(rest, (i) => ({ + [inspect.custom]: () => stringifyTranscoderDef(i), + })), + { depth: null } + ); + return false; + } + }, + onTranscoderDefArgumentEnd() { + ret += ", "; + }, + }); + + return ret; +}; + +interface FunctionDescriptorDef { + input: { name: string; type: TranscoderDef }[]; + output: TranscoderDef; + mode: "public" | "readonly"; +} + +const toFunctionDescriptorDef = ( + func: ClarityAbiFunction +): void | FunctionDescriptorDef => { + if (func.access === "private") return; + + return { + input: func.args.map((arg) => ({ + name: arg.name, + type: toTranscoderDef(arg).def, + })), + output: toTranscoderDef(func.outputs).def, + mode: func.access === "public" ? "public" : "readonly", + }; +}; + +export const generateContractFromAbi = async ({ + contractName, + principal, + apiHost, + output, + packageName, +}: { + contractName: string; + aliasContractName?: string; + principal: string; + apiHost: string; + output: string; + packageName: string; +}): Promise => { + const url = `${apiHost}/v2/contracts/interface/${principal}/${contractName}`; + const interfaceData = (await fetch(url).then((res) => res.json())) as any; + const functions: Array = interfaceData.functions; + + if (functions.length === 0) return; + + const funcDefs = functions.reduce((acc, func) => { + const res = toFunctionDescriptorDef(func); + if (res) acc[func.name] = res; + return acc; + }, {} as Record); + + const transcoderNames = getAllTranscoderName( + Object.values(funcDefs).flatMap((funcDef) => [ + ...funcDef.input.map((i) => i.type), + funcDef.output, + ]) + ); + + const source = ` +import { +defineContract, +${transcoderNames.join(",\n")} +} from "${packageName}" + +export const ${camelCase(contractName)} = defineContract({ +"${contractName}": ${inspect( + mapValues(funcDefs, (o) => ({ + input: o.input.map((i) => ({ + name: i.name, + type: { + [inspect.custom]: () => stringifyTranscoderDef(i.type), + }, + })), + output: { + [inspect.custom]: () => stringifyTranscoderDef(o.output), + }, + mode: o.mode, + })), + { depth: null } + )} +} as const) + + +`; + + fs.writeFileSync( + path.resolve(output, `./contract_${contractName}.ts`), + source + ); +}; + +export const contractGenerator = async ({ + contracts, + name, + output, + packageName, +}: { + contracts: string[]; + name: string; + output: string; + packageName: string; +}): Promise => { + const importsObjects = contracts.map((n) => `...${camelCase(n)}`); + const importsHeaders = contracts.map( + (n) => `import { ${camelCase(n)} } from "./contract_${n}"` + ); + const code = `import { defineContract } from "${packageName}"; +${importsHeaders.join("\n")} + +export const ${name}Contracts = defineContract({ +${importsObjects.join(",\n")} +}); + + `; /*? */ + + fs.writeFileSync(path.resolve(output, `./contracts_${name}.ts`), code); +}; diff --git a/src/generate/index.ts b/src/generate/index.ts new file mode 100644 index 0000000..8a9e7cb --- /dev/null +++ b/src/generate/index.ts @@ -0,0 +1,31 @@ +import { + contractGenerator, + generateContractFromAbi, +} from "./contractsGenerator"; + +export async function generateContracts( + apiHost: string, + principal: string, + contracts: string[], + output: string, + name: string, + packageName: string = "clarity-codegen" +) { + for (const cname of contracts) { + console.log(`Generating contract ${principal}.${cname}`); + await generateContractFromAbi({ + apiHost: apiHost, + principal: principal, + contractName: cname, + output, + packageName, + }).catch(console.error); + } + + await contractGenerator({ + contracts: contracts, + output: output, + name, + packageName, + }); +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ef7a5ec --- /dev/null +++ b/src/index.ts @@ -0,0 +1,2 @@ +export * from "./runtime/contractBase"; +export * from "./runtime/transcoders"; diff --git a/src/runtime/contractBase.ts b/src/runtime/contractBase.ts new file mode 100644 index 0000000..2b1c31c --- /dev/null +++ b/src/runtime/contractBase.ts @@ -0,0 +1,72 @@ +import { Transcoder } from "./types"; + +export type ReadonlyFunctionDescriptor = { + mode: "readonly"; + input: readonly { name: string; type: Transcoder }[]; + output: Transcoder; +}; + +export type OpenCallFunctionDescriptor = { + mode: "public"; + input: readonly { name: string; type: Transcoder }[]; + output: Transcoder; +}; + +export type FunctionDescriptor = + | ReadonlyFunctionDescriptor + | OpenCallFunctionDescriptor; + +export type ParametersOfDescriptor = D extends FunctionDescriptor + ? D extends { + input: infer Input; + } + ? Input extends readonly { name: string; type: Transcoder }[] + ? { + [K in keyof Input]: Input[K] extends { type: Transcoder } + ? T + : never; + } + : never + : never + : never; + +type ParameterObjOfDescriptorPickType = T extends { + name: N; + type: Transcoder; +} + ? R + : never; +export type ParameterObjOfDescriptor = D extends FunctionDescriptor + ? D extends { + input: infer Input; + } + ? Input extends readonly { name: string; type: Transcoder }[] + ? { + [K in Input[number]["name"]]: ParameterObjOfDescriptorPickType< + Input[number], + K + >; + } + : never + : never + : never; + +export type ReturnTypeOfDescriptor = D extends FunctionDescriptor + ? D extends { + output: infer Output; + } + ? Output extends Transcoder + ? T + : never + : never + : never; + +export function defineContract< + T extends { + [contracts: string]: { + [func: string]: FunctionDescriptor; + }; + } +>(contracts: T): T { + return contracts; +} diff --git a/src/runtime/decoders.ts b/src/runtime/decoders.ts new file mode 100644 index 0000000..0f99a0c --- /dev/null +++ b/src/runtime/decoders.ts @@ -0,0 +1,143 @@ +import { + addressToString, + ClarityType, + ClarityValue, +} from "@stacks/transactions" +import { Decoder, UnboxDecoder } from "./types" + +export class ClarityError extends Error { + constructor(readonly code: number) { + super() + } +} + +export const boolResult: Decoder = result => { + if (result.type === ClarityType.BoolTrue) { + return true + } + if (result.type === ClarityType.BoolFalse) { + return false + } + throw new Error(`Expected integer, got ${result.type}`) +} + +export const principleResult: Decoder = result => { + if (result.type === ClarityType.PrincipalStandard) { + return addressResult(result) + } else if (result.type === ClarityType.PrincipalContract) { + return contractResult(result) + } + throw new Error(`Expected principal, got ${result.type}`) +} + +export const addressResult: Decoder = result => { + if (result.type === ClarityType.PrincipalStandard) { + return addressToString(result.address) + } + throw new Error(`Expected principal, got ${result.type}`) +} + +export const contractResult: Decoder = result => { + if (result.type === ClarityType.PrincipalContract) { + return result.contractName.content + } + throw new Error(`Expected principal, got ${result.type}`) +} + +export const intResult: Decoder = result => { + if (result.type === ClarityType.Int || result.type === ClarityType.UInt) { + return Number(result.value) + } + throw new Error(`Expected integer, got ${result.type}`) +} + +export const stringResult: Decoder = result => { + if ( + result.type === ClarityType.StringASCII || + result.type === ClarityType.StringUTF8 + ) { + return result.data + } + throw new Error(`Expected string, got ${result.type}`) +} + +export const bufferResult: Decoder = result => { + if (result.type === ClarityType.Buffer) { + return result.buffer + } + throw new Error(`Expected buffer, got ${result.type}`) +} + +export function responseSimpleDecoder(success: Decoder): Decoder { + return (value: ClarityValue) => { + if (value.type === ClarityType.ResponseErr) { + if ( + value.value.type === ClarityType.StringASCII || + value.value.type === ClarityType.StringUTF8 + ) { + throw new Error(value.value.data) + } + + if ( + value.value.type === ClarityType.UInt || + value.value.type === ClarityType.Int + ) { + throw new ClarityError(Number(value.value.value)) + } + + throw new Error("Unknown error") + } + + if (value.type === ClarityType.ResponseOk) { + return success(value.value) + } + + return success(value) + } +} + +export function optionalDecoder( + decoder: Decoder, +): Decoder { + return value => { + if (value.type === ClarityType.OptionalNone) { + return undefined + } else if (value.type === ClarityType.OptionalSome) { + return decoder(value.value) + } + return decoder(value) + } +} + +export const noneResult: Decoder = result => { + if (result.type === ClarityType.OptionalNone) { + return null + } + throw new Error(`Expected none, got ${result.type}`) +} + +export function tupleDecoder

>>( + decorators: P, +): Decoder<{ + [K in keyof P]: UnboxDecoder +}> { + return input => { + if (input.type !== ClarityType.Tuple) { + throw new Error(`Expected tuple, got ${input.type}`) + } + const result = {} as any + for (const key of Object.keys(decorators)) { + result[key] = decorators[key as keyof P]!(input.data[key]!) + } + return result + } +} + +export function listDecoder(decoder: Decoder): Decoder { + return value => { + if (value.type === ClarityType.List) { + return value.list.map(decoder) + } + throw new Error(`Expected list, got ${value.type}`) + } +} diff --git a/src/runtime/encoders.ts b/src/runtime/encoders.ts new file mode 100644 index 0000000..f0ed011 --- /dev/null +++ b/src/runtime/encoders.ts @@ -0,0 +1,80 @@ +import { + BooleanCV, + ContractPrincipalCV, + contractPrincipalCV, + falseCV, + listCV, + noneCV, + PrincipalCV, + responseOkCV, + someCV, + standardPrincipalCV, + trueCV, + tupleCV, + TupleCV, + uintCV, +} from "@stacks/transactions"; +import { Encoder, UnboxEncoder } from "./types"; + +export function tupleEncoder

>>( + decorators: P +): Encoder<{ + [K in keyof P]: UnboxEncoder; +}> { + return (input): TupleCV => { + const result = {} as any; + for (const key of Object.keys(decorators)) { + result[key] = decorators[key as keyof P]!(input[key]!); + } + + return tupleCV(result); + }; +} + +export function listEncoder(encoder: Encoder): Encoder { + return (value) => { + return listCV(value.map(encoder)); + }; +} + +export function responseSimpleEncoder(success: Encoder): Encoder { + return (value: T) => { + return responseOkCV(success(value)); + }; +} + +export function principalCV(principal: string): PrincipalCV { + if (principal.includes(".")) { + const [address, contractName] = principal.split("."); + return contractPrincipalCV(address!, contractName!); + } else { + return standardPrincipalCV(principal); + } +} + +export const traitCV = (val: string): ContractPrincipalCV => { + const [addr, name] = val.split("."); + if (addr && name) { + return contractPrincipalCV(addr, name); + } + throw new Error(`can not parse val as trait: ${val}`); +}; + +export const booleanCV = (value: boolean): BooleanCV => { + if (value) { + return trueCV(); + } else { + return falseCV(); + } +}; + +export const numberCV: Encoder = (input) => uintCV(Math.floor(input)); + +export function optional(encoder: Encoder): Encoder { + return (value) => { + if (value === undefined) { + return noneCV(); + } + return someCV(encoder(value)); + }; +} diff --git a/src/runtime/transcoders.ts b/src/runtime/transcoders.ts new file mode 100644 index 0000000..9d0b866 --- /dev/null +++ b/src/runtime/transcoders.ts @@ -0,0 +1,107 @@ +import { bufferCV, noneCV, stringUtf8CV } from "@stacks/transactions"; +import { + boolResult, + bufferResult, + intResult, + listDecoder, + noneResult, + optionalDecoder, + principleResult, + responseSimpleDecoder, + stringResult, + tupleDecoder, +} from "./decoders"; +import { + booleanCV, + listEncoder, + numberCV, + optional, + principalCV, + responseSimpleEncoder, + tupleEncoder, +} from "./encoders"; +import { Decoder, Encoder, Transcoder, UnboxTranscoder } from "./types"; +import {mapValues} from "../utils/helpers"; + +export function transcoders(constructOptions: { + encode: Encoder; + decode: Decoder; +}): Transcoder { + return constructOptions; +} + +export const numberT = transcoders({ + encode: numberCV, + decode: intResult, +}); + +export const stringT = transcoders({ + encode: stringUtf8CV, + decode: stringResult, +}); + +export const booleanT = transcoders({ + encode: booleanCV, + decode: boolResult, +}); + +export const bufferT = transcoders({ + encode: bufferCV, + decode: bufferResult, +}); + +export const principalT = transcoders({ + encode: principalCV, + decode: principleResult, +}); + +export const listT = ( + listItemTranscoder: Transcoder +): Transcoder => { + return transcoders({ + encode: listEncoder(listItemTranscoder.encode), + decode: listDecoder(listItemTranscoder.decode), + }); +}; + +export const tupleT = >>( + transcoderObj: T +): Transcoder<{ + [K in keyof T]: UnboxTranscoder; +}> => { + const encode = tupleEncoder( + mapValues(transcoderObj, (o) => o.encode) + ) as Encoder<{ + [K in keyof T]: UnboxTranscoder; + }>; + + const decode = tupleDecoder( + mapValues(transcoderObj, (o) => o.decode) + ) as Decoder<{ + [K in keyof T]: UnboxTranscoder; + }>; + + return transcoders({ encode, decode }); +}; + +export const optionalT = ( + someTranscoder: Transcoder +): Transcoder => { + return transcoders({ + encode: optional(someTranscoder.encode), + decode: optionalDecoder(someTranscoder.decode), + }); +}; +export const noneT = transcoders({ + encode: noneCV, + decode: noneResult, +}); + +export const responseSimpleT = ( + okValueTransducer: Transcoder +): Transcoder => { + return transcoders({ + encode: responseSimpleEncoder(okValueTransducer.encode), + decode: responseSimpleDecoder(okValueTransducer.decode), + }); +}; diff --git a/src/runtime/types.ts b/src/runtime/types.ts new file mode 100644 index 0000000..e7ee2f9 --- /dev/null +++ b/src/runtime/types.ts @@ -0,0 +1,24 @@ +import { ClarityValue } from "@stacks/transactions"; + +export type Encoder = (value: T) => ClarityValue; + +export type UnboxEncoder> = T extends Encoder + ? R + : never; + +export type Decoder = (value: ClarityValue) => T; + +export type UnboxDecoder> = T extends Decoder + ? R + : never; + +export interface Transcoder { + encode: Encoder; + decode: Decoder; +} + +export type UnboxTranscoder> = T extends Transcoder< + infer R +> + ? R + : never; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts new file mode 100644 index 0000000..af0b009 --- /dev/null +++ b/src/utils/helpers.ts @@ -0,0 +1,13 @@ +export function mapValues, VO>( + obj: T, + mapping: (value: T[K], key: K) => VO +): Record { + return Object.keys(obj).reduce((acc, key: keyof T): Record => { + acc[key] = mapping(obj[key], key); + return acc; + }, {} as Record); +} + +export function assertNever(x: never): never { + throw new Error("Unexpected object: " + x); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7800ddc --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..91b663a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,393 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@noble/hashes@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" + integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== + +"@noble/secp256k1@^1.5.2": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.5.5.tgz#315ab5745509d1a8c8e90d0bdf59823ccf9bcfc3" + integrity sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ== + +"@stacks/common@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@stacks/common/-/common-3.3.0.tgz#d43a3f32981ba8a2b85027b46d84cfb787f8c4eb" + integrity sha512-PVZiGGvl1WwUa47PCF5mPq3KGik/e+DXQZ7NqHBwNi5GOpjAo0M6nPSF1R+iSnHQ7DHtfXSoIQz8PlCxlYIYKw== + dependencies: + "@types/node" "^14.14.43" + bn.js "^5.2.0" + buffer "^6.0.3" + cross-fetch "^3.1.4" + +"@stacks/network@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@stacks/network/-/network-3.3.0.tgz#1e3b4d0917d1d33720986846de7d0100f36a2610" + integrity sha512-s9YCCBoYCETOT4ssYMvSPXc8pthosq0JqzOpvwTsmqdZB8JQfS/XYzzWoT59Wm3hjaz1AaW9YXNxqvh5DRRs9A== + dependencies: + "@stacks/common" "^3.3.0" + +"@stacks/transactions@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@stacks/transactions/-/transactions-3.3.0.tgz#ccc489196dc406d06271631f28f41937b96de897" + integrity sha512-nYm0OufeaQauHfdxuL5dH12GPhkYux8nHX+eTNua0UW6xyE7KpFdk2oS/oCAI/q3r29MaMKuY7uduqelUIbTew== + dependencies: + "@noble/hashes" "^1.0.0" + "@noble/secp256k1" "^1.5.2" + "@stacks/common" "^3.3.0" + "@stacks/network" "^3.3.0" + "@types/bn.js" "^4.11.6" + "@types/node" "^14.14.43" + "@types/randombytes" "^2.0.0" + "@types/sha.js" "^2.4.0" + bn.js "^5.2.0" + c32check "^1.1.3" + cross-fetch "^3.1.4" + lodash.clonedeep "^4.5.0" + randombytes "^2.1.0" + ripemd160-min "^0.0.6" + sha.js "^2.4.11" + smart-buffer "^4.1.0" + +"@types/bn.js@^4.11.6": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/lodash@^4.14.180": + version "4.14.180" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670" + integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g== + +"@types/node-fetch@2": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*", "@types/node@^17.0.23": + version "17.0.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" + integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + +"@types/node@^14.14.43": + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== + +"@types/randombytes@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/randombytes/-/randombytes-2.0.0.tgz#0087ff5e60ae68023b9bc4398b406fea7ad18304" + integrity sha512-bz8PhAVlwN72vqefzxa14DKNT8jK/mV66CSjwdVQM/k3Th3EPKfUtdMniwZgMedQTFuywAsfjnZsg+pEnltaMA== + dependencies: + "@types/node" "*" + +"@types/sha.js@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/sha.js/-/sha.js-2.4.0.tgz#bce682ef860b40f419d024fa08600c3b8d24bb01" + integrity sha512-amxKgPy6WJTKuw8mpUwjX2BSxuBtBmZfRwIUDIuPJKNwGN8CWDli8JTg5ONTWOtcTkHIstvT7oAhhYXqEjStHQ== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.10": + version "17.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" + integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== + dependencies: + "@types/yargs-parser" "*" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bn.js@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +c32check@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/c32check/-/c32check-1.1.3.tgz#232890e4d788afbd4e97e2611a3c251aa63e5977" + integrity sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A== + dependencies: + base-x "^3.0.8" + buffer "^5.6.0" + cross-sha256 "^1.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +cross-fetch@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +cross-sha256@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/cross-sha256/-/cross-sha256-1.2.0.tgz#d7b941d17920a1781b8d2d03a1e55700c75b2082" + integrity sha512-KViLNMDZKV7jwFqjFx+rNhG26amnFYYQ0S+VaFlVvpk8tM+2XbFia/don/SjGHg9WQxnFVi6z64CGPuF3T+nNw== + dependencies: + buffer "^5.6.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +inherits@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +node-fetch@2, node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +prettier@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.1.tgz#d472797e0d7461605c1609808e27b80c0f9cfe17" + integrity sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +ripemd160-min@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/ripemd160-min/-/ripemd160-min-0.0.6.tgz#a904b77658114474d02503e819dcc55853b67e62" + integrity sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +sha.js@^2.4.11: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +smart-buffer@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + +yargs@^17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.0.tgz#9fc9efc96bd3aa2c1240446af28499f0e7593d00" + integrity sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0"