Skip to content

Commit 32980b8

Browse files
authored
Merge pull request #60 from nash-io/ts/multi-mutation-graphql-req
Ts/multi mutation graphql req
2 parents 4ececf3 + 6613865 commit 32980b8

File tree

6 files changed

+343
-3
lines changed

6 files changed

+343
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
<a name="5.2.29"></a>
6+
## [5.2.29](https://github.com/nash-io/api-client-typescript/compare/v5.2.27...v5.2.29) (2021-01-19)
7+
8+
9+
510
<a name="5.2.27"></a>
611
## [5.2.27](https://github.com/nash-io/api-client-typescript/compare/v5.2.25...v5.2.27) (2020-12-16)
712

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@neon-exchange/api-client-typescript",
3-
"version": "5.2.27",
3+
"version": "5.2.29",
44
"description": "Official TypeScript client for interacting with the Nash exchange",
55
"main": "build/main/index.js",
66
"typings": "build/main/index.d.ts",

src/client/client.ts

Lines changed: 295 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ import {
183183
AssetData,
184184
Asset,
185185
MissingNonceError,
186-
InsufficientFundsError
186+
InsufficientFundsError,
187+
PlaceLimitOrderParams,
188+
OrdersPlaced,
189+
OrdersCancelledAndPlaced
187190
} from '../types'
188191
import {
189192
ClientMode,
@@ -192,6 +195,8 @@ import {
192195
GQLResp,
193196
PayloadSignature
194197
} from '../types/client'
198+
import { default as gqlstring } from 'graphql-tag'
199+
195200
import { BlockchainError } from './movements'
196201
import { gqlToString } from './queryPrinter'
197202
import { 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
}

src/client/networks.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ export const ETH_NETWORK: NetworkSettingsRecord = {
4747
contract: '0x00F2B67B5A5EC2FF88B2BE7D5A8D1A39D5929237'
4848
}
4949
},
50-
nodes: ['https://consensus1.eth.nash.io','https://consensus2.eth.nash.io','https://consensus3.eth.nash.io']
50+
nodes: [
51+
'https://consensus1.eth.nash.io',
52+
'https://consensus2.eth.nash.io',
53+
'https://consensus3.eth.nash.io'
54+
]
5155
},
5256
[Networks.TestNet]: {
5357
contracts: {},

src/mutations/orders/cancelOrder.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,19 @@ export const CANCEL_ORDER_MUTATION = gql`
1010
}
1111
${CANCELED_ORDER_FRAGMENT}
1212
`
13+
14+
export const CANCEL_ORDERS_MUTATION = gql`
15+
mutation cancelOrders(
16+
$pA: CancelOrderParams!
17+
$pB: CancelOrderParams!
18+
$sA: Signature!
19+
$sB: Signature!
20+
) {
21+
a: cancelOrder(payload: $pA, signature: $sA) {
22+
orderId
23+
}
24+
b: cancelOrder(payload: $pB, signature: $sB) {
25+
orderId
26+
}
27+
}
28+
`

src/types/order.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,24 @@ export interface OrderPlaced {
6060
status: OrderStatus
6161
ordersTillSignState: number
6262
}
63+
64+
export interface PlaceLimitOrderParams {
65+
allowTaker: boolean
66+
amount: CurrencyAmount
67+
buyOrSell: OrderBuyOrSell
68+
cancellationPolicy: OrderCancellationPolicy
69+
limitPrice: CurrencyPrice
70+
marketName: string
71+
cancelAt?: DateTime
72+
}
73+
74+
export interface OrdersPlaced {
75+
error?: any
76+
orders: OrderPlaced[]
77+
}
78+
79+
export interface OrdersCancelledAndPlaced {
80+
error?: any
81+
cancelled: CancelledOrder[]
82+
orders: OrderPlaced[]
83+
}

0 commit comments

Comments
 (0)