@outcome.xyz/hip4 1.0.0-beta

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/LICENSE ADDED
@@ -0,0 +1,101 @@
1
+ Business Source License 1.1
2
+
3
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
4
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
5
+
6
+ ---
7
+
8
+ Parameters
9
+
10
+ Licensor: Outcome Labs
11
+
12
+ Licensed Work: @outcome.xyz/hip4 v1.0.0-beta (all prior and subsequent versions included)
13
+ The Licensed Work is (c) 2026 Outcome Labs.
14
+
15
+ Additional Use Grant: You may make use of the Licensed Work, provided that
16
+ you may not use the Licensed Work for a Production Use.
17
+
18
+ A "Production Use" is any use of the Licensed Work that
19
+ makes the Licensed Work available to third parties as
20
+ part of a commercial or non-commercial product,
21
+ service, or application, including but not limited to:
22
+ (a) incorporating the Licensed Work into a product or
23
+ service that is offered to third parties;
24
+ (b) using the Licensed Work to operate a service
25
+ accessible by third parties;
26
+ (c) distributing the Licensed Work or derivative works
27
+ to third parties.
28
+
29
+ For purposes of clarity, the following are permitted
30
+ under this license without a separate commercial
31
+ agreement:
32
+ (i) internal evaluation and testing;
33
+ (ii) non-production development and prototyping;
34
+ (iii) academic and educational use;
35
+ (iv) personal, non-commercial projects that are not
36
+ offered as a service to third parties.
37
+
38
+ Any Production Use requires a separate commercial
39
+ license from the Licensor. Contact: support@outcomelabs.xyz
40
+
41
+ A standing perpetual exception to the foregoing
42
+ restriction, granted to the Outcome project, its
43
+ operating entity Outcome Labs, and the Outcome
44
+ open source community, is set out in the file
45
+ LICENSE.OUTCOME-EXCEPTION distributed alongside
46
+ this License. That exception forms part of the
47
+ Licensor's grants under this License.
48
+
49
+ Change Date: May 19, 2028
50
+
51
+ Change License: MIT License
52
+
53
+ ---
54
+
55
+ Terms
56
+
57
+ The Licensor hereby grants you the right to copy, modify, create derivative
58
+ works, redistribute, and make non-production use of the Licensed Work. The
59
+ Licensor may make an Additional Use Grant, above, permitting limited
60
+ production use.
61
+
62
+ Effective on the Change Date, or the fourth anniversary of the first publicly
63
+ available distribution of a specific version of the Licensed Work under this
64
+ License, whichever comes first, the Licensor hereby grants you rights under
65
+ the terms of the Change License, and the rights granted in the paragraph
66
+ above terminate.
67
+
68
+ If your use of the Licensed Work does not comply with the requirements
69
+ currently in effect as described in this License, you must purchase a
70
+ commercial license from the Licensor, its affiliated entities, or authorized
71
+ resellers, or you must refrain from using the Licensed Work.
72
+
73
+ All copies of the original and modified Licensed Work, and derivative works
74
+ of the Licensed Work, are subject to this License. This License applies
75
+ separately for each version of the Licensed Work and the Change Date may vary
76
+ for each version of the Licensed Work released by Licensor.
77
+
78
+ You must conspicuously display this License on each original or modified copy
79
+ of the Licensed Work. If you receive the Licensed Work in original or
80
+ modified form from a third party, the terms and conditions set forth in this
81
+ License apply to your use of that work.
82
+
83
+ Any use of the Licensed Work in violation of this License will automatically
84
+ terminate your rights under this License for the current and all other
85
+ versions of the Licensed Work.
86
+
87
+ This License does not grant you any right in any trademark or logo of
88
+ Licensor or its affiliates (provided that you may use a trademark or logo
89
+ of Licensor as expressly required by this License).
90
+
91
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED
92
+ ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND
93
+ CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES
94
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT,
95
+ AND TITLE.
96
+
97
+ IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY DAMAGES, WHETHER DIRECT,
98
+ INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR
99
+ IN CONNECTION WITH THIS LICENSE OR THE USE OR INABILITY TO USE THE
100
+ LICENSED WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF
101
+ SUCH DAMAGES.
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ <p align="center">
2
+ <img src="./assets/outcome-icon-light.svg" alt="@outcome.xyz/hip4" />
3
+ </p>
4
+
5
+ <h1 align="center">@outcome.xyz/hip4</h1>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@outcome.xyz/hip4"><img src="https://img.shields.io/npm/v/@outcome.xyz/hip4.svg" alt="npm version" /></a>
9
+ <img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="zero dependencies" />
10
+ <img src="https://img.shields.io/npm/l/@outcome.xyz/hip4" alt="license" />
11
+ </p>
12
+
13
+ ---
14
+
15
+ TypeScript SDK for Hyperliquid HIP-4 prediction markets. Zero runtime dependencies.
16
+
17
+ ## Built for developers
18
+
19
+ The SDK is structured around a single adapter with typed sub-modules for each domain - events, market data, account state, trading, wallet, and auth. Everything returns typed responses, WebSocket subscriptions return unsubscribe functions, and all signing (L1 agent + EIP-712) is handled internally with no external crypto dependencies.
20
+
21
+ ```bash
22
+ pnpm add @outcome.xyz/hip4
23
+ ```
24
+
25
+ ```typescript
26
+ import { createHIP4Adapter } from "@outcome.xyz/hip4";
27
+
28
+ const hip4 = createHIP4Adapter({ testnet: true });
29
+ await hip4.initialize();
30
+ ```
31
+
32
+ ## Examples
33
+
34
+ - [`auth-eoa.ts`](examples/auth-eoa.ts) - Agent key approval and auth setup
35
+ - [`get-all-markets.ts`](examples/get-all-markets.ts) - Fetch all markets grouped by type
36
+ - [`get-multi-outcome.ts`](examples/get-multi-outcome.ts) - Multi-outcome markets with live prices
37
+ - [`get-recurring-markets.ts`](examples/get-recurring-markets.ts) - Recurring markets with expiry countdowns
38
+ - [`place-limit-order.ts`](examples/place-limit-order.ts) - Limit order with price validation
39
+ - [`place-market-order.ts`](examples/place-market-order.ts) - Market order with FrontendMarket TIF
40
+ - [`stream-prices.ts`](examples/stream-prices.ts) - Stream live prices via WebSocket
41
+ - [`usdh-ramp.ts`](examples/usdh-ramp.ts) - End-to-end USDH on/off-ramp via Coinbase + Across
42
+
43
+ ## API
44
+
45
+ ### `hip4.events`
46
+
47
+ | Method | Description |
48
+ | -------------------------------- | ------------------------------------------------------------------------ |
49
+ | `fetchEvents(params?)` | List events. Filters: `category`, `active`, `limit`, `offset`, `query` |
50
+ | `fetchEvent(eventId)` | Single event by ID |
51
+ | `fetchCategories()` | Available categories |
52
+ | `fetchMarkets(params?)` | Typed HIP-4 markets with optional grouping by type or question |
53
+ | `fetchSettledOutcome(outcomeId)` | Settlement details for a resolved outcome. Returns `null` if not settled |
54
+
55
+ ### `hip4.marketData`
56
+
57
+ | Method | Description |
58
+ | ------------------------------------------------- | --------------------------------------------- |
59
+ | `fetchOrderBook(marketId, sideIndex?)` | L2 snapshot |
60
+ | `fetchPrice(marketId)` | Both sides, 5s cache |
61
+ | `fetchTrades(marketId, limit?)` | Recent trades |
62
+ | `fetchCandles(marketId, interval?, start?, end?)` | OHLCV candles |
63
+ | `subscribeOrderBook(marketId, cb)` | Real-time L2 book |
64
+ | `subscribePrice(marketId, cb)` | Real-time prices |
65
+ | `subscribeTrades(marketId, cb)` | Real-time trades |
66
+ | `subscribeAllMids(cb)` | All mid-prices across every market |
67
+ | `subscribeActiveAssetCtx(coin, cb)` | Per-spot-coin context (vol, OI, mark) |
68
+ | `subscribeSpotAssetCtxs(cb)` | Bulk spot-asset context updates |
69
+ | `subscribePerpAssetCtx(coin, cb)` | Per-perp-coin context (mark, oracle, funding) |
70
+
71
+ ### `hip4.account`
72
+
73
+ | Method | Description |
74
+ | --------------------------------- | ------------------------------------------ |
75
+ | `fetchPositions(address)` | Outcome positions with resolved side names |
76
+ | `fetchActivity(address)` | Fills, last 30 days |
77
+ | `fetchBalance(address)` | Spot balances |
78
+ | `fetchOpenOrders(address)` | Resting orders |
79
+ | `subscribePositions(address, cb)` | Polling at 10s |
80
+
81
+ ### `hip4.trading`
82
+
83
+ | Method | Description |
84
+ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
85
+ | `placeOrder(params)` | Place market or limit order. Returns `{ success, orderId?, error? }` |
86
+ | `placeOrders(params[])` | Batch place orders in a single signed request |
87
+ | `modifyOrder(params)` | Modify a resting order (price and/or size); preserves queue priority on size-only edits |
88
+ | `cancelOrder(params[])` | Cancel one or more resting orders. Returns `HLCancelResponse` |
89
+ | `scheduleCancel(time)` | Dead-man's switch - registers a future timestamp at which HL cancels every open order from this agent. Pass `null` to clear |
90
+ | `splitOutcome(params)` | Split X quote tokens into X Yes + X No shares of one outcome |
91
+ | `mergeOutcome(params)` | Merge X paired Yes+No shares back into X quote tokens |
92
+ | `mergeQuestion(params)` | Merge X Yes shares from every outcome of a question into X quote tokens |
93
+ | `negateOutcome(params)` | Convert X No shares of one outcome into X Yes shares of every other outcome in the question |
94
+
95
+ ### `hip4.wallet`
96
+
97
+ | Method | Signing | Description |
98
+ | ----------------------------------- | -------- | ------------------------------- |
99
+ | `setSigner(signer)` | - | Set user wallet for EIP-712 ops |
100
+ | `buyUsdh(amount)` | L1 agent | Buy USDH on spot |
101
+ | `sellUsdh(amount)` | L1 agent | Sell USDH on spot |
102
+ | `transferToSpot(amount)` | EIP-712 | Perp -> Spot |
103
+ | `transferToPerps(amount)` | EIP-712 | Spot -> Perp |
104
+ | `withdraw({ destination, amount })` | EIP-712 | Withdraw to external address |
105
+ | `usdSend({ destination, amount })` | EIP-712 | Send to another HL address |
106
+
107
+ ### `hip4.auth`
108
+
109
+ | Method | Description |
110
+ | --------------------------------- | --------------------------------------------------- |
111
+ | `initAuth(walletAddress, signer)` | Accepts viem `PrivateKeyAccount` or ethers `Signer` |
112
+ | `getAuthStatus()` | `"disconnected" \| "pending_approval" \| "ready"` |
113
+ | `clearAuth()` | Reset auth state |
114
+
115
+ ## Market Types
116
+
117
+ `fetchMarkets()` classifies every HIP-4 outcome into one of four types:
118
+
119
+ | Type | Description | Parsed Fields |
120
+ | ---------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
121
+ | `defaultBinary` | Recurring price markets (BTC > $67250 1d) | `underlying`, `targetPrice`, `expiry`, `period` |
122
+ | `labelledBinary` | Standalone binary with custom sides (Hypurr vs Usain Bolt) | Custom side labels |
123
+ | `multiOutcome` | Grouped under a question, with fallback | `questionId`, `questionName`, `isFallback` |
124
+ | `priceBucket` | Recurring multi-bucket price markets (per-bucket Yes/No) | `underlying`, `expiry`, `priceThresholds`, `period`, `bucketIndex`, `lowerBound`, `upperBound` |
125
+
126
+ ```typescript
127
+ // Filter by type
128
+ const binaries = await hip4.events.fetchMarkets({ type: "defaultBinary" });
129
+
130
+ // Group by type
131
+ const grouped = await hip4.events.fetchMarkets({ groupBy: "type" });
132
+
133
+ // Group multi-outcome by question
134
+ const byQuestion = await hip4.events.fetchMarkets({ groupBy: "question" });
135
+ ```
136
+
137
+ ## Configuration
138
+
139
+ ```typescript
140
+ const hip4 = createHIP4Adapter({
141
+ testnet: true,
142
+ // Builder fee - collected on every order placed by this adapter
143
+ builderAddress: "0xYourBuilderAddress",
144
+ builderFee: 100, // 0.1% (tenths of a basis point, 0–1000)
145
+ logger: (level, msg, data) => console.log(level, msg, data),
146
+ });
147
+ ```
148
+
149
+ Per-order builder address/fee can also be passed on `placeOrder` to override the adapter-level config.
150
+
151
+ ## Streams
152
+
153
+ Drop-in price feeds backed by HL's WebSocket. Each takes a callback and returns an unsubscribe function. The snapshot includes the rolling candle history plus the current mid.
154
+
155
+ ```typescript
156
+ import { createPriceFeed, createPerpPriceFeed } from "@outcome.xyz/hip4";
157
+
158
+ // HIP-4 outcome side (uses sideIndex 0 by default)
159
+ const unsub = createPriceFeed(
160
+ hip4.marketData,
161
+ "1758",
162
+ (snapshot) => console.log(snapshot.currentMid, snapshot.candles),
163
+ { interval: "1h" },
164
+ );
165
+ unsub();
166
+ ```
167
+
168
+ | Helper | Use |
169
+ | ---------------------------------------------------------- | ------------------------------------------------------------------ |
170
+ | `createPriceFeed(marketData, marketId, onSnapshot, opts?)` | Live mid + tick-aggregated candle history for a HIP-4 outcome side |
171
+ | `createPerpPriceFeed(client, coin, onSnapshot, opts?)` | Same shape for an HL perp coin |
172
+ | `processTick`, `candleBoundaryMs`, `intervalToMs` | Lower-level candle utilities |
173
+
174
+ ## USDH on/off-ramp (mainnet)
175
+
176
+ Built-in fiat ↔ USDH ramp via Coinbase + Across. Buy: fiat → Coinbase onramp → USDC (Arbitrum) → Across counterfactual → USDH (HyperCore). Sell: USDH (HyperEVM) → Across swap → USDC (Arbitrum) → Coinbase offramp → fiat. See [`examples/usdh-ramp.ts`](examples/usdh-ramp.ts) for the full flow.
177
+
178
+ ## Orderbook utilities
179
+
180
+ ```typescript
181
+ import {
182
+ computeTradeCost,
183
+ computeEstimatedCost,
184
+ computePotentialReturn,
185
+ } from "@outcome.xyz/hip4";
186
+
187
+ const cost = computeTradeCost({
188
+ tokenAmount: 100,
189
+ orderType: "limit",
190
+ limitPriceCents: 55, // 0.55 in cents
191
+ });
192
+ // → { estimatedCost, potentialReturn, displayShares }
193
+ ```
194
+
195
+ ## Signing
196
+
197
+ Both Hyperliquid signing flows are implemented from scratch.
198
+
199
+ **L1 agent signing** (orders, cancels, USDH spot):
200
+
201
+ 1. Sort action keys in canonical order
202
+ 2. MessagePack encode
203
+ 3. Append nonce as BE u64
204
+ 4. Append vault marker byte
205
+ 5. Keccak-256 hash -> `connectionId`
206
+ 6. EIP-712 sign with `Agent` type on chainId `1337`
207
+
208
+ **User-signed EIP-712** (transfers, withdrawals, sends):
209
+
210
+ - Domain: `HyperliquidSignTransaction`, `signatureChainId: 0x66eee`
211
+ - Message filtered to EIP-712 type keys only
212
+ - Requires user wallet, agent keys rejected
213
+
214
+ ## Acknowledgements
215
+
216
+ Signing implementation inspired by [@nktkas/hyperliquid](https://github.com/nktkas/hyperliquid).
217
+
218
+ ## License
219
+
220
+ BUSL-1.1
221
+
222
+ ## Builders
223
+
224
+ Dennis Furrer