UNPKG

bam-ticketing-sdk

Version:

SDK for B.A.M Ticketing API

147 lines (131 loc) 3.94 kB
import { AxiosInstance } from 'axios' import { Digest, KeyPair, TxStatus, SignedDigest, TransactionProposalPayload, BlockchainFunctionParams, } from './types' import { signDigest } from './signer' import { HealthStatus } from '../common/types' import { toSnakeCase } from '../common/converter' /** * Service class for blockchain transactions. */ export class BlockchainService { constructor(readonly client: AxiosInstance, readonly version: string) {} /** * Returns true if the service is reachable * * @returns Services' online status */ async health(): Promise<HealthStatus> { try { const res = await this.client.get(`event/health`) if (res.data.status === 'ok') { return { online: true } } } catch (e) { // Do nothing } return { online: false } } /** * This is the first step in committing data to the blockchain. * Creates a new proposal which need to be signed with the private key. * * @param proposal New proposal data * @returns Digest hash of the proposal */ async createProposal(proposal: TransactionProposalPayload): Promise<Digest> { // The payload is snake cased because chaincode consumes it const res = await this.client.post( `blockchain/${this.version}/transaction/proposal`, { ...proposal, args: [JSON.stringify(toSnakeCase(proposal.args))], } ) return res.data.data } /** * This is the second step in committing data to the blockchain. * Submits the proposal signature so that it can be endorsed. * It is signed with the user's private key. * * @param proposal Proposal's digest and signature * @returns Transaction (tx) digest, used in the commit transaction step */ async createTransaction(proposal: SignedDigest): Promise<Digest> { const res = await this.client.post( `blockchain/${this.version}/transaction/proposal/${proposal.digest}`, { signature: proposal.signature } ) return res.data.data } /** * Third and final step in creating a transaction. * Commits a transaction. Once a proposal is submitted, * signed and endorsed it can be committed as a transaction to the blockchain. * * @param tx Signed transaction * @returns Status of the transaction */ async commitTransaction(tx: SignedDigest): Promise<TxStatus> { const res = await this.client.post( `blockchain/${this.version}/transaction/${tx.digest}`, { signature: tx.signature } ) return res.data.data } /** * Creates a proposal, signs it and commits it to the blockchain. * * @param proposal Transaction proposal containing the bc function and arguments * @param keys Private key and certificate to sign the intermediate steps * @returns Transaction commit status */ async sendTransaction( proposal: BlockchainFunctionParams, keys: KeyPair ): Promise<TxStatus> { const proposalDigest = await this.createProposal({ fcn: proposal.fcn, certificate: keys.certificate, args: proposal.args, }) const proposalSignature = signDigest(keys.privateKey, proposalDigest.digest) const txDigest = await this.createTransaction({ digest: proposalDigest.digest, signature: proposalSignature, }) const txSignature = signDigest(keys.privateKey, txDigest.digest) return this.commitTransaction({ digest: txDigest.digest, signature: txSignature, }) } /** * Sends online transaction to the blockchain service. * * @param proposal Transaction proposal containing the bc function and arguments * @param keys Private key and certificate for which the transaction should be invoked. * @returns Response from the chaincode. */ async sendOnlineTransaction( proposal: BlockchainFunctionParams, keys: KeyPair ): Promise<any> { const body = { ...proposal, ...keys, args: [JSON.stringify(toSnakeCase(proposal.args))], } const res = await this.client.post( `blockchain/${this.version}/transaction`, body ) return res.data.data } }