@graphprotocol/graph-cli
Version:
CLI for building for and deploying to The Graph
240 lines (239 loc) • 10.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const vitest_1 = require("vitest");
const abi_1 = __importDefault(require("../abi"));
const abi_2 = __importDefault(require("./abi"));
let tempdir;
let abi;
let generatedTypes;
vitest_1.describe.concurrent('ABI code generation', () => {
(0, vitest_1.beforeAll)(async () => {
tempdir = await fs_extra_1.default.mkdtemp('abi-codegen');
try {
const filename = path_1.default.join(tempdir, 'ABI.json');
await fs_extra_1.default.writeFile(filename, JSON.stringify([
{
constant: true,
inputs: [],
name: 'read',
outputs: [{ name: '', type: 'bytes32' }],
payable: false,
type: 'function',
},
{
constant: true,
inputs: [
{
name: 'proposalId',
type: 'uint256',
},
{
components: [
{
name: 'foo',
type: 'uint8',
},
{
name: 'bar',
type: 'tuple',
components: [{ name: 'baz', type: 'address' }],
},
],
name: '',
type: 'tuple',
},
],
name: 'getProposal',
outputs: [
{
components: [
{
name: 'result',
type: 'uint8',
},
{
name: 'target',
type: 'address',
},
{
name: 'data',
type: 'bytes',
},
{
name: 'proposer',
type: 'address',
},
{
name: 'feeRecipient',
type: 'address',
},
{
name: 'fee',
type: 'uint256',
},
{
name: 'startTime',
type: 'uint256',
},
{
name: 'yesCount',
type: 'uint256',
},
{
name: 'noCount',
type: 'uint256',
},
],
name: '',
type: 'tuple',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
type: 'function',
stateMutability: 'view',
payable: 'false',
name: 'getProposals',
outputs: [
{
type: 'uint256',
name: 'size',
},
{
type: 'tuple[]',
components: [
{ name: 'first', type: 'uint256' },
{ name: 'second', type: 'string' },
],
},
],
},
{
type: 'function',
stateMutability: 'view',
name: 'overloaded',
inputs: [
{
type: 'string',
},
],
outputs: [
{
type: 'string',
},
],
},
{
type: 'function',
stateMutability: 'view',
name: 'overloaded',
inputs: [
{
type: 'uint256',
},
],
outputs: [
{
type: 'string',
},
],
},
{
type: 'function',
stateMutability: 'view',
name: 'overloaded',
inputs: [
{
type: 'bytes32',
},
],
outputs: [
{
type: 'string',
},
],
},
]), 'utf-8');
abi = abi_1.default.load('Contract', filename);
const codegen = new abi_2.default(abi);
generatedTypes = codegen.generateTypes();
}
finally {
await fs_extra_1.default.remove(tempdir);
}
});
(0, vitest_1.afterAll)(async () => {
await fs_extra_1.default.remove(tempdir);
});
(0, vitest_1.describe)('Generated types', () => {
(0, vitest_1.test)('All expected types are generated', () => {
(0, vitest_1.expect)(generatedTypes.map(type => type.name)).toMatchSnapshot();
});
});
(0, vitest_1.describe)('Contract class', () => {
(0, vitest_1.test)('Exists', () => {
(0, vitest_1.expect)(generatedTypes.find(type => type.name === 'Contract')).toBeDefined();
});
(0, vitest_1.test)('Has methods', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
(0, vitest_1.expect)(contract.methods).toBeInstanceOf(Array);
});
(0, vitest_1.test)('Has `bind` method', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
(0, vitest_1.expect)(contract.methods.find((method) => method.name === 'bind')).toBeDefined();
});
(0, vitest_1.test)('Has methods for all callable functions', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
(0, vitest_1.expect)(contract.methods.map((method) => method.name)).toContain('getProposal');
});
});
(0, vitest_1.describe)('Methods for callable functions', () => {
(0, vitest_1.test)('Have correct parameters', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
(0, vitest_1.expect)(contract.methods.map((method) => [method.name, method.params])).toMatchSnapshot();
});
(0, vitest_1.test)('Have correct return types', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
(0, vitest_1.expect)(contract.methods.map((method) => [method.name, method.returnType])).toMatchSnapshot();
});
});
(0, vitest_1.describe)('Tuples', () => {
(0, vitest_1.test)('Tuple types exist for function parameters', () => {
let tupleType = generatedTypes.find(type => type.name === 'Contract__getProposalInputParam1Struct');
// Verify that the tuple type has methods
(0, vitest_1.expect)(tupleType.methods).toBeDefined();
// Verify that the tuple type has getters for all tuple fields with
// the right return types
(0, vitest_1.expect)(tupleType.methods.map((method) => [method.name, method.returnType])).toMatchSnapshot();
// Inner tuple:
tupleType = generatedTypes.find(type => type.name === 'Contract__getProposalInputParam1BarStruct');
// Verify that the tuple type has methods
(0, vitest_1.expect)(tupleType.methods).toBeDefined();
// Verify that the tuple type has getters for all tuple fields with
// the right return types
(0, vitest_1.expect)(tupleType.methods.map((method) => [method.name, method.returnType])).toMatchSnapshot();
});
(0, vitest_1.test)('Tuple types exist for function return values', () => {
const tupleType = generatedTypes.find(type => type.name === 'Contract__getProposalResultValue0Struct');
// Verify that the tuple type has methods
(0, vitest_1.expect)(tupleType.methods).toBeDefined();
// Verify that the tuple type has getters for all tuple fields with
// the right return types
(0, vitest_1.expect)(tupleType.methods.map((method) => [method.name, method.returnType])).toMatchSnapshot();
});
(0, vitest_1.test)('Function bodies are generated correctly for tuple arrays', () => {
const contract = generatedTypes.find(type => type.name === 'Contract');
const getter = contract.methods.find((method) => method.name === 'getProposals');
(0, vitest_1.expect)(getter.body).not.toContain('toTupleArray<undefined>');
(0, vitest_1.expect)(getter.body).toContain('result[1].toTupleArray<Contract__getProposalsResultValue1Struct>()');
});
});
});