Skip to content

Commit

Permalink
feat: collect metadata from console and upload
Browse files Browse the repository at this point in the history
  • Loading branch information
kittybest committed Oct 3, 2024
1 parent 3a86fab commit 9253cd9
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 55 deletions.
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
164 changes: 164 additions & 0 deletions packages/coordinator/scripts/uploadRoundMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { put } from "@vercel/blob";
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) {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
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) {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
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) {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
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) {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
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": "0xF367D3dAed6d7C6508b70791cF1B0a8354B48543",
"registryManagerContractAddress": "0x7d750119Cd29Bf1d714184b7369A2628555d463a",
"registryManagerContractStartBlock": 17481727,
"maciContractStartBlock": 17481716
}
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
2 changes: 2 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,6 +63,7 @@ type Recipient @entity {
index: BigInt!
deleted: Boolean!
initialized: Boolean!

"relations"
registry: Registry!
}
Expand Down
Loading

0 comments on commit 9253cd9

Please sign in to comment.