mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
updated scripts
This commit is contained in:
parent
280c03dae1
commit
dfb388ce8d
|
@ -22,6 +22,7 @@
|
||||||
"homepage": "https://github.com/InstaDApp/dsa-connectors-new#readme",
|
"homepage": "https://github.com/InstaDApp/dsa-connectors-new#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openzeppelin/contracts": "^3.4.0-solc-0.7",
|
"@openzeppelin/contracts": "^3.4.0-solc-0.7",
|
||||||
|
"@typechain/ethers-v5": "^8.0.5",
|
||||||
"@typechain/hardhat": "^3.0.0",
|
"@typechain/hardhat": "^3.0.0",
|
||||||
"@uniswap/v3-core": "^1.0.0",
|
"@uniswap/v3-core": "^1.0.0",
|
||||||
"@uniswap/v3-periphery": "^1.2.1",
|
"@uniswap/v3-periphery": "^1.2.1",
|
||||||
|
|
|
@ -9,4 +9,3 @@ export const addresses = {
|
||||||
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
|
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export const constants = {
|
export const constants = {
|
||||||
address_zero: "0x0000000000000000000000000000000000000000",
|
address_zero: "0x0000000000000000000000000000000000000000",
|
||||||
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||||
max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
max_value:
|
||||||
};
|
"115792089237316195423570985008687907853269984665640564039457584007913129639935",
|
||||||
|
};
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers, deployments, getUnnamedAccounts } = hre;
|
|
||||||
const { deploy } = deployments;
|
|
||||||
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
|
|
||||||
const deployer = (await getUnnamedAccounts())[0]
|
|
||||||
|
|
||||||
const connector = "ConnectV2InstaPoolV3Avalanche"
|
|
||||||
|
|
||||||
const connectorInstance = await deploy(connector, {
|
|
||||||
from: deployer,
|
|
||||||
})
|
|
||||||
console.log(`${connector} deployed: `, connectorInstance.address);
|
|
||||||
|
|
||||||
await hre.run("sourcify", {
|
|
||||||
address: connectorInstance.address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
|
@ -1,82 +0,0 @@
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers } = hre;
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
|
|
||||||
const CONNECTORS_V2 = "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11";
|
|
||||||
|
|
||||||
const ctokenMapping = {
|
|
||||||
"ETH-A": "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5",
|
|
||||||
"BAT-A": "0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e",
|
|
||||||
"COMP-A": "0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4",
|
|
||||||
"DAI-A": "0x5d3a536e4d6dbd6114cc1ead35777bab948e3643",
|
|
||||||
"REP-A": "0x158079ee67fce2f58472a96584a73c7ab9ac95c1",
|
|
||||||
"UNI-A": "0x35a18000230da775cac24873d00ff85bccded550",
|
|
||||||
"USDC-A": "0x39aa39c021dfbae8fac545936693ac917d5e7563",
|
|
||||||
"USDT-A": "0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9",
|
|
||||||
"WBTC-A": "0xc11b1268c1a384e55c48c2391d8d480264a3a7f4",
|
|
||||||
"WBTC-B": "0xccF4429DB6322D5C611ee964527D42E5d685DD6a",
|
|
||||||
"ZRX-A": "0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407",
|
|
||||||
"YFI-A": "0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946",
|
|
||||||
"SUSHI-A": "0x4b0181102a0112a2ef11abee5563bb4a3176c9d7",
|
|
||||||
"MKR-A": "0x95b4ef2869ebd94beb4eee400a99824bf5dc325b",
|
|
||||||
"AAVE-A": "0xe65cdb6479bac1e22340e4e755fae7e509ecd06c",
|
|
||||||
"TUSD-A": "0x12392f67bdf24fae0af363c24ac620a2f67dad86",
|
|
||||||
"LINK-A": "0xface851a4921ce59e912d19329929ce6da6eb0c7",
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenMapping = {
|
|
||||||
"ETH-A": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
||||||
"BAT-A": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF",
|
|
||||||
"COMP-A": "0xc00e94cb662c3520282e6f5717214004a7f26888",
|
|
||||||
"DAI-A": "0x6b175474e89094c44da98b954eedeac495271d0f",
|
|
||||||
"REP-A": "0x1985365e9f78359a9B6AD760e32412f4a445E862",
|
|
||||||
"UNI-A": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
|
|
||||||
"USDC-A": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
||||||
"USDT-A": "0xdac17f958d2ee523a2206206994597c13d831ec7",
|
|
||||||
"WBTC-A": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
|
||||||
"WBTC-B": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
|
||||||
"ZRX-A": "0xe41d2489571d322189246dafa5ebde1f4699f498",
|
|
||||||
"YFI-A": "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e",
|
|
||||||
"SUSHI-A": "0x6B3595068778DD592e39A122f4f5a5cF09C90fE2",
|
|
||||||
"MKR-A": "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2",
|
|
||||||
"AAVE-A": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
|
|
||||||
"TUSD-A": "0x0000000000085d4780B73119b644AE5ecd22b376",
|
|
||||||
"LINK-A": "0x514910771af9ca656af840dff83e8264ecf986ca",
|
|
||||||
}
|
|
||||||
|
|
||||||
const Mapping = await ethers.getContractFactory("InstaCompoundMapping");
|
|
||||||
const mapping = await Mapping.deploy(
|
|
||||||
CONNECTORS_V2,
|
|
||||||
Object.keys(ctokenMapping),
|
|
||||||
Object.values(tokenMapping),
|
|
||||||
Object.values(ctokenMapping)
|
|
||||||
);
|
|
||||||
await mapping.deployed();
|
|
||||||
|
|
||||||
console.log(`InstaCompoundMapping Deployed: ${mapping.address}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await hre.run("verify:verify", {
|
|
||||||
address: mapping.address,
|
|
||||||
constructorArguments: [
|
|
||||||
CONNECTORS_V2,
|
|
||||||
Object.keys(ctokenMapping),
|
|
||||||
Object.values(tokenMapping),
|
|
||||||
Object.values(ctokenMapping)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Failed to verify: InstaCompoundMapping@${mapping.address}`)
|
|
||||||
console.log(error)
|
|
||||||
console.log()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
|
@ -1,105 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers } = hre;
|
|
||||||
|
|
||||||
let args = process.argv;
|
|
||||||
args = args.splice(2, args.length);
|
|
||||||
let params = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i += 2) {
|
|
||||||
if (args[i][0] !== "-" || args[i][1] !== "-") {
|
|
||||||
console.log("Please add '--' for the key");
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
let key = args[i].slice(2, args[i].length);
|
|
||||||
params[key] = args[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!params.hasOwnProperty('connector')) {
|
|
||||||
console.error("Should include connector params")
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!params.hasOwnProperty('network')) {
|
|
||||||
console.error("Should include network params")
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!params.hasOwnProperty('gasPrice')) {
|
|
||||||
console.error("Should include gas params")
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let privateKey = process.env.PRIVATE_KEY;
|
|
||||||
let provider = new ethers.providers.JsonRpcProvider(hre.config.networks[params['network']].url);
|
|
||||||
let wallet = new ethers.Wallet(privateKey, provider);
|
|
||||||
|
|
||||||
hre.network.name = params['networkName'];
|
|
||||||
hre.network.config = hre.config.networks[params['networkName']];
|
|
||||||
hre.network.provider = provider;
|
|
||||||
let contracts = [];
|
|
||||||
|
|
||||||
const parseFile = async (filePath) => {
|
|
||||||
const data = fs.readFileSync(filePath, "utf-8");
|
|
||||||
let parsedData = data.split("contract ");
|
|
||||||
parsedData = parsedData[parsedData.length - 1].split(" ");
|
|
||||||
parsedData = parsedData[0];
|
|
||||||
return parsedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseDir = async (root, basePath, addPath) => {
|
|
||||||
for(let i = 0; i < root.length; i++) {
|
|
||||||
addPath = "/" + root[i];
|
|
||||||
const dir = fs.readdirSync(basePath + addPath);
|
|
||||||
if(dir.indexOf("main.sol") !== -1) {
|
|
||||||
const fileData = await parseFile(basePath + addPath + "/main.sol");
|
|
||||||
contracts.push(fileData)
|
|
||||||
} else {
|
|
||||||
await parseDir(dir, basePath + addPath, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const main = async () => {
|
|
||||||
const mainnet = fs.readdirSync("./contracts/mainnet/connectors/");
|
|
||||||
const polygon = fs.readdirSync("./contracts/polygon/connectors/");
|
|
||||||
let basePathMainnet = "./contracts/mainnet/connectors/";
|
|
||||||
let basePathPolygon = "./contracts/polygon/connectors/";
|
|
||||||
|
|
||||||
const connectorName = params['connector'];
|
|
||||||
|
|
||||||
await parseDir(mainnet, basePathMainnet, "");
|
|
||||||
await parseDir(polygon, basePathPolygon, "");
|
|
||||||
|
|
||||||
if(contracts.indexOf(connectorName) === -1) {
|
|
||||||
throw new Error("can not find the connector!\n" + "supported connector names are:\n" + contracts.join("\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Connector = await ethers.getContractFactory(connectorName);
|
|
||||||
const connector = await Connector.connect(wallet).deploy({ gasPrice: ethers.utils.parseUnits(params['gasPrice'], "gwei") });
|
|
||||||
await connector.deployed();
|
|
||||||
|
|
||||||
console.log(`${connectorName} Deployed: ${connector.address}`);
|
|
||||||
try {
|
|
||||||
await hre.run("verify:verify", {
|
|
||||||
address: connector.address,
|
|
||||||
constructorArguments: []
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Failed to verify: ${connectorName}@${connector.address}`)
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
return connector.address
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => {
|
|
||||||
console.log("Done successfully");
|
|
||||||
process.exit(0)
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log("error:", err);
|
|
||||||
process.exit(1);
|
|
||||||
})
|
|
|
@ -1,36 +0,0 @@
|
||||||
const hre = require('hardhat')
|
|
||||||
const { ethers } = hre
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
if (hre.network.name === 'mainnet') {
|
|
||||||
console.log(
|
|
||||||
'\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort'
|
|
||||||
)
|
|
||||||
} else if (hre.network.name === 'hardhat') {
|
|
||||||
console.log(
|
|
||||||
'\n\n Deploying Contracts to hardhat.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const InstaMappingController = await ethers.getContractFactory('InstaMappingController')
|
|
||||||
const instaMappingController = await InstaMappingController.deploy()
|
|
||||||
await instaMappingController.deployed()
|
|
||||||
|
|
||||||
console.log('InstaMappingController deployed: ', instaMappingController.address)
|
|
||||||
|
|
||||||
if (hre.network.name === 'mainnet') {
|
|
||||||
await hre.run('verify:verify', {
|
|
||||||
address: instaMappingController.address,
|
|
||||||
constructorArguments: []
|
|
||||||
})
|
|
||||||
} else if (hre.network.name === 'hardhat') {
|
|
||||||
console.log("Contracts deployed.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
|
@ -1,38 +0,0 @@
|
||||||
const hre = require('hardhat')
|
|
||||||
const { ethers } = hre
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
if (hre.network.name === 'mainnet') {
|
|
||||||
console.log(
|
|
||||||
'\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort'
|
|
||||||
)
|
|
||||||
} else if (hre.network.name === 'hardhat') {
|
|
||||||
console.log(
|
|
||||||
'\n\n Deploying Contracts to hardhat.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const mappingContract = "CONTRACT_NAME"
|
|
||||||
|
|
||||||
const InstaProtocolMapping = await ethers.getContractFactory(mappingContract)
|
|
||||||
const instaProtocolMapping = await InstaProtocolMapping.deploy()
|
|
||||||
await instaProtocolMapping.deployed()
|
|
||||||
|
|
||||||
console.log(`${mappingContract} deployed: `, instaProtocolMapping.address)
|
|
||||||
|
|
||||||
if (hre.network.name === 'mainnet') {
|
|
||||||
await hre.run('verify:verify', {
|
|
||||||
address: instaProtocolMapping.address,
|
|
||||||
constructorArguments: []
|
|
||||||
})
|
|
||||||
} else if (hre.network.name === 'hardhat') {
|
|
||||||
console.log("Contracts deployed.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
|
@ -1,23 +0,0 @@
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers } = hre;
|
|
||||||
|
|
||||||
const deployConnector = require("./deployConnector");
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const address = await deployConnector("ConnectOne") // Example
|
|
||||||
|
|
||||||
const connectorsAbi = [
|
|
||||||
"function addConnectors(string[] _connectorNames, address[] _connectors)"
|
|
||||||
]
|
|
||||||
|
|
||||||
const connectorsContract = new ethers.Contract("0x84b457c6D31025d56449D5A01F0c34bF78636f67", connectorsAbi, ethers.provider);
|
|
||||||
|
|
||||||
await connectorsContract.addConnectors(['1inch'], [address])
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
const abis = require("./constant/abis");
|
|
||||||
const addresses = require("./constant/addresses");
|
|
||||||
const { web3 } = hre;
|
|
||||||
|
|
||||||
const encodeSpells = require("./encodeSpells.js")
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = function (spells) {
|
|
||||||
const encodeSpellsData = encodeSpells(spells);
|
|
||||||
const targetType = "string[]";
|
|
||||||
let argTypes = [targetType, "bytes[]"];
|
|
||||||
return web3.eth.abi.encodeParameters(argTypes, [
|
|
||||||
encodeSpellsData[0],
|
|
||||||
encodeSpellsData[1],
|
|
||||||
]);
|
|
||||||
};
|
|
|
@ -1,15 +0,0 @@
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers } = hre;
|
|
||||||
const addresses = require("./constant/addresses");
|
|
||||||
const abis = require("../constant/abis");
|
|
||||||
|
|
||||||
const instaImplementations_m1 = require("../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json")
|
|
||||||
|
|
||||||
module.exports = async function (owner) {
|
|
||||||
const instaIndex = await ethers.getContractAt(abis.core.instaIndex, addresses.core.instaIndex)
|
|
||||||
|
|
||||||
const tx = await instaIndex.build(owner, 2, owner);
|
|
||||||
const receipt = await tx.wait()
|
|
||||||
const event = receipt.events.find(a => a.event === "LogAccountCreated")
|
|
||||||
return await ethers.getContractAt(instaImplementations_m1.abi, event.args.account)
|
|
||||||
};
|
|
20
scripts/polygon/buildDSAv2.ts
Normal file
20
scripts/polygon/buildDSAv2.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { ethers } from "hardhat";
|
||||||
|
|
||||||
|
import { addresses } from "./constant/addresses";
|
||||||
|
import { abis } from "../constant/abis";
|
||||||
|
|
||||||
|
import { abi } from "../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json";
|
||||||
|
|
||||||
|
module.exports = async function(owner: any) {
|
||||||
|
const instaIndex = await ethers.getContractAt(
|
||||||
|
abis.core.instaIndex,
|
||||||
|
addresses.core.instaIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
const tx = await instaIndex.build(owner, 2, owner);
|
||||||
|
const receipt = await tx.wait();
|
||||||
|
const event = receipt.events.find(
|
||||||
|
(a: { event: string }) => a.event === "LogAccountCreated"
|
||||||
|
);
|
||||||
|
return await ethers.getContractAt(abi, event.args.account);
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
export const addresses = {
|
||||||
connectors: {
|
connectors: {
|
||||||
basic: "0x1cAF5EC802ca602E98139AD96A8f2B7BC524264E",
|
basic: "0x1cAF5EC802ca602E98139AD96A8f2B7BC524264E",
|
||||||
auth: "0xf6474aD0dA75A0dE15D2c915e601D9f754B9e6fe",
|
auth: "0xf6474aD0dA75A0dE15D2c915e601D9f754B9e6fe",
|
|
@ -1,7 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
address_zero: "0x0000000000000000000000000000000000000000",
|
|
||||||
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
||||||
matic_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
||||||
max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
|
||||||
};
|
|
||||||
|
|
7
scripts/polygon/constant/constant.ts
Normal file
7
scripts/polygon/constant/constant.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export const constant = {
|
||||||
|
address_zero: "0x0000000000000000000000000000000000000000",
|
||||||
|
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||||
|
matic_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||||
|
max_value:
|
||||||
|
"115792089237316195423570985008687907853269984665640564039457584007913129639935",
|
||||||
|
};
|
|
@ -1,30 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
"matic": {
|
|
||||||
"type": "token",
|
|
||||||
"symbol": "MATIC",
|
|
||||||
"name": "Matic",
|
|
||||||
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
||||||
"decimals": 18
|
|
||||||
},
|
|
||||||
"eth": {
|
|
||||||
"type": "token",
|
|
||||||
"symbol": "ETH",
|
|
||||||
"name": "Ethereum",
|
|
||||||
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
||||||
"decimals": 18
|
|
||||||
},
|
|
||||||
"dai": {
|
|
||||||
"type": "token",
|
|
||||||
"symbol": "DAI",
|
|
||||||
"name": "DAI Stable",
|
|
||||||
"address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
|
|
||||||
"decimals": 18
|
|
||||||
},
|
|
||||||
"usdc": {
|
|
||||||
"type": "token",
|
|
||||||
"symbol": "USDC",
|
|
||||||
"name": "USD Coin",
|
|
||||||
"address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
|
|
||||||
"decimals": 6
|
|
||||||
}
|
|
||||||
}
|
|
30
scripts/polygon/constant/tokens.ts
Normal file
30
scripts/polygon/constant/tokens.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
export const tokens = {
|
||||||
|
matic: {
|
||||||
|
type: "token",
|
||||||
|
symbol: "MATIC",
|
||||||
|
name: "Matic",
|
||||||
|
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
||||||
|
decimals: 18,
|
||||||
|
},
|
||||||
|
eth: {
|
||||||
|
type: "token",
|
||||||
|
symbol: "ETH",
|
||||||
|
name: "Ethereum",
|
||||||
|
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
||||||
|
decimals: 18,
|
||||||
|
},
|
||||||
|
dai: {
|
||||||
|
type: "token",
|
||||||
|
symbol: "DAI",
|
||||||
|
name: "DAI Stable",
|
||||||
|
address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
|
||||||
|
decimals: 18,
|
||||||
|
},
|
||||||
|
usdc: {
|
||||||
|
type: "token",
|
||||||
|
symbol: "USDC",
|
||||||
|
name: "USD Coin",
|
||||||
|
address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
|
||||||
|
decimals: 6,
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,19 +0,0 @@
|
||||||
const abis = require("../constant/abis");
|
|
||||||
const addresses = require("./constant/addresses");
|
|
||||||
|
|
||||||
const hre = require("hardhat");
|
|
||||||
const { ethers, waffle } = hre;
|
|
||||||
const { deployContract } = waffle;
|
|
||||||
const fs = require("fs")
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = async function ({connectorName, contractArtifact, signer, connectors}) {
|
|
||||||
const connectorInstanace = await deployContract(signer, contractArtifact, []);
|
|
||||||
|
|
||||||
await connectors.connect(signer).addConnectors([connectorName], [connectorInstanace.address])
|
|
||||||
|
|
||||||
addresses.connectors[connectorName] = connectorInstanace.address
|
|
||||||
abis.connectors[connectorName] = contractArtifact.abi;
|
|
||||||
|
|
||||||
return connectorInstanace;
|
|
||||||
};
|
|
26
scripts/polygon/deployAndEnableConnector.ts
Normal file
26
scripts/polygon/deployAndEnableConnector.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import "@nomiclabs/hardhat-waffle";
|
||||||
|
|
||||||
|
import { addresses } from "./constant/addresses";
|
||||||
|
import { abis } from "../constant/abis";
|
||||||
|
|
||||||
|
import * as hre from "hardhat";
|
||||||
|
const { ethers, waffle } = hre;
|
||||||
|
const { deployContract } = waffle;
|
||||||
|
|
||||||
|
module.exports = async function({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact,
|
||||||
|
signer,
|
||||||
|
connectors,
|
||||||
|
}) {
|
||||||
|
const connectorInstanace = await deployContract(signer, contractArtifact, []);
|
||||||
|
|
||||||
|
await connectors
|
||||||
|
.connect(signer)
|
||||||
|
.addConnectors([connectorName], [connectorInstanace.address]);
|
||||||
|
|
||||||
|
addresses.connectors[connectorName] = connectorInstanace.address;
|
||||||
|
abis.connectors[connectorName] = contractArtifact.abi;
|
||||||
|
|
||||||
|
return connectorInstanace;
|
||||||
|
};
|
|
@ -1,18 +0,0 @@
|
||||||
const abis = require("../constant/abis");
|
|
||||||
const addresses = require("./constant/addresses");
|
|
||||||
const { web3 } = hre;
|
|
||||||
|
|
||||||
module.exports = function (spells) {
|
|
||||||
const targets = spells.map(a => a.connector)
|
|
||||||
const calldatas = spells.map(a => {
|
|
||||||
const functionName = a.method;
|
|
||||||
// console.log(functionName)
|
|
||||||
const abi = abis.connectors[a.connector].find(b => {
|
|
||||||
return b.name === functionName
|
|
||||||
});
|
|
||||||
// console.log(functionName)
|
|
||||||
if (!abi) throw new Error("Couldn't find function")
|
|
||||||
return web3.eth.abi.encodeFunctionCall(abi, a.args)
|
|
||||||
})
|
|
||||||
return [targets, calldatas]
|
|
||||||
};
|
|
18
scripts/polygon/encodeSpells.ts
Normal file
18
scripts/polygon/encodeSpells.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { addresses } from "./constant/addresses";
|
||||||
|
import { abis } from "../constant/abis";
|
||||||
|
import { web3 } from "hardhat";
|
||||||
|
|
||||||
|
module.exports = function(spells: any[]) {
|
||||||
|
const targets = spells.map((a) => a.connector);
|
||||||
|
const calldatas = spells.map((a) => {
|
||||||
|
const functionName = a.method;
|
||||||
|
// console.log(functionName)
|
||||||
|
const abi = abis.connectors[a.connector].find((b: { name: any }) => {
|
||||||
|
return b.name === functionName;
|
||||||
|
});
|
||||||
|
// console.log(functionName)
|
||||||
|
if (!abi) throw new Error("Couldn't find function");
|
||||||
|
return web3.eth.abi.encodeFunctionCall(abi, a.args);
|
||||||
|
});
|
||||||
|
return [targets, calldatas];
|
||||||
|
};
|
|
@ -1,7 +1,6 @@
|
||||||
const hre = require("hardhat");
|
const { ethers, network } = "hardhat";
|
||||||
const { ethers } = hre;
|
import { addresses } from "./constant/addresses";
|
||||||
const addresses = require("./constant/addresses");
|
import { abis } from "../constant/abis";
|
||||||
const abis = require("../constant/abis");
|
|
||||||
|
|
||||||
module.exports = async function() {
|
module.exports = async function() {
|
||||||
const [_, __, ___, wallet3] = await ethers.getSigners();
|
const [_, __, ___, wallet3] = await ethers.getSigners();
|
||||||
|
@ -12,7 +11,7 @@ module.exports = async function() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const masterAddress = await instaIndex.master(); // TODO: make it constant?
|
const masterAddress = await instaIndex.master(); // TODO: make it constant?
|
||||||
await hre.network.provider.request({
|
await network.provider.request({
|
||||||
method: "hardhat_impersonateAccount",
|
method: "hardhat_impersonateAccount",
|
||||||
params: [masterAddress],
|
params: [masterAddress],
|
||||||
});
|
});
|
|
@ -1,370 +0,0 @@
|
||||||
const fs = require('fs')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
const forbiddenStrings = ['selfdestruct']
|
|
||||||
|
|
||||||
const getConnectorsList = async (connectorsRootsDirs) => {
|
|
||||||
try {
|
|
||||||
const connectors = []
|
|
||||||
for (let index = 0; index < connectorsRootsDirs.length; index++) {
|
|
||||||
const dirs = [connectorsRootsDirs[index]]
|
|
||||||
while (dirs.length) {
|
|
||||||
const currentDir = dirs.pop()
|
|
||||||
const subs = fs.readdirSync(currentDir, { withFileTypes: true })
|
|
||||||
for (let index = 0; index < subs.length; index++) {
|
|
||||||
const sub = subs[index]
|
|
||||||
if (sub.isFile() && sub.name === 'main.sol') {
|
|
||||||
connectors.push(currentDir)
|
|
||||||
} else if (sub.isDirectory()) {
|
|
||||||
dirs.push(`${currentDir}/${sub.name}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return connectors.map(dir => ({ path: dir }))
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkCodeForbidden = async (code, codePath) => {
|
|
||||||
try {
|
|
||||||
const forbidden = []
|
|
||||||
for (let i1 = 0; i1 < forbiddenStrings.length; i1++) {
|
|
||||||
const forbiddenStr = forbiddenStrings[i1]
|
|
||||||
const strs = code.split('\n')
|
|
||||||
for (let i2 = 0; i2 < strs.length; i2++) {
|
|
||||||
if (strs[i2].includes(forbiddenStr)) {
|
|
||||||
forbidden.push(`found '${forbiddenStr}' in ${codePath}:${i2 + 1}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return forbidden
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkForbidden = async (parentPath, codePath = './main.sol') => {
|
|
||||||
try {
|
|
||||||
if (codePath.startsWith('@')) {
|
|
||||||
codePath = path.resolve('node_modules', `./${codePath}`)
|
|
||||||
} else {
|
|
||||||
codePath = path.resolve(parentPath, codePath)
|
|
||||||
}
|
|
||||||
const code = fs.readFileSync(codePath, { encoding: 'utf8' })
|
|
||||||
const forbidden = await checkCodeForbidden(code, codePath)
|
|
||||||
if (code.includes('import')) {
|
|
||||||
const importsPathes = code
|
|
||||||
.split('\n')
|
|
||||||
.filter(str => str.includes('import') && str.includes('from') && str.includes('.sol'))
|
|
||||||
.map(str => str.split('from')[1].replace(/["; ]/gi, ''))
|
|
||||||
for (let index = 0; index < importsPathes.length; index++) {
|
|
||||||
const forbiddenErrors = await checkForbidden(
|
|
||||||
path.parse(codePath).dir,
|
|
||||||
importsPathes[index]
|
|
||||||
)
|
|
||||||
forbidden.push(...forbiddenErrors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return codePath.endsWith('main.sol') ? { forbiddenErrors: forbidden, code } : forbidden
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkEvents = async (connector) => {
|
|
||||||
try {
|
|
||||||
const errors = []
|
|
||||||
const warnings = []
|
|
||||||
const eventsPath = `${connector.path}/events.sol`
|
|
||||||
const mainPath = `${connector.path}/main.sol`
|
|
||||||
if (connector.events.length) {
|
|
||||||
const eventNames = []
|
|
||||||
for (let i1 = 0; i1 < connector.mainEvents.length; i1++) {
|
|
||||||
const mainEvent = connector.mainEvents[i1]
|
|
||||||
const name = mainEvent.split('(')[0]
|
|
||||||
eventNames.push(name)
|
|
||||||
const event = connector.events.find(e => e.split('(')[0].split(' ')[1] === name)
|
|
||||||
if (event) {
|
|
||||||
const mainEventArgs = mainEvent.split('(')[1].split(')')[0].split(',').map(a => a.trim())
|
|
||||||
const eventArgs = event.split('(')[1].split(')')[0].split(',').map(a => a.trim())
|
|
||||||
if (mainEventArgs.length !== eventArgs.length) {
|
|
||||||
errors.push(`arguments amount don't match for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for (let i2 = 0; i2 < mainEventArgs.length; i2++) {
|
|
||||||
if (!mainEventArgs[i2].startsWith(eventArgs[i2].split(' ')[0])) {
|
|
||||||
errors.push(`invalid argument #${i2 + 1} for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errors.push(`event ${name} missing at ${eventsPath}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (connector.mainEvents.length < connector.events.length) {
|
|
||||||
const deprecatedEvents = connector.events.filter(e => {
|
|
||||||
let used = false
|
|
||||||
for (let index = 0; index < eventNames.length; index++) {
|
|
||||||
if (e.split('(')[0].split(' ')[1] === eventNames[index]) used = true
|
|
||||||
}
|
|
||||||
return !used
|
|
||||||
})
|
|
||||||
warnings.push(`${deprecatedEvents.map(e => e.split('(')[0].split(' ')[1]).join(', ')} event(s) not used at ${connector.path}/main.sol`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warnings.push(`missing events file for ${connector.path}/main.sol`)
|
|
||||||
}
|
|
||||||
return { eventsErrors: errors, eventsWarnings: warnings }
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCommments = async (strs) => {
|
|
||||||
try {
|
|
||||||
const comments = []
|
|
||||||
let type
|
|
||||||
for (let index = strs.length - 1; index >= 0; index--) {
|
|
||||||
const str = strs[index]
|
|
||||||
if (!type) {
|
|
||||||
if (str.trim().startsWith('//')) {
|
|
||||||
type = 'single'
|
|
||||||
} else if (str.trim().startsWith('*/')) {
|
|
||||||
type = 'multiple'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type === 'single' && str.trim().startsWith('//')) {
|
|
||||||
comments.push(str.replace(/[/]/gi, '').trim())
|
|
||||||
} else if (type === 'multiple' && !str.trim().startsWith('/**') && !str.trim().startsWith('*/')) {
|
|
||||||
comments.push(str.replace(/[*]/gi, '').trim())
|
|
||||||
} else if (type === 'single' && !str.trim().startsWith('//')) {
|
|
||||||
break
|
|
||||||
} else if (type === 'multiple' && str.trim().startsWith('/**')) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return comments
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseCode = async (connector) => {
|
|
||||||
try {
|
|
||||||
const strs = connector.code.split('\n')
|
|
||||||
const events = []
|
|
||||||
const eventsFirstLines = []
|
|
||||||
let func = []
|
|
||||||
let funcs = []
|
|
||||||
let event = []
|
|
||||||
let mainEvents = []
|
|
||||||
let firstLine
|
|
||||||
let mainEventsLines = []
|
|
||||||
for (let index = 0; index < strs.length; index++) {
|
|
||||||
const str = strs[index]
|
|
||||||
if (str.includes('function') && !str.trim().startsWith('//')) {
|
|
||||||
func = [str]
|
|
||||||
firstLine = index + 1
|
|
||||||
} else if (func.length && !str.trim().startsWith('//')) {
|
|
||||||
func.push(str)
|
|
||||||
}
|
|
||||||
if (func.length && str.startsWith(`${func[0].split('function')[0]}}`)) {
|
|
||||||
funcs.push({
|
|
||||||
raw: func.map(str => str.trim()).join(' '),
|
|
||||||
comments: await getCommments(strs.slice(0, firstLine)),
|
|
||||||
firstLine
|
|
||||||
})
|
|
||||||
func = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const allPublicFuncs = funcs
|
|
||||||
.filter(({ raw }) => {
|
|
||||||
return raw.includes('external') || raw.includes('public')
|
|
||||||
})
|
|
||||||
.map(f => {
|
|
||||||
const name = f.raw.split('(')[0].split('function')[1].trim()
|
|
||||||
return {
|
|
||||||
...f,
|
|
||||||
name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
funcs = allPublicFuncs
|
|
||||||
.filter(({ raw }) => {
|
|
||||||
if (raw.includes('returns')) {
|
|
||||||
const returns = raw.split('returns')[1].split('(')[1].split(')')[0]
|
|
||||||
return returns.includes('string') && returns.includes('bytes')
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
.map(f => {
|
|
||||||
const args = f.raw.split('(')[1].split(')')[0].split(',')
|
|
||||||
.map(arg => arg.trim())
|
|
||||||
.filter(arg => arg !== '')
|
|
||||||
return {
|
|
||||||
...f,
|
|
||||||
args
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const eventsPath = `${connector.path}/events.sol`
|
|
||||||
if (fs.existsSync(eventsPath)) {
|
|
||||||
mainEvents = funcs
|
|
||||||
.map(({ raw }) => raw.split('_eventName')[2].trim().split('"')[1])
|
|
||||||
.filter(raw => !!raw)
|
|
||||||
mainEventsLines = mainEvents.map(me => strs.findIndex(str => str.includes(me)) + 1)
|
|
||||||
const eventsCode = fs.readFileSync(eventsPath, { encoding: 'utf8' })
|
|
||||||
const eventsStrs = eventsCode.split('\n')
|
|
||||||
for (let index = 0; index < eventsStrs.length; index++) {
|
|
||||||
const str = eventsStrs[index]
|
|
||||||
if (str.includes('event')) {
|
|
||||||
event = [str]
|
|
||||||
firstLine = index + 1
|
|
||||||
} else if (event.length && !str.trim().startsWith('//')) {
|
|
||||||
event.push(str)
|
|
||||||
}
|
|
||||||
if (event.length && str.includes(')')) {
|
|
||||||
events.push(event.map(str => str.trim()).join(' '))
|
|
||||||
eventsFirstLines.push(firstLine)
|
|
||||||
event = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...connector,
|
|
||||||
events,
|
|
||||||
eventsFirstLines,
|
|
||||||
mainEvents,
|
|
||||||
mainEventsLines,
|
|
||||||
funcs,
|
|
||||||
allPublicFuncs
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkComments = async (connector) => {
|
|
||||||
try {
|
|
||||||
const errors = []
|
|
||||||
for (let i1 = 0; i1 < connector.funcs.length; i1++) {
|
|
||||||
const func = connector.funcs[i1]
|
|
||||||
for (let i2 = 0; i2 < func.args.length; i2++) {
|
|
||||||
const argName = func.args[i2].split(' ').pop()
|
|
||||||
if (!func.comments.some(
|
|
||||||
comment => comment.startsWith('@param') && comment.split(' ')[1] === argName
|
|
||||||
)) {
|
|
||||||
errors.push(`argument ${argName} has no @param for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const reqs = ['@dev', '@notice']
|
|
||||||
for (let i3 = 0; i3 < reqs.length; i3++) {
|
|
||||||
if (!func.comments.some(comment => comment.startsWith(reqs[i3]))) {
|
|
||||||
errors.push(`no ${reqs[i3]} for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkPublicFuncs = async (connector) => {
|
|
||||||
try {
|
|
||||||
const errors = []
|
|
||||||
for (let i1 = 0; i1 < connector.allPublicFuncs.length; i1++) {
|
|
||||||
const { raw, firstLine, name } = connector.allPublicFuncs[i1]
|
|
||||||
if (!raw.includes('payable')) {
|
|
||||||
errors.push(`public function ${name} is not payable at ${connector.path}/main.sol:${firstLine}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkName = async (connector) => {
|
|
||||||
try {
|
|
||||||
const strs = connector.code.split('\n')
|
|
||||||
let haveName = false
|
|
||||||
for (let index = strs.length - 1; index > 0; index--) {
|
|
||||||
const str = strs[index]
|
|
||||||
if (str.includes('string') && str.includes('public') && str.includes('name = ')) {
|
|
||||||
haveName = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return haveName ? [] : [`name variable missing in ${connector.path}/main.sol`]
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkHeadComments = async (connector) => {
|
|
||||||
try {
|
|
||||||
const errors = []
|
|
||||||
const strs = connector.code.split('\n')
|
|
||||||
let haveTitle = false
|
|
||||||
let haveDev = false
|
|
||||||
for (let index = 0; index < strs.length; index++) {
|
|
||||||
if (!strs[index].includes('{')) {
|
|
||||||
if (strs[index].includes('@title')) haveTitle = true
|
|
||||||
if (strs[index].includes('@dev')) haveDev = true
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!haveTitle) errors.push(`@title missing in ${connector.path}/main.sol`)
|
|
||||||
if (!haveDev) errors.push(`@dev missing in ${connector.path}/main.sol`)
|
|
||||||
return errors
|
|
||||||
} catch (error) {
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function checkMain () {
|
|
||||||
try {
|
|
||||||
const connectorsRootsDirsDefault = ['mainnet', 'polygon'].map(v=> `contracts/${v}/connectors`)
|
|
||||||
const customPathArg = process.argv.find(a => a.startsWith('connector='))
|
|
||||||
const connectorsRootsDirs = customPathArg
|
|
||||||
? [customPathArg.slice(10)]
|
|
||||||
: connectorsRootsDirsDefault
|
|
||||||
const errors = []
|
|
||||||
const warnings = []
|
|
||||||
const connectors = await getConnectorsList(connectorsRootsDirs)
|
|
||||||
for (let index = 0; index < connectors.length; index++) {
|
|
||||||
const { forbiddenErrors, code } = await checkForbidden(connectors[index].path)
|
|
||||||
connectors[index].code = code
|
|
||||||
connectors[index] = await parseCode(connectors[index])
|
|
||||||
const { eventsErrors, eventsWarnings } = await checkEvents(connectors[index])
|
|
||||||
const commentsErrors = await checkComments(connectors[index])
|
|
||||||
const nameErrors = await checkName(connectors[index])
|
|
||||||
const headCommentsErrors = await checkHeadComments(connectors[index])
|
|
||||||
const publicFuncsErrors = await checkPublicFuncs(connectors[index])
|
|
||||||
|
|
||||||
errors.push(...forbiddenErrors)
|
|
||||||
errors.push(...eventsErrors)
|
|
||||||
errors.push(...commentsErrors)
|
|
||||||
errors.push(...nameErrors)
|
|
||||||
errors.push(...headCommentsErrors)
|
|
||||||
errors.push(...publicFuncsErrors)
|
|
||||||
warnings.push(...eventsWarnings)
|
|
||||||
}
|
|
||||||
if (errors.length) {
|
|
||||||
console.log('\x1b[31m%s\x1b[0m', `Total errors: ${errors.length}`)
|
|
||||||
errors.forEach(error => console.log('\x1b[31m%s\x1b[0m', error))
|
|
||||||
} else {
|
|
||||||
console.log('\x1b[32m%s\x1b[0m', 'No Errors Found')
|
|
||||||
}
|
|
||||||
if (warnings.length) {
|
|
||||||
console.log('\x1b[33m%s\x1b[0m', `Total warnings: ${warnings.length}`)
|
|
||||||
warnings.forEach(warning => console.log('\x1b[33m%s\x1b[0m', warning))
|
|
||||||
} else {
|
|
||||||
console.log('\x1b[32m%s\x1b[0m', 'No Warnings Found')
|
|
||||||
}
|
|
||||||
if (errors.length) return Promise.reject(errors.join('\n'))
|
|
||||||
} catch (error) {
|
|
||||||
console.error('check execution error:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = checkMain
|
|
448
status-checks/check.ts
Normal file
448
status-checks/check.ts
Normal file
|
@ -0,0 +1,448 @@
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
const forbiddenStrings: any = ["selfdestruct"];
|
||||||
|
|
||||||
|
const getConnectorsList = async (connectorsRootsDirs: string | any[]) => {
|
||||||
|
try {
|
||||||
|
const connectors = [];
|
||||||
|
for (let index = 0; index < connectorsRootsDirs.length; index++) {
|
||||||
|
const dirs = [connectorsRootsDirs[index]];
|
||||||
|
while (dirs.length) {
|
||||||
|
const currentDir = dirs.pop();
|
||||||
|
const subs = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||||
|
for (let index = 0; index < subs.length; index++) {
|
||||||
|
const sub = subs[index];
|
||||||
|
if (sub.isFile() && sub.name === "main.sol") {
|
||||||
|
connectors.push(currentDir);
|
||||||
|
} else if (sub.isDirectory()) {
|
||||||
|
dirs.push(`${currentDir}/${sub.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connectors.map((dir) => ({ path: dir }));
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkCodeForbidden = async (code: string, codePath: string) => {
|
||||||
|
try {
|
||||||
|
const forbidden = [];
|
||||||
|
for (let i1 = 0; i1 < forbiddenStrings.length; i1++) {
|
||||||
|
const forbiddenStr = forbiddenStrings[i1];
|
||||||
|
const strs = code.split("\n");
|
||||||
|
for (let i2 = 0; i2 < strs.length; i2++) {
|
||||||
|
if (strs[i2].includes(forbiddenStr)) {
|
||||||
|
forbidden.push(`found '${forbiddenStr}' in ${codePath}:${i2 + 1}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return forbidden;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkForbidden = async (parentPath: string, codePath = "./main.sol") => {
|
||||||
|
try {
|
||||||
|
if (codePath.startsWith("@")) {
|
||||||
|
codePath = path.resolve("node_modules", `./${codePath}`);
|
||||||
|
} else {
|
||||||
|
codePath = path.resolve(parentPath, codePath);
|
||||||
|
}
|
||||||
|
const code = fs.readFileSync(codePath, { encoding: "utf8" });
|
||||||
|
const forbidden: any = await checkCodeForbidden(code, codePath);
|
||||||
|
if (code.includes("import")) {
|
||||||
|
const importsPathes = code
|
||||||
|
.split("\n")
|
||||||
|
.filter(
|
||||||
|
(str) =>
|
||||||
|
str.includes("import") &&
|
||||||
|
str.includes("from") &&
|
||||||
|
str.includes(".sol")
|
||||||
|
)
|
||||||
|
.map((str) => str.split("from")[1].replace(/["; ]/gi, ""));
|
||||||
|
for (let index = 0; index < importsPathes.length; index++) {
|
||||||
|
const forbiddenErrors = await checkForbidden(
|
||||||
|
path.parse(codePath).dir,
|
||||||
|
importsPathes[index]
|
||||||
|
);
|
||||||
|
forbidden.push(...forbiddenErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codePath.endsWith("main.sol")
|
||||||
|
? { forbiddenErrors: forbidden, code }
|
||||||
|
: forbidden;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkEvents = async (connector: {
|
||||||
|
path: any;
|
||||||
|
events?: any;
|
||||||
|
mainEvents?: any;
|
||||||
|
mainEventsLines?: any;
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
const errors = [];
|
||||||
|
const warnings = [];
|
||||||
|
const eventsPath = `${connector.path}/events.sol`;
|
||||||
|
const mainPath = `${connector.path}/main.sol`;
|
||||||
|
if (connector.events.length) {
|
||||||
|
const eventNames = [];
|
||||||
|
for (let i1 = 0; i1 < connector.mainEvents.length; i1++) {
|
||||||
|
const mainEvent = connector.mainEvents[i1];
|
||||||
|
const name = mainEvent.split("(")[0];
|
||||||
|
eventNames.push(name);
|
||||||
|
const event = connector.events.find(
|
||||||
|
(e: string) => e.split("(")[0].split(" ")[1] === name
|
||||||
|
);
|
||||||
|
if (event) {
|
||||||
|
const mainEventArgs = mainEvent
|
||||||
|
.split("(")[1]
|
||||||
|
.split(")")[0]
|
||||||
|
.split(",")
|
||||||
|
.map((a: string) => a.trim());
|
||||||
|
const eventArgs = event
|
||||||
|
.split("(")[1]
|
||||||
|
.split(")")[0]
|
||||||
|
.split(",")
|
||||||
|
.map((a: string) => a.trim());
|
||||||
|
if (mainEventArgs.length !== eventArgs.length) {
|
||||||
|
errors.push(
|
||||||
|
`arguments amount don't match for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (let i2 = 0; i2 < mainEventArgs.length; i2++) {
|
||||||
|
if (!mainEventArgs[i2].startsWith(eventArgs[i2].split(" ")[0])) {
|
||||||
|
errors.push(
|
||||||
|
`invalid argument #${i2 + 1} for ${name} at ${mainPath}:${
|
||||||
|
connector.mainEventsLines[i1]
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors.push(`event ${name} missing at ${eventsPath}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (connector.mainEvents.length < connector.events.length) {
|
||||||
|
const deprecatedEvents = connector.events.filter((e) => {
|
||||||
|
let used = false;
|
||||||
|
for (let index = 0; index < eventNames.length; index++) {
|
||||||
|
if (e.split("(")[0].split(" ")[1] === eventNames[index])
|
||||||
|
used = true;
|
||||||
|
}
|
||||||
|
return !used;
|
||||||
|
});
|
||||||
|
warnings.push(
|
||||||
|
`${deprecatedEvents
|
||||||
|
.map((e: string) => e.split("(")[0].split(" ")[1])
|
||||||
|
.join(", ")} event(s) not used at ${connector.path}/main.sol`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warnings.push(`missing events file for ${connector.path}/main.sol`);
|
||||||
|
}
|
||||||
|
return { eventsErrors: errors, eventsWarnings: warnings };
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCommments = async (strs: string | any[]) => {
|
||||||
|
try {
|
||||||
|
const comments = [];
|
||||||
|
let type: string;
|
||||||
|
for (let index = strs.length - 1; index >= 0; index--) {
|
||||||
|
const str = strs[index];
|
||||||
|
if (!type) {
|
||||||
|
if (str.trim().startsWith("//")) {
|
||||||
|
type = "single";
|
||||||
|
} else if (str.trim().startsWith("*/")) {
|
||||||
|
type = "multiple";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type === "single" && str.trim().startsWith("//")) {
|
||||||
|
comments.push(str.replace(/[/]/gi, "").trim());
|
||||||
|
} else if (
|
||||||
|
type === "multiple" &&
|
||||||
|
!str.trim().startsWith("/**") &&
|
||||||
|
!str.trim().startsWith("*/")
|
||||||
|
) {
|
||||||
|
comments.push(str.replace(/[*]/gi, "").trim());
|
||||||
|
} else if (type === "single" && !str.trim().startsWith("//")) {
|
||||||
|
break;
|
||||||
|
} else if (type === "multiple" && str.trim().startsWith("/**")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comments;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseCode = async (connector: { path: any; code?: any }) => {
|
||||||
|
try {
|
||||||
|
const strs = connector.code.split("\n");
|
||||||
|
const events = [];
|
||||||
|
const eventsFirstLines = [];
|
||||||
|
let func = [];
|
||||||
|
let funcs = [];
|
||||||
|
let event = [];
|
||||||
|
let mainEvents = [];
|
||||||
|
let firstLine: number;
|
||||||
|
let mainEventsLines = [];
|
||||||
|
for (let index = 0; index < strs.length; index++) {
|
||||||
|
const str = strs[index];
|
||||||
|
if (str.includes("function") && !str.trim().startsWith("//")) {
|
||||||
|
func = [str];
|
||||||
|
firstLine = index + 1;
|
||||||
|
} else if (func.length && !str.trim().startsWith("//")) {
|
||||||
|
func.push(str);
|
||||||
|
}
|
||||||
|
if (func.length && str.startsWith(`${func[0].split("function")[0]}}`)) {
|
||||||
|
funcs.push({
|
||||||
|
raw: func.map((str) => str.trim()).join(" "),
|
||||||
|
comments: await getCommments(strs.slice(0, firstLine)),
|
||||||
|
firstLine,
|
||||||
|
});
|
||||||
|
func = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const allPublicFuncs = funcs
|
||||||
|
.filter(({ raw }) => {
|
||||||
|
return raw.includes("external") || raw.includes("public");
|
||||||
|
})
|
||||||
|
.map((f) => {
|
||||||
|
const name = f.raw
|
||||||
|
.split("(")[0]
|
||||||
|
.split("function")[1]
|
||||||
|
.trim();
|
||||||
|
return {
|
||||||
|
...f,
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
funcs = allPublicFuncs
|
||||||
|
.filter(({ raw }) => {
|
||||||
|
if (raw.includes("returns")) {
|
||||||
|
const returns = raw
|
||||||
|
.split("returns")[1]
|
||||||
|
.split("(")[1]
|
||||||
|
.split(")")[0];
|
||||||
|
return returns.includes("string") && returns.includes("bytes");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.map((f) => {
|
||||||
|
const args = f.raw
|
||||||
|
.split("(")[1]
|
||||||
|
.split(")")[0]
|
||||||
|
.split(",")
|
||||||
|
.map((arg) => arg.trim())
|
||||||
|
.filter((arg) => arg !== "");
|
||||||
|
return {
|
||||||
|
...f,
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const eventsPath = `${connector.path}/events.sol`;
|
||||||
|
if (fs.existsSync(eventsPath)) {
|
||||||
|
mainEvents = funcs
|
||||||
|
.map(
|
||||||
|
({ raw }) =>
|
||||||
|
raw
|
||||||
|
.split("_eventName")[2]
|
||||||
|
.trim()
|
||||||
|
.split('"')[1]
|
||||||
|
)
|
||||||
|
.filter((raw) => !!raw);
|
||||||
|
mainEventsLines = mainEvents.map(
|
||||||
|
(me) => strs.findIndex((str: string | any[]) => str.includes(me)) + 1
|
||||||
|
);
|
||||||
|
const eventsCode = fs.readFileSync(eventsPath, { encoding: "utf8" });
|
||||||
|
const eventsStrs = eventsCode.split("\n");
|
||||||
|
for (let index = 0; index < eventsStrs.length; index++) {
|
||||||
|
const str = eventsStrs[index];
|
||||||
|
if (str.includes("event")) {
|
||||||
|
event = [str];
|
||||||
|
firstLine = index + 1;
|
||||||
|
} else if (event.length && !str.trim().startsWith("//")) {
|
||||||
|
event.push(str);
|
||||||
|
}
|
||||||
|
if (event.length && str.includes(")")) {
|
||||||
|
events.push(event.map((str) => str.trim()).join(" "));
|
||||||
|
eventsFirstLines.push(firstLine);
|
||||||
|
event = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...connector,
|
||||||
|
events,
|
||||||
|
eventsFirstLines,
|
||||||
|
mainEvents,
|
||||||
|
mainEventsLines,
|
||||||
|
funcs,
|
||||||
|
allPublicFuncs,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkComments = async (connector) => {
|
||||||
|
try {
|
||||||
|
const errors = [];
|
||||||
|
for (let i1 = 0; i1 < connector.funcs.length; i1++) {
|
||||||
|
const func = connector.funcs[i1];
|
||||||
|
for (let i2 = 0; i2 < func.args.length; i2++) {
|
||||||
|
const argName = func.args[i2].split(" ").pop();
|
||||||
|
if (
|
||||||
|
!func.comments.some(
|
||||||
|
(comment: string) =>
|
||||||
|
comment.startsWith("@param") && comment.split(" ")[1] === argName
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
errors.push(
|
||||||
|
`argument ${argName} has no @param for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const reqs = ["@dev", "@notice"];
|
||||||
|
for (let i3 = 0; i3 < reqs.length; i3++) {
|
||||||
|
if (!func.comments.some((comment) => comment.startsWith(reqs[i3]))) {
|
||||||
|
errors.push(
|
||||||
|
`no ${reqs[i3]} for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkPublicFuncs = async (connector: {
|
||||||
|
path: any;
|
||||||
|
allPublicFuncs?: any;
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
const errors = [];
|
||||||
|
for (let i1 = 0; i1 < connector.allPublicFuncs.length; i1++) {
|
||||||
|
const { raw, firstLine, name } = connector.allPublicFuncs[i1];
|
||||||
|
if (!raw.includes("payable")) {
|
||||||
|
errors.push(
|
||||||
|
`public function ${name} is not payable at ${connector.path}/main.sol:${firstLine}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkName = async (connector: { path: any; code?: any }) => {
|
||||||
|
try {
|
||||||
|
const strs = connector.code.split("\n");
|
||||||
|
let haveName = false;
|
||||||
|
for (let index = strs.length - 1; index > 0; index--) {
|
||||||
|
const str = strs[index];
|
||||||
|
if (
|
||||||
|
str.includes("string") &&
|
||||||
|
str.includes("public") &&
|
||||||
|
str.includes("name = ")
|
||||||
|
) {
|
||||||
|
haveName = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return haveName
|
||||||
|
? []
|
||||||
|
: [`name variable missing in ${connector.path}/main.sol`];
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkHeadComments = async (connector: { path: any; code?: any }) => {
|
||||||
|
try {
|
||||||
|
const errors = [];
|
||||||
|
const strs = connector.code.split("\n");
|
||||||
|
let haveTitle = false;
|
||||||
|
let haveDev = false;
|
||||||
|
for (let index = 0; index < strs.length; index++) {
|
||||||
|
if (!strs[index].includes("{")) {
|
||||||
|
if (strs[index].includes("@title")) haveTitle = true;
|
||||||
|
if (strs[index].includes("@dev")) haveDev = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!haveTitle) errors.push(`@title missing in ${connector.path}/main.sol`);
|
||||||
|
if (!haveDev) errors.push(`@dev missing in ${connector.path}/main.sol`);
|
||||||
|
return errors;
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function checkMain() {
|
||||||
|
try {
|
||||||
|
const connectorsRootsDirsDefault = ["mainnet", "polygon"].map(
|
||||||
|
(v) => `contracts/${v}/connectors`
|
||||||
|
);
|
||||||
|
const customPathArg = process.argv.find((a) => a.startsWith("connector="));
|
||||||
|
const connectorsRootsDirs = customPathArg
|
||||||
|
? [customPathArg.slice(10)]
|
||||||
|
: connectorsRootsDirsDefault;
|
||||||
|
const errors = [];
|
||||||
|
const warnings = [];
|
||||||
|
const connectors = await getConnectorsList(connectorsRootsDirs);
|
||||||
|
for (let index = 0; index < connectors.length; index++) {
|
||||||
|
const { forbiddenErrors, code } = await checkForbidden(
|
||||||
|
connectors[index].path
|
||||||
|
);
|
||||||
|
connectors[index].code = code;
|
||||||
|
connectors[index] = await parseCode(connectors[index]);
|
||||||
|
const { eventsErrors, eventsWarnings } = await checkEvents(
|
||||||
|
connectors[index]
|
||||||
|
);
|
||||||
|
const commentsErrors = await checkComments(connectors[index]);
|
||||||
|
const nameErrors = await checkName(connectors[index]);
|
||||||
|
const headCommentsErrors = await checkHeadComments(connectors[index]);
|
||||||
|
const publicFuncsErrors = await checkPublicFuncs(connectors[index]);
|
||||||
|
|
||||||
|
errors.push(...forbiddenErrors);
|
||||||
|
errors.push(...eventsErrors);
|
||||||
|
errors.push(...commentsErrors);
|
||||||
|
errors.push(...nameErrors);
|
||||||
|
errors.push(...headCommentsErrors);
|
||||||
|
errors.push(...publicFuncsErrors);
|
||||||
|
warnings.push(...eventsWarnings);
|
||||||
|
}
|
||||||
|
if (errors.length) {
|
||||||
|
console.log("\x1b[31m%s\x1b[0m", `Total errors: ${errors.length}`);
|
||||||
|
errors.forEach((error) => console.log("\x1b[31m%s\x1b[0m", error));
|
||||||
|
} else {
|
||||||
|
console.log("\x1b[32m%s\x1b[0m", "No Errors Found");
|
||||||
|
}
|
||||||
|
if (warnings.length) {
|
||||||
|
console.log("\x1b[33m%s\x1b[0m", `Total warnings: ${warnings.length}`);
|
||||||
|
warnings.forEach((warning) => console.log("\x1b[33m%s\x1b[0m", warning));
|
||||||
|
} else {
|
||||||
|
console.log("\x1b[32m%s\x1b[0m", "No Warnings Found");
|
||||||
|
}
|
||||||
|
if (errors.length) return Promise.reject(errors.join("\n"));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("check execution error:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default checkMain;
|
|
@ -1,13 +0,0 @@
|
||||||
const checkMain = require('./check')
|
|
||||||
|
|
||||||
module.exports = [{
|
|
||||||
name: 'Solidity check',
|
|
||||||
callback: async () => {
|
|
||||||
try {
|
|
||||||
await checkMain()
|
|
||||||
return 'Check passed!'
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error('Check failed!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
15
status-checks/checks.ts
Normal file
15
status-checks/checks.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import checkMain from "./check";
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
name: "Solidity check",
|
||||||
|
callback: async () => {
|
||||||
|
try {
|
||||||
|
await checkMain();
|
||||||
|
return "Check passed!";
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Check failed!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
|
@ -1,9 +0,0 @@
|
||||||
const checkMain = require('./check');
|
|
||||||
|
|
||||||
(async function runHusky () {
|
|
||||||
try {
|
|
||||||
await checkMain()
|
|
||||||
} catch (error) {
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
})()
|
|
9
status-checks/huskyCheck.ts
Normal file
9
status-checks/huskyCheck.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import checkMain from "./check";
|
||||||
|
|
||||||
|
(async function runHusky() {
|
||||||
|
try {
|
||||||
|
await checkMain();
|
||||||
|
} catch (error) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
|
@ -1,54 +0,0 @@
|
||||||
const cp = require('child_process')
|
|
||||||
const fetch = require('node-fetch')
|
|
||||||
|
|
||||||
const checks = require('./checks')
|
|
||||||
|
|
||||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
|
||||||
|
|
||||||
function getCurrentCommitSha () {
|
|
||||||
return cp
|
|
||||||
.execSync('git rev-parse HEAD')
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
}
|
|
||||||
// The SHA provied by GITHUB_SHA is the merge (PR) commit.
|
|
||||||
// We need to get the current commit sha ourself.
|
|
||||||
const sha = getCurrentCommitSha()
|
|
||||||
|
|
||||||
async function setStatus (context, state, description) {
|
|
||||||
return fetch(`https://api.github.com/repos/${owner}/${repo}/statuses/${sha}`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
state,
|
|
||||||
description,
|
|
||||||
context
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
console.log(`Starting status checks for commit ${sha}`)
|
|
||||||
|
|
||||||
// Run in parallel
|
|
||||||
await Promise.all(
|
|
||||||
checks.map(async check => {
|
|
||||||
const { name, callback } = check
|
|
||||||
|
|
||||||
await setStatus(name, 'pending', 'Running check..')
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await callback()
|
|
||||||
await setStatus(name, 'success', response)
|
|
||||||
} catch (err) {
|
|
||||||
const message = err ? err.message : 'Something went wrong'
|
|
||||||
await setStatus(name, 'failure', message)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log('Finished status checks')
|
|
||||||
})()
|
|
57
status-checks/index.ts
Normal file
57
status-checks/index.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import * as cp from "child_process";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
|
||||||
|
import checkMain from "./check";
|
||||||
|
|
||||||
|
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
|
||||||
|
|
||||||
|
function getCurrentCommitSha() {
|
||||||
|
return cp
|
||||||
|
.execSync("git rev-parse HEAD")
|
||||||
|
.toString()
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
// The SHA provied by GITHUB_SHA is the merge (PR) commit.
|
||||||
|
// We need to get the current commit sha ourself.
|
||||||
|
const sha = getCurrentCommitSha();
|
||||||
|
|
||||||
|
async function setStatus(context, state, description) {
|
||||||
|
return fetch(
|
||||||
|
`https://api.github.com/repos/${owner}/${repo}/statuses/${sha}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
state,
|
||||||
|
description,
|
||||||
|
context,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
console.log(`Starting status checks for commit ${sha}`);
|
||||||
|
|
||||||
|
// Run in parallel
|
||||||
|
await Promise.all(
|
||||||
|
checks.map(async (check) => {
|
||||||
|
const { name, callback } = check;
|
||||||
|
|
||||||
|
await setStatus(name, "pending", "Running check..");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await callback();
|
||||||
|
await setStatus(name, "success", response);
|
||||||
|
} catch (err) {
|
||||||
|
const message = err ? err.message : "Something went wrong";
|
||||||
|
await setStatus(name, "failure", message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Finished status checks");
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user