create-ponder 0.2.6 → 0.2.7

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.
Files changed (2) hide show
  1. package/dist/index.js +67 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { default as prompts } from "prompts";
16
16
  // package.json
17
17
  var package_default = {
18
18
  name: "create-ponder",
19
- version: "0.2.6",
19
+ version: "0.2.7",
20
20
  type: "module",
21
21
  description: "A CLI tool to create Ponder apps",
22
22
  license: "MIT",
@@ -115,22 +115,13 @@ var fromEtherscan = async ({
115
115
  `${pico.red("\u2717")} Invalid block explorer URL (${explorerUrl.href}). Expected path "/address/<contract-address>".`
116
116
  );
117
117
  }
118
- let abiResult = void 0;
119
- try {
120
- abiResult = await getContractAbiAndName(contractAddress, apiUrl, apiKey);
121
- } catch (e) {
122
- const error = e;
123
- throw new Error(
124
- `${pico.red("\u2717")} Failed to fetch contract ABI from block explorer API: ${error.message}`
125
- );
126
- }
127
- if (typeof abiResult.abi !== "string")
128
- throw new Error(
129
- `${pico.red(
130
- "\u2717"
131
- )} Invalid ABI returned from block explorer API. Is the contract verified?`
132
- );
133
- const baseAbi = JSON.parse(abiResult.abi);
118
+ const abiResult = await getContractAbiAndName(
119
+ contractAddress,
120
+ apiUrl,
121
+ apiKey
122
+ );
123
+ warnings.push(...abiResult.warnings);
124
+ const baseAbi = abiResult.abi;
134
125
  let contractName = abiResult.contractName;
135
126
  const abis = [
136
127
  { abi: baseAbi, contractName }
@@ -152,7 +143,11 @@ var fromEtherscan = async ({
152
143
  apiKey
153
144
  );
154
145
  blockNumber = contractCreationBlockNumber;
155
- } catch (error) {
146
+ } catch (e) {
147
+ const error = e;
148
+ warnings.push(
149
+ `Unable to fetch contract deployment block number from block explorer. Error: ${error.message}`
150
+ );
156
151
  }
157
152
  if (baseAbi.find(
158
153
  (item) => item.type === "event" && item.name === "Upgraded" && item.inputs[0].name === "implementation"
@@ -168,18 +163,17 @@ var fromEtherscan = async ({
168
163
  for (const implAddress of implAddresses) {
169
164
  if (!apiKey)
170
165
  await wait(5e3);
171
- const { abi, contractName: implContractName } = await getContractAbiAndName(implAddress, apiUrl, apiKey);
172
- if (typeof abi !== "string") {
173
- warnings.push(
174
- `Unable to fetch ABI for implementation contract ${implAddress}. Please see the proxy contract documentation for more details: https://ponder.sh/docs/guides/add-contracts#multiple-abis`
175
- );
176
- continue;
177
- }
178
- contractName = implContractName;
166
+ const abiResult2 = await getContractAbiAndName(
167
+ implAddress,
168
+ apiUrl,
169
+ apiKey
170
+ );
171
+ warnings.push(...abiResult2.warnings);
179
172
  abis.push({
180
- abi: JSON.parse(abi),
181
- contractName: `${contractName}_${implAddress.slice(0, 6)}`
173
+ abi: abiResult2.abi,
174
+ contractName: `${abiResult2.contractName}_${implAddress.slice(0, 6)}`
182
175
  });
176
+ contractName = abiResult2.contractName;
183
177
  }
184
178
  }
185
179
  mkdirSync(path.join(rootDir, "abis"), { recursive: true });
@@ -281,10 +275,32 @@ var getContractAbiAndName = async (contractAddress, apiUrl, apiKey) => {
281
275
  });
282
276
  if (apiKey)
283
277
  searchParams.append("apikey", apiKey);
284
- const data = await fetchEtherscan(`${apiUrl}?${searchParams.toString()}`);
285
- const abi = data.result[0].ABI;
286
- const contractName = data.result[0].ContractName;
287
- return { abi, contractName };
278
+ const warnings = [];
279
+ let abi;
280
+ let contractName;
281
+ try {
282
+ const data = await fetchEtherscan(`${apiUrl}?${searchParams.toString()}`);
283
+ const rawAbi = data.result[0].ABI;
284
+ if (rawAbi === "Contract source code not verified") {
285
+ warnings.push(
286
+ `Contract ${contractAddress} is unverified or has an empty ABI.`
287
+ );
288
+ abi = [];
289
+ } else {
290
+ abi = JSON.parse(rawAbi);
291
+ }
292
+ contractName = data.result[0].ContractName ?? "";
293
+ if (contractName === "")
294
+ contractName = "UnverifiedContract";
295
+ } catch (e) {
296
+ const error = e;
297
+ warnings.push(
298
+ `Failed to fetch ABI for contract ${contractAddress}. Marking as unverified. Error: ${error.message}`
299
+ );
300
+ abi = [];
301
+ contractName = "UnverifiedContract";
302
+ }
303
+ return { abi, contractName, warnings };
288
304
  };
289
305
  var getProxyImplementationAddresses = async ({
290
306
  contractAddress,
@@ -343,6 +359,21 @@ var getPackageManager = ({
343
359
  throw Error(pico2.red("Undetectable package manager"));
344
360
  };
345
361
 
362
+ // src/helpers/mergeAbis.ts
363
+ import { formatAbiItem } from "viem/utils";
364
+ var isAbiItemEqual = (a, b) => formatAbiItem(a) === formatAbiItem(b);
365
+ var mergeAbis = (abis) => {
366
+ let merged = [];
367
+ for (const abi of abis) {
368
+ for (const item of abi) {
369
+ if (item.type !== "constructor" && item.type !== "receive" && item.type !== "fallback" && !merged.some((m) => isAbiItemEqual(m, item))) {
370
+ merged = [...merged, item];
371
+ }
372
+ }
373
+ }
374
+ return merged;
375
+ };
376
+
346
377
  // src/helpers/notifyUpdate.ts
347
378
  import pico3 from "picocolors";
348
379
  import checkForUpdate from "update-check";
@@ -807,11 +838,11 @@ async function run({
807
838
  await prettier3.format(configContent, { parser: "typescript" })
808
839
  );
809
840
  for (const [name, contract] of Object.entries(config.contracts)) {
810
- const abi = Array.isArray(contract.abi) ? contract.abi[1].abi : contract.abi.abi;
841
+ const abi = Array.isArray(contract.abi) ? mergeAbis(contract.abi.map((a) => a.abi)) : contract.abi.abi;
811
842
  const abiEvents = abi.filter(
812
843
  (item) => item.type === "event" && !item.anonymous
813
844
  );
814
- const eventNamesToWrite = abiEvents.map((event) => event.name).slice(0, 2);
845
+ const eventNamesToWrite = abiEvents.map((event) => event.name).slice(0, 4);
815
846
  const indexingFunctionFileContents = `
816
847
  import { ponder } from '@/generated'
817
848
 
@@ -886,9 +917,9 @@ async function run({
886
917
  }
887
918
  );
888
919
  }
920
+ log2();
889
921
  for (const warning of warnings) {
890
- log2();
891
- log2(pico5.yellow(warning));
922
+ log2(`${pico5.yellow("\u26A0")} ${warning}`);
892
923
  }
893
924
  log2();
894
925
  log2("\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ponder",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "description": "A CLI tool to create Ponder apps",
6
6
  "license": "MIT",