@pear-protocol/exchanges-sdk 0.6.2 → 0.6.4

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 CHANGED
@@ -101,7 +101,7 @@ const exchanges = new ExchangesSDK({
101
101
 
102
102
  Hyperliquid status requires the builder address and the minimum approved fee in tenths of a basis point. Lighter status requires the integrator account and minimum maker/taker approval caps in Lighter fee ticks (parts per million). These thresholds must match the fees configured by the trading backend.
103
103
 
104
- Historical Hyperliquid fill synchronization uses the exchange's globally unique `time:coin:tid` identity. Existing consumers that persisted bare `tid` identifiers must account for the transition overlap. Synchronization also fails closed when the exchange reports a maker rebate: the current core external-fill contract accepts only non-negative fees, so the SDK will not silently turn a rebate into a cost or advance the synchronization watermark past it.
104
+ Historical Hyperliquid fill synchronization identifies fills by bare `tid` and requests them aggregated by time, so partial fills of one crossing order arrive as a single fill. Consumers that persisted composite `time:coin:tid` identifiers must account for the transition overlap. Hyperliquid serves only the 10,000 most recent fills; an account with a longer history imports from that boundary forward, and the snapshot-alignment synthetics cover the residual gap. Synchronization fails closed when the exchange reports a maker rebate: the current core external-fill contract accepts only non-negative fees, so the SDK will not silently turn a rebate into a cost or advance the synchronization watermark past it.
105
105
 
106
106
  ## Account Status
107
107
 
@@ -64,11 +64,10 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
64
64
  return acc;
65
65
  }, {});
66
66
  const allFills = [];
67
- const seenFillIds = /* @__PURE__ */ new Set();
67
+ const seenTids = /* @__PURE__ */ new Set();
68
68
  const addFill = (fill) => {
69
- const fillId = hyperliquidFillId(fill);
70
- if (!seenFillIds.has(fillId)) {
71
- seenFillIds.add(fillId);
69
+ if (!seenTids.has(fill.tid)) {
70
+ seenTids.add(fill.tid);
72
71
  allFills.push(fill);
73
72
  }
74
73
  };
@@ -80,7 +79,7 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
80
79
  type: "userFillsByTime",
81
80
  user: this.address,
82
81
  startTime: cursor,
83
- aggregateByTime: false
82
+ aggregateByTime: true
84
83
  },
85
84
  this.demo
86
85
  );
@@ -104,7 +103,7 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
104
103
  type: "userTwapSliceFillsByTime",
105
104
  user: this.address,
106
105
  startTime: cursor,
107
- aggregateByTime: false
106
+ aggregateByTime: true
108
107
  },
109
108
  this.demo
110
109
  );
@@ -131,12 +130,12 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
131
130
  const tradeFee = new BigNumber(rawFill.fee).minus(rawFill.builderFee ?? "0");
132
131
  if (tradeFee.isNegative()) {
133
132
  throw new Error(
134
- `Hyperliquid fill ${hyperliquidFillId(rawFill)} has a negative net trade fee (${tradeFee.toFixed()}); the backend external-fill contract does not accept Hyperliquid rebates.`
133
+ `Hyperliquid fill ${rawFill.tid} has a negative net trade fee (${tradeFee.toFixed()}); the backend external-fill contract does not accept Hyperliquid rebates.`
135
134
  );
136
135
  }
137
136
  fills.push({
138
137
  connector: "hyperliquid",
139
- exchangeFillId: hyperliquidFillId(rawFill),
138
+ exchangeFillId: rawFill.tid.toFixed(),
140
139
  cloid: rawFill.cloid ?? null,
141
140
  symbol: instrumentId,
142
141
  price: rawFill.px,
@@ -191,9 +190,6 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
191
190
  return rawFill.dir.includes("Close");
192
191
  }
193
192
  }
194
- function hyperliquidFillId(fill) {
195
- return `${fill.time}:${fill.coin}:${fill.tid}`;
196
- }
197
193
  function warnStalledPagination(stream, cursor) {
198
194
  console.warn(`Hyperliquid ${stream} pagination stalled at timestamp ${cursor}; returned history may be incomplete.`);
199
195
  }
@@ -77,18 +77,18 @@ describe("HyperliquidAccountSyncer fill mapping", () => {
77
77
  });
78
78
  expect(fills).toEqual([
79
79
  expect.objectContaining({
80
- exchangeFillId: "1700000000000:BTC:456",
80
+ exchangeFillId: "456",
81
81
  tradeFee: "0.8",
82
82
  builderFee: "0.2"
83
83
  })
84
84
  ]);
85
85
  expect(fetchInfoMock).toHaveBeenCalledWith(expect.objectContaining({ type: "userFillsByTime" }), true);
86
86
  expect(fetchInfoMock).toHaveBeenCalledWith(
87
- expect.objectContaining({ type: "userFillsByTime", aggregateByTime: false }),
87
+ expect.objectContaining({ type: "userFillsByTime", aggregateByTime: true }),
88
88
  true
89
89
  );
90
90
  expect(fetchInfoMock).toHaveBeenCalledWith(
91
- expect.objectContaining({ type: "userTwapSliceFillsByTime", aggregateByTime: false }),
91
+ expect.objectContaining({ type: "userTwapSliceFillsByTime", aggregateByTime: true }),
92
92
  true
93
93
  );
94
94
  });
@@ -125,7 +125,7 @@ describe("HyperliquidAccountSyncer fill mapping", () => {
125
125
  provisionalFills: []
126
126
  })
127
127
  ).rejects.toThrow(
128
- "Hyperliquid fill 1700000000000:BTC:456 has a negative net trade fee (-0.1); the backend external-fill contract does not accept Hyperliquid rebates."
128
+ "Hyperliquid fill 456 has a negative net trade fee (-0.1); the backend external-fill contract does not accept Hyperliquid rebates."
129
129
  );
130
130
  });
131
131
  it("warns when inclusive fill pagination cannot move past the current timestamp", async () => {
@@ -181,7 +181,7 @@ describe("HyperliquidAccountSyncer fill mapping", () => {
181
181
  provisionalFills: []
182
182
  });
183
183
  expect(fills).toHaveLength(1e4);
184
- expect(fetchInfoMock).toHaveBeenCalledWith(expect.objectContaining({ aggregateByTime: false }), true);
184
+ expect(fetchInfoMock).toHaveBeenCalledWith(expect.objectContaining({ aggregateByTime: true }), true);
185
185
  });
186
186
  it("pages through a full retention window of fills", async () => {
187
187
  let page = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/exchanges-sdk",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Pear Protocol Exchanges SDK",
5
5
  "private": false,
6
6
  "type": "module",
@@ -27,9 +27,9 @@
27
27
  "test:watch": "vitest"
28
28
  },
29
29
  "dependencies": {
30
- "@pear-protocol/core-sdk": "^1.12.0",
31
- "@pear-protocol/types": "^1.15.1",
32
- "@pear-protocol/utils": "^0.4.1",
30
+ "@pear-protocol/core-sdk": "^1.12.2",
31
+ "@pear-protocol/types": "^1.17.0",
32
+ "@pear-protocol/utils": "^0.5.0",
33
33
  "bignumber.js": "^11.1.1",
34
34
  "partysocket": "^1.0.3",
35
35
  "viem": "^2.48.8"