Skip to content

Commit

Permalink
Add CSP census example
Browse files Browse the repository at this point in the history
  • Loading branch information
NateWilliams2 committed Apr 11, 2024
1 parent 66360b9 commit ba72b58
Show file tree
Hide file tree
Showing 9 changed files with 1,101 additions and 0 deletions.
17 changes: 17 additions & 0 deletions examples/csp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "csp-tutorial",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@ethersproject/wallet": "^5.7.0",
"@vocdoni/sdk": "https://github.com/vocdoni/vocdoni-sdk.git#main"
},
"scripts": {
"start": "ts-node src/index.ts"
},
"devDependencies": {
"@types/node": "^20.11.25",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
}
}
16 changes: 16 additions & 0 deletions examples/csp/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Vocdoni SDK Tutorial example
==============================

This example is a tutorial to guide you through the most basic possible integration of the Vocdoni SDK in a Typescript project.

It was created to serve as a tutorial for implementing token-based censuses for voting with Vocdoni. The complete tutorial is available [here](https://developer.vocdoni.io/sdk/tutorial).

To execute this example, use the following steps:

~~~bash
git clone git@github.com:vocdoni/vocdoni-sdk.git
cd vocdoni-sdk/examples/tutorial
yarn
yarn start
~~~

16 changes: 16 additions & 0 deletions examples/csp/src/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Account, VocdoniSDKClient } from '@vocdoni/sdk';

export const createAccount = (client: VocdoniSDKClient) => {
return client
.createAccount({
account: new Account({
languages: ['en'],
name: {
default: 'Account name',
},
description: 'Description of the account',
logo: 'https://logo.io',
}),
})
.then(() => client.fetchAccountInfo().then((info) => console.log(info)));
};
12 changes: 12 additions & 0 deletions examples/csp/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { EnvOptions, VocdoniSDKClient } from '@vocdoni/sdk';
import { Wallet } from '@ethersproject/wallet';

export const getDefaultClient = () => {
const wallet = Wallet.createRandom();
const client = new VocdoniSDKClient({
env: EnvOptions.STG,
wallet: wallet,
});

return { wallet, client };
};
46 changes: 46 additions & 0 deletions examples/csp/src/election.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Census, Election, ElectionStatus, UnpublishedElection, VocdoniSDKClient } from '@vocdoni/sdk';

export const createElection = (census: Census): UnpublishedElection => {
const election: UnpublishedElection = Election.from({
title: 'Election title',
description: 'Election description',
header: 'https://source.unsplash.com/random',
endDate: new Date().getTime() + 100000000,
maxCensusSize: 2000,
census: census,
});

election.addQuestion('This is a title', 'This is a description', [
{
title: 'Option 1',
value: 0,
},
{
title: 'Option 2',
value: 1,
},
]);

return election;
};

const waitForElectionReady = (client: VocdoniSDKClient, electionId: string): Promise<string> => {
return new Promise((f) => setTimeout(f, 5000))
.then(() => client.fetchElection(electionId))
.then((election) => {
if (election.status !== ElectionStatus.ONGOING) {
return waitForElectionReady(client, electionId);
}
return Promise.resolve(electionId);
});
};

export const publishElection = (client: VocdoniSDKClient, election: UnpublishedElection): Promise<string> => {
return client.createElection(election).then((electionId) => {
client.setElectionId(electionId);
console.log('Election created!', electionId);
console.log('View this election at ' + client.explorerUrl + '/processes/show/#/' + electionId);
console.log('Waiting for election to be published...');
return waitForElectionReady(client, electionId);
});
};
25 changes: 25 additions & 0 deletions examples/csp/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getDefaultClient } from './client';
import { createElection, publishElection } from './election';
import { castVotes, countVotes } from './vote';
import { CspCensus } from '@vocdoni/sdk';
import { createAccount } from './account';

// Testing CSP
const CSP_URL = 'https://csp-dev-simplemath.vocdoni.net/v1';
const CSP_PUBKEY = '025de8cb8de1005aa939c1403e37e1fa165ebc758da49cb37215c6237d01591104';

async function main() {
console.log('Initializing client...');
const { client } = getDefaultClient();
console.log('Creating account...');
await createAccount(client);
console.log('Creating election...');
const election = createElection(new CspCensus(CSP_PUBKEY, CSP_URL));
const electionId = await publishElection(client, election);
console.log('Voting...');
await castVotes(electionId);
console.log('Getting results...');
await countVotes(client);
}

main();
41 changes: 41 additions & 0 deletions examples/csp/src/vote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Wallet } from '@ethersproject/wallet';
import { EnvOptions, ICspFinalStepResponse, ICspIntermediateStepResponse, VocdoniSDKClient, Vote } from '@vocdoni/sdk';

export const castVotes = (electionId: string) => {
var votePromises = [];
for (let i = 0; i < 10; i++) {
const voter = Wallet.createRandom();
const client = new VocdoniSDKClient({ env: EnvOptions.STG, wallet: voter, electionId: electionId });
votePromises.push(
new Promise<void>(async (resolve) => {
// Auth steps for the CSP (can vary of the type of the CSP)
const step0 = (await client.cspStep(0, ['Name test'])) as ICspIntermediateStepResponse;
// Auth step 1: for this CSP, add the two values and return the result
const challenge = step0.response.reduce((accumulator, value) => +accumulator + +value, 0).toString();
const step1 = (await client.cspStep(1, [challenge], step0.authToken)) as ICspFinalStepResponse;

// Request a CSP signature of the voter's address, proven by the token
const signature = await client.cspSign(voter.address, step1.token);

// Create a random vote alongside the CSP signature
const vote = client.cspVote(new Vote([Math.round(Math.random())]), signature);

// Submit the vote as usual
await client.submitVote(vote);
resolve();
})
);
}
return Promise.all(votePromises);
};

export const countVotes = (client: VocdoniSDKClient) => {
return client.fetchElection().then((election) => {
console.log('Election results: ');
election.questions.forEach((question) => {
question.choices.forEach((choice) => {
console.log(choice.title.default + ': ' + choice.results);
});
});
});
};
6 changes: 6 additions & 0 deletions examples/csp/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"include": ["src"],
"compilerOptions": {
"rootDir": "./src",
}
}
Loading

0 comments on commit ba72b58

Please sign in to comment.