Skip to content

Commit 021cc5c

Browse files
authored
Merge pull request #1 from nash-io/ts/autostatesync
change default behavior to auto sign state when necessary
2 parents cb1b1e0 + 05e4458 commit 021cc5c

File tree

5 files changed

+87
-2
lines changed

5 files changed

+87
-2
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,25 @@ See also the [websockets example](https://gitlab.com/nash-io-public/api-client-t
114114
## Managing API key policies
115115

116116
For more information on how to set up policies for API keys, consult the [API key policies wiki page](https://gitlab.com/nash-io-public/api-client-typescript/-/wikis/Apikey-policies).
117+
118+
119+
## State signing
120+
121+
In order to assure your blockchain balances remain in sync with your trading balances, the client must 'sign' their state every so often before placing more orders. By default, the client will take care of this in the background for you and you will not need to worry about this.
122+
123+
In special cases where a user has more than one client process running at once which is placing a high volume of orders, it is advisable to take a more custom approach. To turn of auto state syncing, initialize the client like so:
124+
125+
```
126+
const nash = new Client(EnvironmentConfiguration.sandbox, {autoSignState: false})
127+
```
128+
129+
You will then be responsible for signing states when necessary. The current restriction is that states must be signed every 100 open orders, so the client should keep track and make sure to sign state before this limit is reached, otherwise placing an order will raise an error.
130+
131+
This is done using the following call:
132+
133+
```
134+
const states = await client.getSignAndSyncStates()
135+
```
136+
137+
If you are running a high volume of orders from different clients on the same account and having difficulty managing this process, please reach out to support and we will be glad to help with an optimal solution.
138+

src/client/client.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,10 @@ const BLOCKCHAIN_TO_BIP44 = {
272272
[Blockchain.NEO]: BIP44.NEO
273273
}
274274

275+
const ORDERS_REMAINING_TO_AUTOSYNC_AT = 20
275276
const NEP5_OLD_ASSETS = ['nos', 'phx', 'guard', 'lx', 'ava']
276277
export const MISSING_NONCES = 'missing_asset_nonces'
278+
export const MAX_ORDERS_REACHED = 'Maximal number of orders have been reached'
277279
export const MAX_SIGN_STATE_RECURSION = 5
278280

279281
export class Client {
@@ -317,7 +319,7 @@ export class Client {
317319
private tradedAssets: string[] = []
318320
private assetNonces: { [key: string]: number[] }
319321
private currentOrderNonce: number
320-
322+
private signStateInProgress: boolean
321323
/**
322324
* Create a new instance of [[Client]]
323325
*
@@ -337,6 +339,7 @@ export class Client {
337339
...opts
338340
}
339341
this.clientOpts = {
342+
autoSignState: true,
340343
runRequestsOverWebsockets: false,
341344
headers: {},
342345
...clientOpts
@@ -1608,6 +1611,8 @@ export class Client {
16081611
public async getSignAndSyncStates(
16091612
sync = false
16101613
): Promise<SyncStatesData | SignStatesData> {
1614+
this.signStateInProgress = true
1615+
16111616
const emptyStates: GetStatesData = {
16121617
states: [],
16131618
recycledOrders: [],
@@ -1616,6 +1621,8 @@ export class Client {
16161621
const signStatesRecursive: SignStatesData = await this.signStates(
16171622
emptyStates
16181623
)
1624+
this.signStateInProgress = false
1625+
16191626
if (sync) {
16201627
const syncResult = await this.syncStates(signStatesRecursive)
16211628
return syncResult
@@ -1936,10 +1943,22 @@ export class Client {
19361943
})
19371944
measurementPlaceOrder.end()
19381945
measurementPlaceLimitOrder.end()
1946+
1947+
await this.handleOrderPlaced(result.data.placeLimitOrder)
1948+
19391949
return result.data.placeLimitOrder
19401950
} catch (e) {
1951+
let replaceOrder = false
19411952
if (e.message.includes(MISSING_NONCES)) {
1953+
replaceOrder = true
19421954
await this.updateTradedAssetNonces()
1955+
} else if (e.message.includes(MAX_ORDERS_REACHED)) {
1956+
if (this.clientOpts.autoSignState && !this.signStateInProgress) {
1957+
replaceOrder = true
1958+
await this.getSignAndSyncStates()
1959+
}
1960+
}
1961+
if (replaceOrder) {
19431962
return await this.placeLimitOrder(
19441963
allowTaker,
19451964
amount,
@@ -2026,12 +2045,23 @@ export class Client {
20262045
})
20272046
measurementPlaceOrder.end()
20282047
measurementPlaceMarketOrder.end()
2048+
await this.handleOrderPlaced(result.data.placeMarketOrder)
20292049
return result.data.placeMarketOrder
20302050
} catch (e) {
2051+
let replaceOrder = false
20312052
if (e.message.includes(MISSING_NONCES)) {
2053+
replaceOrder = true
20322054
await this.updateTradedAssetNonces()
2055+
} else if (e.message.includes(MAX_ORDERS_REACHED)) {
2056+
if (this.clientOpts.autoSignState && !this.signStateInProgress) {
2057+
replaceOrder = true
2058+
await this.getSignAndSyncStates()
2059+
}
2060+
}
2061+
if (replaceOrder) {
20332062
return await this.placeMarketOrder(amount, buyOrSell, marketName)
20342063
}
2064+
20352065
return this.handleOrderError(e, signedPayload)
20362066
}
20372067
}
@@ -2136,11 +2166,20 @@ export class Client {
21362166
})
21372167
measurementPlaceOrder.end()
21382168
measurementPlaceMarketOrder.end()
2139-
2169+
await this.handleOrderPlaced(result.data.placeStopLimitOrder)
21402170
return result.data.placeStopLimitOrder
21412171
} catch (e) {
2172+
let replaceOrder = false
21422173
if (e.message.includes(MISSING_NONCES)) {
2174+
replaceOrder = true
21432175
await this.updateTradedAssetNonces()
2176+
} else if (e.message.includes(MAX_ORDERS_REACHED)) {
2177+
if (this.clientOpts.autoSignState && !this.signStateInProgress) {
2178+
replaceOrder = true
2179+
await this.getSignAndSyncStates()
2180+
}
2181+
}
2182+
if (replaceOrder) {
21442183
return await this.placeStopLimitOrder(
21452184
allowTaker,
21462185
amount,
@@ -2238,10 +2277,20 @@ export class Client {
22382277
})
22392278
measurementPlaceOrder.end()
22402279
measurementPlaceMarketOrder.end()
2280+
await this.handleOrderPlaced(result.data.placeStopMarketOrder)
22412281
return result.data.placeStopMarketOrder
22422282
} catch (e) {
2283+
let replaceOrder = false
22432284
if (e.message.includes(MISSING_NONCES)) {
2285+
replaceOrder = true
22442286
await this.updateTradedAssetNonces()
2287+
} else if (e.message.includes(MAX_ORDERS_REACHED)) {
2288+
if (this.clientOpts.autoSignState && !this.signStateInProgress) {
2289+
replaceOrder = true
2290+
await this.getSignAndSyncStates()
2291+
}
2292+
}
2293+
if (replaceOrder) {
22452294
return await this.placeStopMarketOrder(
22462295
amount,
22472296
buyOrSell,
@@ -2254,6 +2303,17 @@ export class Client {
22542303
}
22552304
}
22562305

2306+
private handleOrderPlaced = async (order: OrderPlaced): Promise<void> => {
2307+
if (
2308+
this.clientOpts.autoSignState &&
2309+
order.ordersTillSignState < ORDERS_REMAINING_TO_AUTOSYNC_AT &&
2310+
!this.signStateInProgress
2311+
) {
2312+
console.info('Will auto sign state: ', order.ordersTillSignState)
2313+
await this.getSignAndSyncStates()
2314+
}
2315+
}
2316+
22572317
private handleOrderError(error: Error, signedPayload: any): any {
22582318
if (error.message.includes(MISSING_NONCES)) {
22592319
this.updateTradedAssetNonces()

src/client/environments.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface ClientOptions {
2020
// The socketsocket conneciton supports 1 header. "User-Agent"
2121
// while the others support all, but you cannot override content-type nor the authorization token
2222
headers?: Record<string, string>
23+
autoSignState?: boolean
2324
}
2425
export const EnvironmentConfiguration = {
2526
production: {

src/mutations/orders/fragments/orderPlacedFragment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ export const ORDER_PLACED_FRAGMENT = gql`
44
fragment orderPlacedFields on OrderPlaced {
55
id
66
status
7+
ordersTillSignState
78
}
89
`

src/types/order.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ export enum OrderType {
5555
export interface OrderPlaced {
5656
id: string
5757
status: OrderStatus
58+
ordersTillSignState: number
5859
}

0 commit comments

Comments
 (0)