Skip to content
5 changes: 0 additions & 5 deletions .changeset/@graphprotocol_graph-cli-1829-dependencies.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/heavy-socks-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphprotocol/graph-cli': patch
---

Fix `graph add` flag parameters parsing
67 changes: 34 additions & 33 deletions packages/cli/src/commands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import EthereumABI from '../protocols/ethereum/abi.js';
import Protocol from '../protocols/index.js';
import Subgraph from '../subgraph.js';

const DEFAULT_CONTRACT_NAME = 'Contract';

export default class AddCommand extends Command {
static description = 'Adds a new datasource to a subgraph.';

Expand All @@ -36,14 +38,14 @@ export default class AddCommand extends Command {
char: 'h',
}),
abi: Flags.string({
summary: 'Path to the contract ABI.',
summary: 'Path to the contract ABI. If not provided, will be fetched from contract API.',
}),
'start-block': Flags.string({
summary: 'The block number to start indexing events from.',
summary:
'The block number to start indexing events from. If not provided, will be fetched from contract API',
}),
'contract-name': Flags.string({
summary: 'Name of the contract.',
default: 'Contract',
summary: 'Name of the contract. If not provided, will be fetched from contract API',
}),
'merge-entities': Flags.boolean({
summary: 'Whether to merge entities with the same name.',
Expand Down Expand Up @@ -79,17 +81,8 @@ export default class AddCommand extends Command {
const registry = await loadRegistry();
const contractService = new ContractService(registry);

let startBlock = startBlockFlag;
let contractName = contractNameFlag;

const entities = getEntities(manifest);
const contractNames = getContractNames(manifest);
if (contractNames.includes(contractName)) {
this.error(
`Datasource or template with name ${contractName} already exists, please choose a different name.`,
{ exit: 1 },
);
}
let startBlock = startBlockFlag ? parseInt(startBlockFlag).toString() : startBlockFlag;
let contractName = contractNameFlag || DEFAULT_CONTRACT_NAME;

let ethabi = null;
if (abi) {
Expand All @@ -103,44 +96,36 @@ export default class AddCommand extends Command {
'Fetching ABI from contract API...',
'Failed to fetch ABI',
'Warning fetching ABI',
() => contractService?.getABI(EthereumABI, network, address),
() => contractService.getABI(EthereumABI, network, address),
),
);
if (!ethabi) throw Error;
} catch (error) {
// we cannot ask user to do prompt in test environment
if (process.env.NODE_ENV !== 'test') {
const { abi: abiFromFile } = await prompt.ask<{ abi: EthereumABI }>([
const { abi: abiFile } = await prompt.ask<{ abi: string }>([
{
type: 'input',
name: 'abi',
message: 'ABI file (path)',
initial: ethabi,
validate: async (value: string) => {
try {
EthereumABI.load(contractName, value);
return true;
} catch (e) {
this.error(e.message);
}
},
result: async (value: string) => {
try {
return EthereumABI.load(contractName, value);
} catch (e) {
return e.message;
return `Failed to load ABI from ${value}: ${e.message}`;
}
},
},
]);
ethabi = abiFromFile;
ethabi = EthereumABI.load(contractName, abiFile);
}
}
}

try {
if (isLocalHost) throw Error; // Triggers user prompting without waiting for Etherscan lookup to fail

startBlock ||= Number(await contractService?.getStartBlock(network, address)).toString();
startBlock ||= Number(await contractService.getStartBlock(network, address)).toString();
} catch (error) {
// we cannot ask user to do prompt in test environment
if (process.env.NODE_ENV !== 'test') {
Expand All @@ -163,8 +148,10 @@ export default class AddCommand extends Command {

try {
if (isLocalHost) throw Error; // Triggers user prompting without waiting for Etherscan lookup to fail

contractName = (await contractService?.getContractName(network, address)) ?? '';
if (contractName === DEFAULT_CONTRACT_NAME) {
contractName =
(await contractService.getContractName(network, address)) ?? DEFAULT_CONTRACT_NAME;
}
} catch (error) {
// not asking user to do prompt in test environment
if (process.env.NODE_ENV !== 'test') {
Expand All @@ -184,6 +171,15 @@ export default class AddCommand extends Command {
}
}

const entities = getEntities(manifest);
const contractNames = getContractNames(manifest);
if (contractNames.includes(contractName)) {
this.error(
`Datasource or template with name ${contractName} already exists, please choose a different name.`,
{ exit: 1 },
);
}

await writeABI(ethabi, contractName);

const { collisionEntities, onlyCollisions, abiData } = updateEventNamesOnCollision(
Expand Down Expand Up @@ -246,9 +242,14 @@ export default class AddCommand extends Command {
});
}

await withSpinner('Running codegen', 'Failed to run codegen', 'Warning during codegen', () =>
system.run(yarn ? 'yarn codegen' : 'npm run codegen'),
await withSpinner(
'Running codegen',
'Failed to run codegen',
'Warning during codegen',
async () => await system.run(yarn ? 'yarn codegen' : 'npm run codegen'),
);

this.exit(0);
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/cli/tests/cli/add.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ describe('Add command', () => {
'0x2E645469f354BB4F5c8a05B3b30A929361cf77eC',
'--contract-name',
'Gravatar',
'--start-block',
'6175244',
'--abi',
`${EXAMPLE_SUBGRAPH_PATH}/abis/Gravity.json`,
],
Expand Down
1 change: 1 addition & 0 deletions packages/cli/tests/cli/add/expected/subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dataSources:
source:
address: "0x2E645469f354BB4F5c8a05B3b30A929361cf77eC"
abi: Gravatar
startBlock: 6175244
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down
Loading