Skip to content

Commit

Permalink
feat: 🎸 Add Polygon Support + Multiple ABI Options
Browse files Browse the repository at this point in the history
  • Loading branch information
0xDaksh committed Apr 28, 2021
1 parent 57b1379 commit f35f651
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 71 deletions.
115 changes: 82 additions & 33 deletions scripts/addConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@
*/

import Web3 from "web3";
import inquirer from "inquirer"
import {connectorsV1} from '../src/addresses/mainnet/connectorsV1'
import {connectorsV2_M1} from '../src/addresses/mainnet/connectorsV2_M1'
import { Obj, appendFile, checkFile, readFile, writeFile, getAbiDir, getAbiPath, getAbiTemplate, addressV1Path, addressV2Path, getABI } from "./utils";
import inquirer from "inquirer";
import { connectorsV1 as mConnectorsV1 } from '../src/addresses/mainnet/connectorsV1';
import { connectorsV2_M1 as mConnectorsV2_M1 } from '../src/addresses/mainnet/connectorsV2_M1';
import { connectorsV1 as pConnectorsV1 } from "../src/addresses/polygon/connectorsV1";
import { connectorsV2_M1 as pConnectorsV2_M1 } from '../src/addresses/polygon/connectorsV2_M1';
import { Obj, checkFile, getAbiDir, getAbiPath, getAbiTemplate, mainnetAddressV1Path, mainnetAddressV2Path, polygonAddressV1Path, polygonAddressV2Path, getABI } from "./utils";
import fs from 'fs'

const mainnetConnectorsV1 = connectorsV1 as Obj;
const mainnetConnectorsV2 = connectorsV2_M1 as Obj;
const mainnetConnectorsV1 = mConnectorsV1 as Obj;
const mainnetConnectorsV2 = mConnectorsV2_M1 as Obj;
const polygonConnectorsV1 = pConnectorsV1 as Obj;
const polygonConnectorsV2 = pConnectorsV2_M1 as Obj;
let connectorsV1Template = `export const connectorsV1 = `;
let connectorsV2Template = `export const connectorsV2_M1 = `;

const abiChoices = ["From Address (Only for Mainnet)", "From JSON File Path", "From JSON (via URL)"]
const questions = [
{
type: "input",
Expand All @@ -32,12 +38,12 @@ const questions = [
validate: (name: string) => {
try {
Function('var ' + name);
} catch(_) {
} catch (_) {
return false || "Connector variable name is required!"
}
return true;
}
},
return true;
}
},
{
type: "list",
name: "version",
Expand All @@ -48,58 +54,101 @@ const questions = [
type: "input",
name: "address",
message: "What's the connector address?",
validate: (address: string) => Web3.utils.isAddress(address) || "Enter a valid address!"
validate: (address: string) => Web3.utils.isAddress(address) || "Enter a valid address!"
},
{
type: "list",
name: "chain",
message: "Which Chain?",
choices: ["Mainnet", "Polygon"]
},
{
type: "list",
name: "abi_type",
message: "How to get the ABI?",
choices: abiChoices,
}
];


