From 3f31b3196ae1dd3b5828e0d349bee3f51e36cc08 Mon Sep 17 00:00:00 2001 From: Marc Velmer Date: Tue, 28 Nov 2023 15:47:03 +0100 Subject: [PATCH] Added `nextElectionId` function --- src/api/election.ts | 33 +++++++++++++++++++++++++++++++ src/services/election.ts | 19 ++++++++++++++++++ test/integration/election.test.ts | 20 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/api/election.ts b/src/api/election.ts index 6df99a31..4e24d5f3 100644 --- a/src/api/election.ts +++ b/src/api/election.ts @@ -4,6 +4,7 @@ import { API } from './api'; enum ElectionAPIMethods { INFO = '/elections', + NEXT_ELECTION_ID = '/elections/id', PRICE = '/elections/price', KEYS = '/elections/{id}/keys', CREATE = '/elections', @@ -138,6 +139,13 @@ export interface IElectionCreateResponse { metadataURL: number; } +export interface IElectionNextIdResponse { + /** + * The next election identifier + */ + electionID: string; +} + export enum CensusTypeEnum { CENSUS_UNKNOWN = 'CENSUS_UNKNOWN', OFF_CHAIN_TREE = 'OFF_CHAIN_TREE', @@ -409,6 +417,31 @@ export abstract class ElectionAPI extends API { .catch(this.isApiError); } + /** + * Returns the next election id. + * + * @param {string} url API endpoint URL + * @param {string} organizationId The identifier of the organization + * @param {number} censusOrigin The census origin + * @param {IVoteMode} envelopeType The envelope type + * @returns {Promise} + */ + public static nextElectionId( + url: string, + organizationId: string, + censusOrigin: number, + envelopeType?: Partial + ): Promise { + return axios + .post(url + ElectionAPIMethods.NEXT_ELECTION_ID, { + organizationId, + censusOrigin, + envelopeType, + }) + .then((response) => response.data) + .catch(this.isApiError); + } + /** * Returns the number of votes of a given election * diff --git a/src/services/election.ts b/src/services/election.ts index 8bce71f0..89fa12c5 100644 --- a/src/services/election.ts +++ b/src/services/election.ts @@ -198,6 +198,25 @@ export class ElectionService extends Service implements ElectionServicePropertie return ElectionAPI.create(this.url, payload, metadata); } + /** + * Returns the next election id. + * + * @param {string} address The address of the account + * @param {UnpublishedElection} election The unpublished election + * @returns {Promise} The next election identifier + */ + nextElectionId(address: string, election: UnpublishedElection): Promise { + invariant(this.url, 'No URL set'); + const censusOrigin = ElectionCore.censusOriginFromCensusType(election.census.type); + return ElectionAPI.nextElectionId(this.url, address, censusOrigin, { + serial: false, // TODO + anonymous: election.electionType.anonymous, + encryptedVotes: election.electionType.secretUntilTheEnd, + uniqueValues: election.voteType.uniqueChoices, + costFromWeight: election.voteType.costFromWeight, + }).then((response) => response.electionID); + } + /** * Fetches the encryption keys from the specified process. * diff --git a/test/integration/election.test.ts b/test/integration/election.test.ts index e39c0dff..76b20ea9 100644 --- a/test/integration/election.test.ts +++ b/test/integration/election.test.ts @@ -916,4 +916,24 @@ describe('Election integration tests', () => { expect(election.census.censusURI).toEqual(census2.censusURI); }); }, 185000); + it('should return the next election id', async () => { + const census = new PlainCensus(); + census.add(await Wallet.createRandom().getAddress()); + + const election = createElection(census); + + await client.createAccount(); + + await client + .createElection(election) + .then((electionId) => { + expect(electionId).toMatch(/^[0-9a-fA-F]{64}$/); + client.setElectionId(electionId); + return waitForElectionReady(client, electionId); + }) + .then(async () => { + const nextElectionId = await client.electionService.nextElectionId(await client.wallet.getAddress(), election); + expect(nextElectionId).toEqual(client.electionId.slice(0, -1) + '1'); + }); + }, 85000); });