UNPKG

@vocdoni/sdk

Version:

⚒️An SDK for building applications on top of Vocdoni API

708 lines (618 loc) 15.9 kB
import axios from 'axios'; import { API, PaginationResponse } from './api'; import { ErrTransactionNotFound } from './errors'; import { FetchBlocksParametersWithPagination, FetchFeesParametersWithPagination, FetchOrganizationParametersWithPagination, FetchTransactionsParametersWithPagination, FetchTransfersParametersWithPagination, } from '../services'; import { Tx } from './chain'; export * from './chain/'; enum ChainAPIMethods { INFO = '/chain/info', COSTS = '/chain/info/electionPriceFactors', CIRCUITS = '/chain/info/circuit', TX_COSTS = '/chain/transactions/cost', TX_INFO = '/chain/transactions/{txHash}', TX_LIST = '/chain/transactions', SUBMIT_TX = '/chain/transactions', ORGANIZATION_LIST = '/chain/organizations', VALIDATORS_LIST = '/chain/validators', BLOCK_INFO_HASH = '/chain/blocks/hash/{blockHash}', BLOCK_INFO_HEIGHT = '/chain/blocks/{blockHeight}', BLOCK_LIST = '/chain/blocks', DATE_TO_BLOCK = '/chain/dateToBlock/{timestamp}', BLOCK_TO_DATE = '/chain/blockToDate/{height}', FEES_LIST = '/chain/fees', TRANSFERS = '/chain/transfers', } export interface IChainGetInfoResponse { /** * The id of the current chain */ chainId: string; /** * The different block times from the chain. */ blockTime: number[]; /** * The number of elections existing on the Vochain. */ electionCount: number; /** * The number of organizations existing on the Vochain. */ organizationCount: number; /** * The time of the genesis block. */ genesisTime: string; /** * The height or actual block of the current chain. */ height: number; /** * Whether the blockchain is syncing. */ syncing: boolean; /** * The timestamp of the actual block. */ blockTimestamp: number; /** * The number of transactions. */ transactionCount: number; /** * The number of validators. */ validatorCount: number; /** * The number of votes. */ voteCount: number; /** * The circuit configuration tag. */ circuitConfigurationTag: string; /** * The maximum size of a census. */ maxCensusSize: number; } export interface IChainGetCostsResponse { /** * The base price. */ basePrice: number; /** * The capacity of the chain. */ capacity: number; /** * The factors. */ factors: { k1: number; k2: number; k3: number; k4: number; k5: number; k6: number; k7: number; }; } export interface IChainGetCircuitResponse { /** * The base uri of the files. */ uri: string; /** * The path of the circuit. */ circuitPath: string; /** * The circuit levels. */ levels: number; /** * The hash of the proving key file. */ zKeyHash: string; /** * The name of the proving key file. */ zKeyFilename: string; /** * The hash of the verification key file. */ vKeyHash: string; /** * The name of the verification key file. */ vKeyFilename: string; /** * The hash of the WASM file. */ wasmHash: string; /** * The name of the WASM file. */ wasmFilename: string; } export enum TransactionType { VOTE_ENVELOPE = 'vote', NEW_PROCESS_TX = 'newProcess', ADMIN_TX = 'admin', SET_PROCESS_TX = 'setProcess', REGISTER_KEY_TX = 'registerKey', MINT_TOKENS_TX = 'mintTokens', SEND_TOKENS_TX = 'sendTokens', SET_TRANSACTION_COSTS_TX = 'setTransactionCosts', SET_ACCOUNT_TX = 'setAccount', COLLECT_FAUCET_TX = 'collectFaucet', SET_KEYKEEPER_TX = 'setKeykeeper', } export interface IChainTxCosts { costs: { AddDelegateForAccount: number; CollectFaucet: number; CreateAccount: number; DelAccountSIK: number; DelDelegateForAccount: number; NewProcess: number; RegisterKey: number; SendTokens: number; SetAccountInfoURI: number; SetAccountSIK: number; SetAccountValidator: number; SetProcessCensus: number; SetProcessDuration: number; SetProcessQuestionIndex: number; SetProcessStatus: number; }; } export interface IChainTxReference { /** * The hash of the transaction. */ hash: string; /** * The number of the block where the transaction is. */ height: number; /** * The index of the transaction inside the block. */ index: number; /** * The type of the transaction. */ type: TransactionType; /** * The subtype of the transaction. */ subtype: string; /** * The signer of the transaction. */ signer: string; } export interface IChainSubmitTxResponse { /** * The hash of the transaction */ hash: string; /** * The response data (can vary depending on the transaction type) */ response: string; /** * The response code */ code: number; } export interface IChainTxListResponse extends IChainTxList, PaginationResponse {} export interface IChainTxList { /** * List of transactions */ transactions: Array<IChainTxReference>; } export interface IChainBlocksListResponse extends IChainBlocksList, PaginationResponse {} export interface IChainBlocksList { /** * List of blocks */ blocks: Array<IBlock>; } export interface IBlock { chainId: string; height: number; time: string; hash: string; proposer: string; lastBlockHash: string; txCount: number; } export interface IChainTransfersListResponse extends IChainTransfersList, PaginationResponse {} export interface IChainTransfersList { /** * List of transfers */ transfers: Array<ITransfer>; } export interface ITransfer { amount: number; from: string; height: number; txHash: string; timestamp: string; to: string; } export interface IChainOrganizationResponse { /** * The identifier of the organization */ organizationID: string; /** * The number of elections */ electionCount: number; } export interface IChainOrganizationListResponse extends OrganizationList, PaginationResponse {} export interface OrganizationList { /** * The list of organizations */ organizations: Array<IChainOrganizationResponse>; } interface BlockID { hash: string; parts: { total: number; hash: string; }; } export interface IChainBlockInfoResponse { hash: string; header: { appHash: string; chainId: string; consensusHash: string; dataHash: string; evidenceHash: string; height: number; lastBlockId: BlockID; lastCommitHash: string; lastResultsHash: string; nextValidatorsHash: string; proposerAddress: string; time: string; validatorsHash: string; version: { block: number; app: number; }; }; txCount: number; } interface IDateToBlockResponse { height: number; } interface IBlockToDateResponse { date: string; } export interface IChainValidator { /** * Current power of the validator */ power: number; /** * Validator public key */ pubKey: string; /** * Validator address */ address: string; /** * Validator name reference. Could be empty. */ name: string; /** * Block height when validator joint */ joinHeight: number; /** * Total block proposals count */ proposals: number; /** * Validatos effectivity. Between 0 and 100 */ score: number; /** * Validator address */ validatorAddress: string; /** * Number ob validated blocks (not created) */ votes: number; } export interface IChainValidatorsListResponse { /** * The list of validators */ validators: Array<IChainValidator>; } export type Fee = { /** * The cost of the transaction */ cost: number; /** * The account generating the transaction */ from: string; /** * The block number */ height: number; /** * The transaction hash */ reference: string; /** * The timestamp of the transaction */ timestamp: string; /** * The type of the transaction */ txType: string; }; export interface IChainFeesListResponse extends IFeesList, PaginationResponse {} export interface IFeesList { /** * The list of fees */ fees: Array<Fee>; } export abstract class ChainAPI extends API { /** * Cannot be constructed. */ private constructor() { super(); } /** * Fetches info about the blockchain status. * * @param url - API endpoint URL */ public static info(url: string): Promise<IChainGetInfoResponse> { return axios .get<IChainGetInfoResponse>(url + ChainAPIMethods.INFO) .then((response) => response.data) .catch(this.isApiError); } /** * Fetches info about the blockchain costs. * * @param url - API endpoint URL */ public static costs(url: string): Promise<IChainGetCostsResponse> { return axios .get<IChainGetCostsResponse>(url + ChainAPIMethods.COSTS) .then((response) => response.data) .catch(this.isApiError); } /** * Fetches info about the blockchain anonymous circuits. * * @param url - API endpoint URL */ public static circuits(url: string): Promise<IChainGetCircuitResponse> { return axios .get<IChainGetCircuitResponse>(url + ChainAPIMethods.CIRCUITS) .then((response) => response.data) .catch(this.isApiError); } /** * Fetches a circuit. * * @param url - Circuit URL */ public static circuit(url: string): Promise<Uint8Array> { return axios .get<Uint8Array>(url, { responseType: 'arraybuffer' }) .then((response) => new Uint8Array(response.data)) .catch(this.isApiError); } /** * Returns the list of transactions and its cost * @param url - API endpoint URL */ public static txCosts(url: string): Promise<IChainTxCosts> { return axios .get<IChainTxCosts>(url + ChainAPIMethods.TX_COSTS) .then((response) => { return response.data; }) .catch(this.isApiError); } /** * Fetches information about a transaction from the blockchain. * * @param url - API endpoint URL * @param txHash - The transaction hash which we want to retrieve the info from */ public static txInfo(url: string, txHash: string): Promise<Tx> { return axios .get<Tx>(url + ChainAPIMethods.TX_INFO.replace('{txHash}', txHash)) .then((response) => { if (response.status === 204) { throw new ErrTransactionNotFound(); } return response.data; }) .catch(this.isApiError); } /** * Submits a transaction to the blockchain * * @param url - API endpoint URL * @param payload - The transaction data payload */ public static submitTx(url: string, payload: string): Promise<IChainSubmitTxResponse> { return axios .post<IChainSubmitTxResponse>(url + ChainAPIMethods.SUBMIT_TX, { payload }) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of transactions * * @param url - {string} url API endpoint URL * @param params - The parameters to filter the transactions */ public static txList( url: string, params?: Partial<FetchTransactionsParametersWithPagination> ): Promise<IChainTxListResponse> { const queryParams = this.createQueryParams(params); return axios .get<IChainTxListResponse>(url + ChainAPIMethods.TX_LIST + (queryParams ? '?' + queryParams : '')) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of transfers * * @param url - {string} url API endpoint URL * @param params - The parameters to filter the transfers */ public static transfers( url: string, params?: Partial<FetchTransfersParametersWithPagination> ): Promise<IChainTransfersListResponse> { const queryParams = this.createQueryParams(params); return axios .get<IChainTransfersListResponse>(url + ChainAPIMethods.TRANSFERS + (queryParams ? '?' + queryParams : '')) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of fees * * @param url - {string} url API endpoint URL * @param params - The parameters to filter the fees */ public static feesList( url: string, params?: Partial<FetchFeesParametersWithPagination> ): Promise<IChainFeesListResponse> { const queryParams = this.createQueryParams(params); return axios .get<IChainFeesListResponse>(url + ChainAPIMethods.FEES_LIST + (queryParams ? '?' + queryParams : '')) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of organizations * * @param url - API endpoint URL * @param params - The parameters to filter the organizations */ public static organizationList( url: string, params?: Partial<FetchOrganizationParametersWithPagination> ): Promise<IChainOrganizationListResponse> { const queryParams = this.createQueryParams(params); return axios .get<IChainOrganizationListResponse>( url + ChainAPIMethods.ORGANIZATION_LIST + (queryParams ? '?' + queryParams : '') ) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of validators * * @param url - API endpoint URL */ public static validatorsList(url: string): Promise<IChainValidatorsListResponse> { return axios .get<IChainValidatorsListResponse>(url + ChainAPIMethods.VALIDATORS_LIST) .then((response) => response.data) .catch(this.isApiError); } /** * Get block information by hash * * @param url - API endpoint URL * @param hash - block hash */ public static blockInfoHash(url: string, hash: string): Promise<IChainBlockInfoResponse> { return axios .get<IChainBlockInfoResponse>(url + ChainAPIMethods.BLOCK_INFO_HASH.replace('{blockHash}', hash)) .then((response) => response.data) .catch(this.isApiError); } /** * Get block information by height * * @param url - API endpoint URL * @param height - block height */ public static blockInfoHeight(url: string, height: number): Promise<IChainBlockInfoResponse> { return axios .get<IChainBlockInfoResponse>(url + ChainAPIMethods.BLOCK_INFO_HEIGHT.replace('{blockHeight}', height.toString())) .then((response) => response.data) .catch(this.isApiError); } /** * Returns the list of blocks * * @param url - {string} url API endpoint URL * @param params - The parameters to filter the blocks */ public static blocksList( url: string, params?: Partial<FetchBlocksParametersWithPagination> ): Promise<IChainBlocksListResponse> { const queryParams = this.createQueryParams(params); return axios .get<IChainBlocksListResponse>(url + ChainAPIMethods.BLOCK_LIST + (queryParams ? '?' + queryParams : '')) .then((response) => response.data) .catch(this.isApiError); } /** * By a given date give the estimate block for the current Vochain. * @param url - API URL * @param timeStamp - unix format timestamp */ public static dateToBlock(url: string, timeStamp: number): Promise<IDateToBlockResponse> { return axios .get<IDateToBlockResponse>(url + ChainAPIMethods.DATE_TO_BLOCK.replace('{timestamp}', String(timeStamp))) .then((response) => response.data) .catch(this.isApiError); } /** * Return approximate date by a given block height. * * @param url - API URL * @param height - block height to calculate approximate timestamp * @return {Promise<IBlockToDateResponse>} */ public static blockToDate(url: string, height: number): Promise<IBlockToDateResponse> { return axios .get<IBlockToDateResponse>(url + ChainAPIMethods.BLOCK_TO_DATE.replace('{height}', String(height))) .then((response) => response.data) .catch(this.isApiError); } }