(async () => {
const answers = await inquirer.prompt(questions);
const abi = await getABI(answers.address);
const abi_idx = abiChoices.indexOf(answers.abi_type)
if (answers.chain === "Polygon" && abi_idx === 0) {
console.log("\n\n❌ Sorry but Fetching ABI from address only works with Mainnet ❌\n")
process.exit(0);
}

const abi = await getABI(abi_idx, answers);
await checkFile(getAbiPath(answers))

if (answers.version === 1) {
if (mainnetConnectorsV1[answers.variable_name]) {
throw new Error("Mainnet Connectors V1 already contains " + answers.variable);
}
mainnetConnectorsV1[answers.variable_name] = answers.address;
connectorsV1Template += JSON.stringify(mainnetConnectorsV1, null, 4);
if (answers.chain === "Mainnet") {
if (mainnetConnectorsV1[answers.variable_name]) {
throw new Error("Mainnet Connectors V1 already contains " + answers.variable);
}
mainnetConnectorsV1[answers.variable_name] = answers.address;
connectorsV1Template += JSON.stringify(mainnetConnectorsV1, null, 4);

// save the file
await writeFile(addressV1Path, connectorsV1Template);
console.log(`🚀 ${addressV1Path} [updated]`)
} else {
if (mainnetConnectorsV2[answers.name]) {
throw new Error("Mainnet Connectors V2 already contains " + answers.name);
// save the file
fs.writeFileSync(mainnetAddressV1Path, connectorsV1Template);
console.log(`🚀 ${mainnetAddressV1Path} [updated]`)
} else {
if (polygonConnectorsV1[answers.variable_name]) {
throw new Error("Polygon Connectors V1 already contains " + answers.variable_name);
}
polygonConnectorsV1[answers.variable_name] = answers.address;
connectorsV1Template += JSON.stringify(polygonConnectorsV1, null, 4);

// save the file
fs.writeFileSync(polygonAddressV1Path, connectorsV1Template)
console.log(`🚀 ${polygonAddressV1Path} [updated]`)
}
mainnetConnectorsV2[answers.name] = answers.address;
connectorsV2Template += JSON.stringify(mainnetConnectorsV2, null, 4);
} else {
if (answers.chain === "Mainnet") {
if (mainnetConnectorsV2[answers.name]) {
throw new Error("Mainnet Connectors V2 already contains " + answers.name);
}
mainnetConnectorsV2[answers.name] = answers.address;
connectorsV2Template += JSON.stringify(mainnetConnectorsV2, null, 4);

// save the file
await writeFile(addressV2Path, connectorsV2Template);
console.log(`🚀 ${addressV2Path} [updated]`)
// save the file
fs.writeFileSync(mainnetAddressV2Path, connectorsV2Template);
console.log(`🚀 ${mainnetAddressV2Path} [updated]`)

} else {
if (polygonConnectorsV2[answers.name]) {
throw new Error("Polygon Connectors V2 already contains " + answers.name);
}
polygonConnectorsV2[answers.name] = answers.address;
connectorsV2Template += JSON.stringify(polygonConnectorsV2, null, 4);

// save the file
fs.writeFileSync(polygonAddressV2Path, connectorsV2Template);
console.log(`🚀 ${polygonAddressV2Path} [updated]`)
}
}

const abiFileContent = getAbiTemplate(answers.variable_name, abi);
await writeFile(getAbiPath(answers), abiFileContent);
await fs.writeFileSync(getAbiPath(answers), abiFileContent);
console.log(`🚀 ${getAbiPath(answers)} [created]`)

const abiDir = getAbiDir(answers);

if (answers.version === 1) {
await appendFile(`${abiDir}/index.ts`, `export * from './${answers.name}'`);
fs.appendFileSync(`${abiDir}/index.ts`, `export * from './${answers.name}'`);
console.log(`🚀 ${abiDir}/index.ts [updated]`)
} else {
const content = await readFile(`${abiDir}/index.ts`);
const content = fs.readFileSync(`${abiDir}/index.ts`, 'utf-8');
const match = /export/.exec(content)!;
let beforeExport = content.slice(0, match.index).trim();
let afterExport = content.slice(match.index, content.length).split(`{\n`);
beforeExport += `\nimport {${answers.variable_name}} from './${answers.name}'`;

const final = `${beforeExport}\n${afterExport[0]}{\n "${answers.name}": ${answers.variable_name},\n${afterExport[1]}`;

// save the file
await writeFile(`${abiDir}/index.ts`, final);
await fs.writeFileSync(`${abiDir}/index.ts`, final);
console.log(`🚀 ${abiDir}/index.ts [updated]`)
}
})();
87 changes: 49 additions & 38 deletions scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as fs from 'fs';
import inquirer from 'inquirer';
import fetch from 'node-fetch';
import URL from "url";
import Path from "path"

export interface Obj {
[key: string]: string;
}

export const checkFile = (fileName: string) => {
return new Promise((resolve ,reject) => {
return new Promise((resolve, reject) => {
fs.access(fileName, (err) => {
if (err) return resolve(null);

Expand All @@ -15,50 +18,58 @@ export const checkFile = (fileName: string) => {
})
}

export const writeFile = (filePath: string, fileContent: string) => {
return new Promise((resolve, reject) => {
fs.writeFile(filePath, fileContent, (err) => {
if (err) return reject(err);

return resolve(null);
})
})
}

export const appendFile = (filePath: string, fileContent: string) => {
return new Promise((resolve, reject) => {
fs.appendFile(filePath, fileContent, (err) => {
if (err) return reject(err);

return resolve(null);
});
});
}

export const readFile = (filePath: string): Promise<string> => {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (err, content) => {
if (err) return reject(err);

return resolve(content);
})
})
}


export const getAbiPath = (answers: Obj) => `src/abi/connectors/v${answers.version}/${answers.name}.ts`;
export const getAbiDir = (answers: Obj) => `src/abi/connectors/v${answers.version}`;
export const addressV1Path = `src/addresses/mainnet/connectorsV1.ts`;
export const addressV2Path = `src/addresses/mainnet/connectorsV2_M1.ts`;
export const mainnetAddressV1Path = `src/addresses/mainnet/connectorsV1.ts`;
export const mainnetAddressV2Path = `src/addresses/mainnet/connectorsV2_M1.ts`;
export const polygonAddressV1Path = `src/addresses/polygon/connectorsV1.ts`;
export const polygonAddressV2Path = `src/addresses/polygon/connectorsV2_M1.ts`;
export const getAbiTemplate = (varName: string, abi: string) => `
import { AbiItem } from 'web3-utils'
export const ${varName}: AbiItem[] = ${abi}
`.trim();

export const getABI = async (address: string): Promise<string> => {
export const getABI = async (abi_idx: number, answers: Obj): Promise<string> => {
console.log('🔮 Fetching ABI')
const res = await fetch(`https://api.etherscan.io/api?module=contract&action=getabi&address=${address}&apikey=${process.env.API_KEY_TOKEN}`);
const {result} = await res.json();
return result;

if (abi_idx === 0) {
const res = await fetch(`https://api.etherscan.io/api?module=contract&action=getabi&address=${answers.address}&apikey=${process.env.API_KEY_TOKEN}`);
const { result } = await res.json();
return result;
} else if (abi_idx === 1) {
const data = await inquirer.prompt([
{
type: "input",
name: "path",
message: "Enter the JSON File Path:",
validate: (value: string) => !!value || "File Path is required."
}
]);



return JSON.stringify(fs.readFileSync(Path.resolve(data.path), 'utf-8'));
} else {
const data = await inquirer.prompt([
{
type: "input",
name: "url",
message: "Enter the URL:",
validate: (value: string) => {
try {
new URL.URL(value)
return true;
} catch (e) {
return "Wrong URL Entered."
}
}
}
])

const res = await fetch(data.url);
const json = res.json();

return JSON.stringify(json);
}
}

0 comments on commit f35f651

Please sign in to comment.