@alice-network/zos-lib
Version:
JavaScript library for the ZeppelinOS smart contract platform
97 lines • 5.14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const encodeCall_1 = __importDefault(require("../helpers/encodeCall"));
const ContractAST_1 = __importDefault(require("./ContractAST"));
const Bytecode_1 = require("./Bytecode");
const ZWeb3_1 = __importDefault(require("../artifacts/ZWeb3"));
function buildDeploymentCallData(contract, args) {
if (contract.schema.linkedBytecode === '')
throw new Error(`A bytecode must be provided for contract ${contract.schema.contractName}`);
if (Bytecode_1.hasUnlinkedVariables(contract.schema.linkedBytecode))
throw new Error(`${contract.schema.contractName} bytecode contains unlinked libraries: ${Bytecode_1.getSolidityLibNames(contract.schema.linkedBytecode).join(', ')}`);
return ZWeb3_1.default.contract(contract.schema.abi).deploy({ data: contract.schema.linkedBytecode, arguments: args }).encodeABI();
}
exports.buildDeploymentCallData = buildDeploymentCallData;
function buildCallData(contract, methodName, args) {
const method = getABIFunction(contract, methodName, args);
const argTypes = method.inputs.map((input) => input.type);
const callData = encodeCall_1.default(method.name, argTypes, args);
return { method, callData };
}
exports.buildCallData = buildCallData;
function getABIFunction(contract, methodName, args) {
const targetMethod = tryGetTargetFunction(contract, methodName, args);
if (targetMethod)
methodName = targetMethod.name;
const matchArgsTypes = (fn) => targetMethod && fn.inputs.every((input, index) => targetMethod.inputs[index] && targetMethod.inputs[index].type === input.type);
const matchNameAndArgsLength = (fn) => fn.name === methodName && fn.inputs.length === args.length;
let abiMethods = contract.schema.abi.filter((fn) => matchNameAndArgsLength(fn) && matchArgsTypes(fn));
if (abiMethods.length === 0)
abiMethods = contract.schema.abi.filter((fn) => matchNameAndArgsLength(fn));
switch (abiMethods.length) {
case 0: throw Error(`Could not find method ${methodName} with ${args.length} arguments in contract ${contract.schema.contractName}`);
case 1: return abiMethods[0];
default: throw Error(`Found more than one match for function ${methodName} with ${args.length} arguments in contract ${contract.schema.contractName}`);
}
}
exports.getABIFunction = getABIFunction;
function tryGetTargetFunction(contract, methodName, args) {
// Match foo(uint256,string) as method name, and look for that in the ABI
const match = methodName.match(/^\s*(.+)\((.*)\)\s*$/);
if (match) {
const name = match[1];
const inputs = match[2].split(',').map((arg) => ({ type: arg }));
return { name, inputs };
}
// Otherwise, look for the most derived contract
const methodNode = tryGetFunctionNodeFromMostDerivedContract(contract, methodName, args);
if (methodNode) {
const inputs = methodNode.parameters.parameters.map((parameter) => {
const typeString = parameter.typeDescriptions.typeString;
const type = typeString.includes('contract') ? 'address' : typeString;
return { name: parameter.name, type };
});
return { name: methodNode.name, inputs };
}
}
function tryGetFunctionNodeFromMostDerivedContract(contract, methodName, args) {
const linearizedBaseContracts = tryGetLinearizedBaseContracts(contract);
if (!linearizedBaseContracts)
return null;
const nodeMatches = (node) => (node.nodeType === 'FunctionDefinition' &&
node.name === methodName &&
node.parameters.parameters.length === args.length);
for (const aContract of linearizedBaseContracts) {
const funs = aContract.nodes.filter(nodeMatches);
switch (funs.length) {
case 0: continue;
case 1: return funs[0];
default: throw Error(`Found more than one match for function ${methodName} with ${args.length} arguments in contract ${contract.schema.contractName}`);
}
}
throw Error(`Could not find method ${methodName} with ${args.length} arguments in contract ${contract.schema.contractName}`);
}
function tryGetLinearizedBaseContracts(contract) {
try {
const ast = new ContractAST_1.default(contract, null, { nodesFilter: ['ContractDefinition', 'FunctionDefinition'] });
return ast.getLinearizedBaseContracts(true);
}
catch (err) {
// This lookup may fail on contracts loaded from libraries, so we just silently fail and fall back to other methods
return null;
}
}
function callDescription(method, args) {
const argsDescriptions = method.inputs.map((input, index) => ` - ${input.name} (${input.type}): ${JSON.stringify(args[index])}`);
return `${method.name} with: \n${argsDescriptions.join('\n')}`;
}
exports.callDescription = callDescription;
exports.default = {
buildCallData,
getABIFunction,
callDescription,
};
//# sourceMappingURL=ABIs.js.map