import db , { pgpE } from 'shared/driver/db/index' ; import { IAsset , Transaction } from 'shared/model/transaction' ; import SharedTransactionPGRepo from 'shared/repository/transaction/pg' ; import queries from 'core/repository/queries/transaction' ; import { BlockId } from 'shared/repository/block' ; import { RawTransaction , TransactionId } from 'shared/model/types' ; import { ResponseEntity } from 'shared/model/response' ; import { logger } from 'shared/util/logger' ; export interface ITransactionPGRepository < T extends IAsset > { deleteById ( trsId ) : Promise < ResponseEntity < Array < string > > > ; getByBlockIds ( blockIds ) : Promise < ResponseEntity < { [ blockId ] : Array < Transaction < IAsset > > ; } > > ; getById ( trsId ) : Promise < Transaction < T > > ; getMany ( limit , offset ) : Promise < Array < Transaction < T > > > ; isExist ( trsId ) : Promise < boolean > ; save ( trs ) : Promise < ResponseEntity < void > > ; } class TransactionPGRepo implements ITransactionPGRepository < IAsset > { private readonly tableName : string = 'trs' ; private readonly tableFields : Array < string > = [ 'id' , 'block_id' , 'type' , 'created_at' , 'sender_public_key' , 'signature' , 'second_signature' , 'fee' , 'salt' , 'asset' , ] ; private readonly columnSet = new pgpE . helpers . ColumnSet ( this . tableFields , { table : this . tableName } ) ; async deleteById ( trsId ) { try { const response = await db . many ( queries . deleteByIds , [ trsId ] ) ; return new ResponseEntity ( { data : response . map ( item => item . id ) } ) ; } catch ( error ) { logger . debug ( `[Core][Repository][Transaction][deleteById] error.stack: ${ error . stack }` ) ; return new ResponseEntity ( { errors : [ `Unable to remove transactions. Error: ${ error }` ] } ) ; } } async getByBlockIds ( blockIds ) { try { const rawTransactions = await db . many ( queries . getByBlockIds , [ blockIds ] ) ; const result = { } ; rawTransactions . forEach ( ( rawTransaction ) => { const transaction = SharedTransactionPGRepo . deserialize ( rawTransaction ) ; if ( ! result [ transaction . blockId ] ) { result [ transaction . blockId ] = [ ] ; } result [ transaction . blockId ] . push ( transaction ) ; } ) ; return new ResponseEntity ( { data : result } ) ; } catch ( error ) { return new ResponseEntity ( { errors : [ `Unable to load transactions by blocks ids from database. Error: ${ error }` ] , } ) ; } } async getById ( trsId ) { const rawTransaction = await db . oneOrNone ( queries . getById , { id : trsId } ) ; if ( ! rawTransaction ) { return ; } return SharedTransactionPGRepo . deserialize ( rawTransaction ) ; } async getMany ( limit , offset ) { let result = [ ] ; const rawTransactions = await db . manyOrNone ( queries . getTransactionBatch , { limit , offset } ) ; if ( ! rawTransactions ) { return result ; } rawTransactions . forEach ( ( rawTransaction ) => { result . push ( SharedTransactionPGRepo . deserialize ( rawTransaction ) ) ; } ) ; return result ; } async isExist ( trsId ) { const transaction = await this . getById ( trsId ) ; return ! ! transaction ; } createInsertQuery ( transactions ) { const serializedTransactions = transactions . map ( ( transaction ) => SharedTransactionPGRepo . serialize ( transaction ) ) ; return pgpE . helpers . insert ( serializedTransactions , this . columnSet ) ; } async save ( trs ) { const transactions = [ ] . concat ( trs ) ; const query = this . createInsertQuery ( transactions ) ; try { await db . query ( query ) ; } catch ( error ) { logger . debug ( `[Core][Repository][Transaction][save] error.stack: ${ error . stack }` ) ; return new ResponseEntity ( { errors : [ `Unable to save transactions to database. Error: ${ error }` ] , } ) ; } return new ResponseEntity ( ) ; } } export default new TransactionPGRepo ( ) ;