@lifi/perps-sdk-provider-ondo 22.0.0 → 23.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 +14 -0
- package/dist/cjs/OndoProvider.d.ts.map +1 -1
- package/dist/cjs/OndoProvider.js +3 -7
- 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 +6 -0
- package/dist/cjs/websocket/OndoWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/OndoWsProvider.js +125 -33
- package/dist/cjs/websocket/OndoWsProvider.js.map +1 -1
- package/dist/esm/OndoProvider.d.ts.map +1 -1
- package/dist/esm/OndoProvider.js +5 -6
- 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 +7 -5
- package/dist/esm/websocket/OndoWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/OndoWsProvider.js +127 -43
- package/dist/esm/websocket/OndoWsProvider.js.map +1 -1
- 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 +7 -5
- package/dist/types/websocket/OndoWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/OndoProvider.ts +12 -17
- 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 +156 -45
|
@@ -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
|
|
@@ -8,20 +8,20 @@
|
|
|
8
8
|
* power-of-ten grid implied by `priceDecimals` / `szDecimals`. Prices round
|
|
9
9
|
* half-up to the nearest tick; sizes truncate toward zero to the lot.
|
|
10
10
|
*/
|
|
11
|
-
import { type Market } from '@lifi/perps-types';
|
|
11
|
+
import { type DecimalString, type Market } from '@lifi/perps-types';
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Snap a price onto an Ondo market's tick grid: half-up to the nearest
|
|
14
|
+
* `priceIncrement` (or the grid implied by `priceDecimals`), trailing zeros
|
|
15
|
+
* stripped.
|
|
16
16
|
*
|
|
17
17
|
* @throws {PerpsError} `ValidationError` when the market carries neither
|
|
18
18
|
* `priceIncrement` nor `priceDecimals` — without the venue's tick grid no
|
|
19
19
|
* correct price can be produced.
|
|
20
20
|
* @public
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function snapOrderPrice(market: Market, price: DecimalString): DecimalString;
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Snap a size onto an Ondo market's lot grid: truncated toward zero (never
|
|
25
25
|
* rounded up, so the size cannot exceed the user's balance) to the market's
|
|
26
26
|
* `sizeIncrement` (or the grid implied by `szDecimals`), trailing zeros
|
|
27
27
|
* stripped.
|
|
@@ -29,5 +29,5 @@ export declare function formatOrderPrice(market: Market, price: number): string;
|
|
|
29
29
|
* @param size - Size in base-asset units as a non-negative magnitude.
|
|
30
30
|
* @public
|
|
31
31
|
*/
|
|
32
|
-
export declare function
|
|
32
|
+
export declare function snapOrderSize(market: Market, size: DecimalString): DecimalString;
|
|
33
33
|
//# sourceMappingURL=orderFormatting.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orderFormatting.d.ts","sourceRoot":"","sources":["../../../src/utils/orderFormatting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"orderFormatting.d.ts","sourceRoot":"","sources":["../../../src/utils/orderFormatting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,MAAM,EAEZ,MAAM,mBAAmB,CAAA;AAmB1B;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,GACnB,aAAa,CAOf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,GAClB,aAAa,CAUf"}
|
|
@@ -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
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* half-up to the nearest tick; sizes truncate toward zero to the lot.
|
|
10
10
|
*/
|
|
11
11
|
import { PerpsError } from '@lifi/perps-sdk';
|
|
12
|
-
import { PerpsErrorCode } from '@lifi/perps-types';
|
|
12
|
+
import { PerpsErrorCode, } from '@lifi/perps-types';
|
|
13
13
|
import Big from 'big.js';
|
|
14
14
|
const powerOfTenIncrement = (decimals) => new Big(`1e-${decimals}`);
|
|
15
15
|
const priceGrid = (market) => {
|
|
@@ -20,19 +20,19 @@ const priceGrid = (market) => {
|
|
|
20
20
|
return powerOfTenIncrement(market.priceDecimals);
|
|
21
21
|
}
|
|
22
22
|
throw new PerpsError(PerpsErrorCode.ValidationError, `Market '${market.id}' carries no price grid; Ondo order prices cannot ` +
|
|
23
|
-
`be
|
|
23
|
+
`be snapped without the market's tick increment.`);
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Snap a price onto an Ondo market's tick grid: half-up to the nearest
|
|
27
|
+
* `priceIncrement` (or the grid implied by `priceDecimals`), trailing zeros
|
|
28
|
+
* stripped.
|
|
29
29
|
*
|
|
30
30
|
* @throws {PerpsError} `ValidationError` when the market carries neither
|
|
31
31
|
* `priceIncrement` nor `priceDecimals` — without the venue's tick grid no
|
|
32
32
|
* correct price can be produced.
|
|
33
33
|
* @public
|
|
34
34
|
*/
|
|
35
|
-
export function
|
|
35
|
+
export function snapOrderPrice(market, price) {
|
|
36
36
|
const increment = priceGrid(market);
|
|
37
37
|
const snapped = new Big(price)
|
|
38
38
|
.div(increment)
|
|
@@ -41,7 +41,7 @@ export function formatOrderPrice(market, price) {
|
|
|
41
41
|
return snapped.eq(0) ? '0' : snapped.toFixed();
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Snap a size onto an Ondo market's lot grid: truncated toward zero (never
|
|
45
45
|
* rounded up, so the size cannot exceed the user's balance) to the market's
|
|
46
46
|
* `sizeIncrement` (or the grid implied by `szDecimals`), trailing zeros
|
|
47
47
|
* stripped.
|
|
@@ -49,7 +49,7 @@ export function formatOrderPrice(market, price) {
|
|
|
49
49
|
* @param size - Size in base-asset units as a non-negative magnitude.
|
|
50
50
|
* @public
|
|
51
51
|
*/
|
|
52
|
-
export function
|
|
52
|
+
export function snapOrderSize(market, size) {
|
|
53
53
|
const increment = market.sizeIncrement !== undefined
|
|
54
54
|
? new Big(market.sizeIncrement)
|
|
55
55
|
: powerOfTenIncrement(market.szDecimals);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orderFormatting.js","sourceRoot":"","sources":["../../../src/utils/orderFormatting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"orderFormatting.js","sourceRoot":"","sources":["../../../src/utils/orderFormatting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAGL,cAAc,GACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,GAAG,MAAM,QAAQ,CAAA;AAExB,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAO,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAA;AAEhF,MAAM,SAAS,GAAG,CAAC,MAAc,EAAO,EAAE;IACxC,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IACvC,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,mBAAmB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;IAClD,CAAC;IACD,MAAM,IAAI,UAAU,CAClB,cAAc,CAAC,eAAe,EAC9B,WAAW,MAAM,CAAC,EAAE,oDAAoD;QACtE,iDAAiD,CACpD,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,KAAoB;IAEpB,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC;SAC3B,GAAG,CAAC,SAAS,CAAC;SACd,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC;SACzB,KAAK,CAAC,SAAS,CAAC,CAAA;IACnB,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,IAAmB;IAEnB,MAAM,SAAS,GACb,MAAM,CAAC,aAAa,KAAK,SAAS;QAChC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;QAC/B,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;SAC1B,GAAG,CAAC,SAAS,CAAC;SACd,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC;SACvB,KAAK,CAAC,SAAS,CAAC,CAAA;IACnB,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;AAChD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ProviderWithdrawableBalance } from '@lifi/perps-sdk';
|
|
2
2
|
import type { OndoBalanceSummary } from '../types/wire.js';
|
|
3
3
|
/**
|
|
4
4
|
* The single route an Ondo withdrawal draws on: `withdrawableMargin`, the
|
|
@@ -8,9 +8,9 @@ import type { OndoBalanceSummary } from '../types/wire.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @param assetId - `Asset.id` the row is keyed by.
|
|
10
10
|
* @param withdrawalFeeUsd - The account's `withdrawalFeeUSD`. Ondo collateral
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* is USDC, so the USD fee is the row fee 1:1 in collateral units. Ondo
|
|
12
|
+
* charges it on top of the requested amount. Absent leaves the row without a
|
|
13
|
+
* fee.
|
|
14
14
|
* @public
|
|
15
15
|
*/
|
|
16
16
|
export declare const ondoWithdrawableBalances: (assetId: string, balance: OndoBalanceSummary, withdrawalFeeUsd?: string) => ProviderWithdrawableBalance[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withdrawableBalances.d.ts","sourceRoot":"","sources":["../../../src/utils/withdrawableBalances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"withdrawableBalances.d.ts","sourceRoot":"","sources":["../../../src/utils/withdrawableBalances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAG1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS,MAAM,EACf,SAAS,kBAAkB,EAC3B,mBAAmB,MAAM,KACxB,2BAA2B,EAuB7B,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { calculateWithdrawMax, } from '@lifi/perps-sdk';
|
|
1
2
|
import { toWireBig } from './decimal.js';
|
|
2
3
|
/**
|
|
3
4
|
* The single route an Ondo withdrawal draws on: `withdrawableMargin`, the
|
|
@@ -7,9 +8,9 @@ import { toWireBig } from './decimal.js';
|
|
|
7
8
|
*
|
|
8
9
|
* @param assetId - `Asset.id` the row is keyed by.
|
|
9
10
|
* @param withdrawalFeeUsd - The account's `withdrawalFeeUSD`. Ondo collateral
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* is USDC, so the USD fee is the row fee 1:1 in collateral units. Ondo
|
|
12
|
+
* charges it on top of the requested amount. Absent leaves the row without a
|
|
13
|
+
* fee.
|
|
13
14
|
* @public
|
|
14
15
|
*/
|
|
15
16
|
export const ondoWithdrawableBalances = (assetId, balance, withdrawalFeeUsd) => {
|
|
@@ -17,18 +18,17 @@ export const ondoWithdrawableBalances = (assetId, balance, withdrawalFeeUsd) =>
|
|
|
17
18
|
if (!available.gt(0)) {
|
|
18
19
|
return [];
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
];
|
|
21
|
+
const row = {
|
|
22
|
+
assetId,
|
|
23
|
+
route: 'perps',
|
|
24
|
+
available: available.toFixed(),
|
|
25
|
+
...(withdrawalFeeUsd === undefined
|
|
26
|
+
? {}
|
|
27
|
+
: {
|
|
28
|
+
withdrawalFee: toWireBig(withdrawalFeeUsd, 'account.withdrawalFeeUSD').toFixed(),
|
|
29
|
+
isFeeDeducted: false,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
return [{ ...row, max: calculateWithdrawMax(row) }];
|
|
33
33
|
};
|
|
34
34
|
//# sourceMappingURL=withdrawableBalances.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withdrawableBalances.js","sourceRoot":"","sources":["../../../src/utils/withdrawableBalances.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"withdrawableBalances.js","sourceRoot":"","sources":["../../../src/utils/withdrawableBalances.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,GAErB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,OAAe,EACf,OAA2B,EAC3B,gBAAyB,EACM,EAAE;IACjC,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,CAAC,kBAAkB,EAC1B,4BAA4B,CAC7B,CAAA;IACD,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,GAAG,GAAG;QACV,OAAO;QACP,KAAK,EAAE,OAAgB;QACvB,SAAS,EAAE,SAAS,CAAC,OAAO,EAAE;QAC9B,GAAG,CAAC,gBAAgB,KAAK,SAAS;YAChC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,aAAa,EAAE,SAAS,CACtB,gBAAgB,EAChB,0BAA0B,CAC3B,CAAC,OAAO,EAAE;gBACX,aAAa,EAAE,KAAK;aACrB,CAAC;KACP,CAAA;IACD,OAAO,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AACrD,CAAC,CAAA"}
|
|
@@ -10,6 +10,7 @@ interface SubState {
|
|
|
10
10
|
};
|
|
11
11
|
needsAuth: boolean;
|
|
12
12
|
address?: Address;
|
|
13
|
+
authGeneration?: number;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Options for {@link ondoWsProvider} / {@link OndoWsProvider}.
|
|
@@ -52,6 +53,7 @@ export declare class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
52
53
|
* positions frame, which is what moves them.
|
|
53
54
|
*/
|
|
54
55
|
private accountSummary;
|
|
56
|
+
private accountSummaryGeneration;
|
|
55
57
|
/**
|
|
56
58
|
* Serializes the balance re-read: a single trade event emits a fills frame
|
|
57
59
|
* and a positions frame together, and two concurrent REST reads can resolve
|
|
@@ -65,6 +67,9 @@ export declare class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
65
67
|
/** The single address this connection's login is bound to. */
|
|
66
68
|
private accountAddress;
|
|
67
69
|
private loginPromise;
|
|
70
|
+
private authGeneration;
|
|
71
|
+
private authBindingRefs;
|
|
72
|
+
private closeGeneration;
|
|
68
73
|
constructor(wsUrl?: string, providerKey?: string, options?: OndoWsProviderOptions, client?: PerpsSDKClient);
|
|
69
74
|
subscribeQuote(params: ProviderGetQuoteParams, onQuote: QuoteListener): Promise<() => void>;
|
|
70
75
|
protected toKey(sub: Subscription): string;
|
|
@@ -82,11 +87,7 @@ export declare class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
82
87
|
* false — leaving the binding intact — while any is still live.
|
|
83
88
|
*/
|
|
84
89
|
private releaseBindingIfIdle;
|
|
85
|
-
/**
|
|
86
|
-
* Forget the authenticated binding and cycle the connection. The venue
|
|
87
|
-
* permits one login per socket, so a later subscribe for a different address
|
|
88
|
-
* must authenticate on a fresh connection rather than re-login on this one.
|
|
89
|
-
*/
|
|
90
|
+
/** Release a channel's binding reservation, including one still opening. */
|
|
90
91
|
private releaseBinding;
|
|
91
92
|
/** Register a wire sub, ref-counting the shared authenticated channels. */
|
|
92
93
|
private acquireWire;
|
|
@@ -118,6 +119,7 @@ export declare class OndoWsProvider extends WsProviderBase<SubState> {
|
|
|
118
119
|
private seedAccountSummary;
|
|
119
120
|
/** Re-read the venue balance moved by the frame and re-emit the summary. */
|
|
120
121
|
private refreshAccountSummary;
|
|
122
|
+
private clearAccountSummary;
|
|
121
123
|
private readBalance;
|
|
122
124
|
/** Emit the current account summary from the venue balance figures. */
|
|
123
125
|
private emitAccountSummary;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OndoWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/OndoWsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAGlB,KAAK,cAAc,EAGnB,cAAc,EACd,KAAK,iBAAiB,EAGvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAKV,YAAY,EACb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAgEnC,UAAU,QAAQ;IAChB,yEAAyE;IACzE,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACnE,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"OndoWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/OndoWsProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,7 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
56
56
|
* positions frame, which is what moves them.
|
|
57
57
|
*/
|
|
58
58
|
accountSummary;
|
|
59
|
+
accountSummaryGeneration = 0;
|
|
59
60
|
/**
|
|
60
61
|
* Serializes the balance re-read: a single trade event emits a fills frame
|
|
61
62
|
* and a positions frame together, and two concurrent REST reads can resolve
|
|
@@ -69,6 +70,9 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
69
70
|
/** The single address this connection's login is bound to. */
|
|
70
71
|
accountAddress;
|
|
71
72
|
loginPromise;
|
|
73
|
+
authGeneration = 0;
|
|
74
|
+
authBindingRefs = 0;
|
|
75
|
+
closeGeneration = 0;
|
|
72
76
|
constructor(wsUrl = DEFAULT_ONDO_WS_URL, providerKey = ONDO_PROVIDER_KEY, options = {}, client) {
|
|
73
77
|
super(new ReconnectingWebSocket(wsUrl, { pingPayload: '{"op":"ping"}' }), providerKey);
|
|
74
78
|
this.apiUrl = options.apiUrl ?? DEFAULT_ONDO_API_URL;
|
|
@@ -121,49 +125,95 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
121
125
|
}
|
|
122
126
|
const wireSubs = this.resolveChannel(sub);
|
|
123
127
|
const needsLogin = isAuthChannel(sub.channel) || sub.channel === 'accountSummary';
|
|
124
|
-
|
|
128
|
+
const closeGeneration = this.closeGeneration;
|
|
129
|
+
let authGeneration;
|
|
125
130
|
if (needsLogin) {
|
|
126
131
|
const { address } = sub;
|
|
127
132
|
// Reject before the address binds and before any wire sub registers: a
|
|
128
133
|
// registered sub whose login can never succeed is retried on every
|
|
129
134
|
// reopen without the caller ever seeing the failure.
|
|
130
135
|
await this.requireSession(address);
|
|
136
|
+
if (closeGeneration !== this.closeGeneration) {
|
|
137
|
+
return () => { };
|
|
138
|
+
}
|
|
131
139
|
const bound = address.toLowerCase();
|
|
132
|
-
boundHere = this.accountAddress !== bound;
|
|
133
140
|
this.bindAddress(bound);
|
|
141
|
+
authGeneration = this.authGeneration;
|
|
142
|
+
this.authBindingRefs += 1;
|
|
134
143
|
}
|
|
144
|
+
const summaryGeneration = sub.channel === 'accountSummary'
|
|
145
|
+
? this.accountSummaryGeneration
|
|
146
|
+
: undefined;
|
|
147
|
+
let acquiredWireCount = 0;
|
|
135
148
|
try {
|
|
136
149
|
if (needsLogin) {
|
|
137
150
|
// Account frames carry venue market symbols; the registry supplies the
|
|
138
151
|
// market identity the mapped orders/fills/positions embed.
|
|
139
152
|
await this.registry?.sync();
|
|
140
153
|
}
|
|
141
|
-
if (
|
|
142
|
-
|
|
154
|
+
if (authGeneration !== undefined &&
|
|
155
|
+
authGeneration !== this.authGeneration) {
|
|
156
|
+
return () => { };
|
|
157
|
+
}
|
|
158
|
+
if (sub.channel === 'accountSummary' && summaryGeneration !== undefined) {
|
|
159
|
+
if (summaryGeneration !== this.accountSummaryGeneration) {
|
|
160
|
+
return () => { };
|
|
161
|
+
}
|
|
162
|
+
await this.seedAccountSummary(sub.address, summaryGeneration);
|
|
163
|
+
if (summaryGeneration !== this.accountSummaryGeneration) {
|
|
164
|
+
return () => { };
|
|
165
|
+
}
|
|
143
166
|
}
|
|
144
167
|
// Authenticated wire subs are shared and ref-counted; public ones are 1:1.
|
|
145
168
|
for (const [key, state] of wireSubs) {
|
|
169
|
+
state.authGeneration = authGeneration;
|
|
146
170
|
await this.acquireWire(key, state, needsLogin);
|
|
171
|
+
acquiredWireCount += 1;
|
|
172
|
+
if (authGeneration !== undefined &&
|
|
173
|
+
authGeneration !== this.authGeneration) {
|
|
174
|
+
return () => { };
|
|
175
|
+
}
|
|
147
176
|
}
|
|
148
177
|
await this.rws.ready();
|
|
178
|
+
if (authGeneration !== undefined &&
|
|
179
|
+
authGeneration !== this.authGeneration) {
|
|
180
|
+
return () => { };
|
|
181
|
+
}
|
|
149
182
|
}
|
|
150
183
|
catch (err) {
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
184
|
+
// A failed opening releases only its own binding reservation.
|
|
185
|
+
if (authGeneration === undefined ||
|
|
186
|
+
authGeneration === this.authGeneration) {
|
|
187
|
+
if (summaryGeneration !== undefined) {
|
|
188
|
+
this.clearAccountSummary();
|
|
189
|
+
}
|
|
190
|
+
for (let index = 0; index < acquiredWireCount; index += 1) {
|
|
191
|
+
const [key, state] = wireSubs[index];
|
|
192
|
+
this.releaseWire(key, state, needsLogin);
|
|
193
|
+
}
|
|
194
|
+
if (authGeneration !== undefined) {
|
|
195
|
+
this.releaseBinding();
|
|
196
|
+
}
|
|
156
197
|
}
|
|
157
198
|
throw err;
|
|
158
199
|
}
|
|
159
200
|
return () => {
|
|
160
|
-
if (
|
|
161
|
-
this.
|
|
162
|
-
|
|
201
|
+
if (authGeneration !== undefined &&
|
|
202
|
+
authGeneration !== this.authGeneration) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (summaryGeneration !== undefined) {
|
|
206
|
+
if (summaryGeneration !== this.accountSummaryGeneration) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
this.clearAccountSummary();
|
|
163
210
|
}
|
|
164
211
|
for (const [key, state] of wireSubs) {
|
|
165
212
|
this.releaseWire(key, state, needsLogin);
|
|
166
213
|
}
|
|
214
|
+
if (authGeneration !== undefined) {
|
|
215
|
+
this.releaseBinding();
|
|
216
|
+
}
|
|
167
217
|
};
|
|
168
218
|
}
|
|
169
219
|
/**
|
|
@@ -198,14 +248,15 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
198
248
|
}
|
|
199
249
|
return true;
|
|
200
250
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Forget the authenticated binding and cycle the connection. The venue
|
|
203
|
-
* permits one login per socket, so a later subscribe for a different address
|
|
204
|
-
* must authenticate on a fresh connection rather than re-login on this one.
|
|
205
|
-
*/
|
|
251
|
+
/** Release a channel's binding reservation, including one still opening. */
|
|
206
252
|
releaseBinding() {
|
|
253
|
+
this.authBindingRefs -= 1;
|
|
254
|
+
if (this.authBindingRefs > 0) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
207
257
|
this.accountAddress = undefined;
|
|
208
258
|
this.loginPromise = undefined;
|
|
259
|
+
this.authGeneration += 1;
|
|
209
260
|
this.rws.reconnect();
|
|
210
261
|
}
|
|
211
262
|
/** Register a wire sub, ref-counting the shared authenticated channels. */
|
|
@@ -222,7 +273,9 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
222
273
|
}
|
|
223
274
|
catch (err) {
|
|
224
275
|
// Roll back the ref we just took so a later subscribe re-registers.
|
|
225
|
-
this.
|
|
276
|
+
if (state.authGeneration === this.authGeneration) {
|
|
277
|
+
this.authWireRefs.delete(key);
|
|
278
|
+
}
|
|
226
279
|
throw err;
|
|
227
280
|
}
|
|
228
281
|
}
|
|
@@ -230,6 +283,9 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
230
283
|
/** Mirror of {@link acquireWire}: drop the wire sub on its last release. */
|
|
231
284
|
releaseWire(key, state, shared) {
|
|
232
285
|
if (shared) {
|
|
286
|
+
if (state.authGeneration !== this.authGeneration) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
233
289
|
const remaining = (this.authWireRefs.get(key) ?? 1) - 1;
|
|
234
290
|
if (remaining > 0) {
|
|
235
291
|
this.authWireRefs.set(key, remaining);
|
|
@@ -239,18 +295,21 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
239
295
|
}
|
|
240
296
|
this.unregisterSub(key);
|
|
241
297
|
this.rws.send(JSON.stringify({ op: 'unsubscribe', ...state.frame }));
|
|
242
|
-
// Last authenticated wire gone: forget the binding and cycle the socket so
|
|
243
|
-
// the next address logs in on a fresh connection.
|
|
244
|
-
if (shared && this.authWireRefs.size === 0) {
|
|
245
|
-
this.releaseBinding();
|
|
246
|
-
}
|
|
247
298
|
}
|
|
248
299
|
async sendSubscribe(state) {
|
|
249
300
|
if (state.needsAuth && state.address !== undefined) {
|
|
301
|
+
if (state.authGeneration !== this.authGeneration) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
250
304
|
// Re-assert the binding: a replay after a reconnect (which cleared it on
|
|
251
305
|
// close) must restore the address account frames emit under.
|
|
252
306
|
this.accountAddress = state.address.toLowerCase();
|
|
253
|
-
|
|
307
|
+
const login = this.ensureLogin(state.address);
|
|
308
|
+
await login;
|
|
309
|
+
if (this.loginPromise !== login ||
|
|
310
|
+
state.authGeneration !== this.authGeneration) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
254
313
|
}
|
|
255
314
|
this.rws.send(JSON.stringify({ op: 'subscribe', ...state.frame }));
|
|
256
315
|
}
|
|
@@ -259,6 +318,11 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
259
318
|
this.pendingFunding.clear();
|
|
260
319
|
this.loginPromise = undefined;
|
|
261
320
|
this.accountAddress = undefined;
|
|
321
|
+
this.authGeneration += 1;
|
|
322
|
+
this.closeGeneration += 1;
|
|
323
|
+
this.authWireRefs.clear();
|
|
324
|
+
this.authBindingRefs = 0;
|
|
325
|
+
this.clearAccountSummary();
|
|
262
326
|
}
|
|
263
327
|
/** Wire subs for `sub`, keyed uniquely for the base's replay registry. */
|
|
264
328
|
resolveChannel(sub) {
|
|
@@ -385,12 +449,16 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
385
449
|
*/
|
|
386
450
|
ensureLogin(address) {
|
|
387
451
|
if (this.loginPromise === undefined) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
452
|
+
const login = this.requireSession(address).then((token) => {
|
|
453
|
+
if (this.loginPromise === login) {
|
|
454
|
+
this.rws.send(JSON.stringify({ op: 'login', args: { token: token.token } }));
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
this.loginPromise = login;
|
|
458
|
+
login.catch(() => {
|
|
459
|
+
if (this.loginPromise === login) {
|
|
460
|
+
this.loginPromise = undefined;
|
|
461
|
+
}
|
|
394
462
|
});
|
|
395
463
|
}
|
|
396
464
|
return this.loginPromise;
|
|
@@ -406,23 +474,38 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
406
474
|
* OndoSessionExpiredError} when the SIWE session is missing, matching the
|
|
407
475
|
* other authenticated channels.
|
|
408
476
|
*/
|
|
409
|
-
async seedAccountSummary(address) {
|
|
477
|
+
async seedAccountSummary(address, generation) {
|
|
410
478
|
const token = await this.requireSession(address);
|
|
411
|
-
|
|
412
|
-
|
|
479
|
+
if (generation !== this.accountSummaryGeneration) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
const balance = await this.readBalance(token.token);
|
|
483
|
+
if (generation !== this.accountSummaryGeneration) {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
this.accountSummary = balance;
|
|
487
|
+
this.emitAccountSummary(address);
|
|
413
488
|
}
|
|
414
489
|
/** Re-read the venue balance moved by the frame and re-emit the summary. */
|
|
415
|
-
async refreshAccountSummary(address) {
|
|
490
|
+
async refreshAccountSummary(address, generation) {
|
|
416
491
|
const token = await this.tokenStore.get(address);
|
|
417
|
-
if (token === null ||
|
|
492
|
+
if (token === null ||
|
|
493
|
+
this.accountSummary === undefined ||
|
|
494
|
+
generation !== this.accountSummaryGeneration) {
|
|
418
495
|
return;
|
|
419
496
|
}
|
|
420
497
|
const balance = await this.readBalance(token.token);
|
|
421
|
-
if (this.accountSummary === undefined
|
|
498
|
+
if (this.accountSummary === undefined ||
|
|
499
|
+
generation !== this.accountSummaryGeneration) {
|
|
422
500
|
return;
|
|
423
501
|
}
|
|
424
502
|
this.accountSummary = balance;
|
|
425
|
-
this.emitAccountSummary();
|
|
503
|
+
this.emitAccountSummary(address);
|
|
504
|
+
}
|
|
505
|
+
clearAccountSummary() {
|
|
506
|
+
this.accountSummaryGeneration += 1;
|
|
507
|
+
this.accountSummary = undefined;
|
|
508
|
+
this.accountSummaryChain.reset();
|
|
426
509
|
}
|
|
427
510
|
async readBalance(authToken) {
|
|
428
511
|
const balance = await this.restClient().get('/v1/perps/balance', { authToken });
|
|
@@ -436,13 +519,12 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
436
519
|
};
|
|
437
520
|
}
|
|
438
521
|
/** Emit the current account summary from the venue balance figures. */
|
|
439
|
-
emitAccountSummary() {
|
|
522
|
+
emitAccountSummary(address) {
|
|
440
523
|
const balance = this.accountSummary;
|
|
441
|
-
|
|
442
|
-
if (balance === undefined || address === undefined) {
|
|
524
|
+
if (balance === undefined) {
|
|
443
525
|
return;
|
|
444
526
|
}
|
|
445
|
-
this.emit(`accountSummary:${address}`, {
|
|
527
|
+
this.emit(`accountSummary:${address.toLowerCase()}`, {
|
|
446
528
|
channel: 'accountSummary',
|
|
447
529
|
data: {
|
|
448
530
|
portfolioValue: balance.marginBalance,
|
|
@@ -645,7 +727,8 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
645
727
|
}
|
|
646
728
|
this.emit(`fills:${address}`, { channel: 'fills', data: mapped });
|
|
647
729
|
if (this.accountSummary !== undefined) {
|
|
648
|
-
|
|
730
|
+
const generation = this.accountSummaryGeneration;
|
|
731
|
+
this.accountSummaryChain.push(() => this.refreshAccountSummary(address, generation));
|
|
649
732
|
}
|
|
650
733
|
}
|
|
651
734
|
handlePositions(positions) {
|
|
@@ -666,7 +749,8 @@ export class OndoWsProvider extends WsProviderBase {
|
|
|
666
749
|
data: mapped,
|
|
667
750
|
});
|
|
668
751
|
if (this.accountSummary !== undefined) {
|
|
669
|
-
|
|
752
|
+
const generation = this.accountSummaryGeneration;
|
|
753
|
+
this.accountSummaryChain.push(() => this.refreshAccountSummary(address, generation));
|
|
670
754
|
}
|
|
671
755
|
}
|
|
672
756
|
}
|