@@ -183,7 +183,10 @@ import {
183183 AssetData ,
184184 Asset ,
185185 MissingNonceError ,
186- InsufficientFundsError
186+ InsufficientFundsError ,
187+ PlaceLimitOrderParams ,
188+ OrdersPlaced ,
189+ OrdersCancelledAndPlaced
187190} from '../types'
188191import {
189192 ClientMode ,
@@ -192,6 +195,8 @@ import {
192195 GQLResp ,
193196 PayloadSignature
194197} from '../types/client'
198+ import { default as gqlstring } from 'graphql-tag'
199+
195200import { BlockchainError } from './movements'
196201import { gqlToString } from './queryPrinter'
197202import { CryptoCurrency } from '../constants/currency'
@@ -3854,4 +3859,293 @@ export class Client {
38543859 public getBtcAddress ( ) : string {
38553860 return this . apiKey . child_keys [ BIP44 . BTC ] . address
38563861 }
3862+
3863+ /*
3864+ Updates for placing or cancelling multiple orders in same request
3865+ */
3866+
3867+ /**
3868+ * Cancel a list of orders by ID.
3869+ *
3870+ * @param orderID[]
3871+ * @returns
3872+ *
3873+ * Example
3874+ * ```
3875+ * const cancelledOrders = await nash.cancelOrder(['11','12'])
3876+ * console.log(cancelledOrders)
3877+ * ```
3878+ */
3879+ public async cancelOrders (
3880+ orderIDs : string [ ] ,
3881+ marketName : string
3882+ ) : Promise < CancelledOrder [ ] > {
3883+ if ( orderIDs . length === 0 ) {
3884+ return [ ]
3885+ }
3886+
3887+ const [ a , b ] = marketName . split ( '_' )
3888+ await this . prefillRPoolIfNeededForAssets (
3889+ a as CryptoCurrency ,
3890+ b as CryptoCurrency
3891+ )
3892+
3893+ const cancelOrdersPayloads = await Promise . all (
3894+ orderIDs . map ( async id => {
3895+ const cancelOrderParams = createCancelOrderParams ( id , marketName )
3896+ const signedPayload = await this . signPayload ( cancelOrderParams )
3897+ return signedPayload
3898+ } )
3899+ )
3900+
3901+ const names = this . generateNames ( cancelOrdersPayloads . length )
3902+
3903+ const params = names
3904+ . map ( name => `$p${ name } :CancelOrderParams!, $s${ name } :Signature!` )
3905+ . join ( ',' )
3906+ const aliases = names
3907+ . map (
3908+ name =>
3909+ ` ${ name } : cancelOrder(payload: $p${ name } , signature: $s${ name } ) { orderId }`
3910+ )
3911+ . join ( '\n' )
3912+ const mutationStr = `mutation cancelOrders(${ params } ) {\n${ aliases } \n}`
3913+ const mutation = gqlstring ( mutationStr )
3914+ const variables = { }
3915+ cancelOrdersPayloads . forEach ( ( item , index ) => {
3916+ variables [ `p${ names [ index ] } ` ] = item . payload
3917+ variables [ `s${ names [ index ] } ` ] = item . signature
3918+ } )
3919+ const result = await this . gql . mutate ( {
3920+ mutation,
3921+ variables
3922+ } )
3923+ const cancelledOrders = Object . keys ( result . data ) . map (
3924+ k => result . data [ k ]
3925+ ) as CancelledOrder [ ]
3926+ return cancelledOrders
3927+ }
3928+
3929+ public async placeLimitOrders (
3930+ params : PlaceLimitOrderParams [ ]
3931+ ) : Promise < OrdersPlaced > {
3932+ if ( params . length === 0 ) {
3933+ return {
3934+ orders : [ ]
3935+ }
3936+ }
3937+ await this . prefillRPoolIfNeededForAssets (
3938+ params [ 0 ] . limitPrice . currencyA ,
3939+ params [ 0 ] . limitPrice . currencyB
3940+ )
3941+
3942+ const placeLimitOrderPayloads = await this . generatePlaceOrdersParams ( params )
3943+ const names = this . generateNames ( placeLimitOrderPayloads . length )
3944+
3945+ const paramNames = names
3946+ . map ( name => `$p${ name } :PlaceLimitOrderParams!, $s${ name } :Signature!` )
3947+ . join ( ',' )
3948+ const aliases = names
3949+ . map (
3950+ name =>
3951+ ` ${ name } : placeLimitOrder(affiliateDeveloperCode: $affiliateDeveloperCode, payload: $p${ name } , signature: $s${ name } ) {\n id\n status\n ordersTillSignState\n }`
3952+ )
3953+ . join ( '\n' )
3954+ const mutationStr = `mutation placeLimitOrders($affiliateDeveloperCode: AffiliateDeveloperCode, ${ paramNames } ) {\n${ aliases } \n}`
3955+ const mutation = gqlstring ( mutationStr )
3956+
3957+ const variables = {
3958+ affiliateDeveloperCode : this . affiliateDeveloperCode
3959+ }
3960+
3961+ placeLimitOrderPayloads . forEach ( ( item , index ) => {
3962+ variables [ `p${ names [ index ] } ` ] = item . signedPayload
3963+ variables [ `s${ names [ index ] } ` ] = item . signature
3964+ } )
3965+
3966+ try {
3967+ const result = await this . gql . mutate ( {
3968+ mutation,
3969+ variables
3970+ } )
3971+
3972+ return {
3973+ orders : Object . keys ( result . data ) . map (
3974+ k => result . data [ k ]
3975+ ) as OrderPlaced [ ]
3976+ }
3977+ } catch ( e ) {
3978+ if ( e . message . includes ( MISSING_NONCES ) ) {
3979+ await this . updateTradedAssetNonces ( )
3980+ }
3981+ return {
3982+ error : e ,
3983+ orders : [ ]
3984+ }
3985+ }
3986+ }
3987+
3988+ /**
3989+ * Cancel a list of orders by ID.
3990+ *
3991+ * @param orderID[]
3992+ * @returns
3993+ *
3994+ * Example
3995+ * ```
3996+ * const cancelledOrders = await nash.cancelOrder(['11','12'])
3997+ * console.log(cancelledOrders)
3998+ * ```
3999+ */
4000+ public async cancelAndPlaceOrders (
4001+ orderIDs : string [ ] ,
4002+ marketName : string ,
4003+ orders : PlaceLimitOrderParams [ ]
4004+ ) : Promise < OrdersCancelledAndPlaced > {
4005+ const [ a , b ] = marketName . split ( '_' )
4006+ await this . prefillRPoolIfNeededForAssets (
4007+ a as CryptoCurrency ,
4008+ b as CryptoCurrency
4009+ )
4010+
4011+ const cancelOrdersPayloads = await Promise . all (
4012+ orderIDs . map ( async id => {
4013+ const cancelOrderParams = createCancelOrderParams ( id , marketName )
4014+ const signedPayload = await this . signPayload ( cancelOrderParams )
4015+ return signedPayload
4016+ } )
4017+ )
4018+
4019+ const placeLimitOrderPayloads = await this . generatePlaceOrdersParams ( orders )
4020+
4021+ const cancelNames = this . generateNames ( cancelOrdersPayloads . length )
4022+ const cancelParams = cancelNames
4023+ . map ( name => `$p${ name } :CancelOrderParams!, $s${ name } :Signature!` )
4024+ . join ( ',' )
4025+ const cancelAliases = cancelNames
4026+ . map (
4027+ name =>
4028+ ` ${ name } : cancelOrder(payload: $p${ name } , signature: $s${ name } ) { orderId }`
4029+ )
4030+ . join ( '\n' )
4031+
4032+ const placeNames = this . generateNames (
4033+ orders . length ,
4034+ cancelOrdersPayloads . length
4035+ )
4036+
4037+ const placeOrderParams = placeNames
4038+ . map ( name => `$p${ name } :PlaceLimitOrderParams!, $s${ name } :Signature!` )
4039+ . join ( ',' )
4040+ const placeOrderAliases = placeNames
4041+ . map (
4042+ name =>
4043+ ` ${ name } : placeLimitOrder(affiliateDeveloperCode: $affiliateDeveloperCode, payload: $p${ name } , signature: $s${ name } ) {\n id\n status\n ordersTillSignState\n }`
4044+ )
4045+ . join ( '\n' )
4046+
4047+ const mutationStr = `mutation cancelAndPlaceOrders(${ cancelParams } , ${ placeOrderParams } ${
4048+ placeLimitOrderPayloads . length
4049+ ? ', $affiliateDeveloperCode: AffiliateDeveloperCode'
4050+ : ''
4051+ } ) {\n${ cancelAliases } \n${ placeOrderAliases } \n}`
4052+ const mutation = gqlstring ( mutationStr )
4053+
4054+ const variables : any = { }
4055+ if ( placeLimitOrderPayloads . length > 0 ) {
4056+ variables . affiliateDeveloperCode = this . affiliateDeveloperCode
4057+ }
4058+
4059+ cancelOrdersPayloads . forEach ( ( item , index ) => {
4060+ variables [ `p${ cancelNames [ index ] } ` ] = item . payload
4061+ variables [ `s${ cancelNames [ index ] } ` ] = item . signature
4062+ } )
4063+ placeLimitOrderPayloads . forEach ( ( item , index ) => {
4064+ variables [ `p${ placeNames [ index ] } ` ] = item . signedPayload
4065+ variables [ `s${ placeNames [ index ] } ` ] = item . signature
4066+ } )
4067+
4068+ try {
4069+ const result = await this . gql . mutate ( {
4070+ mutation,
4071+ variables
4072+ } )
4073+ return {
4074+ orders : Object . keys ( result . data )
4075+ . filter ( k => placeNames . indexOf ( k ) > - 1 )
4076+ . map ( k => result . data [ k ] ) as OrderPlaced [ ] ,
4077+ cancelled : Object . keys ( result . data )
4078+ . filter ( k => cancelNames . indexOf ( k ) > - 1 )
4079+ . map ( k => result . data [ k ] ) as CancelledOrder [ ]
4080+ }
4081+ } catch ( e ) {
4082+ if ( e . message . includes ( MISSING_NONCES ) ) {
4083+ await this . updateTradedAssetNonces ( )
4084+ }
4085+ return {
4086+ error : e ,
4087+ orders : [ ] ,
4088+ cancelled : [ ]
4089+ }
4090+ }
4091+ }
4092+
4093+ private generatePlaceOrdersParams = async (
4094+ params : PlaceLimitOrderParams [ ]
4095+ ) : Promise < PayloadSignature [ ] > => {
4096+ return await Promise . all (
4097+ params . map ( async param => {
4098+ const { nonceOrder, noncesFrom, noncesTo } = this . getNoncesForTrade (
4099+ param . marketName ,
4100+ param . buyOrSell
4101+ )
4102+ const normalizedAmount = normalizeAmountForMarket (
4103+ param . amount ,
4104+ this . marketData [ param . marketName ]
4105+ )
4106+ const normalizedLimitPrice = normalizePriceForMarket (
4107+ param . limitPrice ,
4108+ this . marketData [ param . marketName ]
4109+ )
4110+ const placeLimitOrderParams = createPlaceLimitOrderParams (
4111+ param . allowTaker ,
4112+ normalizedAmount ,
4113+ param . buyOrSell ,
4114+ param . cancellationPolicy ,
4115+ normalizedLimitPrice ,
4116+ param . marketName ,
4117+ noncesFrom ,
4118+ noncesTo ,
4119+ nonceOrder ,
4120+ param . cancelAt
4121+ )
4122+ const signedPayload = await this . signPayload ( placeLimitOrderParams )
4123+ return signedPayload
4124+ } )
4125+ )
4126+ }
4127+
4128+ private generateNames = ( total : number , offset : number = 0 ) : string [ ] => {
4129+ const names = [
4130+ 'A' ,
4131+ 'B' ,
4132+ 'C' ,
4133+ 'D' ,
4134+ 'E' ,
4135+ 'F' ,
4136+ 'G' ,
4137+ 'H' ,
4138+ 'I' ,
4139+ 'J' ,
4140+ 'K' ,
4141+ 'L' ,
4142+ 'M' ,
4143+ 'N' ,
4144+ 'O' ,
4145+ 'P' ,
4146+ 'Q'
4147+ ]
4148+
4149+ return names . slice ( offset , offset + total )
4150+ }
38574151}
0 commit comments