|
| 1 | +# Build & Test |
| 2 | + |
| 3 | +## Build System |
| 4 | + |
| 5 | +### tsup Config (`tsup.config.ts`) |
| 6 | + |
| 7 | +Two build targets: |
| 8 | + |
| 9 | +**Main build** (CJS + ESM + DTS): |
| 10 | + |
| 11 | +```ts |
| 12 | +entry: { |
| 13 | + index: 'src/index.ts', |
| 14 | + 'exchange/index': 'src/rest/exchange/index.ts', |
| 15 | + 'utils/index': 'src/utils/index.ts', |
| 16 | + 'websocket/index': 'src/websocket/index.ts', |
| 17 | +} |
| 18 | +format: ['cjs', 'esm'] |
| 19 | +dts: true, clean: true, sourcemap: true, minify: true, target: 'node16' |
| 20 | +``` |
| 21 | + |
| 22 | +**Browser build** (IIFE): |
| 23 | + |
| 24 | +```ts |
| 25 | +entry: ['src/browser.ts'] |
| 26 | +format: ['iife'] |
| 27 | +globalName: 'HyperliquidSDK' |
| 28 | +platform: 'browser', target: 'es2020' |
| 29 | +minify: true, sourcemap: true, clean: false |
| 30 | +``` |
| 31 | + |
| 32 | +### Output Structure |
| 33 | + |
| 34 | +``` |
| 35 | +dist/ |
| 36 | + index.js (CJS) |
| 37 | + index.mjs (ESM) |
| 38 | + index.d.ts (types) |
| 39 | + exchange/ |
| 40 | + index.js, index.mjs, index.d.ts |
| 41 | + utils/ |
| 42 | + index.js, index.mjs, index.d.ts |
| 43 | + websocket/ |
| 44 | + index.js, index.mjs, index.d.ts |
| 45 | + browser.global.js (IIFE for browsers) |
| 46 | +``` |
| 47 | + |
| 48 | +### Package.json Exports |
| 49 | + |
| 50 | +```json |
| 51 | +{ |
| 52 | + ".": { |
| 53 | + "types": "./dist/index.d.ts", |
| 54 | + "browser": "./dist/browser.global.js", |
| 55 | + "require": "./dist/index.js", |
| 56 | + "import": "./dist/index.mjs" |
| 57 | + }, |
| 58 | + "./exchange": { |
| 59 | + "types": "./dist/exchange/index.d.ts", |
| 60 | + "require": "./dist/exchange/index.js", |
| 61 | + "import": "./dist/exchange/index.mjs" |
| 62 | + }, |
| 63 | + "./utils": { |
| 64 | + "types": "./dist/utils/index.d.ts", |
| 65 | + "require": "./dist/utils/index.js", |
| 66 | + "import": "./dist/utils/index.mjs" |
| 67 | + }, |
| 68 | + "./websocket": { |
| 69 | + "types": "./dist/websocket/index.d.ts", |
| 70 | + "require": "./dist/websocket/index.js", |
| 71 | + "import": "./dist/websocket/index.mjs" |
| 72 | + } |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +### Entry Points |
| 77 | + |
| 78 | +| Subpath Export | Entry File | Key Exports | |
| 79 | +| ----------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 80 | +| `hyperliquid` | `src/index.ts` | `Hyperliquid`, `OrderBuilder`, `PlacedOrder`, `Semaphore`, all types, signing functions, wallet utils, stringMath, errors | |
| 81 | +| `hyperliquid/exchange` | `src/rest/exchange/index.ts` | `ExchangeAPI`, all standalone exchange functions, `ExchangeContext` type | |
| 82 | +| `hyperliquid/utils` | `src/utils/index.ts` | All signing functions, `normalizeWallet`, `splitSignature`, `Semaphore`, `SemaphoreRegistry`, `globalSemaphoreRegistry`, stringMath functions, all error classes | |
| 83 | +| `hyperliquid/websocket` | `src/websocket/index.ts` | `WebSocketClient`, `WebSocketSubscriptions`, `WebSocketPayloadManager`, `createWebSocketPayloadManager`, `PayloadGenerator` | |
| 84 | + |
| 85 | +### Build Commands |
| 86 | + |
| 87 | +```bash |
| 88 | +npm run build # tsup (runs format first via prebuild) |
| 89 | +npm run format # prettier --write "src/**/*.{ts,tsx,js,jsx}" |
| 90 | +npm run format:check # prettier --check |
| 91 | +npm run format:all # prettier on all files including json/md |
| 92 | +``` |
| 93 | + |
| 94 | +### Husky & Lint-Staged |
| 95 | + |
| 96 | +- `.husky/` directory for git hooks |
| 97 | +- `lint-staged` in package.json: runs prettier on staged `.ts`, `.tsx`, `.js`, `.jsx`, `.json`, `.md` files |
| 98 | +- `prepare` script: builds on `npm install` (if not production and .git exists) |
| 99 | +- `postinstall` script: sets up husky (if not production and .git exists) |
| 100 | + |
| 101 | +## Test Setup |
| 102 | + |
| 103 | +### Vitest Config (`vitest.config.ts`) |
| 104 | + |
| 105 | +```ts |
| 106 | +{ |
| 107 | + test: { |
| 108 | + globals: true, |
| 109 | + testTimeout: 10000, |
| 110 | + include: ['tests/**/*.test.ts'], |
| 111 | + coverage: { |
| 112 | + provider: 'v8', |
| 113 | + include: ['src/**/*.ts'], |
| 114 | + exclude: ['src/types/**', 'src/validation/**'], |
| 115 | + }, |
| 116 | + }, |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +### Test Commands |
| 121 | + |
| 122 | +```bash |
| 123 | +npm test # vitest run |
| 124 | +npm run test:watch # vitest (watch mode) |
| 125 | +npm run test:coverage # vitest run --coverage |
| 126 | +``` |
| 127 | + |
| 128 | +### Test Files |
| 129 | + |
| 130 | +| File | Tests | |
| 131 | +| ---------------------------- | ------------------------------------------------------------------------------------------------------ | |
| 132 | +| `tests/errors.test.ts` | `parseApiError` mapping, `handleApiError` behavior, error class hierarchy | |
| 133 | +| `tests/orderBuilder.test.ts` | `OrderBuilder` fluent API, validation, all order types | |
| 134 | +| `tests/semaphore.test.ts` | `Semaphore` mutual exclusion, `SemaphoreRegistry` per-key locking, cleanup | |
| 135 | +| `tests/signing.test.ts` | `removeTrailingZeros`, `normalizeTrailingZeros`, `floatToWire`, `orderToWire`, `orderTypeToWire` | |
| 136 | +| `tests/stringMath.test.ts` | `log10Floor`, `multiplyByPow10`, `toPrecisionTruncate`, `toFixedTruncate`, `formatPrice`, `formatSize` | |
| 137 | + |
| 138 | +### Additional Test Scripts |
| 139 | + |
| 140 | +```bash |
| 141 | +npm run test:node # node examples/node-test.js |
| 142 | +npm run test:browser # npx serve -s . -p 3000 (manual browser test) |
| 143 | +npm run test:ws:cjs # build && node scripts/test-ws-connection.cjs |
| 144 | +npm run test:ws:esm # build && node scripts/test-ws-connection.mjs |
| 145 | +npm run test:ws:current# CJS + ESM WebSocket tests |
| 146 | +npm run test:all # Full test suite (build + WS tests + manual browser) |
| 147 | +``` |
| 148 | + |
| 149 | +## Dependencies |
| 150 | + |
| 151 | +### Production |
| 152 | + |
| 153 | +| Package | Version | Purpose | |
| 154 | +| ------------------ | ------------ | -------------------------------------------- | |
| 155 | +| `@msgpack/msgpack` | ^3.0.0-beta2 | Action hash encoding for L1 signing | |
| 156 | +| `axios` | ^1.7.2 | HTTP client for REST API | |
| 157 | +| `ethers` | ^6.13.2 | Wallet from private key, keccak256, getBytes | |
| 158 | +| `valibot` | ^0.29.0 | Response schema validation | |
| 159 | +| `ws` | ^8.18.2 | WebSocket fallback for Node < 23 | |
| 160 | + |
| 161 | +### Dev |
| 162 | + |
| 163 | +| Package | Purpose | |
| 164 | +| --------------------- | ------------------------------------ | |
| 165 | +| `typescript` ^5.0.0 | TypeScript compiler | |
| 166 | +| `tsup` ^8.0.0 | Build tool (esbuild-based) | |
| 167 | +| `vitest` ^3.2.4 | Test runner | |
| 168 | +| `@vitest/coverage-v8` | Coverage provider | |
| 169 | +| `prettier` ^3.5.3 | Code formatter | |
| 170 | +| `husky` ^9.1.7 | Git hooks | |
| 171 | +| `lint-staged` ^15.5.1 | Run linters on staged files | |
| 172 | +| `dotenv` ^16.5.0 | Environment variables for tests | |
| 173 | +| `serve` ^14.0.0 | Static file server for browser tests | |
| 174 | + |
| 175 | +### Engine Requirements |
| 176 | + |
| 177 | +- Node.js >= 18.0.0 |
0 commit comments