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: collect metadata from console and upload #352

Merged
merged 1 commit into from
Oct 3, 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
4 changes: 4 additions & 0 deletions packages/coordinator/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ TEST_PRIVATE_KEY=""

# An RPC API KEY to interact with live networks (used in e2e tests)
RPC_API_KEY=""

# Storage for metadata
# Create a Blob database and get token here: https://vercel.com/dashboard/stores?type=blob
BLOB_READ_WRITE_TOKEN=
5 changes: 4 additions & 1 deletion packages/coordinator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"types": "tsc -p tsconfig.json --noEmit",
"generate-keypair": "pnpm run run:node ./scripts/generateKeypair.ts",
"download-zkeys:test": "pnpm run run:node ./scripts/downloadZKeys.ts test ./zkeys",
"download-zkeys:prod": "pnpm run run:node ./scripts/downloadZKeys.ts prod ./zkeys"
"download-zkeys:prod": "pnpm run run:node ./scripts/downloadZKeys.ts prod ./zkeys",
"upload-round-metadata": "pnpm run run:node ./scripts/uploadRoundMetadata.ts"
},
"dependencies": {
"@graphprotocol/graph-cli": "^0.79.0",
Expand All @@ -38,6 +39,7 @@
"@nestjs/websockets": "^10.3.10",
"@nomicfoundation/hardhat-ethers": "^3.0.8",
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@vercel/blob": "^0.19.0",
"@zerodev/ecdsa-validator": "^5.3.1",
"@zerodev/permissions": "^5.4.3",
"@zerodev/sdk": "^5.3.8",
Expand All @@ -54,6 +56,7 @@
"maci-contracts": "^2.3.0",
"maci-domainobjs": "^2.0.0",
"maci-subgraph": "^2.3.0",
"date-fns": "^4.1.0",
"mustache": "^4.2.0",
"permissionless": ">=0.1.18 <=0.1.29",
"reflect-metadata": "^0.2.0",
Expand Down
160 changes: 160 additions & 0 deletions packages/coordinator/scripts/uploadRoundMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { put } from "@vercel/blob";
ctrlc03 marked this conversation as resolved.
Show resolved Hide resolved
import { parse, isValid } from "date-fns";
import { enGB } from "date-fns/locale";
import dotenv from "dotenv";

import path from "path";
import * as readline from "readline";

export interface RoundMetadata {
roundId: string;
description: string;
startsAt: Date;
registrationEndsAt: Date;
votingStartsAt: Date;
votingEndsAt: Date;
}

interface IUploadMetadataProps {
data: RoundMetadata;
name: string;
}

dotenv.config({ path: path.resolve(import.meta.dirname, "../.env") });

function isValidDate(formattedDateStr: string) {
const splitDate = formattedDateStr.split("-");
const parsed = parse(`${splitDate[2]}/${splitDate[1]}/${splitDate[0]}`, "P", new Date(), { locale: enGB });
return isValid(parsed);
}

export async function uploadRoundMetadata({ data, name }: IUploadMetadataProps): Promise<string> {
const blob = await put(name, JSON.stringify(data), {
access: "public",
token: process.env.BLOB_READ_WRITE_TOKEN,
});

return blob.url;
}

export async function collectMetadata(): Promise<RoundMetadata> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

const askRoundId = () =>
new Promise<string>((resolve) => {
rl.question("How would you name your round? ", (answer) => {
// eslint-disable-next-line no-console
console.log(`Your roundId is: ${answer}`);
resolve(answer);
});
});

const askDescription = () =>
new Promise<string>((resolve) => {
rl.question("Could you briefly introduce this round? ", (answer) => {
// eslint-disable-next-line no-console
console.log(`Your round description is: ${answer}`);
resolve(answer);
});
});

const askStartTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question("When would you like to start this round? (Please respond in the format yyyy-mm-dd) ", (answer) => {
const valid = isValidDate(answer);

if (!valid) {
reject(new Error("Please answer in valid format."));
}

// eslint-disable-next-line no-console
console.log("You would like to start this round at:", answer);
resolve(new Date(answer));
});
});

const askRegistrationEndTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question(
"When would you like to end the registration for applications? (Please respond in the format yyyy-mm-dd) ",
(answer) => {
const valid = isValidDate(answer);

if (!valid) {
reject(new Error("Please answer in valid format."));
}

// eslint-disable-next-line no-console
console.log(`Your application registration end date for this round is: ${answer}`);
resolve(new Date(answer));
},
);
});

const askVotingStartTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question(
"When would you like to start the voting for this round? (Please respond in the format yyyy-mm-dd) ",
(answer) => {
const valid = isValidDate(answer);

if (!valid) {
reject(new Error("Please answer in valid format."));
}

// eslint-disable-next-line no-console
console.log(`Your voting start date for this round is: ${answer}`);
resolve(new Date(answer));
},
);
});

const askVotingEndTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question(
"When would you like to end the voting for this round? (Please respond in the format yyyy-mm-dd) ",
(answer) => {
const valid = isValidDate(answer);

if (!valid) {
reject(new Error("Please answer in valid format."));
}

// eslint-disable-next-line no-console
console.log(`Your voting end date for this round is: ${answer}`);
resolve(new Date(answer));
},
);
});

const roundId = await askRoundId();
const description = await askDescription();
const startsAt = await askStartTime();
const registrationEndsAt = await askRegistrationEndTime();
const votingStartsAt = await askVotingStartTime();
const votingEndsAt = await askVotingEndTime();

rl.close();

return {
roundId,
description,
startsAt,
registrationEndsAt,
votingStartsAt,
votingEndsAt,
};
}

async function main(): Promise<void> {
const metadata = await collectMetadata();
const url = await uploadRoundMetadata({ data: metadata, name: `${metadata.roundId}.json` });

// eslint-disable-next-line no-console
console.log("The url of uploaded metadata is:", url);
}

main();
2 changes: 1 addition & 1 deletion packages/subgraph/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ build
generated
subgraph.yaml
schema.graphql
config/network.json
tests/.bin/
tests/.latest.json

7 changes: 7 additions & 0 deletions packages/subgraph/config/network.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"network": "optimism-sepolia",
"maciContractAddress": "0xac4d16D0541ca7255579b501A2F1D6F3a436521E",
"registryManagerContractAddress": "0xed5875D05DebcDdDbd902f471447dA97c6d26d7E",
"registryManagerContractStartBlock": 17396799,
"maciContractStartBlock": 17396799
}
8 changes: 4 additions & 4 deletions packages/subgraph/config/network.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"network": "optimism-sepolia",
"maciContractAddress": "0xac4d16D0541ca7255579b501A2F1D6F3a436521E",
"registryManagerContractAddress": "0xed5875D05DebcDdDbd902f471447dA97c6d26d7E",
"registryManagerContractStartBlock": 17396799,
"maciContractStartBlock": 17396799
"maciContractAddress": "0xd2A6F62d4d12Fa3552298E8C22F2a08FF0c9771e",
"registryManagerContractAddress": "0xa9C6e12E3F35Cf6F33D3a541f223aa4F70191383",
"registryManagerContractStartBlock": 18071448,
"maciContractStartBlock": 18071444
}
2 changes: 1 addition & 1 deletion packages/subgraph/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"generate:schema": "cp ./schemas/schema.${VERSION:-v1}.graphql schema.graphql",
"prebuild": "pnpm codegen",
"build": "graph build",
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ maci-subgraph",
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ maci",
"create-local": "graph create --node http://localhost:8020/ maci-subgraph",
"remove-local": "graph remove --node http://localhost:8020/ maci-subgraph",
"deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 maci-subgraph --network localhost",
Expand Down
3 changes: 3 additions & 0 deletions packages/subgraph/schemas/schema.v1.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Request @entity {
requestType: RequestType!
index: BigInt
status: Status!

"relations"
recipient: Recipient!
registryManager: RegistryManager!
Expand All @@ -62,12 +63,14 @@ type Recipient @entity {
index: BigInt!
deleted: Boolean!
initialized: Boolean!

"relations"
registry: Registry!
}

type Registry @entity {
id: Bytes! # address
metadataUrl: String
"relations"
poll: Poll
recipients: [Recipient!]! @derivedFrom(field: "registry")
Expand Down
4 changes: 4 additions & 0 deletions packages/subgraph/src/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
PublishMessage as PublishMessageEvent,
SetRegistry as SetRegistryEvent,
} from "../generated/templates/Poll/Poll";
import { Registry as RegistryContract } from "../generated/templates/Registry/Registry";

import { ONE_BIG_INT } from "./utils/constants";
import { createOrLoadRegistry } from "./utils/entity";
Expand Down Expand Up @@ -75,8 +76,11 @@ export function handleSetRegistry(event: SetRegistryEvent): void {
return;
}

const contract = RegistryContract.bind(event.params.registry);

const registry = createOrLoadRegistry(event.params.registry);
registry.poll = poll.id;
registry.metadataUrl = contract.getRegistryMetadataUrl();
registry.save();

poll.registry = event.params.registry;
Expand Down
2 changes: 2 additions & 0 deletions packages/subgraph/templates/subgraph.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ templates:
abis:
- name: Poll
file: ./node_modules/maci-platform-contracts/build/artifacts/contracts/maci/Poll.sol/Poll.json
- name: Registry
file: ./node_modules/maci-platform-contracts/build/artifacts/contracts/registry/BaseRegistry.sol/BaseRegistry.json
0xmad marked this conversation as resolved.
Show resolved Hide resolved
eventHandlers:
- event: MergeMaciState(indexed uint256,indexed uint256)
handler: handleMergeMaciState
Expand Down
Loading
Loading