import AbstractChannelsDatabase from '../AbstractChannelsDatabase' ; import * as BigNumber from 'bignumber.js' ; import IChannelsDatabase from '../IChannelsDatabase' ; import EngineNedb from './EngineNedb' ; import ChannelId from '../../ChannelId' ; import { PaymentChannel , PaymentChannelJSON } from '../../PaymentChannel' ; /**
 * Database layer for {PaymentChannel}
 */ export default class NedbChannelsDatabase extends AbstractChannelsDatabase < EngineNedb > implements IChannelsDatabase { async save ( paymentChannel ) { const document = { kind : this . kind , sender : paymentChannel . sender , receiver : paymentChannel . receiver , value : paymentChannel . value . toString ( ) , spent : paymentChannel . spent . toString ( ) , channelId : paymentChannel . channelId , state : paymentChannel . state , tokenContract : paymentChannel . tokenContract , settlementPeriod : paymentChannel . settlementPeriod , settlingUntil : paymentChannel . settlingUntil . toString ( ) } ; await this . engine . exec ( client => { return client . insert ( document ) ; } ) ; } async firstById ( channelId ) { const query = { kind : this . kind , channelId : channelId . toString ( ) } ; return this . engine . exec ( async ( client ) => { let doc = await client . find < PaymentChannelJSON > ( query ) ; return this . inflatePaymentChannel ( doc [ 0 ] ) ; } ) ; } /**
     * Set amount of money spent on the channel.
     */ async spend ( channelId , spent ) { const query = { kind : this . kind , channelId : channelId . toString ( ) } ; const update = { $set : { spent : spent . toString ( ) } } ; await this . engine . exec ( client => { return client . update ( query , update , { } ) ; } ) ; } async deposit ( channelId , value ) { const channel = await this . firstById ( channelId ) ; if ( ! channel ) { throw new Error ( 'Channel not found.' ) ; } const query = { kind : this . kind , channelId : channelId . toString ( ) } ; const newValue = channel . value . add ( value ) ; const update = { $set : { value : newValue . toString ( ) } } ; await this . engine . exec ( client => { return client . update ( query , update , { } ) ; } ) ; } return { Promise < PaymentChannel > } async all ( ) { let raw = await this . engine . exec ( client => { return client . find < PaymentChannelJSON > ( { kind : this . kind } ) ; } ) ; return this . inflatePaymentChannels ( raw ) ; } async allOpen ( ) { let raw = await this . engine . exec ( client => { return client . find < PaymentChannelJSON > ( { kind : this . kind , state : 0 } ) ; } ) ; let channels = await this . inflatePaymentChannels ( raw ) ; return this . filterByState ( 0 , channels ) ; } async findUsable ( sender , receiver , amount ) { const query = { kind : this . kind , state : 0 , sender , receiver } ; let raw = await this . engine . exec ( client => { return client . find < PaymentChannelJSON > ( query ) ; } ) ; let channels = await this . inflatePaymentChannels ( raw ) ; let filtered = this . filterByState ( 0 , channels ) ; return filtered . find ( ( chan ) => chan . value . greaterThanOrEqualTo ( chan . spent . add ( amount ) ) ) || null ; } async findBySenderReceiver ( sender , receiver ) { let raw = await this . engine . exec ( client => { return client . find < PaymentChannelJSON > ( { sender , receiver , kind : this . kind } ) ; } ) ; return this . inflatePaymentChannels ( raw ) ; } async findBySenderReceiverChannelId ( sender , receiver , channelId ) { let query = { sender , receiver , channelId : channelId . toString ( ) , kind : this . kind } ; let res = await this . engine . exec ( client => { return client . find < PaymentChannelJSON > ( query ) ; } ) ; return this . inflatePaymentChannel ( res [ 0 ] ) ; } async updateState ( channelId , state ) { const query = { kind : this . kind , channelId : channelId . toString ( ) } ; const update = { $set : { state } } ; await this . engine . exec ( client => { return client . update ( query , update , { } ) ; } ) ; } async updateSettlingUntil ( channelId , settlingUntil ) { const query = { kind : this . kind , channelId : channelId . toString ( ) } ; const update = { $set : { settlingUntil : settlingUntil . toString ( ) } } ; await this . engine . exec ( client => { return client . update ( query , update , { } ) ; } ) ; } }