Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upload description to IPFS #27

Merged
merged 1 commit into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions omnibuses/_example_omnibus.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import omnibuses from "../src/omnibuses/omnibuses";
import { call, event } from "../src/votes";

const description = `
1. **Expanding the Simple DVT Module:** Incre a s e the Simple DVT module's staking share limit from 0.5% to 4%, as decided in the [Snapshot vote](https://snapshot.org/#/lido-snapshot.eth/proposal/0xaca2da3c932542e030db8bf5b6e4420bf4aa98bd57bd62b9b8008a4b7398abb2).
2. **Lido Contributors Group Funding:** Trans fer 180,000 LDO within the [EGG st2024 v2 Grant Funding](https://snapshot.org/#/lido-snapshot.eth/proposal/0x2baf3275d15a8494ff94fef58d93bedd2fc28bfea8519f7e86474fc72dc25076) to the [PML multisig](https://app.safe.global/settings/setup?safe=eth:0x17F6b2C738a63a8D3A113a228cfd0b373244633D).
`;

export default omnibuses.create({
network: "mainnet",
description: "",
// launchedOn: 12345678, // Launch block number should be set only if omnibus was successfully launched.
// voteId: 000, // Vote ID should be set only if omnibus is already started.
// executedOn: 12345678, // Execution block number should be set only if vote is passed and omnibus was successfully executed.
Expand Down
3 changes: 3 additions & 0 deletions package.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module "ipfs-only-hash" {
function of(text: string, params: { cidVersion: 1 | 0; rawLeaves: true }): Promise<string>;
}
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"omnibus": "ts-node --files ./scripts/omnibs.ts",
"omnibus:run": "hardhat omnibus:run",
"omnibus:test": "hardhat omnibus:test",
"omnibus:simulate": "hardhat omnibus:simulate",
"omnibus:debug": "hardhat omnibus:simulate _example_omnibus",
"ks:add": "hardhat keystore:add",
"ks:ls": "hardhat keystore:list",
"ks:del": "hardhat keystore:delete",
Expand Down Expand Up @@ -43,9 +45,11 @@
"commander": "^11.1.0",
"dotenv": "^16.3.1",
"hardhat": "2.22.9",
"ipfs-only-hash": "^4.0.0",
"lodash": "^4.17.21",
"mocha": "^10.2.0",
"node-fetch": "^2.7.0",
"pinata-web3": "^0.5.2",
"prompts": "^2.4.2",
"tree-kill": "^1.2.2",
"web3-eth-accounts": "^4.1.1",
Expand Down
851 changes: 851 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/common/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ function ETHERSCAN_TOKEN() {
return process.env.ETHERSCAN_TOKEN;
}

function PINATA_JWT() {
return process.env.PINATA_JWT;
}

function ETHERSCAN_CACHE_ENABLED() {
switch (process.env.ETHERSCAN_CACHE_ENABLED) {
case "true":
Expand Down Expand Up @@ -65,4 +69,5 @@ export default {
ETHERSCAN_TOKEN,
ETHERSCAN_CACHE_ENABLED,
checkEnvVars,
PINATA_JWT,
};
14 changes: 14 additions & 0 deletions src/common/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ const DEFAULT_PROMPTS_OPTIONS = {
},
};

async function confirmOrAbort(message?: string) {
const { isConfirmed } = await prompts({
type: "toggle",
name: "isConfirmed",
message: message ?? "Confirm?",
active: "yes",
inactive: "no",
});
if (!isConfirmed) {
throw new OperationAbortedError();
}
}

async function confirm(message?: string) {
const { isConfirmed } = await prompts({
type: "toggle",
Expand Down Expand Up @@ -101,6 +114,7 @@ export default {
secret,
select,
confirm,
confirmOrAbort,
password,
sigint,
};
12 changes: 12 additions & 0 deletions src/ipfs/ipfs-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import env from "../common/env";
import pinata from "./pinata";

export const getIpfsProvider = async () => {
if (env.PINATA_JWT()) {
return pinata.getProvider();
}
return null;
};

export const instruction =
"you need to add env variable PINATA_JWT, you could get JWT it at https://pinata.cloud site for free";
28 changes: 28 additions & 0 deletions src/ipfs/pinata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PinataSDK } from "pinata-web3";
import env from "../common/env";

const getProvider = () => {
const pinata = new PinataSDK({
pinataJwt: env.PINATA_JWT(),
});

const uploadStringToIpfs = async (string: string, name?: string) => {
try {
const file = new File([string], `${name}.md`, { type: "text/markdown" });

const { IpfsHash } = await pinata.upload.file(file, { cidVersion: 1 });
return IpfsHash;
} catch (err) {
console.error(err);
return "";
}
};

return {
uploadStringToIpfs,
};
};

export default {
getProvider,
};
18 changes: 18 additions & 0 deletions src/ipfs/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Hash from "ipfs-only-hash";

export function getUrlByCidV1(cid: string) {
return `https://${cid}.ipfs.dweb.link`;
}

export async function calculateCid(string: string) {
return await Hash.of(string, { cidVersion: 1, rawLeaves: true });
}

export const isCidUploaded = async (cid: string) => {
try {
const resp = await fetch(getUrlByCidV1(cid), { signal: AbortSignal.timeout(8000) });
return resp.status < 300;
} catch (e) {
return false;
}
};
6 changes: 3 additions & 3 deletions src/omnibuses/checks/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { BigNumberish } from "ethers";
import { BigNumberish, formatEther } from "ethers";
import { assert } from "../../common/assert";
import { CheckContext } from "./checks";

const checkLDOBalance = async ({ contracts }: CheckContext, address: string, balance: BigNumberish) => {
const ldoBalance = await contracts.ldo.balanceOf(address);

assert.equal(ldoBalance, balance);
const ldoExpected = BigInt(balance);
assert.equal(ldoBalance, ldoExpected, `The values differ is ${formatEther(ldoBalance - ldoExpected)} LDO`);
};

export default {
Expand Down
6 changes: 6 additions & 0 deletions src/omnibuses/omnibuses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export interface OmnibusPlan<N extends NetworkName> {
Network where the omnibus must be launched. Supported networks: "mainnet", "holesky".
*/
network: N;
/**
Description will be uploaded to IPFS and CID (IPFS address) will be added to vote metadata
*/
description: string;
/**
* When the omnibus was launched, contains the id of the vote.
*/
Expand All @@ -45,6 +49,7 @@ export interface OmnibusPlan<N extends NetworkName> {

export interface Omnibus {
network: NetworkName;
description: string;
summary: string;
calls: FormattedEvmCall[];
script: string;
Expand All @@ -70,6 +75,7 @@ function create<N extends NetworkName>(plan: OmnibusPlan<N>): Omnibus {
return {
voteId: plan.voteId,
network: plan.network,
description: plan.description,
isLaunched: plan.voteId !== undefined,
isExecuted: plan.executedOn !== undefined,
items: items,
Expand Down
17 changes: 16 additions & 1 deletion src/omnibuses/tools/simulate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import votes, { FormattedEvmCall } from "../../votes";
import bytes from "../../common/bytes";
import { TxTrace } from "../../traces/tx-traces";
import { Omnibus } from "../omnibuses";
import chalk from "chalk";

export interface SimulationGroup {
call: FormattedEvmCall;
Expand All @@ -15,6 +16,8 @@ export const simulateOmnibus = async (
omnibus: Omnibus,
provider: RpcProvider,
): Promise<[gasUsed: bigint, SimulationGroup[]]> => {
console.log(`Simulating the omnibus using "hardhat" node...`);

const snapshotRestorer = await providers.cheats(provider).snapshot();

const { enactReceipt } = await votes.adopt(provider, omnibus.script, omnibus.summary, {
Expand Down Expand Up @@ -50,6 +53,18 @@ export const simulateOmnibus = async (
});
}
await snapshotRestorer.restore();

printOmnibusSimulationResults(enactReceipt.gasUsed, res);
return [enactReceipt.gasUsed, res];
};

export const printOmnibusSimulationResults = (gasUsed: bigint, groups: SimulationGroup[]) => {
console.log(`Enactment gas costs: ${gasUsed}`);
groups.forEach((group, index) => {
console.log(chalk.green(`${index + 1}. ${group.title}`));
console.log(" EVM call:");
console.log(group.call.format(4));
console.log(" Call Trace:");
console.log(group.trace.format(2));
console.log();
});
};
3 changes: 3 additions & 0 deletions src/rpcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ async function spawnNode(name: RpcNodeName, options: RpcNodeOptions = {}): Promi
}

process.on("exit", () => {
console.error(`Stop spawn node "${name}", kill main process`);
treeKill(nodePid);
});

Expand All @@ -161,11 +162,13 @@ async function spawnNode(name: RpcNodeName, options: RpcNodeOptions = {}): Promi
const absoluteLogPath = path.resolve(config.logsDir, `${name}_${port}.log`);
const logStream = createWriteStream(absoluteLogPath, { encoding: "utf-8" });
const errorListener = (chunk: any) => {
console.error(`An error occurred during the process to spawn "${name}: ${chunk.toString()}" `);
logStream.write(chunk.toString());
};

const stop = () => {
return new Promise<void>((resolve) => {
console.error(`Stop spawn node "${name}", kill main process`);
node.on("exit", () => resolve());
treeKill(nodePid);
});
Expand Down
6 changes: 5 additions & 1 deletion src/votes/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ export async function start(
castVote: boolean = false,
overrides?: NonPayableOverrides,
) {
console.log(`Sending the tx to start the vote...`);
const { voting, tokenManager } = lido.chainId(await providers.chainId(creator), creator);

const startVoteScript = evm(
call(voting["newVote(bytes,string,bool,bool)"], [evmScript, description, castVote, false]),
);
return tokenManager.connect(creator).forward(startVoteScript, overrides ?? {});
const tx = await tokenManager.connect(creator).forward(startVoteScript, overrides ?? {});
console.log("Transaction successfully sent:", tx.hash);
return tx;
}

export async function wait(tx: ContractTransactionResponse) {
console.log("Waiting transaction will be confirmed...");
const receipt = await tx.wait();
if (!receipt) {
throw new Error("Invalid confirmations value");
Expand Down
Loading
Loading