@graphprotocol/graph-cli 0.89.0-alpha-20241107203204-e816fce → 0.89.0

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,15 +1,27 @@
1
1
  # @graphprotocol/graph-cli
2
2
 
3
- ## 0.89.0-alpha-20241107203204-e816fce
3
+ ## 0.89.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
7
  - [#1763](https://github.com/graphprotocol/graph-tooling/pull/1763)
8
- [`e816fce`](https://github.com/graphprotocol/graph-tooling/commit/e816fceaffd8432dacbbbd7e2b1a2d2fddbf0cdd)
9
- Thanks [@alinobrasil](https://github.com/alinobrasil)! - new chain urls
8
+ [`58dbd28`](https://github.com/graphprotocol/graph-tooling/commit/58dbd2845b9e336bb06d7cee09929a92db7f2cf5)
9
+ Thanks [@alinobrasil](https://github.com/alinobrasil)! - Add new chain: Lens testnet
10
10
 
11
11
  ### Patch Changes
12
12
 
13
+ - [#1759](https://github.com/graphprotocol/graph-tooling/pull/1759)
14
+ [`1d4217a`](https://github.com/graphprotocol/graph-tooling/commit/1d4217a506b38307ad0d750a9abe37bffa0a734d)
15
+ Thanks [@0237h](https://github.com/0237h)! - Refactor debug log for failed Etherscan ABI lookups
16
+
17
+ - [#1764](https://github.com/graphprotocol/graph-tooling/pull/1764)
18
+ [`0b4cfe9`](https://github.com/graphprotocol/graph-tooling/commit/0b4cfe91091a86a0871d486f91754ea87f302b3e)
19
+ Thanks [@adamazad](https://github.com/adamazad)! - chore(rpcs): update gnosis chain RPC endpoint
20
+
21
+ - [#1766](https://github.com/graphprotocol/graph-tooling/pull/1766)
22
+ [`d2fda94`](https://github.com/graphprotocol/graph-tooling/commit/d2fda940ace2b719354df9da43890c559ebfd3a8)
23
+ Thanks [@0237h](https://github.com/0237h)! - Improve ABI file path validation
24
+
13
25
  - [#1761](https://github.com/graphprotocol/graph-tooling/pull/1761)
14
26
  [`baf36b4`](https://github.com/graphprotocol/graph-tooling/commit/baf36b42bc531f3aee2709c2f55682a7ec44e5ac)
15
27
  Thanks [@alinobrasil](https://github.com/alinobrasil)! - update soneium-testnet blockexplorer url
@@ -3,7 +3,6 @@ export declare const loadAbiFromEtherscan: (ABICtor: typeof ABI, network: string
3
3
  export declare const loadStartBlockForContract: (network: string, address: string) => Promise<string>;
4
4
  export declare const loadContractNameForAddress: (network: string, address: string) => Promise<string>;
5
5
  export declare const fetchDeployContractTransactionFromEtherscan: (network: string, address: string) => Promise<string>;
6
- export declare const fetchContractCreationHashWithRetry: (url: string, retryCount: number) => Promise<any>;
7
6
  export declare const fetchTransactionByHashFromRPC: (network: string, transactionHash: string) => Promise<any>;
8
7
  export declare const fetchSourceCodeFromEtherscan: (network: string, address: string) => Promise<any>;
9
8
  export declare const getContractNameForAddress: (network: string, address: string) => Promise<string>;
@@ -3,24 +3,35 @@ 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.getStartBlockForContract = exports.getContractNameForAddress = exports.fetchSourceCodeFromEtherscan = exports.fetchTransactionByHashFromRPC = exports.fetchContractCreationHashWithRetry = exports.fetchDeployContractTransactionFromEtherscan = exports.loadContractNameForAddress = exports.loadStartBlockForContract = exports.loadAbiFromEtherscan = void 0;
6
+ exports.loadAbiFromBlockScout = exports.getStartBlockForContract = exports.getContractNameForAddress = exports.fetchSourceCodeFromEtherscan = exports.fetchTransactionByHashFromRPC = exports.fetchDeployContractTransactionFromEtherscan = exports.loadContractNameForAddress = exports.loadStartBlockForContract = exports.loadAbiFromEtherscan = void 0;
7
7
  const immutable_1 = __importDefault(require("immutable"));
8
8
  const constants_1 = require("../constants");
9
9
  const debug_1 = __importDefault(require("../debug"));
10
10
  const fetch_1 = __importDefault(require("../fetch"));
11
11
  const spinner_1 = require("./spinner");
12
12
  const logger = (0, debug_1.default)('graph-cli:abi-helpers');
13
+ const fetchFromEtherscan = async (url) => {
14
+ const result = await (0, fetch_1.default)(url);
15
+ let json = {};
16
+ if (result.ok) {
17
+ json = await result.json().catch(error => {
18
+ throw new Error(`Failed to read JSON response from Etherscan: ${error}`);
19
+ });
20
+ // Etherscan returns a JSON object that has a `status`, a `message` and
21
+ // a `result` field. The `status` is '0' in case of errors and '1' in
22
+ // case of success
23
+ if (json.status === '1')
24
+ return json;
25
+ }
26
+ logger('Failed to fetchFromEtherscan: [%s] %s (%s)\n%O', result.status, result.statusText, result.url, json);
27
+ return null;
28
+ };
13
29
  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 () => {
14
30
  const scanApiUrl = getEtherscanLikeAPIUrl(network);
15
- const result = await (0, fetch_1.default)(`${scanApiUrl}?module=contract&action=getabi&address=${address}`);
16
- const json = await result.json();
17
- // Etherscan returns a JSON object that has a `status`, a `message` and
18
- // a `result` field. The `status` is '0' in case of errors and '1' in
19
- // case of success
20
- if (json.status === '1') {
31
+ const json = await fetchFromEtherscan(`${scanApiUrl}?module=contract&action=getabi&address=${address}`);
32
+ if (json)
21
33
  return new ABICtor('Contract', undefined, immutable_1.default.fromJS(JSON.parse(json.result)));
22
- }
23
- throw new Error('ABI not found, try loading it from a local file');
34
+ throw new Error('Try loading it from a local file');
24
35
  });
25
36
  exports.loadAbiFromEtherscan = loadAbiFromEtherscan;
26
37
  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 () => {
@@ -33,8 +44,8 @@ const loadContractNameForAddress = async (network, address) => await (0, spinner
33
44
  exports.loadContractNameForAddress = loadContractNameForAddress;
34
45
  const fetchDeployContractTransactionFromEtherscan = async (network, address) => {
35
46
  const scanApiUrl = getEtherscanLikeAPIUrl(network);
36
- const json = await (0, exports.fetchContractCreationHashWithRetry)(`${scanApiUrl}?module=contract&action=getcontractcreation&contractaddresses=${address}`, 5);
37
- if (json.status === '1') {
47
+ const json = await fetchFromEtherscan(`${scanApiUrl}?module=contract&action=getcontractcreation&contractaddresses=${address}`);
48
+ if (json) {
38
49
  const hash = json.result[0].txHash;
39
50
  logger('Successfully fetchDeployContractTransactionFromEtherscan. txHash: %s', hash);
40
51
  return hash;
@@ -42,24 +53,6 @@ const fetchDeployContractTransactionFromEtherscan = async (network, address) =>
42
53
  throw new Error(`Failed to fetch deploy contract transaction`);
43
54
  };
44
55
  exports.fetchDeployContractTransactionFromEtherscan = fetchDeployContractTransactionFromEtherscan;
45
- const fetchContractCreationHashWithRetry = async (url, retryCount) => {
46
- let json;
47
- for (let i = 0; i < retryCount; i++) {
48
- try {
49
- const result = await (0, fetch_1.default)(url);
50
- json = await result.json();
51
- if (json.status !== '0') {
52
- return json;
53
- }
54
- }
55
- catch (error) {
56
- logger('Failed to fetchContractCreationHashWithRetry: %O', error);
57
- /* empty */
58
- }
59
- }
60
- throw new Error(`Failed to fetch contract creation transaction hash`);
61
- };
62
- exports.fetchContractCreationHashWithRetry = fetchContractCreationHashWithRetry;
63
56
  const fetchTransactionByHashFromRPC = async (network, transactionHash) => {
64
57
  let json;
65
58
  const RPCURL = getPublicRPCEndpoint(network);
@@ -90,12 +83,12 @@ const fetchTransactionByHashFromRPC = async (network, transactionHash) => {
90
83
  exports.fetchTransactionByHashFromRPC = fetchTransactionByHashFromRPC;
91
84
  const fetchSourceCodeFromEtherscan = async (network, address) => {
92
85
  const scanApiUrl = getEtherscanLikeAPIUrl(network);
93
- const result = await (0, fetch_1.default)(`${scanApiUrl}?module=contract&action=getsourcecode&address=${address}`);
94
- const json = await result.json();
95
- if (json.status === '1') {
86
+ const json = await fetchFromEtherscan(`${scanApiUrl}?module=contract&action=getsourcecode&address=${address}`);
87
+ // Have to check that the SourceCode response is not empty due to Etherscan API bug responding with
88
+ // 1 - OK on non-valid contracts.
89
+ if (json.result[0].SourceCode)
96
90
  return json;
97
- }
98
- throw new Error('Failed to fetch contract source code');
91
+ throw new Error(`Failed to fetch contract source code: ${json.result[0].ABI}`);
99
92
  };
100
93
  exports.fetchSourceCodeFromEtherscan = fetchSourceCodeFromEtherscan;
101
94
  const getContractNameForAddress = async (network, address) => {
@@ -324,7 +317,7 @@ const getPublicRPCEndpoint = (network) => {
324
317
  case 'goerli':
325
318
  return 'https://rpc.ankr.com/eth_goerli';
326
319
  case 'gnosis':
327
- return 'https://safe-transaction.gnosis.io';
320
+ return 'https://rpc.gnosischain.com';
328
321
  case 'mainnet':
329
322
  return 'https://rpc.ankr.com/eth';
330
323
  case 'matic':
@@ -491,32 +491,24 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
491
491
  type: 'input',
492
492
  name: 'abi',
493
493
  message: 'ABI file (path)',
494
- initial: initAbi,
494
+ initial: initAbiPath,
495
495
  skip: () => !protocolInstance.hasABIs() ||
496
496
  initFromExample !== undefined ||
497
497
  abiFromEtherscan !== undefined ||
498
- isSubstreams ||
499
- !!initAbiPath,
498
+ isSubstreams,
500
499
  validate: async (value) => {
501
500
  if (initFromExample || abiFromEtherscan || !protocolInstance.hasABIs()) {
502
501
  return true;
503
502
  }
504
503
  const ABI = protocolInstance.getABI();
505
- if (initAbiPath) {
506
- try {
507
- loadAbiFromFile(ABI, initAbiPath);
508
- return true;
509
- }
510
- catch (e) {
511
- this.error(e.message);
512
- }
513
- }
504
+ if (initAbiPath)
505
+ value = initAbiPath;
514
506
  try {
515
507
  loadAbiFromFile(ABI, value);
516
508
  return true;
517
509
  }
518
510
  catch (e) {
519
- this.error(e.message);
511
+ return e.message;
520
512
  }
521
513
  },
522
514
  result: async (value) => {
@@ -524,14 +516,8 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
524
516
  return null;
525
517
  }
526
518
  const ABI = protocolInstance.getABI();
527
- if (initAbiPath) {
528
- try {
529
- return loadAbiFromFile(ABI, initAbiPath);
530
- }
531
- catch (e) {
532
- return e.message;
533
- }
534
- }
519
+ if (initAbiPath)
520
+ value = initAbiPath;
535
521
  try {
536
522
  return loadAbiFromFile(ABI, value);
537
523
  }
@@ -124,7 +124,13 @@ class ABI {
124
124
  return undefined;
125
125
  }
126
126
  static load(name, file) {
127
- const data = JSON.parse(fs_extra_1.default.readFileSync(file).toString());
127
+ let data;
128
+ try {
129
+ data = JSON.parse(fs_extra_1.default.readFileSync(file).toString());
130
+ }
131
+ catch (e) {
132
+ throw Error(`Could not parse ABI: ${e}`);
133
+ }
128
134
  const abi = ABI.normalized(data);
129
135
  if (abi === null || abi === undefined) {
130
136
  throw Error(`No valid ABI in file: ${path_1.default.relative(process.cwd(), file)}`);
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.89.0-alpha-20241107203204-e816fce",
2
+ "version": "0.89.0",
3
3
  "commands": {
4
4
  "add": {
5
5
  "id": "add",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.89.0-alpha-20241107203204-e816fce",
3
+ "version": "0.89.0",
4
4
  "description": "CLI for building for and deploying to The Graph",
5
5
  "license": "(Apache-2.0 OR MIT)",
6
6
  "engines": {