Skip to content

Commit

Permalink
Merge pull request #443 from privacy-scaling-explorations/feat/update…
Browse files Browse the repository at this point in the history
…-upload-metadata-script

feat: improve the upload metadata process
  • Loading branch information
kittybest authored Nov 7, 2024
2 parents 80bb50c + d7b2c64 commit 3ebc5fa
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 52 deletions.
1 change: 1 addition & 0 deletions packages/coordinator/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ zkeys/
proofs/
tally.json
session-keys.json
round-metadata.json
9 changes: 9 additions & 0 deletions packages/coordinator/round-metadata-example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"roundId": "Round-ID",
"description": "This is the test round.",
"startsAt": "2024-11-05T17:00:00.000Z",
"registrationEndsAt": "2024-11-06T10:00:00.000Z",
"votingStartsAt": "2024-11-06T10:00:00.000Z",
"votingEndsAt": "2024-11-06T17:00:00.000Z",
"tallyFile": "[storage url]/[roundId].json"
}
106 changes: 54 additions & 52 deletions packages/coordinator/scripts/uploadRoundMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { parse, isValid } from "date-fns";
import { enGB } from "date-fns/locale";
import dotenv from "dotenv";

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

Expand All @@ -21,13 +22,26 @@ interface IUploadMetadataProps {
name: string;
}

const METADATA_PATH = path.resolve("./round-metadata.json");

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

/**
* A function to check if the input string is a valid date
* @param formattedDateStr a date string to be checked
* @returns if the date string is valid or not
*/
function isValidDate(formattedDateStr: string) {
const parsed = parse(`${formattedDateStr}Z`, "yyyy/M/d H:m:sX", new Date(), { locale: enGB });
return isValid(parsed);
}

/**
* This is a function for uploading metadata to the blob storage
* @param data an object containing metadata information about the round
* @param name the name of the round
* @returns url of the uploaded metadata
*/
export async function uploadRoundMetadata({ data, name }: IUploadMetadataProps): Promise<string> {
// NOTICE! this is when you use vercel storage, if you're using another tool, please change this part.
const blob = await put(name, JSON.stringify(data), {
Expand All @@ -39,6 +53,10 @@ export async function uploadRoundMetadata({ data, name }: IUploadMetadataProps):
return blob.url;
}

/**
* This function collect round information from the console
* @returns an object containing information of the round
*/
export async function collectMetadata(): Promise<RoundMetadata> {
const rl = readline.createInterface({
input: process.stdin,
Expand Down Expand Up @@ -66,7 +84,7 @@ export async function collectMetadata(): Promise<RoundMetadata> {
const askStartTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question(
"When would you like to start this round? (Please respond in the format {Year}/{Month}/{Day} {Hour}:{Minute}:{Second} in UTC time) ",
"When would you like to START this round? (Please respond in the format {Year}/{Month}/{Day} {Hour}:{Minute}:{Second} in YOUR time) ",
(answer) => {
const valid = isValidDate(answer);

Expand All @@ -82,65 +100,40 @@ export async function collectMetadata(): Promise<RoundMetadata> {
});

const askRegistrationEndTime = () =>
new Promise<Date>((resolve, reject) => {
rl.question(
"When would you like to end the registration for applications? (Please respond in the format {Year}/{Month}/{Day} {Hour}:{Minute}:{Second} in UTC time) ",
(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));
},
);
});
new Promise<number>((resolve, reject) => {
rl.question("Please specify the duration of application registration in seconds: ", (answer) => {
const duration = Number(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 {Year}/{Month}/{Day} {Hour}:{Minute}:{Second} in UTC time) ",
(answer) => {
const valid = isValidDate(answer);

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

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

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 {Year}/{Month}/{Day} {Hour}:{Minute}:{Second} in UTC time) ",
(answer) => {
const valid = isValidDate(answer);
new Promise<number>((resolve, reject) => {
rl.question("Please specify the duration of voting in seconds: ", (answer) => {
const duration = Number(answer);

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

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

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

rl.close();

Expand All @@ -151,15 +144,24 @@ export async function collectMetadata(): Promise<RoundMetadata> {
roundId,
description,
startsAt,
registrationEndsAt,
votingStartsAt,
votingEndsAt,
registrationEndsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000),
votingStartsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000),
votingEndsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000 + votingEndsIn * 1000),
tallyFile: `${vercelStoragePrefix}/tally-${roundId}.json`,
};
}

async function main(): Promise<void> {
const metadata = await collectMetadata();
let metadata: RoundMetadata;

// Try to read a metadata file first
if (fs.existsSync(METADATA_PATH)) {
metadata = JSON.parse(fs.readFileSync(METADATA_PATH, "utf-8")) as RoundMetadata;
} else {
// If there's no metadata file provided, collect metadata from console
metadata = await collectMetadata();
}

const url = await uploadRoundMetadata({ data: metadata, name: `${metadata.roundId}.json` });

// eslint-disable-next-line no-console
Expand Down

0 comments on commit 3ebc5fa

Please sign in to comment.