@graphprotocol/graph-cli 0.38.0 → 0.39.0-alpha-20230207063338-667b17a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
+ ## 0.39.0-alpha-20230207063338-667b17a
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1059](https://github.com/graphprotocol/graph-tooling/pull/1059)
8
+ [`90666d6`](https://github.com/graphprotocol/graph-tooling/commit/90666d6dd9f9a6634a6be60c8953710c559d1e5a)
9
+ Thanks [@incrypto32](https://github.com/incrypto32)! - Auto fetch startBlock
10
+
3
11
  ## 0.38.0
4
12
 
5
13
  ### Minor Changes
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.loadAbiFromBlockScout = exports.loadAbiFromEtherscan = void 0;
6
+ exports.loadAbiFromBlockScout = exports.getStartBlockForContract = exports.fetchTransactionByHashFromRPC = exports.fetchContractCreationHashWithRetry = exports.fetchDeployContractTransactionFromEtherscan = exports.loadStartBlockForContract = exports.loadAbiFromEtherscan = void 0;
7
7
  const immutable_1 = __importDefault(require("immutable"));
8
8
  const node_fetch_1 = __importDefault(require("node-fetch"));
9
+ const constants_1 = require("./constants");
9
10
  const spinner_1 = require("./spinner");
10
11
  const loadAbiFromEtherscan = async (ABICtor, network, address) => await (0, spinner_1.withSpinner)(`Fetching ABI from Etherscan`, `Failed to fetch ABI from Etherscan`, `Warnings while fetching ABI from Etherscan`, async () => {
11
12
  const scanApiUrl = getEtherscanLikeAPIUrl(network);
@@ -20,6 +21,74 @@ const loadAbiFromEtherscan = async (ABICtor, network, address) => await (0, spin
20
21
  throw new Error('ABI not found, try loading it from a local file');
21
22
  });
22
23
  exports.loadAbiFromEtherscan = loadAbiFromEtherscan;
24
+ const loadStartBlockForContract = async (network, address) => await (0, spinner_1.withSpinner)(`Fetching Start Block`, `Failed to fetch Start Block`, `Warnings while fetching deploy contract transaction from Etherscan`, async () => {
25
+ return (0, exports.getStartBlockForContract)(network, address);
26
+ });
27
+ exports.loadStartBlockForContract = loadStartBlockForContract;
28
+ const fetchDeployContractTransactionFromEtherscan = async (network, address) => {
29
+ const scanApiUrl = getEtherscanLikeAPIUrl(network);
30
+ const json = await (0, exports.fetchContractCreationHashWithRetry)(`${scanApiUrl}?module=contract&action=getcontractcreation&contractaddresses=${address}`, 5);
31
+ if (json.status === '1') {
32
+ return json.result[0].txHash;
33
+ }
34
+ throw new Error(`Failed to fetch deploy contract transaction`);
35
+ };
36
+ exports.fetchDeployContractTransactionFromEtherscan = fetchDeployContractTransactionFromEtherscan;
37
+ const fetchContractCreationHashWithRetry = async (url, retryCount) => {
38
+ let json;
39
+ try {
40
+ const result = await (0, node_fetch_1.default)(url);
41
+ json = await result.json();
42
+ if (json.status === '0') {
43
+ return await (0, exports.fetchContractCreationHashWithRetry)(url, retryCount - 1);
44
+ }
45
+ return json;
46
+ }
47
+ catch (error) {
48
+ if (retryCount > 0) {
49
+ return await (0, exports.fetchContractCreationHashWithRetry)(url, retryCount - 1);
50
+ }
51
+ throw new Error('Failed to fetch contract creation hash from RPC');
52
+ }
53
+ };
54
+ exports.fetchContractCreationHashWithRetry = fetchContractCreationHashWithRetry;
55
+ const fetchTransactionByHashFromRPC = async (network, transactionHash) => {
56
+ let json;
57
+ try {
58
+ const RPCURL = constants_1.PUBLIC_RPC_ENDPOINTS[String(network)];
59
+ if (!RPCURL)
60
+ throw new Error(`Unable to fetch RPC URL for ${network}`);
61
+ const result = await (0, node_fetch_1.default)(String(RPCURL), {
62
+ method: 'POST',
63
+ headers: {
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: JSON.stringify({
67
+ jsonrpc: '2.0',
68
+ method: 'eth_getTransactionByHash',
69
+ params: [transactionHash],
70
+ id: 1,
71
+ }),
72
+ });
73
+ json = await result.json();
74
+ return json;
75
+ }
76
+ catch (error) {
77
+ throw new Error('Failed to fetch contract creation hash from RPC');
78
+ }
79
+ };
80
+ exports.fetchTransactionByHashFromRPC = fetchTransactionByHashFromRPC;
81
+ const getStartBlockForContract = async (network, address) => {
82
+ try {
83
+ const transactionHash = await (0, exports.fetchDeployContractTransactionFromEtherscan)(network, address);
84
+ const txn = await (0, exports.fetchTransactionByHashFromRPC)(network, transactionHash);
85
+ return parseInt(txn.result.blockNumber, 16);
86
+ }
87
+ catch (error) {
88
+ throw new Error(error);
89
+ }
90
+ };
91
+ exports.getStartBlockForContract = getStartBlockForContract;
23
92
  const loadAbiFromBlockScout = async (ABICtor, network, address) => await (0, spinner_1.withSpinner)(`Fetching ABI from BlockScout`, `Failed to fetch ABI from BlockScout`, `Warnings while fetching ABI from BlockScout`, async () => {
24
93
  const result = await (0, node_fetch_1.default)(`https://blockscout.com/${network.replace('-', '/')}/api?module=contract&action=getabi&address=${address}`);
25
94
  const json = await result.json();
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const abi_1 = require("./abi");
4
+ // An object with some test cases for contract deployment block numbers
5
+ const TEST_CONTRACT_START_BLOCKS = {
6
+ mainnet: {
7
+ '0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd': 10736242,
8
+ },
9
+ matic: {
10
+ '0x0769fd68dFb93167989C6f7254cd0D766Fb2841F': 13911377,
11
+ },
12
+ 'arbitrum-one': {
13
+ '0xF4d73326C13a4Fc5FD7A064217e12780e9Bd62c3': 226981,
14
+ },
15
+ optimism: {
16
+ '0xc35DADB65012eC5796536bD9864eD8773aBc74C4': 7019815,
17
+ },
18
+ fantom: {
19
+ '0xf731202A3cf7EfA9368C2d7bD613926f7A144dB5': 28771200,
20
+ },
21
+ avalanche: {
22
+ '0xc35DADB65012eC5796536bD9864eD8773aBc74C4': 506190,
23
+ },
24
+ moonriver: {
25
+ '0x3dB01570D97631f69bbb0ba39796865456Cf89A5': 800950,
26
+ },
27
+ moonbeam: {
28
+ '0x011E52E4E40CF9498c79273329E8827b21E2e581': 505060,
29
+ },
30
+ bsc: {
31
+ '0xc35DADB65012eC5796536bD9864eD8773aBc74C4': 5205069,
32
+ },
33
+ // Skip tests for these networks because they do not support the etherscan contracts API
34
+ // fuse: {
35
+ // '0x3dB01570D97631f69bbb0ba39796865456Cf89A5': 1000000,
36
+ // },
37
+ // aurora:{
38
+ // '0x76FA7f90D3900eB95Cfc58AB12c916984AeC50c8': 77431034,
39
+ // }
40
+ // celo: {
41
+ // '0x8084936982D089130e001b470eDf58faCA445008': 10186627,
42
+ // },
43
+ // gnosis: {
44
+ // '0xdDCbf776dF3dE60163066A5ddDF2277cB445E0F3': 16655565,
45
+ // },
46
+ };
47
+ describe('getStartBlockForContract', () => {
48
+ for (const [network, contracts] of Object.entries(TEST_CONTRACT_START_BLOCKS)) {
49
+ for (const [contract, startBlockExp] of Object.entries(contracts)) {
50
+ test(`Returns the start block ${network} ${contract} ${startBlockExp}`, async () => {
51
+ //loop through the TEST_CONTRACT_START_BLOCKS object and test each network
52
+ const startBlock = await (0, abi_1.getStartBlockForContract)(network, contract);
53
+ expect(startBlock).toBe(startBlockExp);
54
+ });
55
+ }
56
+ }
57
+ });
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PUBLIC_RPC_ENDPOINTS = void 0;
4
+ exports.PUBLIC_RPC_ENDPOINTS = {
5
+ mainnet: 'https://rpc.ankr.com/eth',
6
+ rinkeby: 'https://rpc.ankr.com/eth_rinkeby',
7
+ goerli: 'https://rpc.ankr.com/eth_goerli',
8
+ 'poa-core': 'https://core.poa.network',
9
+ 'poa-sokol': 'https://sokol.poa.network',
10
+ gnosis: 'https://safe-transaction.gnosis.io',
11
+ matic: 'https://rpc-mainnet.maticvigil.com',
12
+ mumbai: 'https://rpc-mumbai.maticvigil.com',
13
+ fantom: 'https://rpcapi.fantom.network',
14
+ 'fantom-testnet': 'https://rpc.testnet.fantom.network',
15
+ bsc: 'https://bsc-dataseed.binance.org',
16
+ chapel: 'https://rpc.chapel.dev',
17
+ clover: 'https://rpc.clover.finance',
18
+ avalanche: 'https://api.avax.network/ext/bc/C/rpc',
19
+ fuji: 'https://api.avax-test.network/ext/bc/C/rpc',
20
+ celo: 'https://forno.celo.org',
21
+ 'celo-alfajores': 'https://alfajores-forno.celo-testnet.org',
22
+ fuse: 'https://rpc.fuse.io',
23
+ moonbeam: 'https://rpc.api.moonbeam.network',
24
+ moonriver: 'https://moonriver.public.blastapi.io',
25
+ mbase: 'https://rpc.moonbase.moonbeam.network',
26
+ 'arbitrum-one': 'https://arb1.arbitrum.io/rpc',
27
+ 'arbitrum-goerli': 'https://goerli.arbitrum.io/rpc',
28
+ optimism: 'https://mainnet.optimism.io',
29
+ 'optimism-kovan': 'https://kovan.optimism.io',
30
+ aurora: 'https://rpc.mainnet.aurora.dev',
31
+ 'aurora-testnet': 'https://rpc.testnet.aurora.dev',
32
+ };
@@ -44,6 +44,7 @@ const debug_1 = __importDefault(require("../debug"));
44
44
  const protocols_1 = __importDefault(require("../protocols"));
45
45
  const schema_1 = require("../scaffold/schema");
46
46
  const validation_1 = require("../validation");
47
+ const abi_2 = require("./../command-helpers/abi");
47
48
  const protocolChoices = Array.from(protocols_1.default.availableProtocols().keys());
48
49
  const availableNetworks = protocols_1.default.availableNetworks();
49
50
  const DEFAULT_EXAMPLE_SUBGRAPH = 'ethereum/gravatar';
@@ -228,6 +229,16 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
228
229
  // noop
229
230
  }
230
231
  }
232
+ // If startBlock is not set, try to load it.
233
+ if (!startBlock) {
234
+ try {
235
+ // Load startBlock for this contract
236
+ startBlock = Number(await (0, abi_2.loadStartBlockForContract)(network, value)).toString();
237
+ }
238
+ catch (error) {
239
+ // noop
240
+ }
241
+ }
231
242
  return value;
232
243
  },
233
244
  },
@@ -254,8 +265,8 @@ const processInitForm = async (toolbox, { protocol, product, studio, node, abi,
254
265
  type: 'input',
255
266
  name: 'startBlock',
256
267
  message: 'Start Block',
257
- initial: startBlock || '0',
258
- skip: () => fromExample !== undefined || startBlock,
268
+ initial: () => startBlock || '0',
269
+ skip: () => fromExample !== undefined,
259
270
  validate: (value) => parseInt(value) >= 0,
260
271
  result: (value) => {
261
272
  startBlock = value;
@@ -322,6 +333,7 @@ exports.default = {
322
333
  const { print, system } = toolbox;
323
334
  // Read CLI parameters
324
335
  let { protocol, product, studio, node, g, abi, allowSimpleName, fromContract, contractName, fromExample, h, help, indexEvents, network, startBlock, } = toolbox.parameters.options;
336
+ startBlock && (startBlock = Number(startBlock).toString());
325
337
  node || (node = g);
326
338
  ({ node, allowSimpleName } = (0, node_1.chooseNodeUrl)({
327
339
  product,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.38.0",
3
+ "version": "0.39.0-alpha-20230207063338-667b17a",
4
4
  "description": "CLI for building for and deploying to The Graph",
5
5
  "license": "(Apache-2.0 OR MIT)",
6
6
  "engines": {