@lifi/perps-sdk 13.0.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/cjs/client/PerpsClient.d.ts +5 -1
- package/dist/cjs/client/PerpsClient.d.ts.map +1 -1
- package/dist/cjs/client/PerpsClient.js +8 -0
- package/dist/cjs/client/PerpsClient.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +10 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/registry/assetRegistry.d.ts +2 -0
- package/dist/cjs/registry/assetRegistry.d.ts.map +1 -1
- package/dist/cjs/registry/assetRegistry.js +18 -1
- package/dist/cjs/registry/assetRegistry.js.map +1 -1
- package/dist/cjs/registry/referenceDataRegistry.d.ts +5 -2
- package/dist/cjs/registry/referenceDataRegistry.d.ts.map +1 -1
- package/dist/cjs/registry/referenceDataRegistry.js +37 -7
- package/dist/cjs/registry/referenceDataRegistry.js.map +1 -1
- package/dist/cjs/services/getOrders.d.ts +2 -1
- package/dist/cjs/services/getOrders.d.ts.map +1 -1
- package/dist/cjs/services/getOrders.js +2 -0
- package/dist/cjs/services/getOrders.js.map +1 -1
- package/dist/cjs/transport/fetchWithRetry.d.ts.map +1 -1
- package/dist/cjs/transport/fetchWithRetry.js.map +1 -1
- package/dist/cjs/types/provider.d.ts +2 -6
- package/dist/cjs/types/provider.d.ts.map +1 -1
- package/dist/cjs/utils/orderClassification.d.ts +9 -5
- package/dist/cjs/utils/orderClassification.d.ts.map +1 -1
- package/dist/cjs/utils/orderClassification.js +19 -0
- package/dist/cjs/utils/orderClassification.js.map +1 -1
- package/dist/cjs/utils/orderMath.d.ts +2 -2
- package/dist/cjs/utils/orderMath.d.ts.map +1 -1
- package/dist/cjs/utils/orderMath.js +15 -4
- package/dist/cjs/utils/orderMath.js.map +1 -1
- package/dist/cjs/utils/warnOnce.d.ts +2 -0
- package/dist/cjs/utils/warnOnce.d.ts.map +1 -0
- package/dist/cjs/utils/warnOnce.js +22 -0
- package/dist/cjs/utils/warnOnce.js.map +1 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/PerpsClient.d.ts +7 -1
- package/dist/esm/client/PerpsClient.d.ts.map +1 -1
- package/dist/esm/client/PerpsClient.js +10 -0
- package/dist/esm/client/PerpsClient.js.map +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/registry/assetRegistry.d.ts +5 -8
- package/dist/esm/registry/assetRegistry.d.ts.map +1 -1
- package/dist/esm/registry/assetRegistry.js +21 -9
- package/dist/esm/registry/assetRegistry.js.map +1 -1
- package/dist/esm/registry/referenceDataRegistry.d.ts +6 -14
- package/dist/esm/registry/referenceDataRegistry.d.ts.map +1 -1
- package/dist/esm/registry/referenceDataRegistry.js +38 -19
- package/dist/esm/registry/referenceDataRegistry.js.map +1 -1
- package/dist/esm/services/getOrders.d.ts +3 -17
- package/dist/esm/services/getOrders.d.ts.map +1 -1
- package/dist/esm/services/getOrders.js +3 -16
- package/dist/esm/services/getOrders.js.map +1 -1
- package/dist/esm/transport/fetchWithRetry.d.ts +3 -2
- package/dist/esm/transport/fetchWithRetry.d.ts.map +1 -1
- package/dist/esm/transport/fetchWithRetry.js +3 -2
- package/dist/esm/transport/fetchWithRetry.js.map +1 -1
- package/dist/esm/types/api.d.ts +2 -2
- package/dist/esm/types/provider.d.ts +2 -16
- package/dist/esm/types/provider.d.ts.map +1 -1
- package/dist/esm/utils/orderClassification.d.ts +14 -19
- package/dist/esm/utils/orderClassification.d.ts.map +1 -1
- package/dist/esm/utils/orderClassification.js +21 -15
- package/dist/esm/utils/orderClassification.js.map +1 -1
- package/dist/esm/utils/orderMath.d.ts +3 -13
- package/dist/esm/utils/orderMath.d.ts.map +1 -1
- package/dist/esm/utils/orderMath.js +17 -16
- package/dist/esm/utils/orderMath.js.map +1 -1
- package/dist/esm/utils/warnOnce.d.ts +9 -0
- package/dist/esm/utils/warnOnce.d.ts.map +1 -0
- package/dist/esm/utils/warnOnce.js +29 -0
- package/dist/esm/utils/warnOnce.js.map +1 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/client/PerpsClient.d.ts +7 -1
- package/dist/types/client/PerpsClient.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/registry/assetRegistry.d.ts +5 -8
- package/dist/types/registry/assetRegistry.d.ts.map +1 -1
- package/dist/types/registry/referenceDataRegistry.d.ts +6 -14
- package/dist/types/registry/referenceDataRegistry.d.ts.map +1 -1
- package/dist/types/services/getOrders.d.ts +3 -17
- package/dist/types/services/getOrders.d.ts.map +1 -1
- package/dist/types/transport/fetchWithRetry.d.ts +3 -2
- package/dist/types/transport/fetchWithRetry.d.ts.map +1 -1
- package/dist/types/types/api.d.ts +2 -2
- package/dist/types/types/provider.d.ts +2 -16
- package/dist/types/types/provider.d.ts.map +1 -1
- package/dist/types/utils/orderClassification.d.ts +14 -19
- package/dist/types/utils/orderClassification.d.ts.map +1 -1
- package/dist/types/utils/orderMath.d.ts +3 -13
- package/dist/types/utils/orderMath.d.ts.map +1 -1
- package/dist/types/utils/warnOnce.d.ts +9 -0
- package/dist/types/utils/warnOnce.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/client/PerpsClient.ts +26 -0
- package/src/index.ts +6 -2
- package/src/registry/assetRegistry.ts +29 -9
- package/src/registry/referenceDataRegistry.ts +46 -19
- package/src/services/getOrders.ts +5 -17
- package/src/transport/fetchWithRetry.ts +3 -2
- package/src/types/api.ts +2 -2
- package/src/types/provider.ts +2 -21
- package/src/utils/orderClassification.ts +37 -19
- package/src/utils/orderMath.ts +25 -17
- package/src/utils/warnOnce.ts +29 -0
- package/src/version.ts +1 -1
package/dist/types/version.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/perps-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "LI.FI Perps SDK for perpetuals trading",
|
|
5
5
|
"homepage": "https://github.com/lifinance/perps-sdk",
|
|
6
6
|
"bugs": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"big.js": "^7.0.1",
|
|
47
47
|
"partysocket": "^1.1.19",
|
|
48
48
|
"viem": "^2.55.18",
|
|
49
|
-
"@lifi/perps-types": "^
|
|
49
|
+
"@lifi/perps-types": "^13.0.0"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
@@ -9,6 +9,8 @@ import type {
|
|
|
9
9
|
MarketRef,
|
|
10
10
|
MarketSettings,
|
|
11
11
|
MetaActionType,
|
|
12
|
+
Order,
|
|
13
|
+
OrdersResponse,
|
|
12
14
|
PortfolioHistoryResponse,
|
|
13
15
|
Position,
|
|
14
16
|
PositionMarginConstraints,
|
|
@@ -30,6 +32,14 @@ import { getAssetRegistry } from '../registry/assetRegistry.js'
|
|
|
30
32
|
import { createAction } from '../services/createAction.js'
|
|
31
33
|
import { executeAction } from '../services/executeAction.js'
|
|
32
34
|
import { getAccount as fetchAccount } from '../services/getAccount.js'
|
|
35
|
+
import {
|
|
36
|
+
getOrder as fetchOrder,
|
|
37
|
+
type GetOrderParams,
|
|
38
|
+
} from '../services/getOrder.js'
|
|
39
|
+
import {
|
|
40
|
+
getOrders as fetchOrders,
|
|
41
|
+
type GetOrdersParams,
|
|
42
|
+
} from '../services/getOrders.js'
|
|
33
43
|
import { getProviders } from '../services/getProviders.js'
|
|
34
44
|
import type {
|
|
35
45
|
BuildProviderSetupParams,
|
|
@@ -190,6 +200,22 @@ export class PerpsClient {
|
|
|
190
200
|
return resolveProvider(this.sdkClient, provider)
|
|
191
201
|
}
|
|
192
202
|
|
|
203
|
+
/** Read active or historical orders from the selected venue. */
|
|
204
|
+
async getOrders(
|
|
205
|
+
params: GetOrdersParams,
|
|
206
|
+
options?: SDKRequestOptions
|
|
207
|
+
): Promise<OrdersResponse> {
|
|
208
|
+
return fetchOrders(this.sdkClient, params, options)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Read one venue order through the provider's unified mapper. */
|
|
212
|
+
async getOrder(
|
|
213
|
+
params: GetOrderParams,
|
|
214
|
+
options?: SDKRequestOptions
|
|
215
|
+
): Promise<Order> {
|
|
216
|
+
return fetchOrder(this.sdkClient, params, options)
|
|
217
|
+
}
|
|
218
|
+
|
|
193
219
|
/**
|
|
194
220
|
* Ask the provider plugin for the signer-bearing wire fields of `action` —
|
|
195
221
|
* the on-wire `signerAddress` and any signer-derived params (e.g.
|
package/src/index.ts
CHANGED
|
@@ -87,7 +87,7 @@ export { createMemoryStorage } from './storage/storage.js'
|
|
|
87
87
|
export type { StorageAdapter } from './storage/types.js'
|
|
88
88
|
export { errorCodeFromStatus } from './transport/errorCodeFromStatus.js'
|
|
89
89
|
export type { FetchWithRetryOptions } from './transport/fetchWithRetry.js'
|
|
90
|
-
export { fetchWithRetry } from './transport/fetchWithRetry.js'
|
|
90
|
+
export { fetchWithRetry, isAbortError } from './transport/fetchWithRetry.js'
|
|
91
91
|
export type {
|
|
92
92
|
ProviderRetryConfig,
|
|
93
93
|
ResolvedRetryPolicy,
|
|
@@ -160,7 +160,6 @@ export type {
|
|
|
160
160
|
ProviderGetPortfolioHistoryParams,
|
|
161
161
|
ProviderGetPositionsParams,
|
|
162
162
|
ProviderGetQuoteParams,
|
|
163
|
-
ProviderGetRunningTwapsParams,
|
|
164
163
|
ProviderGetWithdrawableBalancesParams,
|
|
165
164
|
QuoteListener,
|
|
166
165
|
SignActionProgress,
|
|
@@ -222,9 +221,13 @@ export {
|
|
|
222
221
|
classifyFill,
|
|
223
222
|
FillClassification,
|
|
224
223
|
isActiveOrderStatus,
|
|
224
|
+
isRegularOrder,
|
|
225
225
|
isStopLossOrder,
|
|
226
226
|
isTakeProfitOrder,
|
|
227
227
|
isTpSlOrder,
|
|
228
|
+
isTriggerOrder,
|
|
229
|
+
isTwapOrder,
|
|
230
|
+
triggerConditionFor,
|
|
228
231
|
} from './utils/orderClassification.js'
|
|
229
232
|
export {
|
|
230
233
|
expectedRealizedPnlForOpenOrder,
|
|
@@ -252,6 +255,7 @@ export type { RemovableIsolatedMarginParams } from './utils/transferMargin.js'
|
|
|
252
255
|
export { removableIsolatedMargin } from './utils/transferMargin.js'
|
|
253
256
|
export { fromBaseUnits, fromBaseUnitsNumber } from './utils/units.js'
|
|
254
257
|
export { validateMargin } from './utils/validation.js'
|
|
258
|
+
export { createWarnOnce } from './utils/warnOnce.js'
|
|
255
259
|
// Version
|
|
256
260
|
export { name, version } from './version.js'
|
|
257
261
|
export { cachePromise } from './websocket/cachePromise.js'
|
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
import type { Asset, AssetsResponse } from '@lifi/perps-types'
|
|
2
|
+
import { PerpsErrorCode } from '@lifi/perps-types'
|
|
3
|
+
import { PerpsError } from '../errors/PerpsError.js'
|
|
2
4
|
import { buildUrl, request } from '../transport/request.js'
|
|
3
5
|
import type { PerpsSDKClient } from '../types/provider.js'
|
|
4
6
|
import { ReferenceDataRegistry } from './referenceDataRegistry.js'
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* {@link getAssetRegistry}.
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
8
|
+
const addressKey = (address: string): string =>
|
|
9
|
+
/^0x[0-9a-f]{40}$/i.test(address) ? address.toLowerCase() : address
|
|
10
|
+
|
|
11
|
+
/** Provider `/assets` index by native `id` and by L1 contract address. @public */
|
|
14
12
|
export class AssetRegistry extends ReferenceDataRegistry<Asset> {
|
|
15
13
|
constructor(client: PerpsSDKClient, provider: string) {
|
|
16
|
-
super(client, provider, 'asset'
|
|
14
|
+
super(client, provider, 'asset', {
|
|
15
|
+
l1Address: (asset) =>
|
|
16
|
+
asset.l1Address === undefined ? undefined : addressKey(asset.l1Address),
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Lookup by provider identity; hexadecimal L1 addresses are case-insensitive. */
|
|
21
|
+
override get(id: string, key: 'id' | 'l1Address' = 'id'): Asset | undefined {
|
|
22
|
+
return key === 'id' ? super.get(id) : this.getByIndex(addressKey(id), key)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Resolve registry membership or report a stale or mis-keyed asset registry. */
|
|
26
|
+
require(id: string, key: 'id' | 'l1Address' = 'id'): Asset {
|
|
27
|
+
const asset = this.get(id, key)
|
|
28
|
+
if (asset === undefined) {
|
|
29
|
+
const error = new PerpsError(
|
|
30
|
+
PerpsErrorCode.ValidationError,
|
|
31
|
+
`[${this.provider}] stale or mis-keyed asset registry: unknown ${key} '${id}'`
|
|
32
|
+
)
|
|
33
|
+
error.tool = this.provider
|
|
34
|
+
throw error
|
|
35
|
+
}
|
|
36
|
+
return asset
|
|
17
37
|
}
|
|
18
38
|
|
|
19
39
|
/**
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
+
import { PerpsErrorCode } from '@lifi/perps-types'
|
|
2
|
+
import { PerpsError } from '../errors/PerpsError.js'
|
|
1
3
|
import type { PerpsSDKClient } from '../types/provider.js'
|
|
4
|
+
import { createWarnOnce } from '../utils/warnOnce.js'
|
|
2
5
|
|
|
3
|
-
/**
|
|
4
|
-
* Per-provider hash index over one of the provider's reference-data lists
|
|
5
|
-
* (`/markets`, `/assets`), keyed by the list's own primary key.
|
|
6
|
-
*
|
|
7
|
-
* NOT a cache: it holds no freshness policy of its own. Every {@link sync}
|
|
8
|
-
* refetches through the HTTP layer, whose `cache-control` headers decide
|
|
9
|
-
* whether the response comes from disk or the network. A lookup miss warns
|
|
10
|
-
* once per id and returns `undefined`; subsequent syncs reconcile the index
|
|
11
|
-
* without replaying the warning for an id that remains absent.
|
|
12
|
-
*
|
|
13
|
-
* @internal
|
|
14
|
-
*/
|
|
6
|
+
/** Atomic provider reference indexes; HTTP cache headers govern freshness. @internal */
|
|
15
7
|
export abstract class ReferenceDataRegistry<T> {
|
|
16
8
|
private index = new Map<string, T>()
|
|
9
|
+
private secondaryIndexes = new Map<string, Map<string, T>>()
|
|
17
10
|
private current: readonly T[] = []
|
|
18
11
|
private inflight: Promise<readonly T[]> | undefined
|
|
19
|
-
private
|
|
12
|
+
private readonly warnOnce = createWarnOnce()
|
|
20
13
|
|
|
21
14
|
protected constructor(
|
|
22
15
|
protected readonly client: PerpsSDKClient,
|
|
23
16
|
readonly provider: string,
|
|
24
|
-
private readonly kind: string
|
|
17
|
+
private readonly kind: string,
|
|
18
|
+
private readonly secondaryKeys: Readonly<
|
|
19
|
+
Record<string, (item: T) => string | undefined>
|
|
20
|
+
> = {}
|
|
25
21
|
) {}
|
|
26
22
|
|
|
27
23
|
/** Fetch the provider's full list through the HTTP layer. */
|
|
@@ -55,16 +51,47 @@ export abstract class ReferenceDataRegistry<T> {
|
|
|
55
51
|
if (item !== undefined) {
|
|
56
52
|
return item
|
|
57
53
|
}
|
|
58
|
-
|
|
59
|
-
this.warnedIds.add(id)
|
|
60
|
-
console.warn(`[${this.provider}] unknown ${this.kind} id '${id}'`)
|
|
61
|
-
}
|
|
54
|
+
this.warnOnce(id, `[${this.provider}] unknown ${this.kind} id '${id}'`)
|
|
62
55
|
return undefined
|
|
63
56
|
}
|
|
64
57
|
|
|
58
|
+
protected getByIndex(id: string, key: string): T | undefined {
|
|
59
|
+
return this.secondaryIndexes.get(key)?.get(id)
|
|
60
|
+
}
|
|
61
|
+
|
|
65
62
|
private async load(): Promise<readonly T[]> {
|
|
66
63
|
const items = await this.fetchItems()
|
|
67
|
-
|
|
64
|
+
const index = new Map<string, T>()
|
|
65
|
+
for (const item of items) {
|
|
66
|
+
const key = this.keyOf(item)
|
|
67
|
+
if (index.has(key)) {
|
|
68
|
+
throw new PerpsError(
|
|
69
|
+
PerpsErrorCode.ValidationError,
|
|
70
|
+
`[${this.provider}] stale or mis-keyed ${this.kind} registry: duplicate id '${key}'`
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
index.set(key, item)
|
|
74
|
+
}
|
|
75
|
+
const secondaryIndexes = new Map<string, Map<string, T>>()
|
|
76
|
+
for (const [name, keyOf] of Object.entries(this.secondaryKeys)) {
|
|
77
|
+
const secondary = new Map<string, T>()
|
|
78
|
+
for (const item of items) {
|
|
79
|
+
const key = keyOf(item)
|
|
80
|
+
if (key === undefined) {
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
if (secondary.has(key)) {
|
|
84
|
+
throw new PerpsError(
|
|
85
|
+
PerpsErrorCode.ValidationError,
|
|
86
|
+
`[${this.provider}] stale or mis-keyed ${this.kind} registry: duplicate ${name} '${key}'`
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
secondary.set(key, item)
|
|
90
|
+
}
|
|
91
|
+
secondaryIndexes.set(name, secondary)
|
|
92
|
+
}
|
|
93
|
+
this.index = index
|
|
94
|
+
this.secondaryIndexes = secondaryIndexes
|
|
68
95
|
this.current = items
|
|
69
96
|
return items
|
|
70
97
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { OrdersResponse } from '@lifi/perps-types'
|
|
1
|
+
import type { OrderStatus, OrdersResponse } from '@lifi/perps-types'
|
|
2
2
|
import type { Address } from 'viem'
|
|
3
3
|
import { requireProvider } from '../client/requireProvider.js'
|
|
4
4
|
import type { SDKRequestOptions } from '../types/config.js'
|
|
5
5
|
import type { PerpsSDKClient } from '../types/provider.js'
|
|
6
|
+
import { ACTIVE_ORDER_STATUSES } from '../utils/orderClassification.js'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Parameters for {@link getOrders}.
|
|
@@ -12,6 +13,7 @@ import type { PerpsSDKClient } from '../types/provider.js'
|
|
|
12
13
|
export interface GetOrdersParams {
|
|
13
14
|
provider: string
|
|
14
15
|
address: Address
|
|
16
|
+
statuses?: OrderStatus[]
|
|
15
17
|
/** Optional opaque `Market.id` filter, not a display symbol. */
|
|
16
18
|
marketId?: string
|
|
17
19
|
/** Maximum items returned; provider defaults and caps apply. */
|
|
@@ -20,22 +22,7 @@ export interface GetOrdersParams {
|
|
|
20
22
|
cursor?: string
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
/**
|
|
24
|
-
* Get open orders and trigger orders for an account. Delegates to the
|
|
25
|
-
* registered venue plugin (direct-to-venue); requires the provider plugin to be
|
|
26
|
-
* registered on the client.
|
|
27
|
-
*
|
|
28
|
-
* @throws {PerpsError} When the provider plugin is not registered, or on
|
|
29
|
-
* backend / network / parsing errors.
|
|
30
|
-
* @example
|
|
31
|
-
* ```ts
|
|
32
|
-
* const { openOrders, triggerOrders } = await getOrders(client, {
|
|
33
|
-
* provider: 'hyperliquid',
|
|
34
|
-
* address: '0x1234...',
|
|
35
|
-
* })
|
|
36
|
-
* ```
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
25
|
+
/** Read account orders with active lifecycle statuses as the default filter. */
|
|
39
26
|
export async function getOrders(
|
|
40
27
|
client: PerpsSDKClient,
|
|
41
28
|
params: GetOrdersParams,
|
|
@@ -44,6 +31,7 @@ export async function getOrders(
|
|
|
44
31
|
return requireProvider(client, params.provider).getOrders(
|
|
45
32
|
{
|
|
46
33
|
address: params.address,
|
|
34
|
+
statuses: params.statuses ?? [...ACTIVE_ORDER_STATUSES],
|
|
47
35
|
marketId: params.marketId,
|
|
48
36
|
limit: params.limit,
|
|
49
37
|
cursor: params.cursor,
|
|
@@ -18,9 +18,10 @@ export interface FetchWithRetryOptions {
|
|
|
18
18
|
/**
|
|
19
19
|
* True when `error` is an `AbortSignal` cancellation (the native `fetch` abort
|
|
20
20
|
* rejection) rather than a genuine network failure. An abort is a deliberate
|
|
21
|
-
* caller action, so
|
|
21
|
+
* caller action, so every transport rethrows it untouched instead of retrying
|
|
22
|
+
* it or wrapping it in a provider error.
|
|
22
23
|
*
|
|
23
|
-
* @
|
|
24
|
+
* @public
|
|
24
25
|
*/
|
|
25
26
|
export function isAbortError(error: unknown): boolean {
|
|
26
27
|
return error instanceof Error && error.name === 'AbortError'
|
package/src/types/api.ts
CHANGED
|
@@ -176,8 +176,8 @@ export interface PlaceOrderParams {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
|
-
*
|
|
180
|
-
*
|
|
179
|
+
* Sends `ActionType.PLACE_TRIGGER_ORDER` with
|
|
180
|
+
* `{ market, side, takeProfit?, stopLoss? }`.
|
|
181
181
|
*
|
|
182
182
|
* @public
|
|
183
183
|
*/
|
package/src/types/provider.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
MarketRef,
|
|
14
14
|
MarketSettings,
|
|
15
15
|
Order,
|
|
16
|
+
OrderStatus,
|
|
16
17
|
OrdersResponse,
|
|
17
18
|
PerpsMarket,
|
|
18
19
|
PerpsSigner,
|
|
@@ -27,7 +28,6 @@ import type {
|
|
|
27
28
|
SignedActionStep,
|
|
28
29
|
SigningMethod,
|
|
29
30
|
TradeType,
|
|
30
|
-
TwapOrder,
|
|
31
31
|
} from '@lifi/perps-types'
|
|
32
32
|
import type { Address } from 'viem'
|
|
33
33
|
import type {
|
|
@@ -223,6 +223,7 @@ export interface ProviderGetMarketSettingsParams {
|
|
|
223
223
|
*/
|
|
224
224
|
export interface ProviderGetOrdersParams {
|
|
225
225
|
address: Address
|
|
226
|
+
statuses?: OrderStatus[]
|
|
226
227
|
/** Optional opaque `Market.id` filter (not a display symbol). */
|
|
227
228
|
marketId?: string
|
|
228
229
|
/** Maximum items returned; provider defaults and caps apply. */
|
|
@@ -231,17 +232,6 @@ export interface ProviderGetOrdersParams {
|
|
|
231
232
|
cursor?: string
|
|
232
233
|
}
|
|
233
234
|
|
|
234
|
-
/**
|
|
235
|
-
* Read params for {@link PerpsProvider.getRunningTwaps}.
|
|
236
|
-
*
|
|
237
|
-
* @public
|
|
238
|
-
*/
|
|
239
|
-
export interface ProviderGetRunningTwapsParams {
|
|
240
|
-
address: Address
|
|
241
|
-
/** Optional opaque `Market.id` filter (not a display symbol). */
|
|
242
|
-
marketId?: string
|
|
243
|
-
}
|
|
244
|
-
|
|
245
235
|
/**
|
|
246
236
|
* Read params for {@link PerpsProvider.getOrder}.
|
|
247
237
|
*
|
|
@@ -457,15 +447,6 @@ export interface PerpsProviderPlugin {
|
|
|
457
447
|
options?: SDKRequestOptions
|
|
458
448
|
): Promise<OrdersResponse>
|
|
459
449
|
|
|
460
|
-
/**
|
|
461
|
-
* Fetch the account's currently running TWAP parent orders directly from the
|
|
462
|
-
* venue. Child slice orders are excluded.
|
|
463
|
-
*/
|
|
464
|
-
getRunningTwaps?(
|
|
465
|
-
params: ProviderGetRunningTwapsParams,
|
|
466
|
-
options?: SDKRequestOptions
|
|
467
|
-
): Promise<TwapOrder[]>
|
|
468
|
-
|
|
469
450
|
getOrder(
|
|
470
451
|
params: ProviderGetOrderParams,
|
|
471
452
|
options?: SDKRequestOptions
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { OpenOrder } from '@lifi/perps-types'
|
|
1
|
+
import type {
|
|
2
|
+
Order,
|
|
3
|
+
RegularOrder,
|
|
4
|
+
TriggerOrder,
|
|
5
|
+
TwapOrder,
|
|
6
|
+
} from '@lifi/perps-types'
|
|
10
7
|
import {
|
|
11
8
|
FillClassification,
|
|
12
9
|
OrderSide,
|
|
13
10
|
OrderStatus,
|
|
14
11
|
OrderType,
|
|
12
|
+
TriggerCondition,
|
|
15
13
|
} from '@lifi/perps-types'
|
|
16
14
|
import { stringToFloat } from './parse.js'
|
|
17
15
|
|
|
@@ -36,7 +34,7 @@ const SL_TYPES = new Set<OrderType>([
|
|
|
36
34
|
* Check if an open order is a Take Profit trigger order.
|
|
37
35
|
* @public
|
|
38
36
|
*/
|
|
39
|
-
export function isTakeProfitOrder(order: Pick<
|
|
37
|
+
export function isTakeProfitOrder(order: Pick<Order, 'type'>): boolean {
|
|
40
38
|
return TP_TYPES.has(order.type)
|
|
41
39
|
}
|
|
42
40
|
|
|
@@ -44,7 +42,7 @@ export function isTakeProfitOrder(order: Pick<OpenOrder, 'type'>): boolean {
|
|
|
44
42
|
* Check if an open order is a Stop Loss trigger order.
|
|
45
43
|
* @public
|
|
46
44
|
*/
|
|
47
|
-
export function isStopLossOrder(order: Pick<
|
|
45
|
+
export function isStopLossOrder(order: Pick<Order, 'type'>): boolean {
|
|
48
46
|
return SL_TYPES.has(order.type)
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -52,17 +50,37 @@ export function isStopLossOrder(order: Pick<OpenOrder, 'type'>): boolean {
|
|
|
52
50
|
* Check if an open order is a TP or SL trigger order.
|
|
53
51
|
* @public
|
|
54
52
|
*/
|
|
55
|
-
export function isTpSlOrder(order: Pick<
|
|
53
|
+
export function isTpSlOrder(order: Pick<Order, 'type'>): boolean {
|
|
56
54
|
return TP_TYPES.has(order.type) || SL_TYPES.has(order.type)
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
/** Narrow an order to a price-activated order. */
|
|
58
|
+
export function isTriggerOrder(order: Order): order is TriggerOrder {
|
|
59
|
+
return isTpSlOrder(order)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Narrow an order to a market or limit order. */
|
|
63
|
+
export function isRegularOrder(order: Order): order is RegularOrder {
|
|
64
|
+
return order.type === OrderType.MARKET || order.type === OrderType.LIMIT
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Narrow an order to a time-weighted execution parent. */
|
|
68
|
+
export function isTwapOrder(order: Order): order is TwapOrder {
|
|
69
|
+
return order.type === OrderType.TWAP
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Derive the trigger price relation from the trigger type and execution side. */
|
|
73
|
+
export function triggerConditionFor(
|
|
74
|
+
type: TriggerOrder['type'],
|
|
75
|
+
side: OrderSide
|
|
76
|
+
): TriggerCondition {
|
|
77
|
+
const takeProfit = TP_TYPES.has(type)
|
|
78
|
+
return takeProfit === (side === OrderSide.SELL)
|
|
79
|
+
? TriggerCondition.ABOVE
|
|
80
|
+
: TriggerCondition.BELOW
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Lifecycle statuses included in order reads by default. */
|
|
66
84
|
export const ACTIVE_ORDER_STATUSES: ReadonlySet<OrderStatus> = new Set([
|
|
67
85
|
OrderStatus.OPEN,
|
|
68
86
|
OrderStatus.PENDING,
|
package/src/utils/orderMath.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type OpenOrder,
|
|
3
2
|
OrderSide,
|
|
3
|
+
OrderStatus,
|
|
4
4
|
type Position,
|
|
5
5
|
PositionSide,
|
|
6
|
+
type RegularOrder,
|
|
6
7
|
type TriggerOrder,
|
|
7
8
|
} from '@lifi/perps-types'
|
|
9
|
+
import { isActiveOrderStatus } from './orderClassification.js'
|
|
8
10
|
import { realizedPnlOnClose } from './positionMath.js'
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -55,10 +57,10 @@ export function resolveCloseSize(
|
|
|
55
57
|
* @public
|
|
56
58
|
*/
|
|
57
59
|
export function expectedRealizedPnlForOpenOrder(
|
|
58
|
-
order:
|
|
60
|
+
order: RegularOrder,
|
|
59
61
|
position: Position | undefined
|
|
60
62
|
): number | null {
|
|
61
|
-
if (!position) {
|
|
63
|
+
if (!position || !isActiveOrderStatus(order.status)) {
|
|
62
64
|
return null
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -70,7 +72,7 @@ export function expectedRealizedPnlForOpenOrder(
|
|
|
70
72
|
return null
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
const limitPrice = Number.parseFloat(order.price)
|
|
75
|
+
const limitPrice = Number.parseFloat(order.price ?? '')
|
|
74
76
|
const entryPrice = Number.parseFloat(position.entryPrice)
|
|
75
77
|
const orderSize = Math.abs(Number.parseFloat(order.remainingSize))
|
|
76
78
|
const positionSize = Math.abs(Number.parseFloat(position.size))
|
|
@@ -100,29 +102,29 @@ export function expectedRealizedPnlForOpenOrder(
|
|
|
100
102
|
})
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
/**
|
|
104
|
-
* Expected rPnL for a TP/SL trigger order against a matching position.
|
|
105
|
-
*
|
|
106
|
-
* A trigger order is by construction a closing leg — its direction is the
|
|
107
|
-
* opposite of the position's. With no matching position there is nothing to
|
|
108
|
-
* close, so rPnL is `null`. The trigger price (always present on the SDK
|
|
109
|
-
* `TriggerOrder` shape) is used as the rPnL price; the optional `limitPrice`
|
|
110
|
-
* for STOP_LIMIT / TAKE_PROFIT_LIMIT is the post-trigger limit, not the rPnL
|
|
111
|
-
* price.
|
|
112
|
-
* @public
|
|
113
|
-
*/
|
|
105
|
+
/** Project the unfilled closing quantity of an active trigger at its trigger price. */
|
|
114
106
|
export function expectedRealizedPnlForTriggerOrder(
|
|
115
107
|
order: TriggerOrder,
|
|
116
108
|
position: Position | undefined
|
|
117
109
|
): number | null {
|
|
118
|
-
if (
|
|
110
|
+
if (
|
|
111
|
+
!position ||
|
|
112
|
+
!isActiveOrderStatus(order.status) ||
|
|
113
|
+
order.status === OrderStatus.PENDING
|
|
114
|
+
) {
|
|
119
115
|
return null
|
|
120
116
|
}
|
|
121
117
|
|
|
122
118
|
const isLong = position.side === PositionSide.LONG
|
|
119
|
+
if (
|
|
120
|
+
(isLong && order.side !== OrderSide.SELL) ||
|
|
121
|
+
(!isLong && order.side !== OrderSide.BUY)
|
|
122
|
+
) {
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
123
125
|
const triggerPrice = Number.parseFloat(order.triggerPrice)
|
|
124
126
|
const entryPrice = Number.parseFloat(position.entryPrice)
|
|
125
|
-
const orderSize = Math.abs(Number.parseFloat(order.
|
|
127
|
+
const orderSize = Math.abs(Number.parseFloat(order.remainingSize))
|
|
126
128
|
const positionSize = Math.abs(Number.parseFloat(position.size))
|
|
127
129
|
if (
|
|
128
130
|
!Number.isFinite(triggerPrice) ||
|
|
@@ -133,6 +135,12 @@ export function expectedRealizedPnlForTriggerOrder(
|
|
|
133
135
|
) {
|
|
134
136
|
return null
|
|
135
137
|
}
|
|
138
|
+
if (
|
|
139
|
+
orderSize === 0 &&
|
|
140
|
+
(Number.parseFloat(order.originalSize) !== 0 || !order.reduceOnly)
|
|
141
|
+
) {
|
|
142
|
+
return null
|
|
143
|
+
}
|
|
136
144
|
|
|
137
145
|
const closeSize = resolveCloseSize(orderSize, positionSize)
|
|
138
146
|
return realizedPnlOnClose({
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The number of keys one warner remembers. Venue wire data supplies the keys,
|
|
3
|
+
* so the memory must not grow for as long as the process runs.
|
|
4
|
+
*/
|
|
5
|
+
const KEY_MEMORY_LIMIT = 256
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Build a warner that writes each distinct key once. The warner forgets the
|
|
9
|
+
* oldest key when its memory is full, so a key it saw long ago can warn a
|
|
10
|
+
* second time.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export const createWarnOnce = (): ((key: string, message: string) => void) => {
|
|
15
|
+
const seen = new Set<string>()
|
|
16
|
+
return (key, message) => {
|
|
17
|
+
if (seen.has(key)) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
if (seen.size >= KEY_MEMORY_LIMIT) {
|
|
21
|
+
const oldest = seen.values().next().value
|
|
22
|
+
if (oldest !== undefined) {
|
|
23
|
+
seen.delete(oldest)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
seen.add(key)
|
|
27
|
+
console.warn(message)
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/version.ts
CHANGED