@lifi/perps-sdk-provider-ondo 9.0.0 → 11.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 +29 -0
- package/dist/cjs/OndoProvider.d.ts.map +1 -1
- package/dist/cjs/OndoProvider.js +41 -40
- package/dist/cjs/OndoProvider.js.map +1 -1
- package/dist/cjs/types/wire.d.ts +35 -0
- package/dist/cjs/types/wire.d.ts.map +1 -1
- package/dist/cjs/utils/depositAddress.d.ts.map +1 -1
- package/dist/cjs/utils/depositAddress.js +3 -0
- package/dist/cjs/utils/depositAddress.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +3 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapActivity.d.ts +5 -3
- package/dist/cjs/utils/mapActivity.d.ts.map +1 -1
- package/dist/cjs/utils/mapActivity.js +72 -13
- package/dist/cjs/utils/mapActivity.js.map +1 -1
- package/dist/cjs/utils/mapFill.d.ts.map +1 -1
- package/dist/cjs/utils/mapFill.js +4 -1
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +4 -2
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/esm/OndoProvider.d.ts.map +1 -1
- package/dist/esm/OndoProvider.js +60 -42
- package/dist/esm/OndoProvider.js.map +1 -1
- package/dist/esm/types/wire.d.ts +53 -0
- package/dist/esm/types/wire.d.ts.map +1 -1
- package/dist/esm/utils/depositAddress.d.ts +3 -2
- package/dist/esm/utils/depositAddress.d.ts.map +1 -1
- package/dist/esm/utils/depositAddress.js +6 -2
- package/dist/esm/utils/depositAddress.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapActivity.d.ts +30 -6
- package/dist/esm/utils/mapActivity.d.ts.map +1 -1
- package/dist/esm/utils/mapActivity.js +98 -14
- package/dist/esm/utils/mapActivity.js.map +1 -1
- package/dist/esm/utils/mapFill.d.ts.map +1 -1
- package/dist/esm/utils/mapFill.js +5 -1
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +5 -1
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +10 -3
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/types/OndoProvider.d.ts.map +1 -1
- package/dist/types/types/wire.d.ts +53 -0
- package/dist/types/types/wire.d.ts.map +1 -1
- package/dist/types/utils/depositAddress.d.ts +3 -2
- package/dist/types/utils/depositAddress.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapActivity.d.ts +30 -6
- package/dist/types/utils/mapActivity.d.ts.map +1 -1
- package/dist/types/utils/mapFill.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +5 -1
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/OndoProvider.ts +103 -76
- package/src/types/wire.ts +63 -0
- package/src/utils/depositAddress.ts +6 -2
- package/src/utils/index.ts +6 -1
- package/src/utils/mapActivity.ts +112 -15
- package/src/utils/mapFill.ts +5 -1
- package/src/utils/mapOrder.ts +12 -3
package/src/OndoProvider.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type ProviderGetPositionsParams,
|
|
18
18
|
type ProviderGetQuoteParams,
|
|
19
19
|
type ProviderGetRunningTwapsParams,
|
|
20
|
+
paginateActivity,
|
|
20
21
|
resolveQuote,
|
|
21
22
|
resolveRetryPolicy,
|
|
22
23
|
type SDKRequestOptions,
|
|
@@ -34,7 +35,10 @@ import type {
|
|
|
34
35
|
ActionStep,
|
|
35
36
|
ActivitiesResponse,
|
|
36
37
|
ActivityItem,
|
|
38
|
+
Fill,
|
|
37
39
|
FillsResponse,
|
|
40
|
+
FundingActivity,
|
|
41
|
+
LiquidationActivity,
|
|
38
42
|
MarketDisplay,
|
|
39
43
|
OndoAccountConfig,
|
|
40
44
|
Order,
|
|
@@ -47,6 +51,7 @@ import type {
|
|
|
47
51
|
SignedActionStep,
|
|
48
52
|
SigningMethod,
|
|
49
53
|
TwapOrder,
|
|
54
|
+
WithdrawalActivity,
|
|
50
55
|
} from '@lifi/perps-types'
|
|
51
56
|
import { ActionType, ActivityType, PerpsErrorCode } from '@lifi/perps-types'
|
|
52
57
|
import type { Address } from 'viem'
|
|
@@ -73,11 +78,12 @@ import type {
|
|
|
73
78
|
OndoOrder,
|
|
74
79
|
OndoPosition,
|
|
75
80
|
OndoTwapOrder,
|
|
81
|
+
OndoWalletDeposit,
|
|
82
|
+
OndoWalletWithdrawal,
|
|
76
83
|
} from './types/wire.js'
|
|
77
84
|
import {
|
|
78
85
|
decodeActivityCursor,
|
|
79
86
|
encodeActivityCursor,
|
|
80
|
-
type OndoActivityCursor,
|
|
81
87
|
} from './utils/activityCursor.js'
|
|
82
88
|
import {
|
|
83
89
|
type ApiParams,
|
|
@@ -92,11 +98,13 @@ import {
|
|
|
92
98
|
formatOrderPrice,
|
|
93
99
|
formatOrderSize,
|
|
94
100
|
listOndoDepositAddress,
|
|
101
|
+
mapDepositActivity,
|
|
95
102
|
mapFill,
|
|
96
103
|
mapFundingActivity,
|
|
97
104
|
mapLiquidationActivity,
|
|
98
105
|
mapOpenPositions,
|
|
99
106
|
mapOrderDetail,
|
|
107
|
+
mapWithdrawalActivity,
|
|
100
108
|
positionMarginConstraints,
|
|
101
109
|
} from './utils/index.js'
|
|
102
110
|
import { mapRunningTwap } from './utils/mapTwap.js'
|
|
@@ -173,6 +181,13 @@ export const ondoProvider = (
|
|
|
173
181
|
|
|
174
182
|
const requireMarketDisplay = (marketId: string): MarketDisplay =>
|
|
175
183
|
toMarketDisplay(marketRegistry().require(marketId))
|
|
184
|
+
// The droppable-row counterpart of `requireMarketDisplay`, for the history
|
|
185
|
+
// surfaces where an id the backend market list does not hold must cost only
|
|
186
|
+
// its own row. The registry warns once per unresolved id.
|
|
187
|
+
const marketDisplay = (marketId: string): MarketDisplay | undefined => {
|
|
188
|
+
const market = marketRegistry().get(marketId)
|
|
189
|
+
return market === undefined ? undefined : toMarketDisplay(market)
|
|
190
|
+
}
|
|
176
191
|
const requirePerpsMarketDisplay = (marketId: string): PerpsMarketDisplay =>
|
|
177
192
|
toPerpsMarketDisplay(marketRegistry().require(marketId))
|
|
178
193
|
|
|
@@ -258,7 +273,7 @@ export const ondoProvider = (
|
|
|
258
273
|
client.get<OndoBalanceSummary>('/v1/perps/balance', {
|
|
259
274
|
authToken: token.token,
|
|
260
275
|
}),
|
|
261
|
-
client.get<OndoPosition[]>('/v1/perps/positions', {
|
|
276
|
+
client.get<OndoPosition[] | null>('/v1/perps/positions', {
|
|
262
277
|
authToken: token.token,
|
|
263
278
|
}),
|
|
264
279
|
client.get<OndoAccountReferral | null>('/v1/account/referral', {
|
|
@@ -286,7 +301,7 @@ export const ondoProvider = (
|
|
|
286
301
|
}
|
|
287
302
|
|
|
288
303
|
const positions: Position[] = mapOpenPositions(
|
|
289
|
-
rawPositions,
|
|
304
|
+
rawPositions ?? [],
|
|
290
305
|
requirePerpsMarketDisplay
|
|
291
306
|
)
|
|
292
307
|
|
|
@@ -385,14 +400,14 @@ export const ondoProvider = (
|
|
|
385
400
|
async (token) => {
|
|
386
401
|
const client = apiClient(opts)
|
|
387
402
|
const [rawPositions] = await Promise.all([
|
|
388
|
-
client.get<OndoPosition[]>('/v1/perps/positions', {
|
|
403
|
+
client.get<OndoPosition[] | null>('/v1/perps/positions', {
|
|
389
404
|
authToken: token.token,
|
|
390
405
|
}),
|
|
391
406
|
marketRegistry().sync(),
|
|
392
407
|
])
|
|
393
408
|
|
|
394
409
|
let positions: Position[] = mapOpenPositions(
|
|
395
|
-
rawPositions,
|
|
410
|
+
rawPositions ?? [],
|
|
396
411
|
requirePerpsMarketDisplay
|
|
397
412
|
)
|
|
398
413
|
if (params.marketId !== undefined) {
|
|
@@ -443,13 +458,9 @@ export const ondoProvider = (
|
|
|
443
458
|
marketRegistry().sync(),
|
|
444
459
|
])
|
|
445
460
|
|
|
446
|
-
const registry = marketRegistry()
|
|
447
461
|
const { openOrders, triggerOrders } = classifyAndMapOrders(
|
|
448
462
|
page.result,
|
|
449
|
-
|
|
450
|
-
const market = registry.get(marketId)
|
|
451
|
-
return market === undefined ? undefined : toMarketDisplay(market)
|
|
452
|
-
}
|
|
463
|
+
marketDisplay
|
|
453
464
|
)
|
|
454
465
|
|
|
455
466
|
const nextCursor = page.pageInfo?.nextCursor
|
|
@@ -547,9 +558,10 @@ export const ondoProvider = (
|
|
|
547
558
|
marketRegistry().sync(),
|
|
548
559
|
])
|
|
549
560
|
|
|
550
|
-
const items = page.result.
|
|
551
|
-
|
|
552
|
-
|
|
561
|
+
const items = page.result.flatMap((fill): Fill[] => {
|
|
562
|
+
const market = marketDisplay(fill.market)
|
|
563
|
+
return market === undefined ? [] : [mapFill(fill, market)]
|
|
564
|
+
})
|
|
553
565
|
|
|
554
566
|
const nextCursor = page.pageInfo?.nextCursor
|
|
555
567
|
return {
|
|
@@ -580,6 +592,9 @@ export const ondoProvider = (
|
|
|
580
592
|
const inputCursor = decodeActivityCursor(params.cursor)
|
|
581
593
|
const client = apiClient(opts)
|
|
582
594
|
|
|
595
|
+
// Ondo publishes no account-to-account transfer history. Its
|
|
596
|
+
// transfer surface moves value between the main and margin wallets
|
|
597
|
+
// of one account, which `TransferActivity` excludes.
|
|
583
598
|
const wantsType = (t: ActivityType): boolean =>
|
|
584
599
|
params.type === undefined || params.type.includes(t)
|
|
585
600
|
const shouldFetch = (
|
|
@@ -595,6 +610,13 @@ export const ondoProvider = (
|
|
|
595
610
|
const v = inputCursor[key]
|
|
596
611
|
return typeof v === 'string' && v.length > 0
|
|
597
612
|
}
|
|
613
|
+
// `/v1/wallet/deposits` and `/v1/wallet/withdrawals` accept no
|
|
614
|
+
// cursor and return the whole history in one response, so each is
|
|
615
|
+
// fetched on the first page only. Its tail rides the cursor's
|
|
616
|
+
// `overflow` list, which is what keeps a later page from either
|
|
617
|
+
// re-fetching the list or losing the rows past the limit.
|
|
618
|
+
const shouldFetchOnce = (t: ActivityType): boolean =>
|
|
619
|
+
wantsType(t) && inputCursor === undefined
|
|
598
620
|
const cursorParams = (
|
|
599
621
|
key: 'fundings' | 'liquidations'
|
|
600
622
|
): ApiParams => {
|
|
@@ -606,77 +628,82 @@ export const ondoProvider = (
|
|
|
606
628
|
pageInfo: undefined,
|
|
607
629
|
})
|
|
608
630
|
|
|
609
|
-
const [fundings, liquidations] =
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
631
|
+
const [fundings, liquidations, deposits, withdrawals] =
|
|
632
|
+
await Promise.all([
|
|
633
|
+
shouldFetch(ActivityType.FUNDING, 'fundings')
|
|
634
|
+
? client.getPage<OndoFundingFeeTransfer>(
|
|
635
|
+
'/v1/perps/funding_fees',
|
|
636
|
+
{
|
|
637
|
+
params: cursorParams('fundings'),
|
|
638
|
+
authToken: token.token,
|
|
639
|
+
}
|
|
640
|
+
)
|
|
641
|
+
: Promise.resolve(emptyPage<OndoFundingFeeTransfer>()),
|
|
642
|
+
shouldFetch(ActivityType.LIQUIDATION, 'liquidations')
|
|
643
|
+
? client.getPage<OndoLiquidationEvent>(
|
|
644
|
+
'/v1/perps/liquidation_history',
|
|
645
|
+
{
|
|
646
|
+
params: cursorParams('liquidations'),
|
|
647
|
+
authToken: token.token,
|
|
648
|
+
}
|
|
649
|
+
)
|
|
650
|
+
: Promise.resolve(emptyPage<OndoLiquidationEvent>()),
|
|
651
|
+
shouldFetchOnce(ActivityType.DEPOSIT)
|
|
652
|
+
? client.get<OndoWalletDeposit[] | null>(
|
|
653
|
+
'/v1/wallet/deposits',
|
|
654
|
+
{
|
|
655
|
+
authToken: token.token,
|
|
656
|
+
}
|
|
657
|
+
)
|
|
658
|
+
: Promise.resolve(null),
|
|
659
|
+
shouldFetchOnce(ActivityType.WITHDRAWAL)
|
|
660
|
+
? client.get<OndoWalletWithdrawal[] | null>(
|
|
661
|
+
'/v1/wallet/withdrawals',
|
|
662
|
+
{ authToken: token.token }
|
|
663
|
+
)
|
|
664
|
+
: Promise.resolve(null),
|
|
665
|
+
// Only the funding and liquidation rows name a market. A ledger
|
|
666
|
+
// request alone must not pull the market list.
|
|
667
|
+
wantsType(ActivityType.FUNDING) ||
|
|
668
|
+
wantsType(ActivityType.LIQUIDATION)
|
|
669
|
+
? marketRegistry().sync()
|
|
670
|
+
: Promise.resolve(),
|
|
671
|
+
])
|
|
630
672
|
|
|
631
673
|
const items: ActivityItem[] = [
|
|
632
|
-
...fundings.result.
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
674
|
+
...fundings.result.flatMap((f): FundingActivity[] => {
|
|
675
|
+
const market = marketDisplay(f.market)
|
|
676
|
+
return market === undefined ? [] : [mapFundingActivity(f, market)]
|
|
677
|
+
}),
|
|
678
|
+
// A liquidation event that names no position is dropped: the
|
|
679
|
+
// public contract guarantees a non-empty `liquidatedPositions`.
|
|
680
|
+
...liquidations.result
|
|
681
|
+
.map((l) => mapLiquidationActivity(l, marketDisplay))
|
|
682
|
+
.filter((a): a is LiquidationActivity => a !== null),
|
|
683
|
+
...(deposits ?? []).map(mapDepositActivity),
|
|
684
|
+
// A withdrawal Ondo reports as failed or cancelled moved no value,
|
|
685
|
+
// and `WithdrawalActivity` carries no status to say so.
|
|
686
|
+
...(withdrawals ?? [])
|
|
687
|
+
.map(mapWithdrawalActivity)
|
|
688
|
+
.filter((a): a is WithdrawalActivity => a !== null),
|
|
638
689
|
]
|
|
639
690
|
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
return true
|
|
651
|
-
})
|
|
652
|
-
|
|
653
|
-
filtered.sort(
|
|
654
|
-
(a, b) =>
|
|
655
|
-
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
691
|
+
const page = paginateActivity(
|
|
692
|
+
items,
|
|
693
|
+
inputCursor?.overflow ?? [],
|
|
694
|
+
params,
|
|
695
|
+
(overflowTail) =>
|
|
696
|
+
encodeActivityCursor({
|
|
697
|
+
fundings: fundings.pageInfo?.nextCursor,
|
|
698
|
+
liquidations: liquidations.pageInfo?.nextCursor,
|
|
699
|
+
overflow: overflowTail,
|
|
700
|
+
})
|
|
656
701
|
)
|
|
657
702
|
|
|
658
|
-
const limit = params.limit ?? filtered.length
|
|
659
|
-
const emitted = filtered.slice(0, limit)
|
|
660
|
-
const overflow = filtered.slice(limit)
|
|
661
|
-
|
|
662
|
-
const nextCursorEnvelope: OndoActivityCursor = {
|
|
663
|
-
fundings: fundings.pageInfo?.nextCursor,
|
|
664
|
-
liquidations: liquidations.pageInfo?.nextCursor,
|
|
665
|
-
overflow,
|
|
666
|
-
}
|
|
667
|
-
const responseCursor = encodeActivityCursor(nextCursorEnvelope)
|
|
668
|
-
const hasMore = responseCursor !== undefined
|
|
669
|
-
|
|
670
703
|
return {
|
|
671
704
|
provider: ONDO_PROVIDER_KEY,
|
|
672
|
-
items:
|
|
673
|
-
pagination:
|
|
674
|
-
limit,
|
|
675
|
-
hasMore,
|
|
676
|
-
...(responseCursor === undefined
|
|
677
|
-
? {}
|
|
678
|
-
: { cursor: responseCursor }),
|
|
679
|
-
},
|
|
705
|
+
items: page.items,
|
|
706
|
+
pagination: page.pagination,
|
|
680
707
|
}
|
|
681
708
|
}
|
|
682
709
|
)
|
package/src/types/wire.ts
CHANGED
|
@@ -274,3 +274,66 @@ export interface OndoAccountInfo {
|
|
|
274
274
|
privacyUnixSecs: number
|
|
275
275
|
marketingConsent: string
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
/** @public */
|
|
279
|
+
export type OndoDepositStatus = 'pending' | 'confirmed'
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Mirrors Ondo's `WalletDeposit` (the `GET /v1/wallet/deposits` result).
|
|
283
|
+
* Carries no id of its own — Ondo addresses a single deposit by `txid`.
|
|
284
|
+
* @public
|
|
285
|
+
*/
|
|
286
|
+
export interface OndoWalletDeposit {
|
|
287
|
+
coin: string
|
|
288
|
+
size: string
|
|
289
|
+
status: OndoDepositStatus
|
|
290
|
+
txid: string
|
|
291
|
+
fromAddress: string
|
|
292
|
+
time: string
|
|
293
|
+
chainId: string
|
|
294
|
+
usdValue: string
|
|
295
|
+
currentConfirmations?: number
|
|
296
|
+
requiredConfirmations?: number
|
|
297
|
+
accountId?: string
|
|
298
|
+
/** Disambiguates two deposits carried by one transaction. */
|
|
299
|
+
logIndex?: string
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** @public */
|
|
303
|
+
export type OndoWithdrawalStatus =
|
|
304
|
+
| 'complete'
|
|
305
|
+
| 'failure'
|
|
306
|
+
| 'pending'
|
|
307
|
+
| 'cancelled'
|
|
308
|
+
| 'unknown'
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Mirrors Ondo's `WalletWithdrawal` (the `GET /v1/wallet/withdrawals` result).
|
|
312
|
+
* @public
|
|
313
|
+
*/
|
|
314
|
+
export interface OndoWalletWithdrawal {
|
|
315
|
+
coin: string
|
|
316
|
+
size: string
|
|
317
|
+
status: OndoWithdrawalStatus
|
|
318
|
+
address: string
|
|
319
|
+
withdrawal_id: string
|
|
320
|
+
txid: string
|
|
321
|
+
customer_withdrawal_id: string
|
|
322
|
+
time: string
|
|
323
|
+
chainId: string
|
|
324
|
+
accountId?: string
|
|
325
|
+
usdValue?: string
|
|
326
|
+
/** Fee in USD, not in the withdrawn asset. */
|
|
327
|
+
usdFee?: string
|
|
328
|
+
from?: OndoAccountWalletKey
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* One side of an Ondo value movement: an account id plus which of that
|
|
333
|
+
* account's two wallets held the value.
|
|
334
|
+
* @public
|
|
335
|
+
*/
|
|
336
|
+
export interface OndoAccountWalletKey {
|
|
337
|
+
id: string
|
|
338
|
+
wallet: 'main' | 'margin'
|
|
339
|
+
}
|
|
@@ -30,6 +30,9 @@ const malformed = (message: string): OndoApiError =>
|
|
|
30
30
|
new OndoApiError(`Ondo deposit-address response is malformed: ${message}`)
|
|
31
31
|
|
|
32
32
|
const entriesFromResult = (result: unknown): unknown[] => {
|
|
33
|
+
if (result === null) {
|
|
34
|
+
return []
|
|
35
|
+
}
|
|
33
36
|
if (Array.isArray(result)) {
|
|
34
37
|
return result
|
|
35
38
|
}
|
|
@@ -45,8 +48,9 @@ const entriesFromResult = (result: unknown): unknown[] => {
|
|
|
45
48
|
|
|
46
49
|
/**
|
|
47
50
|
* Extract the canonical Ethereum USDC address from Ondo's list response.
|
|
48
|
-
*
|
|
49
|
-
* errors so an API/schema failure cannot be mistaken for
|
|
51
|
+
* A `null` result and an empty list are both valid, unsatisfied setup states;
|
|
52
|
+
* malformed records are errors so an API/schema failure cannot be mistaken for
|
|
53
|
+
* an absent address.
|
|
50
54
|
*/
|
|
51
55
|
export const parseOndoDepositAddress = (result: unknown): Address | null => {
|
|
52
56
|
const entries = entriesFromResult(result)
|
package/src/utils/index.ts
CHANGED
|
@@ -25,7 +25,12 @@ export {
|
|
|
25
25
|
parseOndoDepositAddress,
|
|
26
26
|
} from './depositAddress.js'
|
|
27
27
|
export { estimateLiquidationPrice } from './liquidation.js'
|
|
28
|
-
export {
|
|
28
|
+
export {
|
|
29
|
+
mapDepositActivity,
|
|
30
|
+
mapFundingActivity,
|
|
31
|
+
mapLiquidationActivity,
|
|
32
|
+
mapWithdrawalActivity,
|
|
33
|
+
} from './mapActivity.js'
|
|
29
34
|
export { mapFill } from './mapFill.js'
|
|
30
35
|
export {
|
|
31
36
|
classifyAndMapOrders,
|
package/src/utils/mapActivity.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
DepositActivity,
|
|
2
3
|
FundingActivity,
|
|
3
4
|
LiquidationActivity,
|
|
4
5
|
MarketDisplay,
|
|
6
|
+
WithdrawalActivity,
|
|
5
7
|
} from '@lifi/perps-types'
|
|
6
8
|
import { ActivityType } from '@lifi/perps-types'
|
|
7
9
|
import { ONDO_PROVIDER_KEY } from '../constants.js'
|
|
8
10
|
import type {
|
|
9
11
|
OndoFundingFeeTransfer,
|
|
10
12
|
OndoLiquidationEvent,
|
|
13
|
+
OndoWalletDeposit,
|
|
14
|
+
OndoWalletWithdrawal,
|
|
11
15
|
} from '../types/wire.js'
|
|
12
16
|
|
|
13
17
|
/**
|
|
@@ -37,25 +41,118 @@ export const mapFundingActivity = (
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
/**
|
|
40
|
-
* Map an Ondo liquidation event to a {@link LiquidationActivity}
|
|
41
|
-
*
|
|
42
|
-
*
|
|
44
|
+
* Map an Ondo liquidation event to a {@link LiquidationActivity}, or `null`
|
|
45
|
+
* when the event names no triggering position. Ondo margin accounts are
|
|
46
|
+
* cross-only, so `leverageType` is always `'cross'`. Ondo reports no account
|
|
47
|
+
* value at liquidation time, so `accountValue` stays absent. One Ondo event
|
|
48
|
+
* carries the whole cross-margin cascade in `triggeringPositions`, so every
|
|
49
|
+
* resolvable liquidated market and size reaches `liquidatedPositions`.
|
|
43
50
|
*
|
|
51
|
+
* @param resolveMarket - Market identity for an Ondo market id, or `undefined`
|
|
52
|
+
* when the backend market list does not hold it. A triggering position the
|
|
53
|
+
* resolver cannot identify is dropped.
|
|
44
54
|
* @public
|
|
45
55
|
*/
|
|
46
56
|
export const mapLiquidationActivity = (
|
|
47
57
|
event: OndoLiquidationEvent,
|
|
48
|
-
resolveMarket: (market: string) => MarketDisplay
|
|
49
|
-
): LiquidationActivity =>
|
|
50
|
-
|
|
58
|
+
resolveMarket: (market: string) => MarketDisplay | undefined
|
|
59
|
+
): LiquidationActivity | null => {
|
|
60
|
+
const resolvedPositions = (event.triggeringPositions ?? []).flatMap((p) => {
|
|
61
|
+
const market = resolveMarket(p.market)
|
|
62
|
+
return market === undefined ? [] : [{ market, size: p.netQuantity }]
|
|
63
|
+
})
|
|
64
|
+
const [firstPosition, ...restPositions] = resolvedPositions
|
|
65
|
+
if (firstPosition === undefined) {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
id: event.id,
|
|
70
|
+
provider: ONDO_PROVIDER_KEY,
|
|
71
|
+
timestamp: new Date(event.time).toISOString(),
|
|
72
|
+
type: ActivityType.LIQUIDATION,
|
|
73
|
+
...(event.filledQuoteSize === undefined
|
|
74
|
+
? {}
|
|
75
|
+
: { liquidatedNotionalPosition: event.filledQuoteSize }),
|
|
76
|
+
leverageType: 'cross',
|
|
77
|
+
liquidatedPositions: [firstPosition, ...restPositions],
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Ondo reports no transaction id on a deposit it has not yet matched to a
|
|
82
|
+
// chain transaction, so two such deposits would share the bare `deposit:`
|
|
83
|
+
// key. Fall back to the fields the venue does report.
|
|
84
|
+
const depositId = (deposit: OndoWalletDeposit): string => {
|
|
85
|
+
if (deposit.txid === '') {
|
|
86
|
+
return `deposit:${deposit.time}:${deposit.coin}:${deposit.size}`
|
|
87
|
+
}
|
|
88
|
+
return deposit.logIndex === undefined
|
|
89
|
+
? `deposit:${deposit.txid}`
|
|
90
|
+
: `deposit:${deposit.txid}:${deposit.logIndex}`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Map an Ondo wallet deposit to a {@link DepositActivity}. Ondo carries no
|
|
95
|
+
* deposit id on the wire and addresses a single deposit by transaction id, so
|
|
96
|
+
* the id is `deposit:<txid>`, suffixed with `logIndex` when one transaction
|
|
97
|
+
* carried several deposits. `coin` is already a display symbol, so it is the
|
|
98
|
+
* normalized asset identity.
|
|
99
|
+
*
|
|
100
|
+
* @public
|
|
101
|
+
*/
|
|
102
|
+
export const mapDepositActivity = (
|
|
103
|
+
deposit: OndoWalletDeposit
|
|
104
|
+
): DepositActivity => ({
|
|
105
|
+
id: depositId(deposit),
|
|
51
106
|
provider: ONDO_PROVIDER_KEY,
|
|
52
|
-
timestamp: new Date(
|
|
53
|
-
type: ActivityType.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
size: p.netQuantity,
|
|
60
|
-
})),
|
|
107
|
+
timestamp: new Date(deposit.time).toISOString(),
|
|
108
|
+
type: ActivityType.DEPOSIT,
|
|
109
|
+
asset: deposit.coin,
|
|
110
|
+
amount: deposit.size,
|
|
111
|
+
...(deposit.txid === ''
|
|
112
|
+
? {}
|
|
113
|
+
: { explorerLink: `https://scan.li.fi/tx/${deposit.txid}` }),
|
|
61
114
|
})
|
|
115
|
+
|
|
116
|
+
const SETTLING_WITHDRAWAL_STATUSES = new Set<string>([
|
|
117
|
+
'complete',
|
|
118
|
+
'pending',
|
|
119
|
+
'unknown',
|
|
120
|
+
])
|
|
121
|
+
|
|
122
|
+
/** Ondo denominates a withdrawal fee in USD, whatever asset it withdraws. */
|
|
123
|
+
const ONDO_WITHDRAWAL_FEE_SYMBOL = 'USD'
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Map an Ondo wallet withdrawal to a {@link WithdrawalActivity}, or `null`
|
|
127
|
+
* when the venue reports a status under which no value left the account. Ondo
|
|
128
|
+
* charges the fee in USD, so `fee.asset` is `USD` and not the withdrawn asset.
|
|
129
|
+
*
|
|
130
|
+
* @public
|
|
131
|
+
*/
|
|
132
|
+
export const mapWithdrawalActivity = (
|
|
133
|
+
withdrawal: OndoWalletWithdrawal
|
|
134
|
+
): WithdrawalActivity | null => {
|
|
135
|
+
if (!SETTLING_WITHDRAWAL_STATUSES.has(withdrawal.status)) {
|
|
136
|
+
return null
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
id: withdrawal.withdrawal_id,
|
|
140
|
+
provider: ONDO_PROVIDER_KEY,
|
|
141
|
+
timestamp: new Date(withdrawal.time).toISOString(),
|
|
142
|
+
type: ActivityType.WITHDRAWAL,
|
|
143
|
+
asset: withdrawal.coin,
|
|
144
|
+
amount: withdrawal.size,
|
|
145
|
+
// Loose equality also drops a `null` the live API may send for "no fee".
|
|
146
|
+
...(withdrawal.usdFee == null
|
|
147
|
+
? {}
|
|
148
|
+
: {
|
|
149
|
+
fee: {
|
|
150
|
+
amount: withdrawal.usdFee,
|
|
151
|
+
asset: ONDO_WITHDRAWAL_FEE_SYMBOL,
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
...(withdrawal.txid === ''
|
|
155
|
+
? {}
|
|
156
|
+
: { explorerLink: `https://scan.li.fi/tx/${withdrawal.txid}` }),
|
|
157
|
+
}
|
|
158
|
+
}
|
package/src/utils/mapFill.ts
CHANGED
|
@@ -35,7 +35,11 @@ export const mapFill = (fill: OndoFill, market: MarketDisplay): Fill => ({
|
|
|
35
35
|
price: fill.price,
|
|
36
36
|
status: FillStatus.FILLED,
|
|
37
37
|
liquidity: fill.isMaker ? LiquidityRole.MAKER : LiquidityRole.TAKER,
|
|
38
|
-
|
|
38
|
+
// Ondo charges the fill fee in the market's quote asset.
|
|
39
|
+
fee: {
|
|
40
|
+
amount: new Big(fill.fee).minus(fill.feeRebate ?? '0').toFixed(),
|
|
41
|
+
asset: market.quoteAsset.displaySymbol,
|
|
42
|
+
},
|
|
39
43
|
realizedPnl: fill.pnl,
|
|
40
44
|
classification:
|
|
41
45
|
fill.direction !== undefined
|
package/src/utils/mapOrder.ts
CHANGED
|
@@ -22,6 +22,10 @@ const toIso = (time: string): string => new Date(time).toISOString()
|
|
|
22
22
|
const mapSide = (side: OndoOrder['side']): OrderSide =>
|
|
23
23
|
side === 'buy' ? OrderSide.BUY : OrderSide.SELL
|
|
24
24
|
|
|
25
|
+
/** Resting quantity: submitted size minus filled size, in base-asset units. */
|
|
26
|
+
const deriveRemainingSize = (size: string, filledSize: string): string =>
|
|
27
|
+
new Big(size).minus(filledSize).toFixed()
|
|
28
|
+
|
|
25
29
|
/** @public */
|
|
26
30
|
export const mapOrderType = (type: OndoOrderType): OrderType => {
|
|
27
31
|
switch (type) {
|
|
@@ -88,7 +92,11 @@ export const isTriggerOrder = (order: OndoOrder): boolean =>
|
|
|
88
92
|
order.stopOrderType !== undefined ||
|
|
89
93
|
order.triggerPrice !== undefined
|
|
90
94
|
|
|
91
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Map an active non-trigger Ondo order to an {@link OpenOrder}. Ondo reports
|
|
97
|
+
* the submitted and filled quantities only, so `remainingSize` is derived.
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
92
100
|
export const mapOrder = (
|
|
93
101
|
order: OndoOrder,
|
|
94
102
|
market: MarketDisplay
|
|
@@ -97,7 +105,8 @@ export const mapOrder = (
|
|
|
97
105
|
market,
|
|
98
106
|
side: mapSide(order.side),
|
|
99
107
|
type: mapOrderType(order.type),
|
|
100
|
-
|
|
108
|
+
originalSize: new Big(order.size).toFixed(),
|
|
109
|
+
remainingSize: deriveRemainingSize(order.size, order.filledSize),
|
|
101
110
|
price: order.price,
|
|
102
111
|
filledSize: order.filledSize,
|
|
103
112
|
reduceOnly: order.reduceOnly ?? false,
|
|
@@ -177,7 +186,7 @@ export const mapOrderDetail = (
|
|
|
177
186
|
type: mapOrderType(order.type),
|
|
178
187
|
price: order.price,
|
|
179
188
|
originalSize: order.size,
|
|
180
|
-
remainingSize:
|
|
189
|
+
remainingSize: deriveRemainingSize(order.size, order.filledSize),
|
|
181
190
|
filledSize: order.filledSize,
|
|
182
191
|
timeInForce:
|
|
183
192
|
order.timeInForce === undefined
|