@lifi/perps-sdk-provider-ondo 22.0.1 → 24.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 +27 -2
- package/dist/cjs/OndoProvider.d.ts.map +1 -1
- package/dist/cjs/OndoProvider.js +41 -46
- package/dist/cjs/OndoProvider.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 -3
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/liquidation.js +1 -1
- package/dist/cjs/utils/liquidation.js.map +1 -1
- package/dist/cjs/utils/orderFormatting.d.ts +3 -3
- package/dist/cjs/utils/orderFormatting.d.ts.map +1 -1
- package/dist/cjs/utils/orderFormatting.js +5 -5
- package/dist/cjs/utils/orderFormatting.js.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.d.ts +1 -1
- package/dist/cjs/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.js +13 -13
- package/dist/cjs/utils/withdrawableBalances.js.map +1 -1
- package/dist/cjs/websocket/OndoWsProvider.d.ts +1 -1
- package/dist/cjs/websocket/OndoWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/OndoWsProvider.js +2 -2
- package/dist/cjs/websocket/OndoWsProvider.js.map +1 -1
- package/dist/esm/OndoProvider.d.ts +4 -3
- package/dist/esm/OndoProvider.d.ts.map +1 -1
- package/dist/esm/OndoProvider.js +56 -52
- package/dist/esm/OndoProvider.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/liquidation.js +1 -1
- package/dist/esm/utils/liquidation.js.map +1 -1
- package/dist/esm/utils/orderFormatting.d.ts +8 -8
- package/dist/esm/utils/orderFormatting.d.ts.map +1 -1
- package/dist/esm/utils/orderFormatting.js +9 -9
- package/dist/esm/utils/orderFormatting.js.map +1 -1
- package/dist/esm/utils/withdrawableBalances.d.ts +4 -4
- package/dist/esm/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/esm/utils/withdrawableBalances.js +16 -16
- package/dist/esm/utils/withdrawableBalances.js.map +1 -1
- package/dist/esm/websocket/OndoWsProvider.d.ts +8 -7
- package/dist/esm/websocket/OndoWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/OndoWsProvider.js +11 -10
- package/dist/esm/websocket/OndoWsProvider.js.map +1 -1
- package/dist/types/OndoProvider.d.ts +4 -3
- package/dist/types/OndoProvider.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/orderFormatting.d.ts +8 -8
- package/dist/types/utils/orderFormatting.d.ts.map +1 -1
- package/dist/types/utils/withdrawableBalances.d.ts +4 -4
- package/dist/types/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/types/websocket/OndoWsProvider.d.ts +8 -7
- package/dist/types/websocket/OndoWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/OndoProvider.ts +86 -72
- package/src/utils/index.ts +1 -1
- package/src/utils/liquidation.ts +1 -1
- package/src/utils/orderFormatting.ts +19 -9
- package/src/utils/withdrawableBalances.ts +22 -20
- package/src/websocket/OndoWsProvider.ts +18 -15
package/src/OndoProvider.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACTIVE_ORDER_STATUSES,
|
|
3
3
|
type ActionSignerContribution,
|
|
4
|
+
calculateTransferable,
|
|
4
5
|
createWarnOnce,
|
|
5
6
|
type DepositFlow,
|
|
6
7
|
ETHEREUM_USDC,
|
|
@@ -8,8 +9,6 @@ import {
|
|
|
8
9
|
getMarketRegistry,
|
|
9
10
|
getProviders,
|
|
10
11
|
localStorageAdapter,
|
|
11
|
-
maxOf,
|
|
12
|
-
minOf,
|
|
13
12
|
PerpsError,
|
|
14
13
|
type PerpsProviderPlugin,
|
|
15
14
|
type PerpsSDKClient,
|
|
@@ -74,7 +73,6 @@ import {
|
|
|
74
73
|
MarginMode,
|
|
75
74
|
PerpsErrorCode,
|
|
76
75
|
} from '@lifi/perps-types'
|
|
77
|
-
import Big from 'big.js'
|
|
78
76
|
import { type Address, getAddress } from 'viem'
|
|
79
77
|
import { projectOndoConfigSettings } from './accountConfig.js'
|
|
80
78
|
import { getAccountSummary } from './accountSummary.js'
|
|
@@ -123,8 +121,6 @@ import {
|
|
|
123
121
|
import { toWireBig } from './utils/decimal.js'
|
|
124
122
|
import {
|
|
125
123
|
estimateLiquidationPrice,
|
|
126
|
-
formatOrderPrice,
|
|
127
|
-
formatOrderSize,
|
|
128
124
|
listOndoDepositAddress,
|
|
129
125
|
mapDepositActivity,
|
|
130
126
|
mapFill,
|
|
@@ -137,6 +133,8 @@ import {
|
|
|
137
133
|
ondoWithdrawableBalances,
|
|
138
134
|
positionRemovableMargin,
|
|
139
135
|
requireOndoCollateralAsset,
|
|
136
|
+
snapOrderPrice,
|
|
137
|
+
snapOrderSize,
|
|
140
138
|
} from './utils/index.js'
|
|
141
139
|
import { mapPortfolioHistory } from './utils/mapPortfolioHistory.js'
|
|
142
140
|
import {
|
|
@@ -164,9 +162,10 @@ export interface OndoProviderOptions {
|
|
|
164
162
|
*
|
|
165
163
|
* Per-user reads call Ondo's REST API directly — every one requires the
|
|
166
164
|
* session JWT obtained through the SIWE login and stored in the token store.
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
165
|
+
* A data read throws `PerpsErrorCode.SetupRequired` when no session is stored
|
|
166
|
+
* and `PerpsErrorCode.Unauthorized` when Ondo rejects the stored session. A
|
|
167
|
+
* status read (`getAccount`, `accountExists`, `getDepositFlow`,
|
|
168
|
+
* `getWithdrawFlow`) returns the logged-out state instead.
|
|
170
169
|
*
|
|
171
170
|
* @example
|
|
172
171
|
* ```ts
|
|
@@ -274,30 +273,69 @@ export const ondoProvider = (
|
|
|
274
273
|
config: emptyConfig,
|
|
275
274
|
})
|
|
276
275
|
|
|
277
|
-
// Runs an authenticated read against a live session.
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
// session never soft-locks the UI behind a token that looks
|
|
276
|
+
// Runs an authenticated read against a live session. `noSession` answers
|
|
277
|
+
// when no token is stored; `rejected` answers after the venue rejects the
|
|
278
|
+
// stored token mid-call (`OndoSessionExpiredError`), which is evicted first
|
|
279
|
+
// so a rotated session never soft-locks the UI behind a token that looks
|
|
280
|
+
// valid locally.
|
|
281
281
|
const withSession = async <T>(
|
|
282
282
|
address: Address,
|
|
283
|
-
|
|
283
|
+
fallback: {
|
|
284
|
+
noSession: () => T
|
|
285
|
+
rejected: (cause: OndoSessionExpiredError) => T
|
|
286
|
+
},
|
|
284
287
|
fn: (token: OndoAuthToken) => Promise<T>
|
|
285
288
|
): Promise<T> => {
|
|
286
289
|
const token = await tokenStore.get(address)
|
|
287
290
|
if (token === null) {
|
|
288
|
-
return
|
|
291
|
+
return fallback.noSession()
|
|
289
292
|
}
|
|
290
293
|
try {
|
|
291
294
|
return await fn(token)
|
|
292
295
|
} catch (err) {
|
|
293
296
|
if (err instanceof OndoSessionExpiredError) {
|
|
294
297
|
await tokenStore.remove(address)
|
|
295
|
-
return
|
|
298
|
+
return fallback.rejected(err)
|
|
296
299
|
}
|
|
297
300
|
throw err
|
|
298
301
|
}
|
|
299
302
|
}
|
|
300
303
|
|
|
304
|
+
const sessionRequired = (read: string) => (): never => {
|
|
305
|
+
const error = new PerpsError(
|
|
306
|
+
PerpsErrorCode.SetupRequired,
|
|
307
|
+
`Ondo ${read} requires a session token. Run the SIWE login first.`
|
|
308
|
+
)
|
|
309
|
+
error.tool = ONDO_PROVIDER_KEY
|
|
310
|
+
throw error
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const sessionRejected =
|
|
314
|
+
(read: string) =>
|
|
315
|
+
(cause: OndoSessionExpiredError): never => {
|
|
316
|
+
const error = new PerpsError(
|
|
317
|
+
PerpsErrorCode.Unauthorized,
|
|
318
|
+
`Ondo ${read} failed: the venue rejected the session; sign in again.`
|
|
319
|
+
)
|
|
320
|
+
error.tool = ONDO_PROVIDER_KEY
|
|
321
|
+
error.cause = cause
|
|
322
|
+
throw error
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// A data read throws the account's state: an empty result would be
|
|
326
|
+
// indistinguishable from an account with no data.
|
|
327
|
+
const dataRead = (read: string) => ({
|
|
328
|
+
noSession: sessionRequired(read),
|
|
329
|
+
rejected: sessionRejected(read),
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
// A status read reports the logged-out state whether the session is absent
|
|
333
|
+
// or was rejected.
|
|
334
|
+
const statusRead = <T>(loggedOut: () => T) => ({
|
|
335
|
+
noSession: loggedOut,
|
|
336
|
+
rejected: loggedOut,
|
|
337
|
+
})
|
|
338
|
+
|
|
301
339
|
return {
|
|
302
340
|
type: ONDO_PROVIDER_KEY,
|
|
303
341
|
|
|
@@ -313,13 +351,13 @@ export const ondoProvider = (
|
|
|
313
351
|
const apiKeyRegistered = apiKey !== null && hasOndoApiKeyScopes(apiKey)
|
|
314
352
|
return withSession(
|
|
315
353
|
params.address,
|
|
316
|
-
() => {
|
|
354
|
+
statusRead(() => {
|
|
317
355
|
const account = loggedOutAccount(params.address)
|
|
318
356
|
return {
|
|
319
357
|
...account,
|
|
320
358
|
config: { ...emptyConfig, apiKeyRegistered },
|
|
321
359
|
}
|
|
322
|
-
},
|
|
360
|
+
}),
|
|
323
361
|
async (token) => {
|
|
324
362
|
const client = apiClient(opts)
|
|
325
363
|
const [
|
|
@@ -373,16 +411,13 @@ export const ondoProvider = (
|
|
|
373
411
|
units: balance.walletBalance,
|
|
374
412
|
valueUsd: balance.walletBalance,
|
|
375
413
|
price: '1',
|
|
376
|
-
transferable:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
),
|
|
384
|
-
walletBalance
|
|
385
|
-
).toFixed(),
|
|
414
|
+
transferable: calculateTransferable(
|
|
415
|
+
toWireBig(
|
|
416
|
+
balance.withdrawableMargin,
|
|
417
|
+
'balance.withdrawableMargin'
|
|
418
|
+
).toFixed(),
|
|
419
|
+
walletBalance.toFixed()
|
|
420
|
+
),
|
|
386
421
|
},
|
|
387
422
|
]
|
|
388
423
|
: [],
|
|
@@ -420,7 +455,7 @@ export const ondoProvider = (
|
|
|
420
455
|
): Promise<ProviderWithdrawableBalance[]> {
|
|
421
456
|
return withSession(
|
|
422
457
|
params.address,
|
|
423
|
-
(
|
|
458
|
+
dataRead('withdrawable balances read'),
|
|
424
459
|
async (token) => {
|
|
425
460
|
const client = apiClient(opts)
|
|
426
461
|
const [{ providers }, balance, account] = await Promise.all([
|
|
@@ -457,11 +492,7 @@ export const ondoProvider = (
|
|
|
457
492
|
}
|
|
458
493
|
return withSession(
|
|
459
494
|
params.address,
|
|
460
|
-
(
|
|
461
|
-
throw new OndoSessionExpiredError(
|
|
462
|
-
`No valid Ondo session token stored for ${params.address}. Run the SIWE login first.`
|
|
463
|
-
)
|
|
464
|
-
},
|
|
495
|
+
dataRead('market settings read'),
|
|
465
496
|
async (token) => {
|
|
466
497
|
const leverages = await apiClient(opts).get<OndoLeverage[]>(
|
|
467
498
|
'/v1/perps/leverage',
|
|
@@ -496,7 +527,7 @@ export const ondoProvider = (
|
|
|
496
527
|
): Promise<AvailableToTrade | undefined> {
|
|
497
528
|
return withSession(
|
|
498
529
|
params.address,
|
|
499
|
-
()
|
|
530
|
+
dataRead('available-to-trade read'),
|
|
500
531
|
async (token) => {
|
|
501
532
|
const registry = marketRegistry()
|
|
502
533
|
await registry.sync()
|
|
@@ -578,7 +609,7 @@ export const ondoProvider = (
|
|
|
578
609
|
): Promise<boolean> {
|
|
579
610
|
return withSession(
|
|
580
611
|
params.address,
|
|
581
|
-
() => false,
|
|
612
|
+
statusRead(() => false),
|
|
582
613
|
async (token) => {
|
|
583
614
|
await apiClient(opts).get('/v1/account', { authToken: token.token })
|
|
584
615
|
return true
|
|
@@ -595,10 +626,12 @@ export const ondoProvider = (
|
|
|
595
626
|
// before a route has a recipient.
|
|
596
627
|
return withSession<DepositFlow>(
|
|
597
628
|
params.address,
|
|
598
|
-
(
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
629
|
+
statusRead(
|
|
630
|
+
(): DepositFlow => ({
|
|
631
|
+
kind: 'setupRequired',
|
|
632
|
+
setup: [ActionType.SIWE_LOGIN, ActionType.CREATE_DEPOSIT_ADDRESS],
|
|
633
|
+
})
|
|
634
|
+
),
|
|
602
635
|
async (token) => {
|
|
603
636
|
const depositAddress = await listOndoDepositAddress(
|
|
604
637
|
apiClient(opts),
|
|
@@ -627,10 +660,12 @@ export const ondoProvider = (
|
|
|
627
660
|
// offers one destination: the login address.
|
|
628
661
|
return withSession<WithdrawFlow>(
|
|
629
662
|
params.address,
|
|
630
|
-
(
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
663
|
+
statusRead(
|
|
664
|
+
(): WithdrawFlow => ({
|
|
665
|
+
kind: 'setupRequired',
|
|
666
|
+
setup: [ActionType.SIWE_LOGIN, ActionType.ADD_WITHDRAWAL_ADDRESS],
|
|
667
|
+
})
|
|
668
|
+
),
|
|
634
669
|
async (token) => {
|
|
635
670
|
const { addressBook } = await apiClient(
|
|
636
671
|
opts
|
|
@@ -658,11 +693,7 @@ export const ondoProvider = (
|
|
|
658
693
|
): Promise<PositionsResponse> {
|
|
659
694
|
return withSession<PositionsResponse>(
|
|
660
695
|
params.address,
|
|
661
|
-
()
|
|
662
|
-
provider: ONDO_PROVIDER_KEY,
|
|
663
|
-
positions: [],
|
|
664
|
-
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
665
|
-
}),
|
|
696
|
+
dataRead('positions read'),
|
|
666
697
|
async (token) => {
|
|
667
698
|
const client = apiClient(opts)
|
|
668
699
|
const [rawPositions] = await Promise.all([
|
|
@@ -698,11 +729,7 @@ export const ondoProvider = (
|
|
|
698
729
|
): Promise<OrdersResponse> {
|
|
699
730
|
return withSession<OrdersResponse>(
|
|
700
731
|
params.address,
|
|
701
|
-
()
|
|
702
|
-
provider: ONDO_PROVIDER_KEY,
|
|
703
|
-
orders: [],
|
|
704
|
-
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
705
|
-
}),
|
|
732
|
+
dataRead('orders read'),
|
|
706
733
|
async (token) => {
|
|
707
734
|
const statuses =
|
|
708
735
|
params.statuses === undefined
|
|
@@ -865,12 +892,7 @@ export const ondoProvider = (
|
|
|
865
892
|
): Promise<Order> {
|
|
866
893
|
return withSession(
|
|
867
894
|
params.address,
|
|
868
|
-
()
|
|
869
|
-
throw new PerpsError(
|
|
870
|
-
PerpsErrorCode.SDKError,
|
|
871
|
-
'Ondo order lookup requires a session token. Run the SIWE login first.'
|
|
872
|
-
)
|
|
873
|
-
},
|
|
895
|
+
dataRead('order lookup'),
|
|
874
896
|
async (token) => {
|
|
875
897
|
const client = apiClient(opts)
|
|
876
898
|
const [order] = await Promise.all([
|
|
@@ -904,11 +926,7 @@ export const ondoProvider = (
|
|
|
904
926
|
): Promise<FillsResponse> {
|
|
905
927
|
return withSession<FillsResponse>(
|
|
906
928
|
params.address,
|
|
907
|
-
()
|
|
908
|
-
provider: ONDO_PROVIDER_KEY,
|
|
909
|
-
items: [],
|
|
910
|
-
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
911
|
-
}),
|
|
929
|
+
dataRead('fills read'),
|
|
912
930
|
async (token) => {
|
|
913
931
|
const client = apiClient(opts)
|
|
914
932
|
const queryParams: ApiParams = {}
|
|
@@ -951,11 +969,7 @@ export const ondoProvider = (
|
|
|
951
969
|
): Promise<ActivitiesResponse> {
|
|
952
970
|
return withSession<ActivitiesResponse>(
|
|
953
971
|
params.address,
|
|
954
|
-
()
|
|
955
|
-
provider: ONDO_PROVIDER_KEY,
|
|
956
|
-
items: [],
|
|
957
|
-
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
958
|
-
}),
|
|
972
|
+
dataRead('activity read'),
|
|
959
973
|
async (token) => {
|
|
960
974
|
const inputCursor = decodeActivityCursor(params.cursor)
|
|
961
975
|
const client = apiClient(opts)
|
|
@@ -1095,7 +1109,7 @@ export const ondoProvider = (
|
|
|
1095
1109
|
): Promise<PortfolioHistoryResponse> {
|
|
1096
1110
|
return withSession<PortfolioHistoryResponse>(
|
|
1097
1111
|
params.address,
|
|
1098
|
-
(
|
|
1112
|
+
dataRead('portfolio history read'),
|
|
1099
1113
|
async (token) => {
|
|
1100
1114
|
const client = apiClient(opts)
|
|
1101
1115
|
const [graph, summary] = await Promise.all([
|
|
@@ -1129,9 +1143,9 @@ export const ondoProvider = (
|
|
|
1129
1143
|
return getAccountSummary(account)
|
|
1130
1144
|
},
|
|
1131
1145
|
|
|
1132
|
-
|
|
1146
|
+
snapOrderPrice,
|
|
1133
1147
|
|
|
1134
|
-
|
|
1148
|
+
snapOrderSize,
|
|
1135
1149
|
|
|
1136
1150
|
estimateLiquidationPrice,
|
|
1137
1151
|
|
package/src/utils/index.ts
CHANGED
|
@@ -38,6 +38,6 @@ export { mapOrder, mapOrderStatus, mapOrderUpdates } from './mapOrder.js'
|
|
|
38
38
|
export { mapOpenPositions, mapPosition } from './mapPosition.js'
|
|
39
39
|
export { intervalFromBarSpan, mapInterval } from './ohlcvInterval.js'
|
|
40
40
|
export { ondoAsset } from './ondoAsset.js'
|
|
41
|
-
export {
|
|
41
|
+
export { snapOrderPrice, snapOrderSize } from './orderFormatting.js'
|
|
42
42
|
export { positionRemovableMargin } from './transferMargin.js'
|
|
43
43
|
export { ondoWithdrawableBalances } from './withdrawableBalances.js'
|
package/src/utils/liquidation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo order size and price
|
|
2
|
+
* Ondo order size and price snapping for exchange submission.
|
|
3
3
|
*
|
|
4
4
|
* Ondo's tick and lot grids are exact contract increments (`quoteIncrement` /
|
|
5
5
|
* `baseIncrement`) that need not be powers of ten. When the generic
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { PerpsError } from '@lifi/perps-sdk'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
type DecimalString,
|
|
15
|
+
type Market,
|
|
16
|
+
PerpsErrorCode,
|
|
17
|
+
} from '@lifi/perps-types'
|
|
14
18
|
import Big from 'big.js'
|
|
15
19
|
|
|
16
20
|
const powerOfTenIncrement = (decimals: number): Big => new Big(`1e-${decimals}`)
|
|
@@ -25,21 +29,24 @@ const priceGrid = (market: Market): Big => {
|
|
|
25
29
|
throw new PerpsError(
|
|
26
30
|
PerpsErrorCode.ValidationError,
|
|
27
31
|
`Market '${market.id}' carries no price grid; Ondo order prices cannot ` +
|
|
28
|
-
`be
|
|
32
|
+
`be snapped without the market's tick increment.`
|
|
29
33
|
)
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
37
|
+
* Snap a price onto an Ondo market's tick grid: half-up to the nearest
|
|
38
|
+
* `priceIncrement` (or the grid implied by `priceDecimals`), trailing zeros
|
|
39
|
+
* stripped.
|
|
36
40
|
*
|
|
37
41
|
* @throws {PerpsError} `ValidationError` when the market carries neither
|
|
38
42
|
* `priceIncrement` nor `priceDecimals` — without the venue's tick grid no
|
|
39
43
|
* correct price can be produced.
|
|
40
44
|
* @public
|
|
41
45
|
*/
|
|
42
|
-
export function
|
|
46
|
+
export function snapOrderPrice(
|
|
47
|
+
market: Market,
|
|
48
|
+
price: DecimalString
|
|
49
|
+
): DecimalString {
|
|
43
50
|
const increment = priceGrid(market)
|
|
44
51
|
const snapped = new Big(price)
|
|
45
52
|
.div(increment)
|
|
@@ -49,7 +56,7 @@ export function formatOrderPrice(market: Market, price: number): string {
|
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/**
|
|
52
|
-
*
|
|
59
|
+
* Snap a size onto an Ondo market's lot grid: truncated toward zero (never
|
|
53
60
|
* rounded up, so the size cannot exceed the user's balance) to the market's
|
|
54
61
|
* `sizeIncrement` (or the grid implied by `szDecimals`), trailing zeros
|
|
55
62
|
* stripped.
|
|
@@ -57,7 +64,10 @@ export function formatOrderPrice(market: Market, price: number): string {
|
|
|
57
64
|
* @param size - Size in base-asset units as a non-negative magnitude.
|
|
58
65
|
* @public
|
|
59
66
|
*/
|
|
60
|
-
export function
|
|
67
|
+
export function snapOrderSize(
|
|
68
|
+
market: Market,
|
|
69
|
+
size: DecimalString
|
|
70
|
+
): DecimalString {
|
|
61
71
|
const increment =
|
|
62
72
|
market.sizeIncrement !== undefined
|
|
63
73
|
? new Big(market.sizeIncrement)
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
calculateWithdrawMax,
|
|
3
|
+
type ProviderWithdrawableBalance,
|
|
4
|
+
} from '@lifi/perps-sdk'
|
|
2
5
|
import type { OndoBalanceSummary } from '../types/wire.js'
|
|
3
6
|
import { toWireBig } from './decimal.js'
|
|
4
7
|
|
|
@@ -10,9 +13,9 @@ import { toWireBig } from './decimal.js'
|
|
|
10
13
|
*
|
|
11
14
|
* @param assetId - `Asset.id` the row is keyed by.
|
|
12
15
|
* @param withdrawalFeeUsd - The account's `withdrawalFeeUSD`. Ondo collateral
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* is USDC, so the USD fee is the row fee 1:1 in collateral units. Ondo
|
|
17
|
+
* charges it on top of the requested amount. Absent leaves the row without a
|
|
18
|
+
* fee.
|
|
16
19
|
* @public
|
|
17
20
|
*/
|
|
18
21
|
export const ondoWithdrawableBalances = (
|
|
@@ -27,20 +30,19 @@ export const ondoWithdrawableBalances = (
|
|
|
27
30
|
if (!available.gt(0)) {
|
|
28
31
|
return []
|
|
29
32
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
]
|
|
33
|
+
const row = {
|
|
34
|
+
assetId,
|
|
35
|
+
route: 'perps' as const,
|
|
36
|
+
available: available.toFixed(),
|
|
37
|
+
...(withdrawalFeeUsd === undefined
|
|
38
|
+
? {}
|
|
39
|
+
: {
|
|
40
|
+
withdrawalFee: toWireBig(
|
|
41
|
+
withdrawalFeeUsd,
|
|
42
|
+
'account.withdrawalFeeUSD'
|
|
43
|
+
).toFixed(),
|
|
44
|
+
isFeeDeducted: false,
|
|
45
|
+
}),
|
|
46
|
+
}
|
|
47
|
+
return [{ ...row, max: calculateWithdrawMax(row) }]
|
|
46
48
|
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
getMarketRegistry,
|
|
4
4
|
localStorageAdapter,
|
|
5
5
|
type MarketRegistry,
|
|
6
|
+
PerpsError,
|
|
6
7
|
type PerpsSDKClient,
|
|
7
8
|
type ProviderGetQuoteParams,
|
|
8
9
|
type QuoteListener,
|
|
@@ -16,12 +17,13 @@ import {
|
|
|
16
17
|
type WsProviderFactoryParams,
|
|
17
18
|
wsLog,
|
|
18
19
|
} from '@lifi/perps-sdk'
|
|
19
|
-
import
|
|
20
|
-
MarketContext,
|
|
21
|
-
MarketDisplay,
|
|
22
|
-
OndoAccountBalance,
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
import {
|
|
21
|
+
type MarketContext,
|
|
22
|
+
type MarketDisplay,
|
|
23
|
+
type OndoAccountBalance,
|
|
24
|
+
PerpsErrorCode,
|
|
25
|
+
type PerpsMarketDisplay,
|
|
26
|
+
type Subscription,
|
|
25
27
|
} from '@lifi/perps-types'
|
|
26
28
|
import type { Address } from 'viem'
|
|
27
29
|
import { OndoTokenStore } from '../auth/OndoTokenStore.js'
|
|
@@ -44,7 +46,6 @@ import type {
|
|
|
44
46
|
OndoWsMessage,
|
|
45
47
|
OndoWsTrade,
|
|
46
48
|
} from '../types/index.js'
|
|
47
|
-
import { OndoSessionExpiredError } from '../utils/apiClient.js'
|
|
48
49
|
import {
|
|
49
50
|
mapFill,
|
|
50
51
|
mapOrderUpdates,
|
|
@@ -65,7 +66,7 @@ import { intervalFromBarSpan, mapInterval } from '../utils/ohlcvInterval.js'
|
|
|
65
66
|
// connection, sent before the first private subscribe; the venue rejects a
|
|
66
67
|
// second login on the same connection. The JWT comes from the SIWE session in
|
|
67
68
|
// the token store — absent or expired reads back as null and surfaces as
|
|
68
|
-
// `
|
|
69
|
+
// `PerpsError` with `SetupRequired` so callers run the SIWE login. A dropped
|
|
69
70
|
// socket forgets the login, so the guard resets on every close.
|
|
70
71
|
|
|
71
72
|
const ONDO_AUTH_CHANNEL = {
|
|
@@ -580,14 +581,16 @@ export class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
580
581
|
}
|
|
581
582
|
|
|
582
583
|
/**
|
|
583
|
-
* The stored SIWE session for `address`, or {@link
|
|
584
|
-
* when it is absent or expired. Shared by the subscribe-time
|
|
585
|
-
* login op and the account-summary seed so all three report one
|
|
584
|
+
* The stored SIWE session for `address`, or {@link PerpsError} with
|
|
585
|
+
* `SetupRequired` when it is absent or expired. Shared by the subscribe-time
|
|
586
|
+
* guard, the login op and the account-summary seed so all three report one
|
|
587
|
+
* message.
|
|
586
588
|
*/
|
|
587
589
|
private async requireSession(address: Address): Promise<OndoAuthToken> {
|
|
588
590
|
const token = await this.tokenStore.get(address)
|
|
589
591
|
if (token === null) {
|
|
590
|
-
throw new
|
|
592
|
+
throw new PerpsError(
|
|
593
|
+
PerpsErrorCode.SetupRequired,
|
|
591
594
|
`No Ondo session for ${address}. Run the SIWE login before subscribing to account channels.`
|
|
592
595
|
)
|
|
593
596
|
}
|
|
@@ -628,9 +631,9 @@ export class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
628
631
|
|
|
629
632
|
/**
|
|
630
633
|
* Seed the account-summary figures from the REST balance so the first emit
|
|
631
|
-
* is complete before any positions frame lands. Throws {@link
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
+
* is complete before any positions frame lands. Throws {@link PerpsError}
|
|
635
|
+
* with `SetupRequired` when the SIWE session is missing, matching the other
|
|
636
|
+
* authenticated channels.
|
|
634
637
|
*/
|
|
635
638
|
private async seedAccountSummary(
|
|
636
639
|
address: Address,
|