import { OrderStatus } from '@energyweb/exchange-core' ; import { DatabaseService } from '@energyweb/origin-backend-utils' ; import { HttpStatus , INestApplication } from '@nestjs/common' ; import { expect } from 'chai' ; import request from 'supertest' ; import { AccountService } from '../src/pods/account/account.service' ; import { CreateAskDTO } from '../src/pods/order/create-ask.dto' ; import { CreateBidDTO } from '../src/pods/order/create-bid.dto' ; import { Order } from '../src/pods/order/order.entity' ; import { Transfer } from '../src/pods/transfer/transfer.entity' ; import { TransferService } from '../src/pods/transfer/transfer.service' ; import { DB_TABLE_PREFIX } from '../src/utils/tablePrefix' ; import { authenticatedUser , bootstrapTestInstance } from './exchange' ; import { OrderDTO } from './order/order.dto' ; import { TestProduct } from './product/get-product.handler' ; import { createDepositAddress , MWh } from './utils' ; const sleep = ( ms ) => new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ; describe ( 'account ask order send' , ( ) => { let app ; let transferService ; let databaseService ; let accountService ; const user1Id = authenticatedUser . organization . id ; const dummyAsset = { address : '0x9876' , tokenId : '0' , deviceId : '0' , generationFrom : new Date ( '2020-01-01' ) , generationTo : new Date ( '2020-01-31' ) } ; const transactionHash = `0x${ ( ( Math . random ( ) * 0xffffff ) << 0 ) . toString ( 16 ) }` ; const createDeposit = ( address , amount = `${ 1000 * MWh }` , asset = dummyAsset , blockNumber = 123456 ) => { return transferService . createDeposit ( { address , transactionHash , amount , blockNumber , asset } ) ; } ; const confirmDeposit = ( ) => { return transferService . setAsConfirmed ( transactionHash , 10000 ) ; } ; before ( async ( ) => { ( { transferService , accountService , databaseService , app } = await bootstrapTestInstance ( ) ) ; await app . init ( ) ; } ) ; after ( async ( ) => { await databaseService . cleanUp ( ) ; await app . close ( ) ; } ) ; let deposit ; let user1Address ; beforeEach ( async ( ) => { await databaseService . truncate ( `${ DB_TABLE_PREFIX }_order` , `${ DB_TABLE_PREFIX }_transfer` ) ; user1Address = await createDepositAddress ( accountService , user1Id ) ; deposit = await createDeposit ( user1Address ) ; } ) ; it ( 'should not be able to create ask order on unconfirmed deposit' , async ( ) => { const createAsk = { assetId : deposit . asset . id , volume : `${ 100 * MWh }` , price : 100 , validFrom : new Date ( ) } ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . FORBIDDEN ) ; } ) ; it ( 'should be able to create ask order on confirmed deposit' , async ( ) => { await confirmDeposit ( ) ; const createAsk = { assetId : deposit . asset . id , volume : `${ 100 * MWh }` , price : 100 , validFrom : new Date ( ) } ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . CREATED ) . expect ( ( res ) => { const order = res . body as OrderDTO ; expect ( order . price ) . equals ( 100 ) ; expect ( order . startVolume ) . equals ( `${ 100 * MWh }` ) ; expect ( order . assetId ) . equals ( deposit . asset . id ) ; expect ( order . product ) . equals ( TestProduct ) ; } ) ; } ) ; it ( 'should not be able to create ask order bigger than confirmed deposit' , async ( ) => { const createAsk = { assetId : deposit . asset . id , volume : `${ 1001 * MWh }` , price : 100 , validFrom : new Date ( ) } ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . FORBIDDEN ) ; } ) ; it ( 'should not be able to create 2nd ask order bigger than remaining deposit' , async ( ) => { const createAsk = { assetId : deposit . asset . id , volume : `${ 1000 * MWh }` , price : 100 , validFrom : new Date ( ) } ; await confirmDeposit ( ) ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . CREATED ) ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . FORBIDDEN ) ; } ) ; it ( 'should be able to create and cancel bid' , async ( ) => { const volume = `${ 1000 * MWh }` ; const createBid = { price : 100 , validFrom : new Date ( ) , volume , product : TestProduct } ; let order ; await request ( app . getHttpServer ( ) ) . post ( '/orders/bid' ) . send ( createBid ) . expect ( HttpStatus . CREATED ) . expect ( ( res ) => { order = res . body as OrderDTO ; expect ( order . price ) . equals ( 100 ) ; expect ( order . startVolume ) . equals ( volume ) ; expect ( order . status ) . equals ( OrderStatus . Active ) ; } ) ; await request ( app . getHttpServer ( ) ) . post ( `/orders/${ order . id }/cancel` ) . expect ( HttpStatus . ACCEPTED ) . expect ( ( res ) => { const cancelled = res . body as Order ; expect ( cancelled . id ) . equals ( order . id ) ; expect ( cancelled . status ) . equals ( OrderStatus . PendingCancellation ) ; } ) ; await sleep ( 3000 ) ; await request ( app . getHttpServer ( ) ) . get ( `/orders/${ order . id }` ) . expect ( HttpStatus . OK ) . expect ( ( res ) => { const cancelled = res . body as Order ; expect ( cancelled . id ) . equals ( order . id ) ; expect ( cancelled . status ) . equals ( OrderStatus . Cancelled ) ; } ) ; } ) ; it ( 'should not be able to create bid order with decimal volume' , async ( ) => { const volume = `${ 1.1 * MWh }` ; const createBid = { price : 100 , validFrom : new Date ( ) , volume , product : "{ deviceType: ['Solar'] }" } ; await request ( app . getHttpServer ( ) ) . post ( '/orders/bid' ) . send ( createBid ) . expect ( HttpStatus . BAD_REQUEST ) ; } ) ; it ( 'should not be able to create ask order with decimal volume' , async ( ) => { const createAsk = { assetId : deposit . asset . id , volume : `${ 1.1 * MWh }` , price : 100 , validFrom : new Date ( ) } ; await request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . expect ( HttpStatus . BAD_REQUEST ) ; } ) ; it ( 'should not allow to post more asks than deposits' , async ( ) => { await confirmDeposit ( ) ; const createAsk = { assetId : deposit . asset . id , volume : `${ 1000 * MWh }` , price : 100 , validFrom : new Date ( ) } ; for ( let i = 0 ; i < 10 ; i ++ ) { request ( app . getHttpServer ( ) ) . post ( '/orders/ask' ) . send ( createAsk ) . end ( ( ) => { } ) ; } await sleep ( 3000 ) ; await request ( app . getHttpServer ( ) ) . get ( '/orders' ) . expect ( ( res ) => { const orders = res . body as Order [ ] ; expect ( orders ) . to . have . length ( 1 ) ; } ) ; } ) ; } ) ;