Skip to content

Commit

Permalink
Refactored account service
Browse files Browse the repository at this point in the history
  • Loading branch information
marcvelmer committed Sep 12, 2023
1 parent 3bbe4b2 commit fc4e261
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 48 deletions.
64 changes: 20 additions & 44 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { keccak256 } from '@ethersproject/keccak256';
import { Wallet } from '@ethersproject/wallet';
import { Buffer } from 'buffer';
import invariant from 'tiny-invariant';
import { AccountAPI } from './api';
import { AccountCore } from './core/account';
import { ElectionCore } from './core/election';
import { VoteCore } from './core/vote';
Expand All @@ -26,6 +25,8 @@ import {
import { delay } from './util/common';
import { API_URL, EXPLORER_URL, FAUCET_AUTH_TOKEN, FAUCET_URL, TX_WAIT_OPTIONS } from './util/constants';
import {
AccountData,
AccountService,
AnonymousService,
CensusProof,
CensusService,
Expand All @@ -41,24 +42,6 @@ import {
ZkProof,
} from './services';

/**
* @typedef AccountData
* @property {string} address
* @property {number} balance
* @property {number} nonce
* @property {number} electionIndex
* @property {string | null} infoURL
* @property {Account} account
*/
export type AccountData = {
address: string;
balance: number;
nonce: number;
electionIndex: number;
infoURL?: string;
account: Account;
};

export enum EnvOptions {
DEV = 'dev',
STG = 'stg',
Expand Down Expand Up @@ -113,6 +96,7 @@ export class VocdoniSDKClient {
public voteService: VoteService;
public fileService: FileService;
public faucetService: FaucetService;
public accountService: AccountService;

public url: string;
public wallet: Wallet | Signer | null;
Expand Down Expand Up @@ -157,6 +141,10 @@ export class VocdoniSDKClient {
chainService: this.chainService,
});
this.cspService = new CspService({});
this.accountService = new AccountService({
url: this.url,
chainService: this.chainService,
});
}

/**
Expand All @@ -175,27 +163,15 @@ export class VocdoniSDKClient {
* @returns {Promise<AccountData>}
*/
async fetchAccountInfo(address?: string): Promise<AccountData> {
let accountData;
if (!this.wallet && !address) {
throw Error('No account set');
} else if (address) {
accountData = await AccountAPI.info(this.url, address);
this.accountData = await this.accountService.fetchAccountInfo(address);
} else {
accountData = await this.wallet.getAddress().then((address) => AccountAPI.info(this.url, address));
this.accountData = await this.wallet
.getAddress()
.then((address) => this.accountService.fetchAccountInfo(address));
}

this.accountData = accountData;
this.accountData.account = Account.build({
languages: accountData.metadata?.languages,
name: accountData.metadata?.name,
description: accountData.metadata?.description,
feed: accountData.metadata?.newsFeed,
header: accountData.metadata?.media?.header,
avatar: accountData.metadata?.media?.avatar,
logo: accountData.metadata?.media?.logo,
meta: Object.entries(accountData.metadata?.meta ?? []).map(([key, value]) => ({ key, value })),
});

return this.accountData;
}

Expand Down Expand Up @@ -257,10 +233,10 @@ export class VocdoniSDKClient {
): Promise<void> {
return wallet
.getAddress()
.then((address) => Promise.all([AnonymousService.calcSik(address, sik, password), this.fetchChainId()]))
.then(([calculatedSIK, chainId]) => {
.then((address) => AnonymousService.calcSik(address, sik, password))
.then((calculatedSIK) => {
const registerSIKTx = AccountCore.generateRegisterSIKTransaction(electionId, calculatedSIK, censusProof);
return AccountCore.signTransaction(registerSIKTx, chainId, wallet);
return this.accountService.signTransaction(registerSIKTx, wallet);
})
.then((signedTx) => this.chainService.submitTx(signedTx))
.then((hash) => this.waitForTransaction(hash));
Expand Down Expand Up @@ -370,12 +346,12 @@ export class VocdoniSDKClient {
*/
private setAccountInfo(promAccountData: Promise<{ tx: Uint8Array; metadata: string }>): Promise<AccountData> {
const accountTx = promAccountData.then((setAccountInfoTx) =>
AccountCore.signTransaction(setAccountInfoTx.tx, this.chainService.chainData.chainId, this.wallet)
this.accountService.signTransaction(setAccountInfoTx.tx, this.wallet)
);

return Promise.all([promAccountData, accountTx])
.then((accountInfo) => AccountAPI.setInfo(this.url, accountInfo[1], accountInfo[0].metadata))
.then((txData) => this.waitForTransaction(txData.txHash))
.then((accountInfo) => this.accountService.setInfo(accountInfo[1], accountInfo[0].metadata))
.then((txHash) => this.waitForTransaction(txHash))
.then(() => this.fetchAccountInfo());
}

Expand Down Expand Up @@ -430,11 +406,11 @@ export class VocdoniSDKClient {
const faucet = faucetPackage
? Promise.resolve(faucetPackage)
: this.wallet.getAddress().then((address) => this.faucetService.fetchPayload(address));
return Promise.all([this.fetchAccountInfo(), faucet, this.fetchChainId()])
.then(([account, faucet, chainId]) => {
return Promise.all([this.fetchAccountInfo(), faucet])
.then(([account, faucet]) => {
const faucetPackage = this.faucetService.parseFaucetPackage(faucet);
const collectFaucetTx = AccountCore.generateCollectFaucetTransaction(account, faucetPackage);
return AccountCore.signTransaction(collectFaucetTx, chainId, this.wallet);
return this.accountService.signTransaction(collectFaucetTx, this.wallet);
})
.then((signedTx) => this.chainService.submitTx(signedTx))
.then((hash) => this.waitForTransaction(hash))
Expand Down
3 changes: 1 addition & 2 deletions src/core/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import {
TxType,
} from '@vocdoni/proto/vochain';
import { Buffer } from 'buffer';
import { AccountData } from '../client';
import { Account, AccountMetadata } from '../types';
import { TransactionCore } from './transaction';
import { strip0x } from '../util/common';
import { CensusProof, FaucetPackage } from '../services';
import { AccountData, CensusProof, FaucetPackage } from '../services';

export abstract class AccountCore extends TransactionCore {
/**
Expand Down
3 changes: 1 addition & 2 deletions src/core/election.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { AccountData } from '../client';
import {
CensusOrigin,
NewProcessTx,
Expand All @@ -12,7 +11,7 @@ import { AllElectionStatus, CensusType, ElectionStatus, UnpublishedElection } fr
import { TransactionCore } from './transaction';
import { Buffer } from 'buffer';
import { strip0x } from '../util/common';
import { ChainCosts, ChainData } from '../services';
import { AccountData, ChainCosts, ChainData } from '../services';

export abstract class ElectionCore extends TransactionCore {
private static readonly VOCHAIN_BLOCK_TIME_IN_SECONDS = 12;
Expand Down
90 changes: 90 additions & 0 deletions src/services/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Service, ServiceProperties } from './service';
import { ChainService } from './chain';
import { Account } from '../types';
import { AccountAPI } from '../api';
import invariant from 'tiny-invariant';
import { Wallet } from '@ethersproject/wallet';
import { Signer } from '@ethersproject/abstract-signer';
import { AccountCore } from '../core/account';

interface AccountServiceProperties {
chainService: ChainService;
}

type AccountServiceParameters = ServiceProperties & AccountServiceProperties;

/**
* @typedef AccountData
* @property {string} address
* @property {number} balance
* @property {number} nonce
* @property {number} electionIndex
* @property {string | null} infoURL
* @property {Account} account
*/
export type AccountData = {
address: string;
balance: number;
nonce: number;
electionIndex: number;
infoURL?: string;
account: Account;
};

export class AccountService extends Service implements AccountServiceProperties {
public chainService: ChainService;

/**
* Instantiate the election service.
*
* @param {Partial<AccountServiceParameters>} params The service parameters
*/
constructor(params: Partial<AccountServiceParameters>) {
super();
Object.assign(this, params);
}

/**
* Fetches account information.
*
* @param {string} address The account address to fetch the information
* @returns {Promise<AccountData>}
*/
async fetchAccountInfo(address: string): Promise<AccountData> {
invariant(this.url, 'No URL set');
let accountData;
accountData = await AccountAPI.info(this.url, address);

accountData.account = Account.build({
languages: accountData.metadata?.languages,
name: accountData.metadata?.name,
description: accountData.metadata?.description,
feed: accountData.metadata?.newsFeed,
header: accountData.metadata?.media?.header,
avatar: accountData.metadata?.media?.avatar,
logo: accountData.metadata?.media?.logo,
meta: Object.entries(accountData.metadata?.meta ?? []).map(([key, value]) => ({ key, value })),
});

return accountData;
}

/**
* Updates an account with information
*
* @param {string} tx The transaction for setting the account
* @param {string} metadata The account metadata
* @returns {Promise<string>} The transaction hash
*/
setInfo(tx: string, metadata: string): Promise<string> {
invariant(this.url, 'No URL set');
return AccountAPI.setInfo(this.url, tx, metadata).then((response) => response.txHash);
}

async signTransaction(tx: Uint8Array, walletOrSigner: Wallet | Signer): Promise<string> {
invariant(this.chainService, 'No chain service set');
return this.chainService
.fetchChainData()
.then((chainData) => AccountCore.signTransaction(tx, chainData.chainId, walletOrSigner));
}
}
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './account';
export * from './census';
export * from './chain';
export * from './csp';
Expand Down

0 comments on commit fc4e261

Please sign in to comment.