@stryke-xyz/premarket-sdk 1.2.3 → 1.2.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.
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "RedisWsClient", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return RedisWsClient;
9
+ }
10
+ });
11
+ function _class_call_check(instance, Constructor) {
12
+ if (!(instance instanceof Constructor)) {
13
+ throw new TypeError("Cannot call a class as a function");
14
+ }
15
+ }
16
+ function _defineProperties(target, props) {
17
+ for(var i = 0; i < props.length; i++){
18
+ var descriptor = props[i];
19
+ descriptor.enumerable = descriptor.enumerable || false;
20
+ descriptor.configurable = true;
21
+ if ("value" in descriptor) descriptor.writable = true;
22
+ Object.defineProperty(target, descriptor.key, descriptor);
23
+ }
24
+ }
25
+ function _create_class(Constructor, protoProps, staticProps) {
26
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
27
+ if (staticProps) _defineProperties(Constructor, staticProps);
28
+ return Constructor;
29
+ }
30
+ function _define_property(obj, key, value) {
31
+ if (key in obj) {
32
+ Object.defineProperty(obj, key, {
33
+ value: value,
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true
37
+ });
38
+ } else {
39
+ obj[key] = value;
40
+ }
41
+ return obj;
42
+ }
43
+ function scheduleDeferred(callback) {
44
+ return setTimeout(callback, 1000);
45
+ }
46
+ var RedisWsClient = /*#__PURE__*/ function() {
47
+ "use strict";
48
+ function RedisWsClient(url) {
49
+ _class_call_check(this, RedisWsClient);
50
+ _define_property(this, "url", void 0);
51
+ _define_property(this, "ws", void 0);
52
+ _define_property(this, "handlers", void 0);
53
+ _define_property(this, "heartbeat", void 0);
54
+ _define_property(this, "reconnectTimeout", void 0);
55
+ _define_property(this, "shouldReconnect", void 0);
56
+ this.url = url;
57
+ this.handlers = new Map();
58
+ this.reconnectTimeout = null;
59
+ this.shouldReconnect = true;
60
+ this.connect();
61
+ }
62
+ _create_class(RedisWsClient, [
63
+ {
64
+ key: "connect",
65
+ value: function connect() {
66
+ var _this = this;
67
+ if (!this.shouldReconnect) return;
68
+ this.ws = new WebSocket(this.url);
69
+ this.ws.onopen = function() {
70
+ _this.startHeartbeat();
71
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
72
+ try {
73
+ // Re-subscribe to all channels after reconnection
74
+ for(var _iterator = _this.handlers.keys()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
75
+ var channel = _step.value;
76
+ _this.subscribeInternal(channel);
77
+ }
78
+ } catch (err) {
79
+ _didIteratorError = true;
80
+ _iteratorError = err;
81
+ } finally{
82
+ try {
83
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
84
+ _iterator.return();
85
+ }
86
+ } finally{
87
+ if (_didIteratorError) {
88
+ throw _iteratorError;
89
+ }
90
+ }
91
+ }
92
+ };
93
+ this.ws.onmessage = function(event) {
94
+ var message = event.data;
95
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
96
+ try {
97
+ // Redis messages come directly as strings from the bridge
98
+ // Since we subscribe to one channel per client instance in practice,
99
+ // we can call all handlers
100
+ for(var _iterator = _this.handlers.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
101
+ var handlers = _step.value;
102
+ handlers.forEach(function(fn) {
103
+ return fn(message);
104
+ });
105
+ }
106
+ } catch (err) {
107
+ _didIteratorError = true;
108
+ _iteratorError = err;
109
+ } finally{
110
+ try {
111
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
112
+ _iterator.return();
113
+ }
114
+ } finally{
115
+ if (_didIteratorError) {
116
+ throw _iteratorError;
117
+ }
118
+ }
119
+ }
120
+ };
121
+ this.ws.onclose = function() {
122
+ return _this.reconnect();
123
+ };
124
+ this.ws.onerror = function() {
125
+ return _this.ws.close();
126
+ };
127
+ }
128
+ },
129
+ {
130
+ key: "reconnect",
131
+ value: function reconnect() {
132
+ var _this = this;
133
+ if (!this.shouldReconnect) return;
134
+ this.stopHeartbeat();
135
+ this.clearReconnectTimeout();
136
+ this.reconnectTimeout = scheduleDeferred(function() {
137
+ _this.reconnectTimeout = null;
138
+ _this.connect();
139
+ });
140
+ }
141
+ },
142
+ {
143
+ key: "startHeartbeat",
144
+ value: function startHeartbeat() {
145
+ var _this = this;
146
+ this.heartbeat = setInterval(function() {
147
+ if (_this.ws.readyState === WebSocket.OPEN) {
148
+ _this.ws.send(JSON.stringify({
149
+ type: "ping"
150
+ }));
151
+ }
152
+ }, 20000);
153
+ }
154
+ },
155
+ {
156
+ key: "stopHeartbeat",
157
+ value: function stopHeartbeat() {
158
+ if (this.heartbeat) clearInterval(this.heartbeat);
159
+ }
160
+ },
161
+ {
162
+ key: "clearReconnectTimeout",
163
+ value: function clearReconnectTimeout() {
164
+ if (this.reconnectTimeout) {
165
+ clearTimeout(this.reconnectTimeout);
166
+ this.reconnectTimeout = null;
167
+ }
168
+ }
169
+ },
170
+ {
171
+ key: "subscribe",
172
+ value: function subscribe(channel, handler) {
173
+ if (!this.handlers.has(channel)) {
174
+ this.handlers.set(channel, new Set());
175
+ this.subscribeInternal(channel);
176
+ }
177
+ this.handlers.get(channel).add(handler);
178
+ }
179
+ },
180
+ {
181
+ key: "unsubscribe",
182
+ value: function unsubscribe(channel, handler) {
183
+ var handlers = this.handlers.get(channel);
184
+ if (!handlers) return;
185
+ if (handler) {
186
+ handlers.delete(handler);
187
+ if (handlers.size === 0) {
188
+ this.handlers.delete(channel);
189
+ this.unsubscribeInternal(channel);
190
+ }
191
+ } else {
192
+ this.handlers.delete(channel);
193
+ this.unsubscribeInternal(channel);
194
+ }
195
+ }
196
+ },
197
+ {
198
+ key: "subscribeInternal",
199
+ value: function subscribeInternal(channel) {
200
+ if (this.ws.readyState === WebSocket.OPEN) {
201
+ this.ws.send(JSON.stringify({
202
+ type: "subscribe",
203
+ channel: channel
204
+ }));
205
+ }
206
+ }
207
+ },
208
+ {
209
+ key: "unsubscribeInternal",
210
+ value: function unsubscribeInternal(channel) {
211
+ if (this.ws.readyState === WebSocket.OPEN) {
212
+ this.ws.send(JSON.stringify({
213
+ type: "unsubscribe",
214
+ channel: channel
215
+ }));
216
+ }
217
+ }
218
+ },
219
+ {
220
+ key: "close",
221
+ value: function close() {
222
+ this.shouldReconnect = false;
223
+ this.stopHeartbeat();
224
+ this.clearReconnectTimeout();
225
+ if (this.ws) {
226
+ this.ws.onclose = null;
227
+ }
228
+ if (this.ws) {
229
+ this.ws.close();
230
+ }
231
+ }
232
+ }
233
+ ]);
234
+ return RedisWsClient;
235
+ }();
@@ -0,0 +1,89 @@
1
+ # Utilities Guide
2
+
3
+ The `utils` folder contains small reusable helpers that do not belong to one
4
+ domain module but are still part of the SDK's public surface.
5
+
6
+ ## Source map
7
+
8
+ - [`mul-div.ts`](./mul-div.ts) provides deterministic multiply-divide math with
9
+ optional rounding up
10
+ - [`rand-bigint.ts`](./rand-bigint.ts) provides secure random bigint generation
11
+ - [`orderUtils.ts`](./orderUtils.ts) provides token-pair helpers and a
12
+ signature-verification shortcut
13
+
14
+ ## `mulDiv` and `Rounding`
15
+
16
+ `mulDiv(a, b, x, rounding?)` performs integer multiplication and division in one
17
+ step using `bigint` arithmetic.
18
+
19
+ Public exports:
20
+
21
+ - `Rounding`
22
+ - `Ceil`
23
+ - `Floor`
24
+ - `mulDiv(a, b, x, rounding?)`
25
+
26
+ ```ts
27
+ import { Rounding, mulDiv } from "@stryke-xyz/premarket-sdk";
28
+
29
+ const floorValue = mulDiv(10n, 3n, 4n);
30
+ const ceilValue = mulDiv(10n, 3n, 4n, Rounding.Ceil);
31
+ ```
32
+
33
+ This helper is especially relevant to the [Vault guide](../vault/README.md),
34
+ where collateral previews need deterministic rounding behavior.
35
+
36
+ ## `randBigInt`
37
+
38
+ `randBigInt(max)` returns a cryptographically secure random bigint in the range
39
+ `[0, max]`.
40
+
41
+ ```ts
42
+ import { randBigInt } from "@stryke-xyz/premarket-sdk";
43
+
44
+ const salt = randBigInt((1n << 96n) - 1n);
45
+ ```
46
+
47
+ Implementation notes:
48
+
49
+ - it requires `globalThis.crypto.getRandomValues`
50
+ - it throws if no secure random source is available
51
+ - it is used by the exchange order builder for default salts
52
+
53
+ ## Order utility helpers
54
+
55
+ [`orderUtils.ts`](./orderUtils.ts) exports a few low-level helpers that are
56
+ useful when app code needs token-id normalization or direct signature recovery.
57
+
58
+ Public exports:
59
+
60
+ - `optionPrmToPrmTokenId(tokenId)`
61
+ - `prmToOptionPrmTokenId(prmTokenId)`
62
+ - `isComplementaryOptionTokenPair(tokenIdA, tokenIdB)`
63
+ - `verifyOrderSignature(order, signature, chainId, exchangeAddress)`
64
+
65
+ ```ts
66
+ import {
67
+ isComplementaryOptionTokenPair,
68
+ verifyOrderSignature,
69
+ } from "@stryke-xyz/premarket-sdk";
70
+
71
+ const complementary = isComplementaryOptionTokenPair(100n, 101n);
72
+ const signer = await verifyOrderSignature(
73
+ order,
74
+ signature,
75
+ 4326,
76
+ exchangeAddress,
77
+ );
78
+ ```
79
+
80
+ Relationship to the domain modules:
81
+
82
+ - the token-id helpers overlap conceptually with the [Vault guide](../vault/README.md)
83
+ and [Exchange guide](../exchange/README.md)
84
+ - `verifyOrderSignature` is a thin convenience wrapper around exchange
85
+ EIP-712 signer recovery
86
+
87
+ When you want the richer context and invariants, prefer the domain guides. When
88
+ you want the smallest possible helper for a utility task, this module is the
89
+ right place.
@@ -0,0 +1,268 @@
1
+ # Vault Guide
2
+
3
+ The `vault` module documents the SDK surface built around
4
+ `OptionMarketVault`. It covers token-id derivation, collateral and settlement
5
+ math, role constants, and transaction builders for mint, redeem, withdraw,
6
+ rollover, and related flows.
7
+
8
+ ## Source map
9
+
10
+ - [`index.ts`](./index.ts) re-exports the public vault surface
11
+ - [`types.ts`](./types.ts) defines vault-level structs used across helpers
12
+ - [`token-ids.ts`](./token-ids.ts) derives `PRM` and `oPRM` token ids
13
+ - [`collateral.ts`](./collateral.ts) mirrors collateral and payoff math
14
+ - [`transactions.ts`](./transactions.ts) builds calldata and transaction envelopes
15
+ - [`constants.ts`](./constants.ts) exports precision constants and role enums
16
+
17
+ ## What this module is for
18
+
19
+ In plain language:
20
+
21
+ - it tells integrators how option position tokens are identified
22
+ - it lets frontends and services estimate collateral, fees, and payouts without
23
+ re-implementing Solidity math
24
+ - it gives callers ABI-backed transaction builders for the public vault flows
25
+
26
+ ## Vault concepts
27
+
28
+ The vault mints paired ERC-6909 position ids:
29
+
30
+ - `PRM`
31
+ - the collateral-side position token
32
+ - always even
33
+ - `oPRM`
34
+ - the option claim token
35
+ - always odd
36
+
37
+ The pairing rule is simple and intentional:
38
+
39
+ - `oPrmTokenId = prmTokenId | 1`
40
+ - `optionPrmToPrm(tokenId)` clears the low bit and returns the canonical `PRM`
41
+ id whether the input is already `PRM` or `oPRM`
42
+
43
+ This convention is used throughout the SDK and should be treated as canonical.
44
+
45
+ ## Public types
46
+
47
+ The main type definitions live in [`types.ts`](./types.ts):
48
+
49
+ - `VaultInstrument`
50
+ - `{ marketId, tick, isCall }`
51
+ - used when minting or describing a strike-side instrument
52
+ - `VaultMarket`
53
+ - bigint-based market shape matching the vault and registry configuration
54
+ - `PrmInfo`
55
+ - metadata associated with a minted `PRM` family
56
+ - `TokenIdParams`
57
+ - the full parameter set needed to derive a token id
58
+
59
+ [`collateral.ts`](./collateral.ts) also exports calculation-specific types:
60
+
61
+ - `MarketParams`
62
+ - `InstrumentParams`
63
+ - `SpreadBounds`
64
+
65
+ These smaller helper types are useful when callers only need the math helpers
66
+ and not the full market struct.
67
+
68
+ ## Precision constants and roles
69
+
70
+ [`constants.ts`](./constants.ts) exposes the shared vault constants:
71
+
72
+ - `VAULT_TOKEN_PRECISION = 1e18`
73
+ - `FEE_BPS_PRECISION = 1e6`
74
+ - `PNL_PRECISION = 1e18`
75
+ - `Role`
76
+ - typed enum for vault role ids
77
+ - `ROLE_NAMES`
78
+ - a friendly lookup from numeric role to display label
79
+
80
+ Use these constants instead of hardcoding precision values in app code.
81
+
82
+ ## Token-id helpers
83
+
84
+ [`token-ids.ts`](./token-ids.ts) is the public source of truth for position-id
85
+ derivation.
86
+
87
+ Public helpers:
88
+
89
+ - `getPrmTokenId(params)`
90
+ - derives the even `PRM` token id from vault address, instrument, expiry, and
91
+ `chainId`
92
+ - `getOptionPrmTokenId(params)`
93
+ - derives the odd `oPRM` token id
94
+ - `prmToOptionTokenId(prmTokenId)`
95
+ - `optionPrmToPrm(oPrmTokenId)`
96
+ - `isPrmToken(tokenId)`
97
+ - `isOptionPrmToken(tokenId)`
98
+ - `getPositionId(tokenId, userAddress)`
99
+ - stable string key for app-side storage keyed by token and user
100
+
101
+ ```ts
102
+ import {
103
+ getOptionPrmTokenId,
104
+ optionPrmToPrm,
105
+ } from "@stryke-xyz/premarket-sdk";
106
+
107
+ const oPrmTokenId = getOptionPrmTokenId({
108
+ vaultAddress: "0xVault",
109
+ marketId: 12n,
110
+ tick: 1500n,
111
+ isCall: true,
112
+ expiry: 1_735_689_600n,
113
+ chainId: 4326,
114
+ });
115
+
116
+ const prmTokenId = optionPrmToPrm(oPrmTokenId);
117
+ ```
118
+
119
+ Implementation detail worth remembering:
120
+
121
+ - `getPrmTokenId` hashes the vault address, instrument fields, expiry, and
122
+ `chainId`, then left-shifts once to force even parity
123
+
124
+ ## Collateral and settlement math
125
+
126
+ [`collateral.ts`](./collateral.ts) mirrors the important deterministic math used
127
+ by the vault contract. This makes it safe to pre-compute values in the UI or a
128
+ backend without sacrificing contract parity.
129
+
130
+ Public helpers:
131
+
132
+ - `getSpreadWidth(market)`
133
+ - `getSpreadBounds(instrument, market)`
134
+ - `calculateCollateralAmount(prmAmount, instrument, market)`
135
+ - `calculatePrmAmount(collateralAmount, instrument, market)`
136
+ - `calculateSpreadProfit(instrument, market, finalTick, positionSize)`
137
+ - `calculateSpreadLoss(instrument, market, finalTick, positionSize)`
138
+ - `calculateWithdrawableCollateral(instrument, market, finalTick, positionSize)`
139
+ - `getCollateralPerPosition(instrument, market)`
140
+ - `calculateDepositFees(collateralAmount, depositFeeBps, feeBpsPrecision?)`
141
+ - `calculateRedeemFees(profitAmount, redeemFeeBps, feeBpsPrecision?)`
142
+ - `isInTheMoney(instrument, market, finalTick)`
143
+ - `calculateMoneyness(instrument, market, finalTick)`
144
+
145
+ ```ts
146
+ import {
147
+ calculateCollateralAmount,
148
+ calculateWithdrawableCollateral,
149
+ } from "@stryke-xyz/premarket-sdk";
150
+
151
+ const collateral = calculateCollateralAmount(
152
+ 1_000_000_000_000_000_000n,
153
+ { marketId: 1n, tick: 1500n, isCall: true },
154
+ {
155
+ tickSize: 100n,
156
+ tickSpacing: 100n,
157
+ tokensPerTickSize: 1_000_000n,
158
+ isCollateralScaled: false,
159
+ },
160
+ );
161
+
162
+ const withdrawable = calculateWithdrawableCollateral(
163
+ { marketId: 1n, tick: 1500n, isCall: true },
164
+ {
165
+ tickSize: 100n,
166
+ tickSpacing: 100n,
167
+ tokensPerTickSize: 1_000_000n,
168
+ isCollateralScaled: false,
169
+ },
170
+ 1_600n,
171
+ 1_000_000_000_000_000_000n,
172
+ );
173
+ ```
174
+
175
+ Important behavior captured by the SDK:
176
+
177
+ - spread width falls back to `1` when `tickSpacing <= tickSize`
178
+ - strike-scaled collateral uses `instrument.tick`
179
+ - collateral calculation rounds up when the final division is not exact
180
+ - inverse `PRM` previews use floor division
181
+ - payoff and withdraw math use deterministic `bigint` arithmetic throughout
182
+
183
+ ## Transaction builders
184
+
185
+ [`transactions.ts`](./transactions.ts) contains ABI-backed transaction builders.
186
+ These return a lightweight `TransactionCall`:
187
+
188
+ ```ts
189
+ export interface TransactionCall {
190
+ to: `0x${string}`;
191
+ value?: bigint;
192
+ data: Hex;
193
+ }
194
+ ```
195
+
196
+ ### User-facing lifecycle builders
197
+
198
+ - `buildMintTransaction(vaultAddress, instrument, amount)`
199
+ - `buildWithdrawTransaction(vaultAddress, prmTokenId, amount, receiver)`
200
+ - `buildRedeemTransaction(vaultAddress, oPrmTokenId, receiver)`
201
+ - `buildUnwindTransaction(vaultAddress, prmTokenId, amount, receiver)`
202
+ - `buildRolloverTransaction(vaultAddress, oldPrmTokenId)`
203
+ - `buildApproveTransaction(tokenAddress, spender, amount?)`
204
+ - `buildBatchedMintTransactions(collateralTokenAddress, vaultAddress, instrument, collateralAmount, prmAmount)`
205
+ - `buildSetOperatorTransaction(vaultAddress, operator, approved)`
206
+
207
+ ```ts
208
+ import {
209
+ buildApproveTransaction,
210
+ buildMintTransaction,
211
+ } from "@stryke-xyz/premarket-sdk";
212
+
213
+ const approve = buildApproveTransaction(collateralToken, vaultAddress);
214
+ const mint = buildMintTransaction(
215
+ vaultAddress,
216
+ { marketId: 12n, tick: 1500n, isCall: true },
217
+ 1_000_000_000_000_000_000n,
218
+ );
219
+ ```
220
+
221
+ ### Restricted and role-gated builders
222
+
223
+ These functions are exported because they are part of the SDK, but they belong
224
+ to operational or keeper-style flows rather than ordinary end-user integrations:
225
+
226
+ - `buildDelegateRedeemTransaction`
227
+ - `buildDelegateRolloverTransaction`
228
+ - `buildDelegateWithdrawTransaction`
229
+ - `buildFillMarketDeliveryTransaction`
230
+ - `buildSetRolloverEnabledTransaction`
231
+ - `buildSetRoleTransaction`
232
+ - `buildUpdateFinalTickTransaction`
233
+ - `buildUpdateMarketExpiryTransaction`
234
+ - `buildUpdateMarketExpiryFromMarketTransaction`
235
+
236
+ They should usually be used by privileged services, market operators, or
237
+ automation code that already understands the relevant role checks.
238
+
239
+ ## Typical integration patterns
240
+
241
+ ### 1. Preview before mint
242
+
243
+ Use the math helpers and token-id helpers together:
244
+
245
+ 1. derive the target `PRM` or `oPRM` id
246
+ 2. compute required collateral with `calculateCollateralAmount`
247
+ 3. build `approve` and `mint` calls
248
+
249
+ ### 2. Display settlement outcomes
250
+
251
+ Use:
252
+
253
+ - `isInTheMoney`
254
+ - `calculateSpreadProfit`
255
+ - `calculateRedeemFees`
256
+ - `calculateWithdrawableCollateral`
257
+
258
+ This gives UI code a contract-aligned preview for both option holders and
259
+ collateral providers.
260
+
261
+ ### 3. Build sponsored or batched flows
262
+
263
+ `buildBatchedMintTransactions` is especially helpful when a frontend or relayer
264
+ needs to bundle approval and minting into one user operation or multicall-like
265
+ flow.
266
+
267
+ For market configuration and market serialization, continue with the
268
+ [Registry guide](../registry/README.md).