scryptlib
Version:
Javascript SDK for integration of Bitcoin SV Smart Contracts written in sCrypt language.
787 lines • 31.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildTypeResolver = exports.buildTypeResolverFromArtifact = exports.buildContractClass = exports.AbstractContract = exports.SUPPORTED_MINIMUM_VERSION = exports.CURRENT_CONTRACT_ARTIFACT_VERSION = void 0;
const path_1 = require("path");
const _1 = require(".");
const compilerWrapper_1 = require("./compilerWrapper");
const internal_1 = require("./internal");
const scryptTypes_1 = require("./scryptTypes");
const stateful_1 = require("./stateful");
const typeCheck_1 = require("./typeCheck");
exports.CURRENT_CONTRACT_ARTIFACT_VERSION = 9;
exports.SUPPORTED_MINIMUM_VERSION = 8;
class AbstractContract {
// eslint-disable-next-line @typescript-eslint/no-empty-function
/* eslint-disable @typescript-eslint/no-unused-vars */
constructor(...ctorParams) {
this.calledPubFunctions = [];
// This will be set to true, if the contract will expect inline ASM variable values to be set.
this.hasInlineASMVars = false;
this.hexTemplateInlineASM = new Map();
this.hexTemplateArgs = new Map();
this.statePropsArgs = [];
// If true, the contract will read the state from property, if false, the contract will read the state from preimage
// A newly constructed contract always has this set to true, and after invocation, always has it set to false
this.isGenesis = true;
}
get lockingScript() {
if (this.hasInlineASMVars && this.hexTemplateInlineASM.size === 0) {
throw new Error('Values for inline ASM variables have not yet been set! Cannot get locking script.');
}
if (!this.dataPart) {
return this._wrapNOPScript(this.scriptedConstructor?.lockingScript);
}
// append dataPart script to codePart if there is dataPart
return this.codePart.add(this.dataPart);
}
_wrapNOPScript(lockingScript) {
if (this.nopScript) {
return this.nopScript.clone().add(lockingScript);
}
return lockingScript;
}
set txContext(txContext) {
this._txContext = txContext;
}
get txContext() {
return this._txContext;
}
get sourceMapFile() {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
return artifact.sourceMapFile;
}
get file() {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
return artifact.file;
}
get contractName() {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
return artifact.contract;
}
get stateProps() {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
return artifact.stateProps || [];
}
get version() {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
return artifact.version || 0;
}
addFunctionCall(f) {
this.calledPubFunctions.push(f);
}
get resolver() {
return Object.getPrototypeOf(this).constructor.resolver;
}
// replace assembly variables with assembly values
replaceAsmVars(asmVarValues) {
if (asmVarValues) {
for (const key in asmVarValues) {
const val = asmVarValues[key];
this.hexTemplateInlineASM.set(`<${key.startsWith('$') ? key.substring(1) : key}>`, internal_1.bsv.Script.fromASM(val).toHex());
}
}
const hexTemplate = Object.getPrototypeOf(this).constructor.hex;
const lockingScript = (0, internal_1.buildContractCode)(this.hexTemplateArgs, this.hexTemplateInlineASM, hexTemplate);
this.scriptedConstructor.lockingScript = lockingScript;
}
// replace assembly variables with assembly values
get asmArgs() {
const result = {};
for (const entry of this.hexTemplateInlineASM.entries()) {
const name = entry[0].replace('<', '').replace('>', '');
const value = entry[1];
result[name] = internal_1.bsv.Script.fromHex(value).toASM();
}
return result;
}
/**
* @param states an object. Each key of the object is the name of a state property, and each value is the value of the state property.
* @returns a locking script that includes the new states. If you only provide some but not all state properties, other state properties are not modified when calculating the locking script.
*/
getNewStateScript(states) {
const stateArgs = this.statePropsArgs;
if (stateArgs.length === 0) {
throw new Error(`Contract ${this.contractName} does not have any stateful property`);
}
const resolveKeys = [];
const newState = stateArgs.map(arg => {
if (Object.prototype.hasOwnProperty.call(states, arg.name)) {
resolveKeys.push(arg.name);
let state = states[arg.name];
state = this.transformerArg(state, arg, true);
const error = (0, typeCheck_1.checkSupportedParamType)(state, arg, this.resolver);
if (error) {
throw error;
}
return Object.assign({
...arg
}, {
value: state
});
}
else {
return arg;
}
});
Object.keys(states).forEach(key => {
if (resolveKeys.indexOf(key) === -1) {
throw new Error(`Contract ${this.contractName} does not have stateful property ${key}`);
}
});
return this.codePart.add(internal_1.bsv.Script.fromHex(stateful_1.default.buildState(newState, false, this.resolver)));
}
run_verify(unlockingScript, txContext) {
const txCtx = Object.assign({}, this._txContext || {}, txContext || {});
let us;
if (typeof unlockingScript === 'string') {
us = unlockingScript.trim() ? internal_1.bsv.Script.fromASM(unlockingScript.trim()) : new internal_1.bsv.Script('');
}
else {
us = unlockingScript ? unlockingScript : new internal_1.bsv.Script('');
}
const ls = internal_1.bsv.Script.fromHex(this.lockingScript.toHex());
const tx = typeof txCtx.tx === 'string' ? new internal_1.bsv.Transaction(txCtx.tx) : txCtx.tx;
const inputIndex = txCtx.inputIndex;
const inputSatoshis = txCtx.inputSatoshis;
internal_1.bsv.Script.Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
internal_1.bsv.Script.Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
const bsi = new internal_1.bsv.Script.Interpreter();
let failedAt = {};
bsi.stepListener = function (step) {
if (step.fExec || (internal_1.bsv.Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= internal_1.bsv.Opcode.OP_ENDIF)) {
if ((internal_1.bsv.Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= internal_1.bsv.Opcode.OP_ENDIF) || step.opcode.toNumber() === internal_1.bsv.Opcode.OP_RETURN) /**Opreturn */ {
failedAt.opcode = step.opcode;
}
else {
failedAt = step;
}
}
};
const result = bsi.verify(us, ls, tx, inputIndex, internal_1.DEFAULT_FLAGS, new internal_1.bsv.crypto.BN(inputSatoshis));
if (result) {
return {
success: true,
error: ''
};
}
if ((bsi.errstr || '').indexOf('SCRIPT_ERR_NULLFAIL') > -1) {
if (!txCtx) {
throw new Error('should provide txContext when verify');
}
if (!tx) {
throw new Error('should provide txContext.tx when verify');
}
}
failedAt.opcode = failedAt.opcode.toNumber();
return {
success: result,
error: this.fmtError({
error: bsi.errstr || '',
failedAt
})
};
}
/**
* format the error
* @param err the result output by `tx.verifyInputScript(inputIndex)`
* @returns string the formatted error message.
*/
fmtError(err) {
const failedOpCode = err.failedAt.opcode;
let error = `VerifyError: ${err.error}, fails at ${new internal_1.bsv.Opcode(failedOpCode)}\n`;
if (this.sourceMapFile) {
const sourceMapFilePath = (0, internal_1.uri2path)(this.sourceMapFile);
const sourceMap = (0, internal_1.JSONParserSync)(sourceMapFilePath);
const sourcePath = (0, path_1.join)(sourceMapFilePath, this.file);
const srcDir = (0, path_1.dirname)(sourcePath);
const sourceFileName = (0, path_1.basename)(sourcePath);
const sources = sourceMap.sources.map((source) => (0, compilerWrapper_1.getFullFilePath)(source, srcDir, sourceFileName));
const pos = (0, internal_1.findSrcInfoV2)(err.failedAt.pc, sourceMap);
if (pos && sources[pos[1]]) {
error = `VerifyError: ${err.error} \n\t[Go to Source](${(0, internal_1.path2uri)(sources[pos[1]])}#${pos[2]}) fails at ${new internal_1.bsv.Opcode(failedOpCode)}\n`;
}
}
else if (this.version <= 8) {
const artifact = Object.getPrototypeOf(this).constructor.artifact;
const sourceMap = (0, compilerWrapper_1.loadSourceMapfromArtifact)(artifact);
if (sourceMap.length > 0) {
// the complete script may have op_return and data, but compiled output does not have it. So we need to make sure the index is in boundary.
const opcodeIndex = err.failedAt.pc;
if (sourceMap[opcodeIndex]) {
const opcode = sourceMap[opcodeIndex];
if (!opcode.pos || opcode.pos.file === 'std') {
const srcInfo = (0, internal_1.findSrcInfoV1)(sourceMap, opcodeIndex);
if (srcInfo) {
opcode.pos = srcInfo.pos;
}
}
// in vscode termianal need to use [:] to jump to file line, but here need to use [#] to jump to file line in output channel.
if (opcode && opcode.pos) {
error = `VerifyError: ${err.error} \n\t[Go to Source](${(0, internal_1.path2uri)(opcode.pos.file)}#${opcode.pos.line}) fails at ${new internal_1.bsv.Opcode(failedOpCode)}\n`;
}
}
}
}
return error;
}
/**
* Generate a debugger launch configuration for the contract's last called public method
* @param txContext
* @returns a uri of the debugger launch configuration
*/
genLaunchConfig(txContext) {
const txCtx = Object.assign({}, this.txContext || {}, txContext || {});
const lastCalledPubFunction = this.lastCalledPubFunction();
if (lastCalledPubFunction) {
const debugUrl = lastCalledPubFunction.genLaunchConfig(txCtx);
return `[Launch Debugger](${debugUrl.replace(/file:/i, 'scryptlaunch:')})\n`;
}
throw new Error('No public function called');
}
set dataPart(dataInScript) {
throw new Error('Setter for dataPart is not available. Please use: setDataPart() instead');
}
get dataPart() {
if (AbstractContract.isStateful(this)) {
const state = stateful_1.default.buildState(this.statePropsArgs, this.isGenesis, this.resolver);
return internal_1.bsv.Script.fromHex(state);
}
if (this._dataPartInHex) {
return internal_1.bsv.Script.fromHex(this._dataPartInHex);
}
}
/**
* @deprecated use setDataPartInASM setDataPartInHex
* set the data part of the contract
* @param state
* @param isStateHex
*/
setDataPart(state, isStateHex = false) {
if (isStateHex == false) {
console.warn('deprecated, using setDataPartInASM');
this.setDataPartInASM(state);
}
else {
console.warn('deprecated, using setDataPartInHex');
this.setDataPartInHex(state);
}
}
/**
* set the data part of the contract in ASM format
* @param asm
* @param
*/
setDataPartInASM(asm) {
if (AbstractContract.isStateful(this)) {
throw new Error('should not use `setDataPartInASM` for a stateful contract, using `setDataPartInHex`');
}
const dataPartInASM = asm.trim();
this.setDataPartInHex(internal_1.bsv.Script.fromASM(dataPartInASM).toHex());
}
/**
* set the data part of the contract in hex format
* @param hex
*/
setDataPartInHex(hex) {
this._dataPartInHex = hex.trim();
if (AbstractContract.isStateful(this)) {
const [isGenesis, args] = stateful_1.default.parseStateHex(this, this._dataPartInHex);
this.statePropsArgs = args;
this.isGenesis = isGenesis;
}
}
prependNOPScript(nopScript) {
if (nopScript instanceof internal_1.bsv.Script) {
(0, internal_1.checkNOPScript)(nopScript);
}
this.nopScript = nopScript;
}
getPrependNOPScript() {
return this.nopScript;
}
get codePart() {
const contractScript = this.scriptedConstructor.toScript();
// note: do not trim the trailing space
return this._wrapNOPScript(contractScript.clone()).add(internal_1.bsv.Script.fromHex('6a'));
}
get codeHash() {
if (this.dataPart) {
return (0, internal_1.hash160)(this.codePart.toHex());
}
else {
return (0, internal_1.hash160)(this.lockingScript.toHex());
}
}
static getAsmVars(lockingScriptHex) {
const instance = this.fromHex(lockingScriptHex);
return instance.asmArgs;
}
arguments(pubFuncName) {
if (pubFuncName === 'constructor') {
return this.scriptedConstructor.args;
}
for (let i = this.calledPubFunctions.length - 1; i >= 0; i--) {
const called = this.calledPubFunctions[i];
if (called.methodName === pubFuncName) {
return called.args;
}
}
return [];
}
lastCalledPubFunction() {
const index = this.calledPubFunctions.length - 1;
if (index < 0) {
return undefined;
}
return this.calledPubFunctions[index];
}
ctorArgs() {
return this.arguments('constructor');
}
/**
* Get the parameter of the constructor and inline asm vars,
* all values is hex string, need convert it to number or bytes on using
*/
get asmVars() {
return this.ContractClass.getAsmVars(this.scriptedConstructor.toHex());
}
get ContractClass() {
return Object.getPrototypeOf(this).constructor;
}
transformerArgs(args, params, state) {
return params.map((p, index) => this.transformerArg(args[index], p, state));
}
transformerArg(arg, param, state) {
const typeInfo = this.resolver(param.type);
if ((0, internal_1.isArrayType)(typeInfo.finalType)) {
/* eslint-disable @typescript-eslint/no-unused-vars */
const [_, arraySizes] = (0, typeCheck_1.arrayTypeAndSize)(typeInfo.finalType);
if (!Array.isArray(arg)) {
return arg;
}
if (arg.length !== arraySizes[0]) {
return arg;
}
const subType = (0, typeCheck_1.subArrayType)(param.type);
const results = [];
for (let i = 0; i < arraySizes[0]; i++) {
const elem = arg[i];
results.push(this.transformerArg(elem, {
name: `${param.name}${(0, internal_1.subscript)(i, arraySizes)}`,
type: subType
}, state));
}
return results;
}
else if (typeInfo.symbolType === scryptTypes_1.SymbolType.Library) {
const entity = typeInfo.info;
if (entity.name === 'HashedMap') {
if (arg instanceof Map) {
if (state) {
return {
_data: this.ContractClass.toData(arg, param.type)
};
}
else {
return [this.ContractClass.toData(arg, param.type)];
}
}
}
else if (entity.name === 'HashedSet') {
if (arg instanceof Set) {
if (state) {
return {
_data: this.ContractClass.toData(arg, param.type)
};
}
else {
return [this.ContractClass.toData(arg, param.type)];
}
}
}
const params = state ? entity.properties : entity.params;
if (!state && Array.isArray(arg)) {
return params.map((p, index) => {
return this.transformerArg(arg[index], p, state);
});
}
else if (state && typeof arg === 'object') {
return params.reduce((acc, p) => {
Object.assign(acc, {
[p.name]: this.transformerArg(arg[p.name], p, state)
});
return acc;
}, {});
}
}
else if (typeInfo.symbolType === scryptTypes_1.SymbolType.Struct) {
if (!Array.isArray(arg) && typeof arg === 'object') {
const entity = typeInfo.info;
if (entity.name === 'SortedItem') {
if (arg['idx'] === (0, scryptTypes_1.Int)(-1) && (arg['image'] instanceof Map || arg['image'] instanceof Set)) {
/* eslint-disable @typescript-eslint/no-unused-vars */
const [_, genericTypes] = (0, _1.parseGenericType)(typeInfo.finalType);
return Object.assign({}, {
idx: this.ContractClass.findKeyIndex(arg['image'], arg['item'], genericTypes[0]),
item: arg['item']
});
}
return arg;
}
const clone = Object.assign({}, arg);
entity.params.forEach(property => {
if (typeof arg[property.name] !== 'undefined') {
clone[property.name] = this.transformerArg(arg[property.name], property, state);
}
});
return clone;
}
}
else if (typeof arg === 'number') {
return BigInt(arg);
}
return arg;
}
checkArgs(funname, params, ...args) {
if (args.length !== params.length) {
throw new Error(`wrong number of arguments for '${this.contractName}.${funname}', expected ${params.length} but got ${args.length}`);
}
const args_ = this.transformerArgs(args, params, false);
params.forEach((param, index) => {
const arg = args_[index];
const error = (0, typeCheck_1.checkSupportedParamType)(arg, param, this.resolver);
if (error)
throw error;
});
return args_;
}
static fromASM(asm) {
return this.fromHex(internal_1.bsv.Script.fromASM(asm).toHex());
}
static fromHex(hex) {
this.asmContract = true;
const ctor = this;
const obj = new ctor();
this.asmContract = false;
obj.scriptedConstructor = this.abiCoder.encodeConstructorCallFromRawHex(obj, this.hex, hex);
return obj;
}
static fromTransaction(hex, outputIndex = 0) {
const tx = new internal_1.bsv.Transaction(hex);
return this.fromHex(tx.outputs[outputIndex].script.toHex());
}
static isStateful(contract) {
return contract.stateProps.length > 0;
}
// struct / array: sha256 every single element of the flattened struct / array, and concat the result to a joint byte, and sha256 again
// basic type: sha256 every single element
static flattenSha256(data, type) {
const error = (0, typeCheck_1.checkSupportedParamType)(data, {
name: '',
type: type
}, this.resolver);
if (error)
throw error;
const flattened = (0, typeCheck_1.flatternArg)({
name: '',
type: type,
value: data
}, this.resolver, {
state: true,
ignoreValue: false
});
if (flattened.length === 1) {
const hex = stateful_1.default.serialize(flattened[0].value, flattened[0].type);
return internal_1.bsv.crypto.Hash.sha256(Buffer.from(hex, 'hex')).toString('hex');
}
else {
const jointbytes = flattened.map(item => {
const hex = stateful_1.default.serialize(item.value, item.type);
return internal_1.bsv.crypto.Hash.sha256(Buffer.from(hex, 'hex')).toString('hex');
}).join('');
return internal_1.bsv.crypto.Hash.sha256(Buffer.from(jointbytes, 'hex')).toString('hex');
}
}
// sort the map by the result of flattenSha256 of the key
static sortmap(map, keyType) {
return new Map([...map.entries()].sort((a, b) => {
return internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(a[0], keyType), 'hex'), {
endian: 'little'
}).cmp(internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(b[0], keyType), 'hex'), {
endian: 'little'
}));
}));
}
// sort the set by the result of flattenSha256 of the key
static sortset(set, keyType) {
return new Set([...set.keys()].sort((a, b) => {
return internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(a, keyType), 'hex'), {
endian: 'little'
}).cmp(internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(b, keyType), 'hex'), {
endian: 'little'
}));
}));
}
static sortkeys(keys, keyType) {
return keys.sort((a, b) => {
return internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(a, keyType), 'hex'), {
endian: 'little'
}).cmp(internal_1.bsv.crypto.BN.fromSM(Buffer.from(this.flattenSha256(b, keyType), 'hex'), {
endian: 'little'
}));
});
}
// returns index of the HashedMap/HashedSet by the key
static findKeyIndex(collection, key, keyType) {
const keys = [...collection.keys()];
keys.push(key);
const sortedKeys = this.sortkeys(keys, keyType);
const index = sortedKeys.findIndex((entry) => {
if (entry === key) {
return true;
}
return false;
});
return BigInt(index);
}
//serialize the HashedMap / HashedSet, but only flattenSha256 of the key and value
static toData(collection, collectionType) {
/* eslint-disable @typescript-eslint/no-unused-vars */
const [_, genericTypes] = (0, _1.parseGenericType)(collectionType);
let storage = '';
if (collection instanceof Map) {
const sortedMap = this.sortmap(collection, genericTypes[0]);
for (const entry of sortedMap.entries()) {
storage += this.flattenSha256(entry[0], genericTypes[0]) + this.flattenSha256(entry[1], genericTypes[1]);
}
}
else {
const sortedSet = this.sortset(collection, genericTypes[0]);
for (const key of sortedSet.keys()) {
storage += this.flattenSha256(key, genericTypes[0]);
}
}
return (0, scryptTypes_1.Bytes)(storage);
}
}
exports.AbstractContract = AbstractContract;
const invalidMethodName = ['arguments',
'setDataPart',
'setDataPartInASM',
'setDataPartInHex',
'version',
'stateProps',
'sourceMapFile',
'file',
'contractName',
'ctorArgs',
'run_verify',
'replaceAsmVars',
'asmVars',
'asmArguments',
'dataPart',
'lockingScript',
'codeHash',
'codePart',
'resolver',
'getNewStateScript',
'txContext'];
function buildContractClass(artifact) {
if (artifact instanceof internal_1.CompileResult) {
artifact = artifact.toArtifact();
}
if (!artifact.contract) {
throw new Error('Missing field `contract` in artifact');
}
if (!artifact.version) {
throw new Error('Missing field `version` in artifact');
}
if (artifact.version < exports.SUPPORTED_MINIMUM_VERSION) {
throw new Error(`Contract artifact version deprecated, The minimum version number currently supported is ${exports.SUPPORTED_MINIMUM_VERSION}`);
}
if (!artifact.abi) {
throw new Error('Missing field `abi` in artifact');
}
if (!artifact.hex) {
throw new Error('Missing field `hex` in artifact');
}
const ContractClass = class extends AbstractContract {
constructor(...ctorParams) {
super();
if (!ContractClass.asmContract) {
this.scriptedConstructor = ContractClass.abiCoder.encodeConstructorCall(this, ContractClass.hex, ...ctorParams);
}
}
};
ContractClass.artifact = artifact;
ContractClass.resolver = buildTypeResolverFromArtifact(artifact);
ContractClass.abi = artifact.abi;
ContractClass.hex = artifact.hex;
ContractClass.abiCoder = new internal_1.ABICoder(artifact.abi, ContractClass.resolver, artifact.contract);
ContractClass.stateProps = artifact.stateProps || [];
ContractClass.abi.forEach((entity) => {
if (entity.type === _1.ABIEntityType.CONSTRUCTOR) {
return;
}
if (!entity.name || invalidMethodName.indexOf(entity.name) > -1) {
throw new Error(`Method name [${entity.name}] is used by scryptlib now, Pelease change you contract method name!`);
}
ContractClass.prototype[entity.name] = function (...args) {
const call = ContractClass.abiCoder.encodePubFunctionCall(this, entity.name || '', args);
this.addFunctionCall(call);
return call;
};
});
ContractClass.stateProps.forEach(p => {
Object.defineProperty(ContractClass.prototype, p.name, {
get() {
const arg = this.statePropsArgs.find((arg) => {
return arg.name === p.name;
});
if (arg) {
return arg.value;
}
else {
throw new Error(`property ${p.name} does not exists`);
}
},
set(value) {
const arg = this.statePropsArgs.find((arg) => {
return arg.name === p.name;
});
if (arg) {
value = this.transformerArg(value, arg, true);
const error = (0, typeCheck_1.checkSupportedParamType)(value, arg, this.resolver);
if (error)
throw error;
arg.value = value;
this.isGenesis = false;
}
else {
throw new Error(`property ${p.name} does not exists`);
}
}
});
});
return ContractClass;
}
exports.buildContractClass = buildContractClass;
function buildTypeResolverFromArtifact(artifact) {
const alias = artifact.alias || [];
const library = artifact.library || [];
const structs = artifact.structs || [];
const contract = artifact.contract;
return buildTypeResolver(contract, alias, structs, library);
}
exports.buildTypeResolverFromArtifact = buildTypeResolverFromArtifact;
// build a resolver witch can only resolve type
function buildTypeResolver(contract, alias, structs, library, contracts = [], statics = []) {
const resolvedTypes = {};
structs.forEach(element => {
resolvedTypes[element.name] = {
info: element,
generic: (0, typeCheck_1.hasGeneric)(element),
finalType: element.name,
symbolType: scryptTypes_1.SymbolType.Struct
};
});
library.forEach(element => {
resolvedTypes[element.name] = {
info: element,
generic: (0, typeCheck_1.hasGeneric)(element),
finalType: element.name,
symbolType: scryptTypes_1.SymbolType.Library
};
});
contracts.forEach(element => {
resolvedTypes[element.name] = {
info: element,
generic: (0, typeCheck_1.hasGeneric)(element),
finalType: element.name,
symbolType: scryptTypes_1.SymbolType.Contract
};
});
// add std type
resolvedTypes['HashedMap'] = {
info: {
name: 'HashedMap',
params: [
{
name: '_data',
type: 'bytes'
}
],
properties: [
{
name: '_data',
type: 'bytes'
}
],
genericTypes: ['K', 'V']
},
generic: true,
finalType: 'HashedMap',
symbolType: scryptTypes_1.SymbolType.Library
};
resolvedTypes['HashedSet'] = {
info: {
name: 'HashedSet',
params: [
{
name: '_data',
type: 'bytes'
}
],
properties: [
{
name: '_data',
type: 'bytes'
}
],
genericTypes: ['E']
},
generic: true,
finalType: 'HashedSet',
symbolType: scryptTypes_1.SymbolType.Library
};
resolvedTypes['SortedItem'] = {
info: {
name: 'SortedItem',
params: [
{
name: 'item',
type: 'T'
},
{
name: 'idx',
type: 'int'
}
],
genericTypes: ['T']
},
generic: true,
finalType: 'SortedItem',
symbolType: scryptTypes_1.SymbolType.Struct
};
resolvedTypes['PubKeyHash'] = {
finalType: 'Ripemd160',
generic: false,
symbolType: scryptTypes_1.SymbolType.ScryptType
};
const resolver = (type) => {
if (resolvedTypes[type]) {
return resolvedTypes[type];
}
if ((0, scryptTypes_1.isScryptType)(type)) {
return {
generic: false,
finalType: type,
symbolType: scryptTypes_1.SymbolType.ScryptType
};
}
return (0, internal_1.resolveType)(type, resolvedTypes, contract, statics, alias, library);
};
return resolver;
}
exports.buildTypeResolver = buildTypeResolver;
//# sourceMappingURL=contract.js.map