@pear-protocol/exchanges-sdk 0.6.4 → 0.6.6
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/dist/client/base-ws.js +15 -6
- package/dist/client/binance/exchange-ws.js +22 -8
- package/dist/client/binance/rest.js +40 -27
- package/dist/client/binance/ws.js +21 -2
- package/dist/client/bybit/exchange-ws.js +13 -6
- package/dist/client/bybit/rest.js +30 -36
- package/dist/client/bybit/ws.js +16 -2
- package/dist/client/exchange-ws.js +5 -0
- package/dist/client/hmac.js +9 -1
- package/dist/client/hyperliquid/exchange-ws.js +13 -5
- package/dist/client/hyperliquid/rest.js +37 -7
- package/dist/client/hyperliquid/ws.js +10 -4
- package/dist/client/index.js +9 -2
- package/dist/client/lighter/constants.js +4 -0
- package/dist/client/lighter/exchange-ws.js +13 -5
- package/dist/client/lighter/rest.js +153 -18
- package/dist/client/lighter/ws.js +10 -4
- package/dist/client/okx/exchange-ws.js +13 -6
- package/dist/client/okx/rest.js +27 -24
- package/dist/client/okx/ws.js +5 -0
- package/dist/helper/factory.js +3 -0
- package/dist/helper/hyperliquid/helper.js +18 -23
- package/dist/helper/lighter/auth-token.helper.js +68 -0
- package/dist/helper/lighter/cctp-deposit.helper.js +297 -0
- package/dist/helper/lighter/ethereum/abi.js +55 -11
- package/dist/helper/lighter/ethereum/index.js +22 -3
- package/dist/helper/lighter/ethereum/usdc.helper.js +77 -0
- package/dist/helper/lighter/helper.js +112 -37
- package/dist/helper/lighter/index.js +1 -0
- package/dist/helper/lighter/onboarding.helper.js +28 -0
- package/dist/helper/lighter/types.js +6 -1
- package/dist/helper/subaccount.helper.js +20 -0
- package/dist/index.d.ts +200 -1
- package/dist/sdk.js +18 -7
- package/dist/status/base.js +16 -3
- package/dist/status/binance/status.js +3 -0
- package/dist/status/bybit/status.js +3 -0
- package/dist/status/factory.js +3 -0
- package/dist/status/hyperliquid/status.js +8 -6
- package/dist/status/lighter/status.js +11 -3
- package/dist/status/okx/status.js +3 -0
- package/dist/syncer/base.js +79 -24
- package/dist/syncer/binance/syncer.js +14 -13
- package/dist/syncer/bybit/syncer.js +10 -6
- package/dist/syncer/factory.js +3 -0
- package/dist/syncer/hyperliquid/funding.js +3 -0
- package/dist/syncer/hyperliquid/syncer.js +52 -66
- package/dist/syncer/lighter/funding.js +3 -0
- package/dist/syncer/lighter/syncer.js +26 -25
- package/dist/syncer/okx/syncer.js +15 -13
- package/dist/tracker/base.js +15 -5
- package/dist/tracker/binance/mapper.js +5 -1
- package/dist/tracker/binance/tracker.js +63 -23
- package/dist/tracker/binance/types.js +2 -2
- package/dist/tracker/bybit/mapper.js +7 -1
- package/dist/tracker/bybit/tracker.js +68 -24
- package/dist/tracker/bybit/types.js +2 -2
- package/dist/tracker/hyperliquid/const.js +3 -1
- package/dist/tracker/hyperliquid/mapper.js +36 -20
- package/dist/tracker/hyperliquid/tracker.js +147 -54
- package/dist/tracker/hyperliquid/types.js +2 -2
- package/dist/tracker/index.js +3 -0
- package/dist/tracker/lighter/mapper.js +41 -31
- package/dist/tracker/lighter/tracker.js +68 -27
- package/dist/tracker/lighter/types.js +4 -4
- package/dist/tracker/okx/mapper.js +8 -0
- package/dist/tracker/okx/tracker.js +69 -18
- package/dist/tracker/okx/types.js +2 -2
- package/dist/tracker/utils.js +4 -0
- package/package.json +4 -4
- package/dist/client/hyperliquid/client.test.js +0 -41
- package/dist/client/lighter/constants.test.js +0 -22
- package/dist/client/lighter/rest.test.js +0 -158
- package/dist/helper/hyperliquid/helper.test.js +0 -72
- package/dist/helper/lighter/helper.test.js +0 -289
- package/dist/sdk.test.js +0 -117
- package/dist/status/hyperliquid/status.test.js +0 -94
- package/dist/status/lighter/status.test.js +0 -86
- package/dist/syncer/base.test.js +0 -148
- package/dist/syncer/hyperliquid/funding.test.js +0 -63
- package/dist/syncer/hyperliquid/syncer.test.js +0 -271
- package/dist/syncer/lighter/funding.test.js +0 -48
- package/dist/syncer/lighter/syncer.test.js +0 -274
- package/dist/tracker/base.test.js +0 -132
- package/dist/tracker/binance/tracker.test.js +0 -138
- package/dist/tracker/bybit/tracker.test.js +0 -145
- package/dist/tracker/hyperliquid/mapper.test.js +0 -260
- package/dist/tracker/hyperliquid/tracker.test.js +0 -597
- package/dist/tracker/lighter/mapper.test.js +0 -199
- package/dist/tracker/lighter/tracker.test.js +0 -515
- package/dist/tracker/okx/tracker.test.js +0 -126
- package/dist/tracker/utils.test.js +0 -8
|
@@ -3,6 +3,8 @@ import { createExchangeHelper } from '../../helper/factory';
|
|
|
3
3
|
import { HyperliquidAccountType } from '../../tracker/hyperliquid/types';
|
|
4
4
|
import { warningStatus } from '../base';
|
|
5
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
async function checkHyperliquidAccountStatus(config) {
|
|
7
9
|
const reasons = [];
|
|
8
10
|
const options = config.statusOptions;
|
|
@@ -10,7 +12,10 @@ async function checkHyperliquidAccountStatus(config) {
|
|
|
10
12
|
if (builderAddress && !options?.builderFeeTenthsBps) {
|
|
11
13
|
throw new Error("Missing required hyperliquid connect options");
|
|
12
14
|
}
|
|
13
|
-
const helper = createExchangeHelper({
|
|
15
|
+
const helper = createExchangeHelper({
|
|
16
|
+
exchange: "hyperliquid",
|
|
17
|
+
demo: config.demo
|
|
18
|
+
});
|
|
14
19
|
const metadata = config.account.metadata;
|
|
15
20
|
const approvalAddress = metadata && "isSubaccount" in metadata && metadata.isSubaccount ? metadata.mainAccountAddress : config.account.exchangeIdentifier;
|
|
16
21
|
try {
|
|
@@ -37,11 +42,7 @@ async function checkHyperliquidAccountStatus(config) {
|
|
|
37
42
|
}
|
|
38
43
|
if (builderAddress) {
|
|
39
44
|
try {
|
|
40
|
-
const approved = await helper.checkBuilderFeeApproval(
|
|
41
|
-
approvalAddress,
|
|
42
|
-
builderAddress,
|
|
43
|
-
options?.builderFeeTenthsBps
|
|
44
|
-
);
|
|
45
|
+
const approved = await helper.checkBuilderFeeApproval(approvalAddress, builderAddress, options?.builderFeeTenthsBps);
|
|
45
46
|
if (!approved) reasons.push("hyperliquid_builder_fee_not_approved");
|
|
46
47
|
} catch {
|
|
47
48
|
reasons.push("hyperliquid_builder_fee_not_approved");
|
|
@@ -49,5 +50,6 @@ async function checkHyperliquidAccountStatus(config) {
|
|
|
49
50
|
}
|
|
50
51
|
return warningStatus(reasons);
|
|
51
52
|
}
|
|
53
|
+
__name(checkHyperliquidAccountStatus, "checkHyperliquidAccountStatus");
|
|
52
54
|
|
|
53
55
|
export { checkHyperliquidAccountStatus };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { fetchAccountMetadata } from '../../client/lighter/rest';
|
|
2
2
|
import { createExchangeHelper } from '../../helper/factory';
|
|
3
|
+
import { retrieveLighterAuthToken } from '../../helper/lighter/auth-token.helper';
|
|
3
4
|
import { warningStatus } from '../base';
|
|
4
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
8
|
async function checkLighterAccountStatus(config) {
|
|
6
9
|
const reasons = [];
|
|
7
10
|
const options = config.statusOptions;
|
|
@@ -17,11 +20,11 @@ async function checkLighterAccountStatus(config) {
|
|
|
17
20
|
reasons.push("lighter_api_key_invalid");
|
|
18
21
|
} else {
|
|
19
22
|
try {
|
|
20
|
-
const
|
|
23
|
+
const token = await retrieveLighterAuthToken(config.sdk, {
|
|
21
24
|
accountIndex,
|
|
22
25
|
apiKeyIndex: credentials.api_key_index,
|
|
23
26
|
apiPrivateKey: credentials.api_private_key
|
|
24
|
-
});
|
|
27
|
+
}, config.demo);
|
|
25
28
|
await fetchAccountMetadata(accountIndex, token, config.demo);
|
|
26
29
|
} catch {
|
|
27
30
|
reasons.push("lighter_api_key_invalid");
|
|
@@ -29,7 +32,11 @@ async function checkLighterAccountStatus(config) {
|
|
|
29
32
|
}
|
|
30
33
|
if (integratorAccountIndex !== void 0 && integratorMinPerpsMakerFee !== void 0 && integratorMinPerpsTakerFee !== void 0) {
|
|
31
34
|
try {
|
|
32
|
-
const helper = createExchangeHelper({
|
|
35
|
+
const helper = createExchangeHelper({
|
|
36
|
+
exchange: "lighter",
|
|
37
|
+
sdk: config.sdk,
|
|
38
|
+
demo: config.demo
|
|
39
|
+
});
|
|
33
40
|
const approved = await helper.checkIntegratorApproval(accountIndex, integratorAccountIndex, {
|
|
34
41
|
minPerpsMakerFee: integratorMinPerpsMakerFee,
|
|
35
42
|
minPerpsTakerFee: integratorMinPerpsTakerFee
|
|
@@ -41,5 +48,6 @@ async function checkLighterAccountStatus(config) {
|
|
|
41
48
|
}
|
|
42
49
|
return warningStatus(reasons);
|
|
43
50
|
}
|
|
51
|
+
__name(checkLighterAccountStatus, "checkLighterAccountStatus");
|
|
44
52
|
|
|
45
53
|
export { checkLighterAccountStatus };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { fetchAccountConfig } from '../../client/okx/rest';
|
|
2
2
|
import { warningStatus } from '../base';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
async function checkOkxAccountStatus(config) {
|
|
5
7
|
const reasons = [];
|
|
6
8
|
try {
|
|
@@ -10,5 +12,6 @@ async function checkOkxAccountStatus(config) {
|
|
|
10
12
|
}
|
|
11
13
|
return warningStatus(reasons);
|
|
12
14
|
}
|
|
15
|
+
__name(checkOkxAccountStatus, "checkOkxAccountStatus");
|
|
13
16
|
|
|
14
17
|
export { checkOkxAccountStatus };
|
package/dist/syncer/base.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { computeEntryPriceForAsset, computeSyncPayload } from '@pear-protocol/utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
const OVERLAP_MS = 6e4;
|
|
4
6
|
class BaseAccountSyncer {
|
|
7
|
+
static {
|
|
8
|
+
__name(this, "BaseAccountSyncer");
|
|
9
|
+
}
|
|
5
10
|
sdk;
|
|
6
11
|
connector;
|
|
7
12
|
account;
|
|
@@ -19,17 +24,27 @@ class BaseAccountSyncer {
|
|
|
19
24
|
const [{ positions: openPositions }, { fills: provisionalFills }, { instruments }, watermark] = await Promise.all([
|
|
20
25
|
this.sdk.core.positions.openLite(),
|
|
21
26
|
this.sdk.core.fills.provisionals(),
|
|
22
|
-
this.sdk.core.instruments.lite({
|
|
23
|
-
|
|
27
|
+
this.sdk.core.instruments.lite({
|
|
28
|
+
connector: this.connector
|
|
29
|
+
}),
|
|
30
|
+
this.sdk.core.sync.fills.since({
|
|
31
|
+
overlapMs: OVERLAP_MS
|
|
32
|
+
})
|
|
24
33
|
]);
|
|
25
34
|
const entryBySymbol = await this.loadEntryBySymbol(openPositions);
|
|
26
|
-
return {
|
|
35
|
+
return {
|
|
36
|
+
openPositions,
|
|
37
|
+
entryBySymbol,
|
|
38
|
+
provisionalFills,
|
|
39
|
+
instruments,
|
|
40
|
+
watermark
|
|
41
|
+
};
|
|
27
42
|
}
|
|
28
43
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
* Global per-symbol cost-basis entry of existing open positions, derived by pulling each
|
|
45
|
+
* position's fills and folding them (mirrors example-ui). One call per open position today —
|
|
46
|
+
* can collapse to a single endpoint later.
|
|
47
|
+
*/
|
|
33
48
|
async loadEntryBySymbol(openPositions) {
|
|
34
49
|
const responses = await Promise.all(openPositions.map((position) => this.sdk.core.fills.details(position.id)));
|
|
35
50
|
const fills = responses.flatMap((response) => response.fills).sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
@@ -56,7 +71,9 @@ class BaseAccountSyncer {
|
|
|
56
71
|
openPositions,
|
|
57
72
|
provisionalFills
|
|
58
73
|
});
|
|
59
|
-
const exchangePositions = await this.listExternalPositions({
|
|
74
|
+
const exchangePositions = await this.listExternalPositions({
|
|
75
|
+
instruments
|
|
76
|
+
});
|
|
60
77
|
return {
|
|
61
78
|
exchangePositions,
|
|
62
79
|
externalFills,
|
|
@@ -90,14 +107,20 @@ class BaseAccountSyncer {
|
|
|
90
107
|
const { firstSyncTrim } = payload;
|
|
91
108
|
let meta = {
|
|
92
109
|
...payload.meta,
|
|
93
|
-
...
|
|
110
|
+
...payload.meta.externalMaxTs === null ? {} : {
|
|
111
|
+
newestFillTs: payload.meta.externalMaxTs
|
|
112
|
+
},
|
|
113
|
+
...firstSyncStartedAt === void 0 ? {} : {
|
|
114
|
+
firstSyncStartedAt
|
|
115
|
+
}
|
|
94
116
|
};
|
|
95
117
|
if (firstSyncTrim) {
|
|
96
|
-
console.log(
|
|
97
|
-
`${this.connector}: first-sync trim \u2014 dropped ${firstSyncTrim.trimmedCount} pre-cutoff fills (cutoffTs=${firstSyncTrim.cutoffTs})`
|
|
98
|
-
);
|
|
118
|
+
console.log(`${this.connector}: first-sync trim \u2014 dropped ${firstSyncTrim.trimmedCount} pre-cutoff fills (cutoffTs=${firstSyncTrim.cutoffTs})`);
|
|
99
119
|
if (meta.externalMaxTs !== null && firstSyncTrim.trimmedMaxTs >= meta.externalMaxTs - OVERLAP_MS) {
|
|
100
|
-
meta = {
|
|
120
|
+
meta = {
|
|
121
|
+
...meta,
|
|
122
|
+
externalMaxTs: meta.externalMaxTs + OVERLAP_MS + 1
|
|
123
|
+
};
|
|
101
124
|
}
|
|
102
125
|
}
|
|
103
126
|
const createBody = {
|
|
@@ -105,7 +128,9 @@ class BaseAccountSyncer {
|
|
|
105
128
|
exchangePositions: payload.exchangePositions,
|
|
106
129
|
meta
|
|
107
130
|
};
|
|
108
|
-
const bytes = new Blob([
|
|
131
|
+
const bytes = new Blob([
|
|
132
|
+
JSON.stringify(createBody)
|
|
133
|
+
]).size;
|
|
109
134
|
if (bytes > 50 * 1024) {
|
|
110
135
|
await this.sdk.core.sync.fills.createBulk(createBody);
|
|
111
136
|
return;
|
|
@@ -113,22 +138,36 @@ class BaseAccountSyncer {
|
|
|
113
138
|
await this.sdk.core.sync.fills.create(createBody);
|
|
114
139
|
}
|
|
115
140
|
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
141
|
+
* Pull historical funding payments since the funding watermark and post them.
|
|
142
|
+
* Independent of the fill sync cycle (`synchronizeFills`) — funding rows are
|
|
143
|
+
* immutable and upsert idempotently, so this is driven on its own cadence.
|
|
144
|
+
*/
|
|
120
145
|
async synchronizeFunding() {
|
|
121
146
|
const [{ instruments }, watermark] = await Promise.all([
|
|
122
|
-
this.sdk.core.instruments.lite({
|
|
123
|
-
|
|
147
|
+
this.sdk.core.instruments.lite({
|
|
148
|
+
connector: this.connector
|
|
149
|
+
}),
|
|
150
|
+
this.sdk.core.sync.funding.since({
|
|
151
|
+
overlapMs: 6e4
|
|
152
|
+
})
|
|
124
153
|
]);
|
|
125
|
-
const payments = await this.listExternalFunding({
|
|
154
|
+
const payments = await this.listExternalFunding({
|
|
155
|
+
since: new Date(watermark.sinceMs),
|
|
156
|
+
instruments
|
|
157
|
+
});
|
|
126
158
|
if (payments.length === 0) {
|
|
127
159
|
return;
|
|
128
160
|
}
|
|
129
161
|
const externalMaxTs = Math.max(...payments.map((payment) => payment.timestamp));
|
|
130
|
-
const createBody = {
|
|
131
|
-
|
|
162
|
+
const createBody = {
|
|
163
|
+
payments,
|
|
164
|
+
meta: {
|
|
165
|
+
externalMaxTs
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const bytes = new Blob([
|
|
169
|
+
JSON.stringify(createBody)
|
|
170
|
+
]).size;
|
|
132
171
|
if (bytes > 50 * 1024) {
|
|
133
172
|
await this.sdk.core.sync.funding.createBulk(createBody);
|
|
134
173
|
return;
|
|
@@ -144,8 +183,24 @@ class BaseAccountSyncer {
|
|
|
144
183
|
console.error(`${this.connector}: position/fill fetch failed \u2014 sync cycle aborted, retry next tick`, error);
|
|
145
184
|
return;
|
|
146
185
|
}
|
|
147
|
-
|
|
186
|
+
try {
|
|
187
|
+
await this.computeAndPostSync(state, snapshot);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
if (isSyncCreateDeferral(error)) {
|
|
190
|
+
console.log(`${this.connector}: sync cycle deferred by the server (${error.errorCode}) \u2014 retry next tick`);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function isSyncCreateDeferral(error) {
|
|
198
|
+
if (typeof error !== "object" || error === null) {
|
|
199
|
+
return false;
|
|
148
200
|
}
|
|
201
|
+
const { status, errorCode } = error;
|
|
202
|
+
return status === 409 && typeof errorCode === "string" && errorCode.startsWith("SYNC_CREATE_");
|
|
149
203
|
}
|
|
204
|
+
__name(isSyncCreateDeferral, "isSyncCreateDeferral");
|
|
150
205
|
|
|
151
206
|
export { BaseAccountSyncer };
|
|
@@ -2,18 +2,22 @@ import BigNumber from 'bignumber.js';
|
|
|
2
2
|
import { fetchAllPositionRisk, fetchUserTradesSince, fetchAllOrdersSince } from '../../client/binance/rest';
|
|
3
3
|
import { BaseAccountSyncer } from '../base';
|
|
4
4
|
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
7
|
class BinanceAccountSyncer extends BaseAccountSyncer {
|
|
8
|
+
static {
|
|
9
|
+
__name(this, "BinanceAccountSyncer");
|
|
10
|
+
}
|
|
6
11
|
creds;
|
|
7
12
|
constructor(config) {
|
|
8
13
|
super(config);
|
|
9
14
|
this.creds = config.credentials;
|
|
10
15
|
}
|
|
11
|
-
async listExternalPositions({
|
|
12
|
-
instruments
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
);
|
|
16
|
+
async listExternalPositions({ instruments }) {
|
|
17
|
+
const contractSizeByInstrumentId = new Map(instruments.map((instrument) => [
|
|
18
|
+
instrument.id,
|
|
19
|
+
instrument.precision.quantity.contractSize
|
|
20
|
+
]));
|
|
17
21
|
const rawPositions = await fetchAllPositionRisk(this.creds, this.demo);
|
|
18
22
|
return rawPositions.reduce((positions, rawPosition) => {
|
|
19
23
|
const signedSize = new BigNumber(rawPosition.positionAmt);
|
|
@@ -33,15 +37,12 @@ class BinanceAccountSyncer extends BaseAccountSyncer {
|
|
|
33
37
|
return positions;
|
|
34
38
|
}, []);
|
|
35
39
|
}
|
|
36
|
-
async listExternalFills({
|
|
37
|
-
since,
|
|
38
|
-
instruments,
|
|
39
|
-
openPositions,
|
|
40
|
-
provisionalFills
|
|
41
|
-
}) {
|
|
40
|
+
async listExternalFills({ since, instruments, openPositions, provisionalFills }) {
|
|
42
41
|
const knownInstrumentIds = new Set(instruments.map((instrument) => instrument.id));
|
|
43
42
|
const requestedInstrumentIds = this.collectRequestedInstrumentIds(openPositions, provisionalFills);
|
|
44
|
-
const instrumentIds = [
|
|
43
|
+
const instrumentIds = [
|
|
44
|
+
...requestedInstrumentIds
|
|
45
|
+
].filter((instrumentId) => knownInstrumentIds.has(instrumentId));
|
|
45
46
|
if (!instrumentIds.length) {
|
|
46
47
|
return [];
|
|
47
48
|
}
|
|
@@ -2,19 +2,23 @@ import BigNumber from 'bignumber.js';
|
|
|
2
2
|
import { fetchPositions, fetchExecutionsSince } from '../../client/bybit/rest';
|
|
3
3
|
import { BaseAccountSyncer } from '../base';
|
|
4
4
|
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
7
|
class BybitAccountSyncer extends BaseAccountSyncer {
|
|
8
|
+
static {
|
|
9
|
+
__name(this, "BybitAccountSyncer");
|
|
10
|
+
}
|
|
6
11
|
creds;
|
|
7
12
|
constructor(config) {
|
|
8
13
|
super(config);
|
|
9
14
|
this.creds = config.credentials;
|
|
10
15
|
}
|
|
11
|
-
async listExternalPositions({
|
|
12
|
-
instruments
|
|
13
|
-
}) {
|
|
16
|
+
async listExternalPositions({ instruments }) {
|
|
14
17
|
const rawPositions = await fetchPositions(this.creds, "USDT", this.demo);
|
|
15
|
-
const contractSizeByInstrumentId = new Map(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const contractSizeByInstrumentId = new Map(instruments.map((instrument) => [
|
|
19
|
+
instrument.id,
|
|
20
|
+
instrument.precision.quantity.contractSize
|
|
21
|
+
]));
|
|
18
22
|
return rawPositions.reduce((positions, rawPosition) => {
|
|
19
23
|
if (!rawPosition.size || rawPosition.size === "0" || !rawPosition.side) return positions;
|
|
20
24
|
const contractSize = contractSizeByInstrumentId.get(rawPosition.symbol) ?? 1;
|
package/dist/syncer/factory.js
CHANGED
|
@@ -4,6 +4,8 @@ import { HyperliquidAccountSyncer } from './hyperliquid/syncer';
|
|
|
4
4
|
import { LighterAccountSyncer } from './lighter/syncer';
|
|
5
5
|
import { OkxAccountSyncer } from './okx/syncer';
|
|
6
6
|
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
9
|
function createAccountSyncer(exchange, config) {
|
|
8
10
|
switch (exchange) {
|
|
9
11
|
case "binance":
|
|
@@ -22,5 +24,6 @@ function createAccountSyncer(exchange, config) {
|
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
}
|
|
27
|
+
__name(createAccountSyncer, "createAccountSyncer");
|
|
25
28
|
|
|
26
29
|
export { createAccountSyncer };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function toFundingPaymentEntries(events, symbolToInstrumentId) {
|
|
4
6
|
return events.reduce((entries, event) => {
|
|
5
7
|
const instrumentId = symbolToInstrumentId[event.delta.coin];
|
|
@@ -20,5 +22,6 @@ function toFundingPaymentEntries(events, symbolToInstrumentId) {
|
|
|
20
22
|
return entries;
|
|
21
23
|
}, []);
|
|
22
24
|
}
|
|
25
|
+
__name(toFundingPaymentEntries, "toFundingPaymentEntries");
|
|
23
26
|
|
|
24
27
|
export { toFundingPaymentEntries };
|
|
@@ -3,36 +3,37 @@ import { fetchInfo } from '../../client/hyperliquid/rest';
|
|
|
3
3
|
import { BaseAccountSyncer } from '../base';
|
|
4
4
|
import { toFundingPaymentEntries } from './funding';
|
|
5
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
const HYPERLIQUID_FILL_PAGE_LIMIT = 2e3;
|
|
7
9
|
class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
10
|
+
static {
|
|
11
|
+
__name(this, "HyperliquidAccountSyncer");
|
|
12
|
+
}
|
|
8
13
|
address;
|
|
9
14
|
constructor(config) {
|
|
10
15
|
super(config);
|
|
11
16
|
this.address = config.account.exchangeIdentifier;
|
|
12
17
|
}
|
|
13
|
-
async listExternalPositions({
|
|
14
|
-
instruments
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
instrument.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.demo
|
|
33
|
-
)
|
|
34
|
-
)
|
|
35
|
-
);
|
|
18
|
+
async listExternalPositions({ instruments }) {
|
|
19
|
+
const instrumentByBase = new Map(instruments.map((instrument) => [
|
|
20
|
+
instrument.base,
|
|
21
|
+
{
|
|
22
|
+
id: instrument.id,
|
|
23
|
+
contractSize: instrument.precision.quantity.contractSize
|
|
24
|
+
}
|
|
25
|
+
]));
|
|
26
|
+
const perpDexs = await fetchInfo({
|
|
27
|
+
type: "perpDexs"
|
|
28
|
+
}, this.demo);
|
|
29
|
+
const dexNames = [
|
|
30
|
+
...new Set(perpDexs.map((perpDex) => perpDex?.name ?? ""))
|
|
31
|
+
];
|
|
32
|
+
const states = await Promise.all(dexNames.map((dex) => fetchInfo({
|
|
33
|
+
type: "clearinghouseState",
|
|
34
|
+
user: this.address,
|
|
35
|
+
dex
|
|
36
|
+
}, this.demo)));
|
|
36
37
|
const assetPositions = states.flatMap((state) => state.assetPositions);
|
|
37
38
|
return assetPositions.reduce((positions, { position: rawPosition }) => {
|
|
38
39
|
const szi = new BigNumber(rawPosition.szi);
|
|
@@ -55,34 +56,28 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
55
56
|
return positions;
|
|
56
57
|
}, []);
|
|
57
58
|
}
|
|
58
|
-
async listExternalFills({
|
|
59
|
-
since,
|
|
60
|
-
instruments
|
|
61
|
-
}) {
|
|
59
|
+
async listExternalFills({ since, instruments }) {
|
|
62
60
|
const instrumentSymbolToIdMap = instruments.reduce((acc, instrument) => {
|
|
63
61
|
acc[instrument.base] = instrument.id;
|
|
64
62
|
return acc;
|
|
65
63
|
}, {});
|
|
66
64
|
const allFills = [];
|
|
67
65
|
const seenTids = /* @__PURE__ */ new Set();
|
|
68
|
-
const addFill = (fill) => {
|
|
66
|
+
const addFill = /* @__PURE__ */ __name((fill) => {
|
|
69
67
|
if (!seenTids.has(fill.tid)) {
|
|
70
68
|
seenTids.add(fill.tid);
|
|
71
69
|
allFills.push(fill);
|
|
72
70
|
}
|
|
73
|
-
};
|
|
71
|
+
}, "addFill");
|
|
74
72
|
let cursor = since.getTime();
|
|
75
73
|
let batchSize;
|
|
76
74
|
do {
|
|
77
|
-
const batch = await fetchInfo(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
this.demo
|
|
85
|
-
);
|
|
75
|
+
const batch = await fetchInfo({
|
|
76
|
+
type: "userFillsByTime",
|
|
77
|
+
user: this.address,
|
|
78
|
+
startTime: cursor,
|
|
79
|
+
aggregateByTime: true
|
|
80
|
+
}, this.demo);
|
|
86
81
|
batchSize = batch.length;
|
|
87
82
|
for (const rawFill of batch) {
|
|
88
83
|
addFill(rawFill);
|
|
@@ -98,15 +93,12 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
98
93
|
} while (batchSize === HYPERLIQUID_FILL_PAGE_LIMIT);
|
|
99
94
|
cursor = since.getTime();
|
|
100
95
|
do {
|
|
101
|
-
const twapBatch = await fetchInfo(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
},
|
|
108
|
-
this.demo
|
|
109
|
-
);
|
|
96
|
+
const twapBatch = await fetchInfo({
|
|
97
|
+
type: "userTwapSliceFillsByTime",
|
|
98
|
+
user: this.address,
|
|
99
|
+
startTime: cursor,
|
|
100
|
+
aggregateByTime: true
|
|
101
|
+
}, this.demo);
|
|
110
102
|
batchSize = twapBatch.length;
|
|
111
103
|
for (const item of twapBatch) {
|
|
112
104
|
addFill(item.fill);
|
|
@@ -128,11 +120,6 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
128
120
|
return fills;
|
|
129
121
|
}
|
|
130
122
|
const tradeFee = new BigNumber(rawFill.fee).minus(rawFill.builderFee ?? "0");
|
|
131
|
-
if (tradeFee.isNegative()) {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Hyperliquid fill ${rawFill.tid} has a negative net trade fee (${tradeFee.toFixed()}); the backend external-fill contract does not accept Hyperliquid rebates.`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
123
|
fills.push({
|
|
137
124
|
connector: "hyperliquid",
|
|
138
125
|
exchangeFillId: rawFill.tid.toFixed(),
|
|
@@ -145,15 +132,14 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
145
132
|
timestamp: rawFill.time,
|
|
146
133
|
tradeFee: tradeFee.toFixed(),
|
|
147
134
|
builderFee: new BigNumber(rawFill.builderFee ?? "0").abs().toFixed(),
|
|
148
|
-
liquidation: rawFill.liquidation ? {
|
|
135
|
+
liquidation: rawFill.liquidation ? {
|
|
136
|
+
mark: rawFill.liquidation.markPx
|
|
137
|
+
} : null
|
|
149
138
|
});
|
|
150
139
|
return fills;
|
|
151
140
|
}, []);
|
|
152
141
|
}
|
|
153
|
-
async listExternalFunding({
|
|
154
|
-
since,
|
|
155
|
-
instruments
|
|
156
|
-
}) {
|
|
142
|
+
async listExternalFunding({ since, instruments }) {
|
|
157
143
|
const instrumentSymbolToIdMap = instruments.reduce((acc, instrument) => {
|
|
158
144
|
acc[instrument.base] = instrument.id;
|
|
159
145
|
return acc;
|
|
@@ -163,14 +149,11 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
163
149
|
let cursor = since.getTime();
|
|
164
150
|
let batchSize;
|
|
165
151
|
do {
|
|
166
|
-
const batch = await fetchInfo(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
this.demo
|
|
173
|
-
);
|
|
152
|
+
const batch = await fetchInfo({
|
|
153
|
+
type: "userFunding",
|
|
154
|
+
user: this.address,
|
|
155
|
+
startTime: cursor
|
|
156
|
+
}, this.demo);
|
|
174
157
|
batchSize = batch.length;
|
|
175
158
|
for (const event of batch) {
|
|
176
159
|
allEvents.set(`${event.time}:${event.delta.coin}:${event.hash}`, event);
|
|
@@ -184,7 +167,9 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
184
167
|
cursor = nextCursor;
|
|
185
168
|
}
|
|
186
169
|
} while (batchSize === PAGE_LIMIT);
|
|
187
|
-
return toFundingPaymentEntries([
|
|
170
|
+
return toFundingPaymentEntries([
|
|
171
|
+
...allEvents.values()
|
|
172
|
+
], instrumentSymbolToIdMap);
|
|
188
173
|
}
|
|
189
174
|
isReduceOnly(rawFill) {
|
|
190
175
|
return rawFill.dir.includes("Close");
|
|
@@ -193,5 +178,6 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
193
178
|
function warnStalledPagination(stream, cursor) {
|
|
194
179
|
console.warn(`Hyperliquid ${stream} pagination stalled at timestamp ${cursor}; returned history may be incomplete.`);
|
|
195
180
|
}
|
|
181
|
+
__name(warnStalledPagination, "warnStalledPagination");
|
|
196
182
|
|
|
197
183
|
export { HyperliquidAccountSyncer };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function toFundingPaymentEntries(events, instrumentIds) {
|
|
4
6
|
return events.reduce((entries, event) => {
|
|
5
7
|
const instrumentId = event.market_id.toString();
|
|
@@ -22,5 +24,6 @@ function toFundingPaymentEntries(events, instrumentIds) {
|
|
|
22
24
|
return entries;
|
|
23
25
|
}, []);
|
|
24
26
|
}
|
|
27
|
+
__name(toFundingPaymentEntries, "toFundingPaymentEntries");
|
|
25
28
|
|
|
26
29
|
export { toFundingPaymentEntries };
|