@stryke-xyz/premarket-sdk 1.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/dist/abi/AggregationRouterV6.abi.json +1186 -0
- package/dist/abi/NativeOrderFactory.abi.json +291 -0
- package/dist/abi/NativeOrderImpl.abi.json +381 -0
- package/dist/abi/limitOrderProtocol.json +63 -0
- package/dist/address.d.ts +13 -0
- package/dist/address.js +32 -0
- package/dist/api/filler.d.ts +109 -0
- package/dist/api/filler.js +289 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +3 -0
- package/dist/api/order-helper.d.ts +59 -0
- package/dist/api/order-helper.js +112 -0
- package/dist/api/orderbook-api.d.ts +36 -0
- package/dist/api/orderbook-api.js +69 -0
- package/dist/bps.d.ts +35 -0
- package/dist/bps.js +52 -0
- package/dist/config/chains.d.ts +50 -0
- package/dist/config/chains.js +21 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.js +103 -0
- package/dist/config/markets.d.ts +53 -0
- package/dist/config/markets.js +125 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +30 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +21 -0
- package/dist/limit-order/amounts.d.ts +14 -0
- package/dist/limit-order/amounts.js +19 -0
- package/dist/limit-order/eip712/domain.d.ts +10 -0
- package/dist/limit-order/eip712/domain.js +18 -0
- package/dist/limit-order/eip712/eip712.types.d.ts +23 -0
- package/dist/limit-order/eip712/eip712.types.js +1 -0
- package/dist/limit-order/eip712/index.d.ts +3 -0
- package/dist/limit-order/eip712/index.js +3 -0
- package/dist/limit-order/eip712/order-typed-data-builder.d.ts +6 -0
- package/dist/limit-order/eip712/order-typed-data-builder.js +25 -0
- package/dist/limit-order/extensions/extension-builder.d.ts +35 -0
- package/dist/limit-order/extensions/extension-builder.js +83 -0
- package/dist/limit-order/extensions/extension.d.ts +45 -0
- package/dist/limit-order/extensions/extension.js +108 -0
- package/dist/limit-order/extensions/extension.spec.d.ts +1 -0
- package/dist/limit-order/extensions/extension.spec.js +17 -0
- package/dist/limit-order/extensions/fee-taker/errors.d.ts +2 -0
- package/dist/limit-order/extensions/fee-taker/errors.js +2 -0
- package/dist/limit-order/extensions/fee-taker/fee-calculator.d.ts +40 -0
- package/dist/limit-order/extensions/fee-taker/fee-calculator.js +83 -0
- package/dist/limit-order/extensions/fee-taker/fee-calculator.spec.d.ts +1 -0
- package/dist/limit-order/extensions/fee-taker/fee-calculator.spec.js +14 -0
- package/dist/limit-order/extensions/fee-taker/fee-taker.extension.d.ts +130 -0
- package/dist/limit-order/extensions/fee-taker/fee-taker.extension.js +249 -0
- package/dist/limit-order/extensions/fee-taker/fee-taker.extension.spec.d.ts +1 -0
- package/dist/limit-order/extensions/fee-taker/fee-taker.extension.spec.js +72 -0
- package/dist/limit-order/extensions/fee-taker/fees.d.ts +19 -0
- package/dist/limit-order/extensions/fee-taker/fees.js +36 -0
- package/dist/limit-order/extensions/fee-taker/index.d.ts +7 -0
- package/dist/limit-order/extensions/fee-taker/index.js +7 -0
- package/dist/limit-order/extensions/fee-taker/integrator-fee.d.ts +13 -0
- package/dist/limit-order/extensions/fee-taker/integrator-fee.js +28 -0
- package/dist/limit-order/extensions/fee-taker/resolver-fee.d.ts +19 -0
- package/dist/limit-order/extensions/fee-taker/resolver-fee.js +28 -0
- package/dist/limit-order/extensions/fee-taker/types.d.ts +4 -0
- package/dist/limit-order/extensions/fee-taker/types.js +1 -0
- package/dist/limit-order/extensions/fee-taker/whitelist-half-address.d.ts +18 -0
- package/dist/limit-order/extensions/fee-taker/whitelist-half-address.js +26 -0
- package/dist/limit-order/extensions/index.d.ts +3 -0
- package/dist/limit-order/extensions/index.js +3 -0
- package/dist/limit-order/index.d.ts +10 -0
- package/dist/limit-order/index.js +10 -0
- package/dist/limit-order/interaction.d.ts +16 -0
- package/dist/limit-order/interaction.js +25 -0
- package/dist/limit-order/interaction.spec.d.ts +1 -0
- package/dist/limit-order/interaction.spec.js +8 -0
- package/dist/limit-order/limit-order-with-fee.d.ts +59 -0
- package/dist/limit-order/limit-order-with-fee.js +94 -0
- package/dist/limit-order/limit-order-with-fee.spec.d.ts +1 -0
- package/dist/limit-order/limit-order-with-fee.spec.js +31 -0
- package/dist/limit-order/limit-order.d.ts +63 -0
- package/dist/limit-order/limit-order.js +211 -0
- package/dist/limit-order/limit-order.spec.d.ts +1 -0
- package/dist/limit-order/limit-order.spec.js +103 -0
- package/dist/limit-order/maker-traits.d.ts +200 -0
- package/dist/limit-order/maker-traits.js +309 -0
- package/dist/limit-order/maker-traits.spec.d.ts +1 -0
- package/dist/limit-order/maker-traits.spec.js +102 -0
- package/dist/limit-order/source-track.d.ts +1 -0
- package/dist/limit-order/source-track.js +22 -0
- package/dist/limit-order/taker-traits.d.ts +141 -0
- package/dist/limit-order/taker-traits.js +207 -0
- package/dist/limit-order/types.d.ts +24 -0
- package/dist/limit-order/types.js +1 -0
- package/dist/limit-order/verification.d.ts +16 -0
- package/dist/limit-order/verification.js +108 -0
- package/dist/limit-order-contract/index.d.ts +4 -0
- package/dist/limit-order-contract/index.js +4 -0
- package/dist/limit-order-contract/limit-order-contract.d.ts +34 -0
- package/dist/limit-order-contract/limit-order-contract.js +79 -0
- package/dist/limit-order-contract/native-order-factory.d.ts +10 -0
- package/dist/limit-order-contract/native-order-factory.js +22 -0
- package/dist/limit-order-contract/native-order-impl.d.ts +10 -0
- package/dist/limit-order-contract/native-order-impl.js +24 -0
- package/dist/limit-order-contract/proxy-factory.d.ts +20 -0
- package/dist/limit-order-contract/proxy-factory.js +32 -0
- package/dist/limit-order-contract/proxy-factory.spec.d.ts +1 -0
- package/dist/limit-order-contract/proxy-factory.spec.js +16 -0
- package/dist/limit-order-contract/types.d.ts +6 -0
- package/dist/limit-order-contract/types.js +1 -0
- package/dist/ponder/client/index.d.ts +23 -0
- package/dist/ponder/client/index.js +44 -0
- package/dist/ponder/client/queries/markets.d.ts +30 -0
- package/dist/ponder/client/queries/markets.js +200 -0
- package/dist/ponder/client/queries/positions.d.ts +13 -0
- package/dist/ponder/client/queries/positions.js +406 -0
- package/dist/ponder/client/types/history.d.ts +94 -0
- package/dist/ponder/client/types/history.js +1 -0
- package/dist/ponder/client/types/index.d.ts +5 -0
- package/dist/ponder/client/types/index.js +5 -0
- package/dist/ponder/client/types/market.d.ts +45 -0
- package/dist/ponder/client/types/market.js +1 -0
- package/dist/ponder/client/types/position.d.ts +32 -0
- package/dist/ponder/client/types/position.js +1 -0
- package/dist/ponder/client/types/serializers.d.ts +57 -0
- package/dist/ponder/client/types/serializers.js +248 -0
- package/dist/ponder/client/types/user.d.ts +5 -0
- package/dist/ponder/client/types/user.js +1 -0
- package/dist/ponder/client/utils.d.ts +1 -0
- package/dist/ponder/client/utils.js +32 -0
- package/dist/ponder/generated/index.d.ts +18 -0
- package/dist/ponder/generated/index.js +20 -0
- package/dist/ponder/generated/runtime/batcher.d.ts +105 -0
- package/dist/ponder/generated/runtime/batcher.js +188 -0
- package/dist/ponder/generated/runtime/createClient.d.ts +17 -0
- package/dist/ponder/generated/runtime/createClient.js +24 -0
- package/dist/ponder/generated/runtime/error.d.ts +18 -0
- package/dist/ponder/generated/runtime/error.js +15 -0
- package/dist/ponder/generated/runtime/fetcher.d.ts +10 -0
- package/dist/ponder/generated/runtime/fetcher.js +67 -0
- package/dist/ponder/generated/runtime/generateGraphqlOperation.d.ts +30 -0
- package/dist/ponder/generated/runtime/generateGraphqlOperation.js +128 -0
- package/dist/ponder/generated/runtime/index.d.ts +11 -0
- package/dist/ponder/generated/runtime/index.js +10 -0
- package/dist/ponder/generated/runtime/linkTypeMap.d.ts +9 -0
- package/dist/ponder/generated/runtime/linkTypeMap.js +83 -0
- package/dist/ponder/generated/runtime/typeSelection.d.ts +28 -0
- package/dist/ponder/generated/runtime/typeSelection.js +3 -0
- package/dist/ponder/generated/runtime/types.d.ts +55 -0
- package/dist/ponder/generated/runtime/types.js +2 -0
- package/dist/ponder/generated/schema.d.ts +3026 -0
- package/dist/ponder/generated/schema.js +222 -0
- package/dist/ponder/generated/types.d.ts +2393 -0
- package/dist/ponder/generated/types.js +6915 -0
- package/dist/ponder/index.d.ts +2 -0
- package/dist/ponder/index.js +2 -0
- package/dist/ponder/types.d.ts +3 -0
- package/dist/ponder/types.js +1 -0
- package/dist/rfq-order/index.d.ts +1 -0
- package/dist/rfq-order/index.js +1 -0
- package/dist/rfq-order/rfq-order.d.ts +21 -0
- package/dist/rfq-order/rfq-order.js +22 -0
- package/dist/rfq-order/rfq-order.spec.d.ts +1 -0
- package/dist/rfq-order/rfq-order.spec.js +27 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +2 -0
- package/dist/shared/types.d.ts +79 -0
- package/dist/shared/types.js +12 -0
- package/dist/shared/utils.d.ts +7 -0
- package/dist/shared/utils.js +19 -0
- package/dist/sync/clients/balance-client.d.ts +41 -0
- package/dist/sync/clients/balance-client.js +139 -0
- package/dist/sync/clients/base-client.d.ts +47 -0
- package/dist/sync/clients/base-client.js +154 -0
- package/dist/sync/clients/order-client.d.ts +18 -0
- package/dist/sync/clients/order-client.js +151 -0
- package/dist/sync/index.d.ts +5 -0
- package/dist/sync/index.js +3 -0
- package/dist/sync/redis-ws-client.d.ts +18 -0
- package/dist/sync/redis-ws-client.js +88 -0
- package/dist/sync/types.d.ts +20 -0
- package/dist/sync/types.js +1 -0
- package/dist/utils/mul-div.d.ts +5 -0
- package/dist/utils/mul-div.js +13 -0
- package/dist/utils/orderUtils.d.ts +19 -0
- package/dist/utils/orderUtils.js +51 -0
- package/dist/utils/rand-bigint.d.ts +1 -0
- package/dist/utils/rand-bigint.js +13 -0
- package/dist/utils/rand-bigint.spec.d.ts +1 -0
- package/dist/utils/rand-bigint.spec.js +11 -0
- package/dist/validations.d.ts +1 -0
- package/dist/validations.js +3 -0
- package/package.json +60 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { OrderStatus } from "../../shared/types.js";
|
|
2
|
+
import { BaseSyncClient } from "./base-client.js";
|
|
3
|
+
export class OrderbookSyncClient extends BaseSyncClient {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
// Build full config with channel
|
|
6
|
+
const fullConfig = {
|
|
7
|
+
...config,
|
|
8
|
+
channel: `orderbook:market:${config.marketId}`,
|
|
9
|
+
};
|
|
10
|
+
super(fullConfig);
|
|
11
|
+
this.expireCheckInterval = null;
|
|
12
|
+
}
|
|
13
|
+
async connect() {
|
|
14
|
+
await super.connect();
|
|
15
|
+
this.startExpireCheck();
|
|
16
|
+
}
|
|
17
|
+
async fetchSnapshot() {
|
|
18
|
+
try {
|
|
19
|
+
if (!this.config.snapshotUrl) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const url = `${this.config.snapshotUrl}/api/orders?marketId=${this.config.marketId}&status=ACTIVE`;
|
|
23
|
+
const response = await fetch(url);
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Snapshot fetch failed: ${response.status} ${response.statusText}`);
|
|
26
|
+
}
|
|
27
|
+
const data = (await response.json());
|
|
28
|
+
if (data.success && data.data) {
|
|
29
|
+
const orders = data.data.orders || data.data;
|
|
30
|
+
const snapshotSeq = data.data.seq || data.seq || 0;
|
|
31
|
+
this.dataMap.clear();
|
|
32
|
+
orders.forEach((order) => {
|
|
33
|
+
this.dataMap.set(order.orderHash, order);
|
|
34
|
+
});
|
|
35
|
+
this.lastSeq = snapshotSeq;
|
|
36
|
+
this.notifySnapshotListeners(orders);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error("Error fetching snapshot:", error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
applyMessage(message) {
|
|
44
|
+
const change = message.change;
|
|
45
|
+
switch (change.type) {
|
|
46
|
+
case "INSERT":
|
|
47
|
+
if (change.order) {
|
|
48
|
+
this.dataMap.set(change.orderHash, change.order);
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
case "UPDATE":
|
|
52
|
+
if (change.order) {
|
|
53
|
+
// Only keep the order if it's still ACTIVE, otherwise remove it
|
|
54
|
+
// (CANCELLED and FILLED orders should not be in the orderbook)
|
|
55
|
+
if (change.order.status === OrderStatus.ACTIVE) {
|
|
56
|
+
this.dataMap.set(change.orderHash, change.order);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.dataMap.delete(change.orderHash);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case "DELETE":
|
|
64
|
+
this.dataMap.delete(change.orderHash);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
this.changeListeners.forEach((listener) => {
|
|
68
|
+
try {
|
|
69
|
+
listener(change);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error("Error in change listener:", error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async recoverGap(fromSeq, toSeq) {
|
|
77
|
+
if (!this.config.gapRecoveryUrl) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const gapSize = toSeq - fromSeq + 1;
|
|
81
|
+
if (gapSize > 1000) {
|
|
82
|
+
await this.fullResync();
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
this.setStatus("recovering");
|
|
86
|
+
try {
|
|
87
|
+
const url = `${this.config.gapRecoveryUrl}/api/sync/messages?marketId=${this.config.marketId}&fromSeq=${fromSeq}&toSeq=${toSeq}`;
|
|
88
|
+
const response = await fetch(url);
|
|
89
|
+
const data = (await response.json());
|
|
90
|
+
if (data.success && data.data) {
|
|
91
|
+
const messages = data.data;
|
|
92
|
+
messages.sort((a, b) => a.seq - b.seq);
|
|
93
|
+
this.setStatus("synced");
|
|
94
|
+
return messages;
|
|
95
|
+
}
|
|
96
|
+
this.setStatus("synced");
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
await this.fullResync();
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getOrders() {
|
|
105
|
+
return Array.from(this.dataMap.values());
|
|
106
|
+
}
|
|
107
|
+
getOrder(orderHash) {
|
|
108
|
+
return this.dataMap.get(orderHash);
|
|
109
|
+
}
|
|
110
|
+
startExpireCheck() {
|
|
111
|
+
// Clear any existing interval
|
|
112
|
+
if (this.expireCheckInterval) {
|
|
113
|
+
clearInterval(this.expireCheckInterval);
|
|
114
|
+
}
|
|
115
|
+
// Check for expired orders every 1 second
|
|
116
|
+
this.expireCheckInterval = setInterval(() => {
|
|
117
|
+
const now = Math.floor(Date.now() / 1000);
|
|
118
|
+
const expiredOrders = [];
|
|
119
|
+
for (const [orderHash, order] of this.dataMap.entries()) {
|
|
120
|
+
// Check if order has expired
|
|
121
|
+
if (order.expiresAt && order.expiresAt < now) {
|
|
122
|
+
expiredOrders.push(orderHash);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Remove expired orders and notify listeners
|
|
126
|
+
for (const orderHash of expiredOrders) {
|
|
127
|
+
this.dataMap.delete(orderHash);
|
|
128
|
+
const change = {
|
|
129
|
+
type: "DELETE",
|
|
130
|
+
orderHash,
|
|
131
|
+
};
|
|
132
|
+
this.changeListeners.forEach((listener) => {
|
|
133
|
+
try {
|
|
134
|
+
listener(change);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.error("Error in change listener:", error);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}, 1000);
|
|
142
|
+
}
|
|
143
|
+
async disconnect() {
|
|
144
|
+
// Clear expire check interval
|
|
145
|
+
if (this.expireCheckInterval) {
|
|
146
|
+
clearInterval(this.expireCheckInterval);
|
|
147
|
+
this.expireCheckInterval = null;
|
|
148
|
+
}
|
|
149
|
+
await super.disconnect();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BaseSyncClient } from "./clients/base-client.js";
|
|
2
|
+
export { OrderbookSyncClient } from "./clients/order-client.js";
|
|
3
|
+
export { BalanceSyncClient } from "./clients/balance-client.js";
|
|
4
|
+
export type { OrderChange, SequencedMessage, SyncClientConfig, SyncStatus, } from "./types.js";
|
|
5
|
+
export type { BalanceData, BalanceUpdateMessage, BalanceSyncClientConfig, } from "./clients/balance-client.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type Handler<T = any> = (data: T) => void;
|
|
2
|
+
export declare class RedisWsClient {
|
|
3
|
+
private url;
|
|
4
|
+
private ws;
|
|
5
|
+
private handlers;
|
|
6
|
+
private heartbeat?;
|
|
7
|
+
constructor(url: string);
|
|
8
|
+
private connect;
|
|
9
|
+
private reconnect;
|
|
10
|
+
private startHeartbeat;
|
|
11
|
+
private stopHeartbeat;
|
|
12
|
+
subscribe<T>(channel: string, handler: Handler<T>): void;
|
|
13
|
+
unsubscribe(channel: string, handler?: Handler): void;
|
|
14
|
+
private subscribeInternal;
|
|
15
|
+
private unsubscribeInternal;
|
|
16
|
+
close(): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export class RedisWsClient {
|
|
2
|
+
constructor(url) {
|
|
3
|
+
this.url = url;
|
|
4
|
+
this.handlers = new Map();
|
|
5
|
+
this.connect();
|
|
6
|
+
}
|
|
7
|
+
connect() {
|
|
8
|
+
this.ws = new WebSocket(this.url);
|
|
9
|
+
this.ws.onopen = () => {
|
|
10
|
+
this.startHeartbeat();
|
|
11
|
+
// Re-subscribe to all channels after reconnection
|
|
12
|
+
for (const channel of this.handlers.keys()) {
|
|
13
|
+
this.subscribeInternal(channel);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
this.ws.onmessage = (event) => {
|
|
17
|
+
const message = event.data;
|
|
18
|
+
// Redis messages come directly as strings from the bridge
|
|
19
|
+
// Since we subscribe to one channel per client instance in practice,
|
|
20
|
+
// we can call all handlers
|
|
21
|
+
for (const handlers of this.handlers.values()) {
|
|
22
|
+
handlers.forEach((fn) => fn(message));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
this.ws.onclose = () => this.reconnect();
|
|
26
|
+
this.ws.onerror = () => this.ws.close();
|
|
27
|
+
}
|
|
28
|
+
reconnect() {
|
|
29
|
+
this.stopHeartbeat();
|
|
30
|
+
setTimeout(() => this.connect(), 1000);
|
|
31
|
+
}
|
|
32
|
+
startHeartbeat() {
|
|
33
|
+
this.heartbeat = setInterval(() => {
|
|
34
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
35
|
+
this.ws.send(JSON.stringify({ type: "ping" }));
|
|
36
|
+
}
|
|
37
|
+
}, 20000);
|
|
38
|
+
}
|
|
39
|
+
stopHeartbeat() {
|
|
40
|
+
if (this.heartbeat)
|
|
41
|
+
clearInterval(this.heartbeat);
|
|
42
|
+
}
|
|
43
|
+
subscribe(channel, handler) {
|
|
44
|
+
if (!this.handlers.has(channel)) {
|
|
45
|
+
this.handlers.set(channel, new Set());
|
|
46
|
+
this.subscribeInternal(channel);
|
|
47
|
+
}
|
|
48
|
+
this.handlers.get(channel).add(handler);
|
|
49
|
+
}
|
|
50
|
+
unsubscribe(channel, handler) {
|
|
51
|
+
const handlers = this.handlers.get(channel);
|
|
52
|
+
if (!handlers)
|
|
53
|
+
return;
|
|
54
|
+
if (handler) {
|
|
55
|
+
handlers.delete(handler);
|
|
56
|
+
if (handlers.size === 0) {
|
|
57
|
+
this.handlers.delete(channel);
|
|
58
|
+
this.unsubscribeInternal(channel);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.handlers.delete(channel);
|
|
63
|
+
this.unsubscribeInternal(channel);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
subscribeInternal(channel) {
|
|
67
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
68
|
+
this.ws.send(JSON.stringify({
|
|
69
|
+
type: "subscribe",
|
|
70
|
+
channel,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
unsubscribeInternal(channel) {
|
|
75
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
76
|
+
this.ws.send(JSON.stringify({
|
|
77
|
+
type: "unsubscribe",
|
|
78
|
+
channel,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
close() {
|
|
83
|
+
this.stopHeartbeat();
|
|
84
|
+
if (this.ws) {
|
|
85
|
+
this.ws.close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StoredOrder } from "../shared/types.js";
|
|
2
|
+
export type SyncStatus = "connecting" | "syncing" | "synced" | "recovering" | "disconnected" | "error";
|
|
3
|
+
export interface OrderChange {
|
|
4
|
+
type: "INSERT" | "UPDATE" | "DELETE";
|
|
5
|
+
orderHash: string;
|
|
6
|
+
order?: StoredOrder;
|
|
7
|
+
}
|
|
8
|
+
export interface SequencedMessage {
|
|
9
|
+
seq: number;
|
|
10
|
+
marketId: string;
|
|
11
|
+
change: OrderChange;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
}
|
|
14
|
+
export interface SyncClientConfig {
|
|
15
|
+
redisUrl: string;
|
|
16
|
+
gapRecoveryUrl?: string;
|
|
17
|
+
marketId: string;
|
|
18
|
+
snapshotUrl?: string;
|
|
19
|
+
channel?: string;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export var Rounding;
|
|
2
|
+
(function (Rounding) {
|
|
3
|
+
Rounding[Rounding["Ceil"] = 0] = "Ceil";
|
|
4
|
+
Rounding[Rounding["Floor"] = 1] = "Floor";
|
|
5
|
+
})(Rounding || (Rounding = {}));
|
|
6
|
+
// todo: move to more appropriate place
|
|
7
|
+
export function mulDiv(a, b, x, rounding = Rounding.Floor) {
|
|
8
|
+
const res = (a * b) / x;
|
|
9
|
+
if (rounding === Rounding.Ceil && (a * b) % x > 0) {
|
|
10
|
+
return res + 1n;
|
|
11
|
+
}
|
|
12
|
+
return res;
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Hex } from "viem";
|
|
2
|
+
import { LimitOrder } from "../limit-order";
|
|
3
|
+
import type { OrderSignature } from "../shared/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Build makerAssetSuffix for ERC6909 extension
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildMakerAssetSuffix(tokenAddress: string, tokenId: Hex): string;
|
|
8
|
+
/**
|
|
9
|
+
* Decode asset suffix (makerAssetSuffix or takerAssetSuffix) to extract token address and tokenId
|
|
10
|
+
* Format: 0x + [32 bytes padded token address] + [32 bytes tokenId] + [32 bytes offset] + [32 bytes length]
|
|
11
|
+
*/
|
|
12
|
+
export declare function decodeAssetSuffix(suffix: string): {
|
|
13
|
+
token: `0x${string}`;
|
|
14
|
+
tokenId: bigint;
|
|
15
|
+
} | null;
|
|
16
|
+
/**
|
|
17
|
+
* Verify order signature and recover signer address
|
|
18
|
+
*/
|
|
19
|
+
export declare function verifyOrderSignature(limitOrder: LimitOrder, signature: OrderSignature, chainId: number): Promise<string>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { pad, toHex, recoverAddress, concat } from "viem";
|
|
2
|
+
/**
|
|
3
|
+
* Build makerAssetSuffix for ERC6909 extension
|
|
4
|
+
*/
|
|
5
|
+
export function buildMakerAssetSuffix(tokenAddress, tokenId) {
|
|
6
|
+
const tokenPadded = pad(tokenAddress, { size: 32 }).slice(2);
|
|
7
|
+
const tokenIdPadded = pad(tokenId, { size: 32 }).slice(2);
|
|
8
|
+
const offsetPadded = pad(toHex(192), { size: 32 }).slice(2);
|
|
9
|
+
const lengthPadded = pad(toHex(0), { size: 32 }).slice(2);
|
|
10
|
+
return "0x" + tokenPadded + tokenIdPadded + offsetPadded + lengthPadded;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Decode asset suffix (makerAssetSuffix or takerAssetSuffix) to extract token address and tokenId
|
|
14
|
+
* Format: 0x + [32 bytes padded token address] + [32 bytes tokenId] + [32 bytes offset] + [32 bytes length]
|
|
15
|
+
*/
|
|
16
|
+
export function decodeAssetSuffix(suffix) {
|
|
17
|
+
if (suffix === "0x" || suffix.length < 130)
|
|
18
|
+
return null;
|
|
19
|
+
const data = suffix.slice(2); // Remove 0x prefix
|
|
20
|
+
if (data.length < 128)
|
|
21
|
+
return null; // Need at least 64 bytes (128 hex chars) for address + tokenId
|
|
22
|
+
// Token address is in the last 20 bytes (40 hex chars) of the first 32-byte chunk
|
|
23
|
+
// Bytes 0-31: padded address (address is in bytes 12-31, hex chars 24-64)
|
|
24
|
+
const tokenAddressHex = ("0x" + data.slice(24, 64));
|
|
25
|
+
// TokenId is in the second 32-byte chunk
|
|
26
|
+
// Bytes 32-63: tokenId (hex chars 64-128)
|
|
27
|
+
const tokenIdHex = "0x" + data.slice(64, 128);
|
|
28
|
+
const tokenId = BigInt(tokenIdHex);
|
|
29
|
+
return {
|
|
30
|
+
token: tokenAddressHex,
|
|
31
|
+
tokenId,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify order signature and recover signer address
|
|
36
|
+
*/
|
|
37
|
+
export async function verifyOrderSignature(limitOrder, signature, chainId) {
|
|
38
|
+
const orderHash = limitOrder.getOrderHash(chainId);
|
|
39
|
+
// Extract v from vs
|
|
40
|
+
const vsBigInt = BigInt(signature.vs);
|
|
41
|
+
const v = vsBigInt >> BigInt(255) === BigInt(1) ? 28 : 27;
|
|
42
|
+
const sMask = (BigInt(1) << BigInt(255)) - BigInt(1);
|
|
43
|
+
const s = pad(toHex(vsBigInt & sMask), { size: 32 });
|
|
44
|
+
// Reconstruct full signature
|
|
45
|
+
const fullSignature = concat([signature.r, s, toHex(v)]);
|
|
46
|
+
const recoveredAddress = await recoverAddress({
|
|
47
|
+
hash: orderHash,
|
|
48
|
+
signature: fullSignature,
|
|
49
|
+
});
|
|
50
|
+
return recoveredAddress.toLowerCase();
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function randBigInt(max: number | bigint): bigint;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { randomBytes } from 'ethers';
|
|
2
|
+
export function randBigInt(max) {
|
|
3
|
+
let bytesCount = 0;
|
|
4
|
+
max = BigInt(max) + 1n;
|
|
5
|
+
let rest = max;
|
|
6
|
+
while (rest) {
|
|
7
|
+
rest = rest >> 8n;
|
|
8
|
+
bytesCount += 1;
|
|
9
|
+
}
|
|
10
|
+
const bytes = randomBytes(bytesCount);
|
|
11
|
+
const val = bytes.reduce((acc, val, i) => acc + (BigInt(val) << BigInt(i * 8)), 0n);
|
|
12
|
+
return val % max;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { randBigInt } from './rand-bigint.js';
|
|
2
|
+
describe('randBigint', () => {
|
|
3
|
+
it('should generate rand bigint in correct interval', () => {
|
|
4
|
+
expect(randBigInt(1)).toBeGreaterThanOrEqual(0n);
|
|
5
|
+
expect(randBigInt(1)).toBeLessThanOrEqual(1n);
|
|
6
|
+
expect(randBigInt(10n)).toBeGreaterThanOrEqual(0);
|
|
7
|
+
expect(randBigInt(10n)).toBeLessThanOrEqual(10n);
|
|
8
|
+
expect(randBigInt(2n << 96n)).toBeGreaterThanOrEqual(0);
|
|
9
|
+
expect(randBigInt(2n << 96n)).toBeLessThanOrEqual(2n << 96n);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isInt(val: number): boolean;
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stryke-xyz/premarket-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "bun test",
|
|
21
|
+
"test:e2e": "bun test test/e2e/index.test.ts",
|
|
22
|
+
"ponder:codegen": "genql --schema ./src/ponder/schema.graphql --output ./src/ponder/generated",
|
|
23
|
+
"fill-orderbook": "bun run scripts/fill-orderbook.ts"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@1inch/byte-utils": "3.0.0",
|
|
27
|
+
"ethers": "6.13.5"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@1inch/eslint-config": "3.0.7",
|
|
31
|
+
"@1inch/tsconfig": "^1.0.9",
|
|
32
|
+
"@swc/cli": "0.7.7",
|
|
33
|
+
"@swc/core": "^1.13.3",
|
|
34
|
+
"@swc/jest": "^0.2.39",
|
|
35
|
+
"@types/jest": "^30.0.0",
|
|
36
|
+
"@types/node": "^22.17.0",
|
|
37
|
+
"@typescript-eslint/eslint-plugin": "~8.20.0",
|
|
38
|
+
"@typescript-eslint/parser": "~8.20.0",
|
|
39
|
+
"axios": "^1.12.0",
|
|
40
|
+
"eslint": "^9.32.0",
|
|
41
|
+
"eslint-config-prettier": "~10.1.8",
|
|
42
|
+
"eslint-config-standard": "^17.1.0",
|
|
43
|
+
"eslint-import-resolver-typescript": "3.7.0",
|
|
44
|
+
"eslint-plugin-import": "~2.31.0",
|
|
45
|
+
"eslint-plugin-n": "^17.21.3",
|
|
46
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
47
|
+
"eslint-plugin-promise": "^7.2.1",
|
|
48
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
49
|
+
"generate-changelog": "1.8.0",
|
|
50
|
+
"jest": "^30.0.5",
|
|
51
|
+
"prettier": "^3.6.2",
|
|
52
|
+
"testcontainers": "^11.5.1",
|
|
53
|
+
"tsdoc-markdown": "^1.4.1",
|
|
54
|
+
"tslib": "2.8.1",
|
|
55
|
+
"typescript": "5.8.3",
|
|
56
|
+
"bun-types": "^1.0.0",
|
|
57
|
+
"@genql/cli": "^3.0.0",
|
|
58
|
+
"viem": "^2.7.0"
|
|
59
|
+
}
|
|
60
|
+
}
|