@metamask-previews/perps-controller 17.2.0-preview-f87e9ae41 → 17.4.0-preview-fb486948f
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/CHANGELOG.md +19 -1
- package/dist/services/LighterClientService.d.ts.map +1 -1
- package/dist/services/LighterClientService.js +1 -0
- package/dist/services/LighterClientService.js.map +1 -1
- package/dist/services/TerminalMarketService.d.ts +1 -1
- package/dist/services/TerminalMarketService.d.ts.map +1 -1
- package/dist/services/TerminalMarketService.js +11 -2
- package/dist/services/TerminalMarketService.js.map +1 -1
- package/dist/types/index.d.ts +8 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/lighter-types.d.ts +2 -0
- package/dist/types/lighter-types.d.ts.map +1 -1
- package/dist/types/lighter-types.js.map +1 -1
- package/dist/utils/lighterAdapter.d.ts.map +1 -1
- package/dist/utils/lighterAdapter.js +4 -1
- package/dist/utils/lighterAdapter.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [17.4.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add optional `id` field to `PerpsMarketData` type, populated from the v3 Terminal snapshot endpoint ([#10356](https://github.com/MetaMask/core/pull/10356))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Bump `GLOBAL_SNAPSHOT_SCHEMA_VERSION` from `2` to `3` to consume the v3 `/perpetuals` Terminal endpoint, which adds a stable `id` per market ([#10356](https://github.com/MetaMask/core/pull/10356))
|
|
19
|
+
|
|
20
|
+
## [17.3.0]
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Use Lighter's reported executed amount for order filled sizes so canceled orders do not appear fully filled. ([#10308](https://github.com/MetaMask/core/pull/10308))
|
|
25
|
+
|
|
10
26
|
## [17.2.0]
|
|
11
27
|
|
|
12
28
|
### Changed
|
|
@@ -932,7 +948,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
932
948
|
|
|
933
949
|
- Bump `@metamask/controller-utils` from `^11.18.0` to `^11.19.0` ([#7995](https://github.com/MetaMask/core/pull/7995))
|
|
934
950
|
|
|
935
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.
|
|
951
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.4.0...HEAD
|
|
952
|
+
[17.4.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.3.0...@metamask/perps-controller@17.4.0
|
|
953
|
+
[17.3.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.2.0...@metamask/perps-controller@17.3.0
|
|
936
954
|
[17.2.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.1.0...@metamask/perps-controller@17.2.0
|
|
937
955
|
[17.1.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@17.0.0...@metamask/perps-controller@17.1.0
|
|
938
956
|
[17.0.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@16.2.0...@metamask/perps-controller@17.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterClientService.d.ts","sourceRoot":"","sources":["../../src/services/LighterClientService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAqBH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,KAAK,EACV,sBAAsB,EACtB,kCAAkC,EAClC,2BAA2B,EAC3B,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,+BAA+B,EAE/B,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,EAC7B,kBAAkB,EAClB,+BAA+B,EAC/B,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAElB,8BAA8B,EAC9B,8BAA8B,EAC/B,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"LighterClientService.d.ts","sourceRoot":"","sources":["../../src/services/LighterClientService.ts"],"names":[],"mappings":"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"}
|
|
@@ -141,6 +141,7 @@ const OrderStruct = type({
|
|
|
141
141
|
ownerAccountIndex: NonNegativeIntegerStruct,
|
|
142
142
|
initialBaseAmount: PositiveDecimalStringStruct,
|
|
143
143
|
remainingBaseAmount: NonNegativeDecimalStringStruct,
|
|
144
|
+
filledBaseAmount: optional(NonNegativeDecimalStringStruct),
|
|
144
145
|
price: PositiveDecimalStringStruct,
|
|
145
146
|
isAsk: boolean(),
|
|
146
147
|
type: string(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterClientService.js","sourceRoot":"","sources":["../../src/services/LighterClientService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,EACN,MAAM,EACN,IAAI,EACJ,KAAK,GACN,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AA0BvC;;GAEG;AACH,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE3C,MAAM,kBAAkB,GAAG,MAAM,CAAS,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CACnE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAC3D,CAAC;AACF,MAAM,iBAAiB,GAAG,MAAM,CAAS,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE,CACjE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAChE,CAAC;AACF,MAAM,wBAAwB,GAAG,MAAM,CACrC,2BAA2B,EAC3B,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,KAAK,QAAQ;IACvB,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;IAC3C,CAAC,CAAC,KAAK,CACZ,CAAC;AACF,MAAM,wBAAwB,GAAG,CAAC,KAAc,EAAiB,EAAE;IACjE,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,kDAAkD,CAAC,IAAI,CAAC,KAAK,CAAC,EAC/D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC,CAAC;AACF,MAAM,yBAAyB,GAAG,MAAM,CACtC,uBAAuB,EACvB,CAAC,KAAK,EAAE,EAAE,CAAC,wBAAwB,CAAC,KAAK,CAAC,KAAK,IAAI,CACpD,CAAC;AACF,MAAM,8BAA8B,GAAG,MAAM,CAC3C,oCAAoC,EACpC,CAAC,KAAK,EAAE,EAAE;IACR,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC,CAAC;AACxC,CAAC,CACF,CAAC;AACF,MAAM,kBAAkB,GAAG,MAAM,CAC/B,uBAAuB,EACvB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,kBAAkB,IAAI,KAAK,KAAK,mBAAmB,CACzE,CAAC;AACF,MAAM,2BAA2B,GAAG,MAAM,CACxC,gCAAgC,EAChC,CAAC,KAAK,EAAE,EAAE;IACR,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC;AACvC,CAAC,CACF,CAAC;AACF,MAAM,6BAA6B,GAAG,MAAM,CAC1C,4BAA4B,EAC5B,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAC7E,CAAC;AACF,MAAM,+BAA+B,GAAG,MAAM,CAC5C,+BAA+B,EAC/B,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,KAAK,QAAQ;IACzB,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;IAC3B,KAAK,IAAI,CAAC;IACV,KAAK,IAAI,MAAM,CAClB,CAAC;AACF,MAAM,gCAAgC,GAAG,KAAK,CAAC;IAC7C,6BAA6B;IAC7B,8BAA8B;CAC/B,CAAC,CAAC;AACH,MAAM,kBAAkB,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;CAC5B,CAAC,CAAC;AACH,MAAM,cAAc,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,wBAAwB;IAClC,MAAM,EAAE,MAAM,EAAE;IAChB,qBAAqB,EAAE,8BAA8B;IACrD,cAAc,EAAE,wBAAwB;IACxC,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,8BAA8B;IACxC,aAAa,EAAE,8BAA8B;IAC7C,aAAa,EAAE,8BAA8B;IAC7C,aAAa,EAAE,yBAAyB;IACxC,WAAW,EAAE,yBAAyB;IACtC,gBAAgB,EAAE,8BAA8B;IAChD,UAAU,EAAE,QAAQ,CAAC,iBAAiB,CAAC;CACxC,CAAC,CAAC;AACH,MAAM,aAAa,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,iBAAiB;IAC9B,KAAK,EAAE,wBAAwB;IAC/B,SAAS,EAAE,MAAM,EAAE;IACnB,aAAa,EAAE,wBAAwB;IACvC,eAAe,EAAE,wBAAwB;IACzC,iBAAiB,EAAE,wBAAwB;IAC3C,MAAM,EAAE,iBAAiB;IACzB,UAAU,EAAE,8BAA8B;IAC1C,gBAAgB,EAAE,8BAA8B;IAChD,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;CAC3C,CAAC,CAAC;AACH,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAC9E,0EAA0E;AAC1E,MAAM,oBAAoB,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,iBAAiB;IAC9B,KAAK,EAAE,wBAAwB;IAC/B,SAAS,EAAE,MAAM,EAAE;CACpB,CAAC,CAAC;AACH,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE;IAChB,QAAQ,EAAE,wBAAwB;IAClC,UAAU,EAAE,MAAM,EAAE;IACpB,MAAM,EAAE,MAAM,EAAE;IAChB,QAAQ,EAAE,yBAAyB;IACnC,QAAQ,EAAE,yBAAyB;IACnC,aAAa,EAAE,8BAA8B;IAC7C,cAAc,EAAE,8BAA8B;IAC9C,qBAAqB,EAAE,wBAAwB;IAC/C,sBAAsB,EAAE,wBAAwB;IAChD,sBAAsB,EAAE,wBAAwB;CACjD,CAAC,CAAC;AACH,MAAM,sBAAsB,GAAG,CAC7B,MAGC,EACQ,EAAE,CACX,MAAM,CAAC,MAAM,KAAK,UAAU;IAC5B,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAC/C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,MAAM,YAAY,GAAG,MAAM,CACzB,gBAAgB,EAChB,+CAA+C,EAC/C,sBAAsB,CACvB,CAAC;AACF,MAAM,sBAAsB,GAAG,IAAI,CAAC;IAClC,GAAG,gBAAgB,CAAC,MAAM;IAC1B,cAAc,EAAE,6BAA6B;IAC7C,4BAA4B,EAAE,QAAQ,CAAC,+BAA+B,CAAC;IACvE,wBAAwB,EAAE,QAAQ,CAAC,+BAA+B,CAAC;IACnE,yBAAyB,EAAE,QAAQ,CAAC,+BAA+B,CAAC;IACpE,gBAAgB,EAAE,6BAA6B;IAC/C,oBAAoB,EAAE,6BAA6B;IACnD,qBAAqB,EAAE,6BAA6B;IACpD,aAAa,EAAE,6BAA6B;IAC5C,cAAc,EAAE,6BAA6B;IAC7C,gBAAgB,EAAE,kBAAkB;IACpC,YAAY,EAAE,6BAA6B;IAC3C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC;CACjD,CAAC,CAAC;AACH,MAAM,6BAA6B,GAAG,CAAC,MAKtC,EAAW,EAAE,CACZ,MAAM,CAAC,MAAM,KAAK,UAAU;IAC5B;QACE,MAAM,CAAC,4BAA4B;QACnC,MAAM,CAAC,wBAAwB;QAC/B,MAAM,CAAC,yBAAyB;KACjC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;AACvD,MAAM,kBAAkB,GAAG,MAAM,CAC/B,MAAM,CACJ,sBAAsB,EACtB,+CAA+C,EAC/C,sBAAsB,CACvB,EACD,gDAAgD,EAChD,6BAA6B,CAC9B,CAAC;AACF,MAAM,WAAW,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,wBAAwB;IACpC,gBAAgB,EAAE,wBAAwB;IAC1C,WAAW,EAAE,wBAAwB;IACrC,iBAAiB,EAAE,wBAAwB;IAC3C,iBAAiB,EAAE,2BAA2B;IAC9C,mBAAmB,EAAE,8BAA8B;IACnD,KAAK,EAAE,2BAA2B;IAClC,KAAK,EAAE,OAAO,EAAE;IAChB,IAAI,EAAE,MAAM,EAAE;IACd,WAAW,EAAE,MAAM,EAAE;IACrB,UAAU,EAAE,KAAK,CAAC,CAAC,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,EAAE;IAChB,WAAW,EAAE,iBAAiB;IAC9B,SAAS,EAAE,wBAAwB;IACnC,YAAY,EAAE,QAAQ,CAAC,8BAA8B,CAAC;IACtD,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,QAAQ,CAAC,wBAAwB,CAAC;IACpD,aAAa,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACjC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACpC,iBAAiB,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACrC,iBAAiB,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;CACtC,CAAC,CAAC;AACH,MAAM,WAAW,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,wBAAwB;IACjC,MAAM,EAAE,MAAM,EAAE;IAChB,IAAI,EAAE,MAAM,EAAE;IACd,QAAQ,EAAE,wBAAwB;IAClC,IAAI,EAAE,2BAA2B;IACjC,KAAK,EAAE,2BAA2B;IAClC,SAAS,EAAE,2BAA2B;IACtC,KAAK,EAAE,wBAAwB;IAC/B,KAAK,EAAE,wBAAwB;IAC/B,YAAY,EAAE,wBAAwB;IACtC,YAAY,EAAE,wBAAwB;IACtC,UAAU,EAAE,OAAO,EAAE;IACrB,SAAS,EAAE,wBAAwB;IACnC,aAAa,EAAE,QAAQ,CAAC,yBAAyB,CAAC;IAClD,aAAa,EAAE,QAAQ,CAAC,yBAAyB,CAAC;IAClD,QAAQ,EAAE,QAAQ,CAAC,gCAAgC,CAAC;IACpD,QAAQ,EAAE,QAAQ,CAAC,gCAAgC,CAAC;IACpD,uBAAuB,EAAE,8BAA8B;IACvD,uBAAuB,EAAE,8BAA8B;IACvD,wBAAwB,EAAE,OAAO,EAAE;IACnC,wBAAwB,EAAE,OAAO,EAAE;CACpC,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG;IACtB,UAAU,EAAE,IAAI,CAAC;QACf,GAAG,kBAAkB,CAAC,MAAM;QAC5B,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC;KAChC,CAAC;IACF,gBAAgB,EAAE,IAAI,CAAC;QACrB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,gBAAgB,EAAE,KAAK,CAAC,kBAAkB,CAAC;KAC5C,CAAC;IACF,OAAO,EAAE,IAAI,CAAC;QACZ,GAAG,kBAAkB,CAAC,MAAM;QAC5B,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;KAC/B,CAAC;IACF,iBAAiB,EAAE,IAAI,CAAC;QACtB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,SAAS,EAAE,MAAM,EAAE;QACnB,WAAW,EAAE,KAAK,CAAC,oBAAoB,CAAC;KACzC,CAAC;IACF,OAAO,EAAE,IAAI,CAAC;QACZ,GAAG,kBAAkB,CAAC,MAAM;QAC5B,OAAO,EAAE,KAAK,CACZ,IAAI,CAAC;YACH,YAAY,EAAE,wBAAwB;YACtC,WAAW,EAAE,wBAAwB;YACrC,KAAK,EAAE,wBAAwB;YAC/B,SAAS,EAAE,MAAM,EAAE;SACpB,CAAC,CACH;KACF,CAAC;IACF,SAAS,EAAE,IAAI,CAAC;QACd,GAAG,kBAAkB,CAAC,MAAM;QAC5B,KAAK,EAAE,wBAAwB;KAChC,CAAC;IACF,WAAW,EAAE,IAAI,CAAC;QAChB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,IAAI,EAAE,MAAM,EAAE;QACd,YAAY,EAAE,wBAAwB;QACtC,WAAW,EAAE,wBAAwB;QACrC,KAAK,EAAE,wBAAwB;QAC/B,MAAM,EAAE,iBAAiB;KAC1B,CAAC;IACF,eAAe,EAAE,IAAI,CAAC;QACpB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,MAAM,EAAE,MAAM,EAAE;KACjB,CAAC;IACF,YAAY,EAAE,IAAI,CAAC;QACjB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;KAC3B,CAAC;IACF,cAAc,EAAE,IAAI,CAAC;QACnB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,IAAI,CAAC;QACb,GAAG,kBAAkB,CAAC,MAAM;QAC5B,QAAQ,EAAE,KAAK,CACb,IAAI,CAAC;YACH,EAAE,EAAE,MAAM,EAAE;YACZ,OAAO,EAAE,wBAAwB;YACjC,MAAM,EAAE,2BAA2B;YACnC,SAAS,EAAE,wBAAwB;YACnC,MAAM,EAAE,MAAM,EAAE;YAChB,QAAQ,EAAE,MAAM,EAAE;SACnB,CAAC,CACH;QACD,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF,WAAW,EAAE,IAAI,CAAC;QAChB,GAAG,kBAAkB,CAAC,MAAM;QAC5B,SAAS,EAAE,KAAK,CACd,IAAI,CAAC;YACH,EAAE,EAAE,MAAM,EAAE;YACZ,OAAO,EAAE,wBAAwB;YACjC,MAAM,EAAE,2BAA2B;YACnC,SAAS,EAAE,wBAAwB;YACnC,MAAM,EAAE,MAAM,EAAE;YAChB,IAAI,EAAE,MAAM,EAAE;YACd,QAAQ,EAAE,MAAM,EAAE;SACnB,CAAC,CACH;QACD,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF,SAAS,EAAE,IAAI,CAAC;QACd,GAAG,kBAAkB,CAAC,MAAM;QAC5B,SAAS,EAAE,KAAK,CACd,IAAI,CAAC;YACH,EAAE,EAAE,MAAM,EAAE;YACZ,OAAO,EAAE,wBAAwB;YACjC,MAAM,EAAE,2BAA2B;YACnC,GAAG,EAAE,8BAA8B;YACnC,SAAS,EAAE,wBAAwB;YACnC,IAAI,EAAE,kBAAkB;YACxB,aAAa,EAAE,MAAM,EAAE;YACvB,WAAW,EAAE,MAAM,EAAE;YACrB,gBAAgB,EAAE,wBAAwB;YAC1C,cAAc,EAAE,wBAAwB;YACxC,MAAM,EAAE,MAAM,EAAE;SACjB,CAAC,CACH;QACD,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF,MAAM,EAAE,IAAI,CAAC;QACX,GAAG,kBAAkB,CAAC,MAAM;QAC5B,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,IAAI,CAAC;QACb,GAAG,kBAAkB,CAAC,MAAM;QAC5B,gBAAgB,EAAE,KAAK,CACrB,IAAI,CAAC;YACH,SAAS,EAAE,wBAAwB;YACnC,QAAQ,EAAE,wBAAwB;YAClC,SAAS,EAAE,wBAAwB;YACnC,MAAM,EAAE,yBAAyB;YACjC,IAAI,EAAE,yBAAyB;YAC/B,YAAY,EAAE,8BAA8B;YAC5C,YAAY,EAAE,MAAM,EAAE;SACvB,CAAC,CACH;KACF,CAAC;IACF,GAAG,EAAE,IAAI,CAAC;QACR,GAAG,kBAAkB,CAAC,MAAM;QAC5B,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,GAAG,EAAE,QAAQ,CACX,KAAK,CACH,IAAI,CAAC;YACH,SAAS,EAAE,wBAAwB;YACnC,QAAQ,EAAE,kBAAkB;YAC5B,MAAM,EAAE,kBAAkB;YAC1B,OAAO,EAAE,kBAAkB;YAC3B,MAAM,EAAE,kBAAkB;SAC3B,CAAC,CACH,CACF;KACF,CAAC;IACF,OAAO,EAAE,IAAI,CAAC;QACZ,GAAG,kBAAkB,CAAC,MAAM;QAC5B,CAAC,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,CAAC,EAAE,QAAQ,CACT,KAAK,CACH,IAAI,CAAC;YACH,CAAC,EAAE,wBAAwB;YAC3B,CAAC,EAAE,kBAAkB;YACrB,CAAC,EAAE,kBAAkB;YACrB,CAAC,EAAE,kBAAkB;YACrB,CAAC,EAAE,kBAAkB;YACrB,CAAC,EAAE,kBAAkB;SACtB,CAAC,CACH,CACF;KACF,CAAC;CACM,CAAC;AAEX;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAC3D,IAAI,CAAC,WAAW,EAAE,CACnB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;YACrE,UAAU,CAAC,GAAG,CAAC;YACf,sBAAsB,CAAC,KAAK,CAAC;SAC9B,CAAC,CACH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAqB;IAElC,YAAY,OAAe,EAAE,IAAa;QACxC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,oBAAoB;IACtB,KAAK,CAA4B;IAEjC,UAAU,CAAU;IAE7B,aAAa,GAAkC,IAAI,CAAC;IAEpD,iBAAiB,GAAG,CAAC,CAAC;IAEtB,YAAY,IAA+B,EAAE,MAA8B;QACzE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;IACrC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED,IAAI,OAAO;QACT,OAAO,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,YAAY,GAAG,KAAK;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IACE,CAAC,YAAY;YACb,IAAI,CAAC,aAAa;YAClB,GAAG,GAAG,IAAI,CAAC,iBAAiB,GAAG,oBAAoB,EACnD,CAAC;YACD,OAAO,IAAI,CAAC,aAAa,CAAC;QAC5B,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAC9B,oBAAoB,EACpB,eAAe,CAAC,UAAU,CAC3B,CAAC;QACF,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,UAAU,CAAC;QACzC,IAAI,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC7B,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB;QACvB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,0BAA0B,EAC1B,eAAe,CAAC,gBAAgB,CACjC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,iBAAiB,CACrB,YAAoB;QAEpB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,kCAAkC,YAAY,EAAE,EAChD,eAAe,CAAC,OAAO,CACxB,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,sBAAsB,CAC1B,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,0CAA0C,SAAS,EAAE,EACrD,eAAe,CAAC,iBAAiB,CAClC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CACd,YAAoB,EACpB,WAAW,GAAG,GAAG;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,iCAAiC,YAAY,kBAAkB,WAAW,EAAE,EAC5E,eAAe,CAAC,OAAO,CACxB,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAChB,YAAoB,EACpB,WAAmB;QAEnB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,mCAAmC,YAAY,kBAAkB,WAAW,EAAE,EAC9E,eAAe,CAAC,SAAS,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,4BAA4B,kBAAkB,CAAC,MAAM,CAAC,EAAE,EACxD,eAAe,CAAC,WAAW,CAC5B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,eAAe,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC7D,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CACnB,YAAoB,EACpB,SAAiB,EACjB,QAAQ,GAAG,GAAG;QAEd,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,6CAA6C,YAAY,cAAc,QAAQ,EAAE,EACjF,eAAe,CAAC,YAAY,EAC5B,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,iBAAiB,CACrB,YAAoB,EACpB,SAAiB,EACjB,KAAK,GAAG,EAAE,EACV,MAAe,EACf,QAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,+CAA+C,YAAY,UAAU,KAAK,GACxE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,kBAAkB,CAAC,MAAM,CAAC,EACnE,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,QAAQ,EAAE,EAAE,EAC3D,eAAe,CAAC,cAAc,EAC9B,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,iBAAiB,CACrB,YAAoB,EACpB,SAAiB,EACjB,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,yCAAyC,YAAY,eAAe,SAAS,EAAE,EAC/E,eAAe,CAAC,QAAQ,EACxB,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,kBAAkB,CACtB,YAAoB,EACpB,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,0CAA0C,YAAY,EAAE,EACxD,eAAe,CAAC,WAAW,EAC3B,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,kBAAkB,CACtB,YAAoB,EACpB,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,0CAA0C,YAAY,EAAE,EACxD,eAAe,CAAC,SAAS,EACzB,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS,CACb,YAAoB,EACpB,SAAiB,EACjB,KAAyB;QAEzB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAChD,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,wDAAwD,KAAK,kBAAkB,YAAY,oBACzF,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,kBAAkB,CAAC,MAAM,CAAC,EACnE,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,GAC1C,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,QAAQ,EACtD,EAAE,EACF,eAAe,CAAC,MAAM,EACtB,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,mBAAmB,CACvB,YAAoB,EACpB,SAAiB,EACjB,KAAK,GAAG,EAAE;QAEV,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,yCAAyC,YAAY,wBAAwB,KAAK,6BAA6B,EAC/G,eAAe,CAAC,QAAQ,EACxB,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAM,CACV,YAAoB,EACpB,SAAiB,EACjB,cAAsB,EACtB,YAAoB,EACpB,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,8BAA8B,YAAY,6BAA6B,SAAS,oBAAoB,cAAc,kBAAkB,YAAY,EAAE,EAClJ,eAAe,CAAC,GAAG,EACnB,EAAE,aAAa,EAAE,SAAS,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,UAAU,CACd,QAAgB,EAChB,UAAkB,EAClB,cAAsB,EACtB,YAAoB,EACpB,SAAiB;QAEjB,OAAO,MAAM,IAAI,CAAC,IAAI,CACpB,6BAA6B,QAAQ,eAAe,UAAU,oBAAoB,cAAc,kBAAkB,YAAY,eAAe,SAAS,EAAE,EACxJ,eAAe,CAAC,OAAO,CACxB,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC;YAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAClC,gBAAgB,EAChB;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE;SACtB,EACD,eAAe,CAAC,eAAe,CAChC,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEQ,IAAI,GAAG,KAAK,EACnB,IAAY,EACZ,cAAuC,EACvC,OAAgC,EACf,EAAE;QACnB,OAAO,MAAM,IAAI,CAAC,QAAQ,CACxB,IAAI,EACJ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAC1B,cAAc,CACf,CAAC;IACJ,CAAC,CAAC;IAEO,QAAQ,GAAG,KAAK,EACvB,IAAY,EACZ,IAAyE,EACzE,cAAuC,EACtB,EAAE;QACnB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CACxB,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EACxB,uBAAuB,CACxB,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,MAAM,OAAO,GAAY,sBAAsB,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YACvE,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YAEpC,qEAAqE;YACrE,gEAAgE;YAChE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,OAAO,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;gBACzC,MAAM,IAAI,eAAe,CACvB,OAAO,CAAC,OAAO,IAAI,2BAA2B,QAAQ,CAAC,MAAM,GAAG,EAChE,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,CAChC,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,eAAe,CACvB,GAAG,6BAA6B,iBAAiB,IAAI,KACnD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;gBACrC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,qCAAqC,EAAE;gBACnE,GAAG;gBACH,KAAK;aACN,CAAC,CAAC;YACH,MAAM,IAAI,eAAe,CACvB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;CACH","sourcesContent":["/**\n * Lighter Client Service\n *\n * Thin REST client for the zkLighter API. No SDK dependency — endpoints are\n * called with the platform `fetch` global. Each successful endpoint response\n * is decoded before it reaches provider signing or trading logic.\n *\n * Endpoints used (https://apidocs.lighter.xyz):\n * - GET /api/v1/orderBooks market metadata\n * - GET /api/v1/orderBookDetails market stats\n * - GET /api/v1/account account (+positions) by index\n * - GET /api/v1/accountsByL1Address account discovery\n * - GET /api/v1/apikeys registered venue keys\n * - GET /api/v1/nextNonce per-key nonce\n * - GET /api/v1/accountActiveOrders open orders (auth token header)\n * - POST /api/v1/sendTx submit signed L2 transaction\n */\n\nimport type { Struct } from '@metamask/superstruct';\nimport {\n array,\n assert,\n boolean,\n define,\n optional,\n record,\n refine,\n string,\n type,\n union,\n} from '@metamask/superstruct';\n\nimport {\n getLighterHttpEndpoint,\n LIGHTER_DATA_INTEGRITY_PREFIX,\n LIGHTER_HTTP_TIMEOUT_MS,\n} from '../constants/lighterConfig.js';\nimport type { PerpsPlatformDependencies } from '../types/index.js';\nimport type {\n LighterAccountResponse,\n LighterAccountsByL1AddressResponse,\n LighterActiveOrdersResponse,\n LighterApiKeysResponse,\n LighterNetwork,\n LighterNextNonceResponse,\n LighterTxLookupResponse,\n LighterOrderBookMeta,\n LighterOrderBookDetailsResponse,\n LighterOrderBooksResponse,\n LighterCandlesResponse,\n LighterDepositHistoryResponse,\n LighterInactiveOrdersResponse,\n LighterPnlResponse,\n LighterPositionFundingsResponse,\n LighterSendTxResponse,\n LighterTradesResponse,\n LighterTradesQuery,\n LighterTransferType,\n LighterTransferHistoryResponse,\n LighterWithdrawHistoryResponse,\n} from '../types/lighter-types.js';\n\n/**\n * Duration market metadata stays cached before a refetch.\n */\nconst MARKETS_CACHE_TTL_MS = 5 * 60 * 1000;\n\nconst FiniteNumberStruct = define<number>('finite number', (value) =>\n typeof value === 'number' ? Number.isFinite(value) : false,\n);\nconst SafeIntegerStruct = define<number>('safe integer', (value) =>\n typeof value === 'number' ? Number.isSafeInteger(value) : false,\n);\nconst NonNegativeIntegerStruct = define<number>(\n 'non-negative safe integer',\n (value) =>\n typeof value === 'number'\n ? Number.isSafeInteger(value) && value >= 0\n : false,\n);\nconst parseStrictDecimalString = (value: unknown): number | null => {\n if (\n typeof value !== 'string' ||\n !/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/u.test(value)\n ) {\n return null;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n};\nconst SignedDecimalStringStruct = define<string>(\n 'finite decimal string',\n (value) => parseStrictDecimalString(value) !== null,\n);\nconst NonNegativeDecimalStringStruct = define<string>(\n 'non-negative finite decimal string',\n (value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed >= 0;\n },\n);\nconst TransferTypeStruct = define<LighterTransferType>(\n 'Lighter transfer type',\n (value) => value === 'L2TransferInflow' || value === 'L2TransferOutflow',\n);\nconst PositiveDecimalStringStruct = define<string>(\n 'positive finite decimal string',\n (value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed > 0;\n },\n);\nconst NonNegativeFiniteNumberStruct = define<number>(\n 'non-negative finite number',\n (value) => typeof value === 'number' && Number.isFinite(value) && value >= 0,\n);\nconst NonNegativeMarginFractionStruct = define<number>(\n 'margin fraction in [0, 10000]',\n (value) =>\n typeof value === 'number' &&\n Number.isSafeInteger(value) &&\n value >= 0 &&\n value <= 10_000,\n);\nconst NonNegativeFinancialNumberStruct = union([\n NonNegativeFiniteNumberStruct,\n NonNegativeDecimalStringStruct,\n]);\nconst BaseResponseStruct = type({\n code: SafeIntegerStruct,\n message: optional(string()),\n});\nconst PositionStruct = type({\n marketId: NonNegativeIntegerStruct,\n symbol: string(),\n initialMarginFraction: NonNegativeDecimalStringStruct,\n openOrderCount: NonNegativeIntegerStruct,\n sign: SafeIntegerStruct,\n position: NonNegativeDecimalStringStruct,\n avgEntryPrice: NonNegativeDecimalStringStruct,\n positionValue: NonNegativeDecimalStringStruct,\n unrealizedPnl: SignedDecimalStringStruct,\n realizedPnl: SignedDecimalStringStruct,\n liquidationPrice: NonNegativeDecimalStringStruct,\n marginMode: optional(SafeIntegerStruct),\n});\nconst AccountStruct = type({\n code: SafeIntegerStruct,\n accountType: SafeIntegerStruct,\n index: NonNegativeIntegerStruct,\n l1Address: string(),\n cancelAllTime: NonNegativeIntegerStruct,\n totalOrderCount: NonNegativeIntegerStruct,\n pendingOrderCount: NonNegativeIntegerStruct,\n status: SafeIntegerStruct,\n collateral: NonNegativeDecimalStringStruct,\n availableBalance: NonNegativeDecimalStringStruct,\n positions: optional(array(PositionStruct)),\n});\n// The address-discovery endpoint is an identity lookup, not a financial read:\n// live responses can carry sparse balance fields (for example an empty\n// `availableBalance`). Validate only the fields its sole consumer needs. Full\n// account reads retain AccountStruct and its strict financial validation.\nconst AccountSummaryStruct = type({\n accountType: SafeIntegerStruct,\n index: NonNegativeIntegerStruct,\n l1Address: string(),\n});\nconst MarketBaseStruct = type({\n symbol: string(),\n marketId: NonNegativeIntegerStruct,\n marketType: string(),\n status: string(),\n takerFee: SignedDecimalStringStruct,\n makerFee: SignedDecimalStringStruct,\n minBaseAmount: NonNegativeDecimalStringStruct,\n minQuoteAmount: NonNegativeDecimalStringStruct,\n supportedSizeDecimals: NonNegativeIntegerStruct,\n supportedPriceDecimals: NonNegativeIntegerStruct,\n supportedQuoteDecimals: NonNegativeIntegerStruct,\n});\nconst hasValidMarketMinimums = (\n market: Pick<\n LighterOrderBookMeta,\n 'status' | 'minBaseAmount' | 'minQuoteAmount'\n >,\n): boolean =>\n market.status === 'inactive' ||\n [market.minBaseAmount, market.minQuoteAmount].every((value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed > 0;\n });\nconst MarketStruct = refine(\n MarketBaseStruct,\n 'positive minimum amounts for tradable markets',\n hasValidMarketMinimums,\n);\nconst MarketDetailBaseStruct = type({\n ...MarketBaseStruct.schema,\n lastTradePrice: NonNegativeFiniteNumberStruct,\n defaultInitialMarginFraction: optional(NonNegativeMarginFractionStruct),\n minInitialMarginFraction: optional(NonNegativeMarginFractionStruct),\n maintenanceMarginFraction: optional(NonNegativeMarginFractionStruct),\n dailyTradesCount: NonNegativeFiniteNumberStruct,\n dailyBaseTokenVolume: NonNegativeFiniteNumberStruct,\n dailyQuoteTokenVolume: NonNegativeFiniteNumberStruct,\n dailyPriceLow: NonNegativeFiniteNumberStruct,\n dailyPriceHigh: NonNegativeFiniteNumberStruct,\n dailyPriceChange: FiniteNumberStruct,\n openInterest: NonNegativeFiniteNumberStruct,\n dailyChart: record(string(), FiniteNumberStruct),\n});\nconst hasValidMarketMarginFractions = (market: {\n status: string;\n defaultInitialMarginFraction?: number;\n minInitialMarginFraction?: number;\n maintenanceMarginFraction?: number;\n}): boolean =>\n market.status === 'inactive' ||\n [\n market.defaultInitialMarginFraction,\n market.minInitialMarginFraction,\n market.maintenanceMarginFraction,\n ].every((value) => value === undefined || value > 0);\nconst MarketDetailStruct = refine(\n refine(\n MarketDetailBaseStruct,\n 'positive minimum amounts for tradable markets',\n hasValidMarketMinimums,\n ),\n 'positive margin fractions for tradable markets',\n hasValidMarketMarginFractions,\n);\nconst OrderStruct = type({\n orderIndex: NonNegativeIntegerStruct,\n clientOrderIndex: NonNegativeIntegerStruct,\n marketIndex: NonNegativeIntegerStruct,\n ownerAccountIndex: NonNegativeIntegerStruct,\n initialBaseAmount: PositiveDecimalStringStruct,\n remainingBaseAmount: NonNegativeDecimalStringStruct,\n price: PositiveDecimalStringStruct,\n isAsk: boolean(),\n type: string(),\n timeInForce: string(),\n reduceOnly: union([FiniteNumberStruct, boolean()]),\n status: string(),\n orderExpiry: SafeIntegerStruct,\n timestamp: NonNegativeIntegerStruct,\n triggerPrice: optional(NonNegativeDecimalStringStruct),\n orderId: optional(string()),\n parentOrderIndex: optional(NonNegativeIntegerStruct),\n parentOrderId: optional(string()),\n toCancelOrderId0: optional(string()),\n toTriggerOrderId0: optional(string()),\n toTriggerOrderId1: optional(string()),\n});\nconst TradeStruct = type({\n tradeId: NonNegativeIntegerStruct,\n txHash: string(),\n type: string(),\n marketId: NonNegativeIntegerStruct,\n size: PositiveDecimalStringStruct,\n price: PositiveDecimalStringStruct,\n usdAmount: PositiveDecimalStringStruct,\n askId: NonNegativeIntegerStruct,\n bidId: NonNegativeIntegerStruct,\n askAccountId: NonNegativeIntegerStruct,\n bidAccountId: NonNegativeIntegerStruct,\n isMakerAsk: boolean(),\n timestamp: NonNegativeIntegerStruct,\n askAccountPnl: optional(SignedDecimalStringStruct),\n bidAccountPnl: optional(SignedDecimalStringStruct),\n takerFee: optional(NonNegativeFinancialNumberStruct),\n makerFee: optional(NonNegativeFinancialNumberStruct),\n takerPositionSizeBefore: NonNegativeDecimalStringStruct,\n makerPositionSizeBefore: NonNegativeDecimalStringStruct,\n takerPositionSignChanged: boolean(),\n makerPositionSignChanged: boolean(),\n});\n\nconst ResponseStructs = {\n orderBooks: type({\n ...BaseResponseStruct.schema,\n orderBooks: array(MarketStruct),\n }),\n orderBookDetails: type({\n ...BaseResponseStruct.schema,\n orderBookDetails: array(MarketDetailStruct),\n }),\n account: type({\n ...BaseResponseStruct.schema,\n accounts: array(AccountStruct),\n }),\n accountsByAddress: type({\n ...BaseResponseStruct.schema,\n l1Address: string(),\n subAccounts: array(AccountSummaryStruct),\n }),\n apiKeys: type({\n ...BaseResponseStruct.schema,\n apiKeys: array(\n type({\n accountIndex: NonNegativeIntegerStruct,\n apiKeyIndex: NonNegativeIntegerStruct,\n nonce: NonNegativeIntegerStruct,\n publicKey: string(),\n }),\n ),\n }),\n nextNonce: type({\n ...BaseResponseStruct.schema,\n nonce: NonNegativeIntegerStruct,\n }),\n transaction: type({\n ...BaseResponseStruct.schema,\n hash: string(),\n accountIndex: NonNegativeIntegerStruct,\n apiKeyIndex: NonNegativeIntegerStruct,\n nonce: NonNegativeIntegerStruct,\n status: SafeIntegerStruct,\n }),\n sendTransaction: type({\n ...BaseResponseStruct.schema,\n txHash: string(),\n }),\n activeOrders: type({\n ...BaseResponseStruct.schema,\n orders: array(OrderStruct),\n }),\n inactiveOrders: type({\n ...BaseResponseStruct.schema,\n nextCursor: optional(string()),\n orders: array(OrderStruct),\n }),\n deposits: type({\n ...BaseResponseStruct.schema,\n deposits: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n status: string(),\n l1TxHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n withdrawals: type({\n ...BaseResponseStruct.schema,\n withdraws: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n status: string(),\n type: string(),\n l1TxHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n transfers: type({\n ...BaseResponseStruct.schema,\n transfers: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n fee: NonNegativeDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n type: TransferTypeStruct,\n fromL1Address: string(),\n toL1Address: string(),\n fromAccountIndex: NonNegativeIntegerStruct,\n toAccountIndex: NonNegativeIntegerStruct,\n txHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n trades: type({\n ...BaseResponseStruct.schema,\n nextCursor: optional(string()),\n trades: array(TradeStruct),\n }),\n fundings: type({\n ...BaseResponseStruct.schema,\n positionFundings: array(\n type({\n timestamp: NonNegativeIntegerStruct,\n marketId: NonNegativeIntegerStruct,\n fundingId: NonNegativeIntegerStruct,\n change: SignedDecimalStringStruct,\n rate: SignedDecimalStringStruct,\n positionSize: NonNegativeDecimalStringStruct,\n positionSide: string(),\n }),\n ),\n }),\n pnl: type({\n ...BaseResponseStruct.schema,\n resolution: optional(string()),\n pnl: optional(\n array(\n type({\n timestamp: NonNegativeIntegerStruct,\n tradePnl: FiniteNumberStruct,\n inflow: FiniteNumberStruct,\n outflow: FiniteNumberStruct,\n volume: FiniteNumberStruct,\n }),\n ),\n ),\n }),\n candles: type({\n ...BaseResponseStruct.schema,\n r: optional(string()),\n c: optional(\n array(\n type({\n t: NonNegativeIntegerStruct,\n o: FiniteNumberStruct,\n h: FiniteNumberStruct,\n l: FiniteNumberStruct,\n c: FiniteNumberStruct,\n v: FiniteNumberStruct,\n }),\n ),\n ),\n }),\n} as const;\n\n/**\n * Convert a snake_case wire key to camelCase.\n *\n * @param key - Wire key (e.g. `min_base_amount`).\n * @returns camelCase key (e.g. `minBaseAmount`).\n */\nfunction toCamelKey(key: string): string {\n return key.replace(/_([a-z0-9])/gu, (_match, char: string) =>\n char.toUpperCase(),\n );\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n * The zkLighter wire format is snake_case; parsed shapes in this package\n * follow camelCase conventions (see types/lighter-types.ts).\n *\n * @param value - Parsed JSON value.\n * @returns The value with camelCase keys.\n */\nexport function convertKeysToCamelCase(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(convertKeysToCamelCase);\n }\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, entry]) => [\n toCamelKey(key),\n convertKeysToCamelCase(entry),\n ]),\n );\n }\n return value;\n}\n\n/**\n * Error thrown for non-2xx HTTP responses or API-level error codes.\n */\nexport class LighterApiError extends Error {\n readonly code: number | undefined;\n\n constructor(message: string, code?: number) {\n super(message);\n this.name = 'LighterApiError';\n this.code = code;\n }\n}\n\n/**\n * REST client for the zkLighter API.\n */\nexport class LighterClientService {\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #isTestnet: boolean;\n\n #marketsCache: LighterOrderBookMeta[] | null = null;\n\n #marketsCacheTime = 0;\n\n constructor(deps: PerpsPlatformDependencies, config: { isTestnet: boolean }) {\n this.#deps = deps;\n this.#isTestnet = config.isTestnet;\n }\n\n get network(): LighterNetwork {\n return this.#isTestnet ? 'testnet' : 'mainnet';\n }\n\n get baseUrl(): string {\n return getLighterHttpEndpoint(this.network);\n }\n\n /**\n * Fetch market metadata, cached for 5 minutes.\n *\n * @param forceRefresh - Skip the cache and refetch.\n * @returns Market metadata entries.\n */\n async getOrderBooks(forceRefresh = false): Promise<LighterOrderBookMeta[]> {\n const now = Date.now();\n if (\n !forceRefresh &&\n this.#marketsCache &&\n now - this.#marketsCacheTime < MARKETS_CACHE_TTL_MS\n ) {\n return this.#marketsCache;\n }\n\n const response = await this.#get<LighterOrderBooksResponse>(\n '/api/v1/orderBooks',\n ResponseStructs.orderBooks,\n );\n this.#marketsCache = response.orderBooks;\n this.#marketsCacheTime = now;\n return response.orderBooks;\n }\n\n /**\n * Fetch market stats for all markets.\n *\n * @returns Order book details entries.\n */\n async getOrderBookDetails(): Promise<LighterOrderBookDetailsResponse> {\n return await this.#get<LighterOrderBookDetailsResponse>(\n '/api/v1/orderBookDetails',\n ResponseStructs.orderBookDetails,\n );\n }\n\n /**\n * Fetch an account (including positions) by its Lighter index.\n *\n * @param accountIndex - The Lighter account index.\n * @returns Account payload.\n */\n async getAccountByIndex(\n accountIndex: number,\n ): Promise<LighterAccountResponse> {\n return await this.#get<LighterAccountResponse>(\n `/api/v1/account?by=index&value=${accountIndex}`,\n ResponseStructs.account,\n );\n }\n\n /**\n * Discover Lighter accounts owned by an L1 address.\n *\n * @param l1Address - The owning EVM address.\n * @returns Accounts payload.\n */\n async getAccountsByL1Address(\n l1Address: string,\n ): Promise<LighterAccountsByL1AddressResponse> {\n return await this.#get<LighterAccountsByL1AddressResponse>(\n `/api/v1/accountsByL1Address?l1_address=${l1Address}`,\n ResponseStructs.accountsByAddress,\n );\n }\n\n /**\n * Fetch registered API keys for an account.\n *\n * @param accountIndex - The Lighter account index.\n * @param apiKeyIndex - Key slot, or 255 for all slots.\n * @returns API keys payload.\n */\n async getApiKeys(\n accountIndex: number,\n apiKeyIndex = 255,\n ): Promise<LighterApiKeysResponse> {\n return await this.#get<LighterApiKeysResponse>(\n `/api/v1/apikeys?account_index=${accountIndex}&api_key_index=${apiKeyIndex}`,\n ResponseStructs.apiKeys,\n );\n }\n\n /**\n * Fetch the next nonce for a key slot.\n *\n * @param accountIndex - The Lighter account index.\n * @param apiKeyIndex - Key slot.\n * @returns Next nonce payload.\n */\n async getNextNonce(\n accountIndex: number,\n apiKeyIndex: number,\n ): Promise<LighterNextNonceResponse> {\n return await this.#get<LighterNextNonceResponse>(\n `/api/v1/nextNonce?account_index=${accountIndex}&api_key_index=${apiKeyIndex}`,\n ResponseStructs.nextNonce,\n );\n }\n\n /**\n * Look up a transaction by its exact hash (`GET /api/v1/tx`). Used to\n * resolve submission-acceptance ambiguity authoritatively: an exact-hash\n * match proves the signed payload reached the sequencer.\n *\n * Contract: a venue-confirmed \"transaction not found\" (API error code\n * 21500) resolves to NULL; transport failures and every other API error\n * RETHROW — they are ambiguity, never evidence of non-acceptance.\n *\n * @param txHash - The signed transaction hash.\n * @returns The venue's transaction payload, or null when the venue\n * confirms the hash is unknown.\n */\n async getTx(txHash: string): Promise<LighterTxLookupResponse | null> {\n try {\n return await this.#get<LighterTxLookupResponse>(\n `/api/v1/tx?by=hash&value=${encodeURIComponent(txHash)}`,\n ResponseStructs.transaction,\n );\n } catch (error) {\n if (error instanceof LighterApiError && error.code === 21500) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch active (open) orders for an account.\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer (`_createAuthToken`).\n * @param marketId - Optional market filter (255 = all markets).\n * @returns Active orders payload.\n */\n async getActiveOrders(\n accountIndex: number,\n authToken: string,\n marketId = 255,\n ): Promise<LighterActiveOrdersResponse> {\n return await this.#get<LighterActiveOrdersResponse>(\n `/api/v1/accountActiveOrders?account_index=${accountIndex}&market_id=${marketId}`,\n ResponseStructs.activeOrders,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch historical (inactive) orders: filled and canceled lifecycle\n * states, newest first (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param limit - Maximum entries per page.\n * @param cursor - Pagination cursor from a previous page's `nextCursor`.\n * @param marketId - Optional market filter (official `market_id` query\n * param) — sharply bounds history scans to one symbol.\n * @returns Inactive orders payload.\n */\n async getInactiveOrders(\n accountIndex: number,\n authToken: string,\n limit = 50,\n cursor?: string,\n marketId?: number,\n ): Promise<LighterInactiveOrdersResponse> {\n return await this.#get<LighterInactiveOrdersResponse>(\n `/api/v1/accountInactiveOrders?account_index=${accountIndex}&limit=${limit}${\n cursor === undefined ? '' : `&cursor=${encodeURIComponent(cursor)}`\n }${marketId === undefined ? '' : `&market_id=${marketId}`}`,\n ResponseStructs.inactiveOrders,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L1→L2 deposit history (auth token required). The venue requires\n * both the account index and its L1 address on this endpoint.\n *\n * @param accountIndex - The Lighter account index.\n * @param l1Address - The account's L1 address.\n * @param authToken - Auth token minted by the signer.\n * @returns Deposit history payload (newest first, cursor-paged).\n */\n async getDepositHistory(\n accountIndex: number,\n l1Address: string,\n authToken: string,\n ): Promise<LighterDepositHistoryResponse> {\n return await this.#get<LighterDepositHistoryResponse>(\n `/api/v1/deposit/history?account_index=${accountIndex}&l1_address=${l1Address}`,\n ResponseStructs.deposits,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L2→L1 withdrawal history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @returns Withdrawal history payload (newest first, cursor-paged).\n */\n async getWithdrawHistory(\n accountIndex: number,\n authToken: string,\n ): Promise<LighterWithdrawHistoryResponse> {\n return await this.#get<LighterWithdrawHistoryResponse>(\n `/api/v1/withdraw/history?account_index=${accountIndex}`,\n ResponseStructs.withdrawals,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L2 transfer history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @returns Transfer history payload (newest first, cursor-paged).\n */\n async getTransferHistory(\n accountIndex: number,\n authToken: string,\n ): Promise<LighterTransferHistoryResponse> {\n return await this.#get<LighterTransferHistoryResponse>(\n `/api/v1/transfer/history?account_index=${accountIndex}`,\n ResponseStructs.transfers,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch account trade history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param query - Pagination, range, and market filters.\n * @returns Trades payload (newest first).\n */\n async getTrades(\n accountIndex: number,\n authToken: string,\n query: LighterTradesQuery,\n ): Promise<LighterTradesResponse> {\n const { limit, cursor, from, marketId } = query;\n return await this.#get<LighterTradesResponse>(\n `/api/v1/trades?sort_by=timestamp&sort_dir=desc&limit=${limit}&account_index=${accountIndex}&market_type=perp${\n cursor === undefined ? '' : `&cursor=${encodeURIComponent(cursor)}`\n }${from === undefined ? '' : `&from=${from}`}${\n marketId === undefined ? '' : `&market_id=${marketId}`\n }`,\n ResponseStructs.trades,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch user funding payment history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param limit - Max entries.\n * @returns Position fundings payload.\n */\n async getPositionFundings(\n accountIndex: number,\n authToken: string,\n limit = 50,\n ): Promise<LighterPositionFundingsResponse> {\n return await this.#get<LighterPositionFundingsResponse>(\n `/api/v1/positionFunding?account_index=${accountIndex}&market_id=255&limit=${limit}&sort_by=timestamp&side=all`,\n ResponseStructs.fundings,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch account PnL history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param startTimestamp - Range start (ms).\n * @param endTimestamp - Range end (ms).\n * @param countBack - Records counted back from range end.\n * @returns PnL payload.\n */\n async getPnl(\n accountIndex: number,\n authToken: string,\n startTimestamp: number,\n endTimestamp: number,\n countBack: number,\n ): Promise<LighterPnlResponse> {\n return await this.#get<LighterPnlResponse>(\n `/api/v1/pnl?by=index&value=${accountIndex}&resolution=1d&count_back=${countBack}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}`,\n ResponseStructs.pnl,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch an OHLCV candle series for a market.\n *\n * @param marketId - Numeric Lighter market id.\n * @param resolution - Candle resolution (e.g. `1m`, `15m`, `1h`, `1d`).\n * @param startTimestamp - Range start (ms).\n * @param endTimestamp - Range end (ms).\n * @param countBack - Number of candles counted back from the range end.\n * @returns Candle series payload.\n */\n async getCandles(\n marketId: number,\n resolution: string,\n startTimestamp: number,\n endTimestamp: number,\n countBack: number,\n ): Promise<LighterCandlesResponse> {\n return await this.#get<LighterCandlesResponse>(\n `/api/v1/candles?market_id=${marketId}&resolution=${resolution}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}&count_back=${countBack}`,\n ResponseStructs.candles,\n );\n }\n\n /**\n * Submit a signed L2 transaction.\n *\n * @param txType - L2 transaction type code (see lighterConfig).\n * @param txInfo - Serialized signed transaction JSON.\n * @returns Send result payload.\n */\n async sendTx(txType: number, txInfo: string): Promise<LighterSendTxResponse> {\n const body = new URLSearchParams({\n tx_type: String(txType),\n tx_info: txInfo,\n });\n\n const response = await this.#request<LighterSendTxResponse>(\n '/api/v1/sendTx',\n {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n },\n ResponseStructs.sendTransaction,\n );\n return response;\n }\n\n readonly #get = async <Result extends { code: number; message?: string }>(\n path: string,\n responseStruct: Struct<Result, unknown>,\n headers?: Record<string, string>,\n ): Promise<Result> => {\n return await this.#request<Result>(\n path,\n { method: 'GET', headers },\n responseStruct,\n );\n };\n\n readonly #request = async <Result extends { code: number; message?: string }>(\n path: string,\n init: { method: string; headers?: Record<string, string>; body?: string },\n responseStruct: Struct<Result, unknown>,\n ): Promise<Result> => {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n LIGHTER_HTTP_TIMEOUT_MS,\n );\n\n try {\n const response = await fetch(url, {\n method: init.method,\n headers: init.headers,\n body: init.body,\n signal: controller.signal,\n });\n\n const payload: unknown = convertKeysToCamelCase(await response.json());\n assert(payload, BaseResponseStruct);\n\n // Lighter returns HTTP 200 with an application-level error code, and\n // 4xx/5xx with `{code, message}` bodies — treat both uniformly.\n if (!response.ok || payload.code !== 200) {\n throw new LighterApiError(\n payload.message ?? `Lighter API error (HTTP ${response.status})`,\n payload.code ?? response.status,\n );\n }\n try {\n assert(payload, responseStruct);\n } catch (error) {\n throw new LighterApiError(\n `${LIGHTER_DATA_INTEGRITY_PREFIX} response for ${path}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n return payload;\n } catch (error) {\n if (error instanceof LighterApiError) {\n throw error;\n }\n this.#deps.debugLogger?.log?.('LighterClientService request failed', {\n url,\n error,\n });\n throw new LighterApiError(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n clearTimeout(timeout);\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"LighterClientService.js","sourceRoot":"","sources":["../../src/services/LighterClientService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lighter Client Service\n *\n * Thin REST client for the zkLighter API. No SDK dependency — endpoints are\n * called with the platform `fetch` global. Each successful endpoint response\n * is decoded before it reaches provider signing or trading logic.\n *\n * Endpoints used (https://apidocs.lighter.xyz):\n * - GET /api/v1/orderBooks market metadata\n * - GET /api/v1/orderBookDetails market stats\n * - GET /api/v1/account account (+positions) by index\n * - GET /api/v1/accountsByL1Address account discovery\n * - GET /api/v1/apikeys registered venue keys\n * - GET /api/v1/nextNonce per-key nonce\n * - GET /api/v1/accountActiveOrders open orders (auth token header)\n * - POST /api/v1/sendTx submit signed L2 transaction\n */\n\nimport type { Struct } from '@metamask/superstruct';\nimport {\n array,\n assert,\n boolean,\n define,\n optional,\n record,\n refine,\n string,\n type,\n union,\n} from '@metamask/superstruct';\n\nimport {\n getLighterHttpEndpoint,\n LIGHTER_DATA_INTEGRITY_PREFIX,\n LIGHTER_HTTP_TIMEOUT_MS,\n} from '../constants/lighterConfig.js';\nimport type { PerpsPlatformDependencies } from '../types/index.js';\nimport type {\n LighterAccountResponse,\n LighterAccountsByL1AddressResponse,\n LighterActiveOrdersResponse,\n LighterApiKeysResponse,\n LighterNetwork,\n LighterNextNonceResponse,\n LighterTxLookupResponse,\n LighterOrderBookMeta,\n LighterOrderBookDetailsResponse,\n LighterOrderBooksResponse,\n LighterCandlesResponse,\n LighterDepositHistoryResponse,\n LighterInactiveOrdersResponse,\n LighterPnlResponse,\n LighterPositionFundingsResponse,\n LighterSendTxResponse,\n LighterTradesResponse,\n LighterTradesQuery,\n LighterTransferType,\n LighterTransferHistoryResponse,\n LighterWithdrawHistoryResponse,\n} from '../types/lighter-types.js';\n\n/**\n * Duration market metadata stays cached before a refetch.\n */\nconst MARKETS_CACHE_TTL_MS = 5 * 60 * 1000;\n\nconst FiniteNumberStruct = define<number>('finite number', (value) =>\n typeof value === 'number' ? Number.isFinite(value) : false,\n);\nconst SafeIntegerStruct = define<number>('safe integer', (value) =>\n typeof value === 'number' ? Number.isSafeInteger(value) : false,\n);\nconst NonNegativeIntegerStruct = define<number>(\n 'non-negative safe integer',\n (value) =>\n typeof value === 'number'\n ? Number.isSafeInteger(value) && value >= 0\n : false,\n);\nconst parseStrictDecimalString = (value: unknown): number | null => {\n if (\n typeof value !== 'string' ||\n !/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/u.test(value)\n ) {\n return null;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n};\nconst SignedDecimalStringStruct = define<string>(\n 'finite decimal string',\n (value) => parseStrictDecimalString(value) !== null,\n);\nconst NonNegativeDecimalStringStruct = define<string>(\n 'non-negative finite decimal string',\n (value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed >= 0;\n },\n);\nconst TransferTypeStruct = define<LighterTransferType>(\n 'Lighter transfer type',\n (value) => value === 'L2TransferInflow' || value === 'L2TransferOutflow',\n);\nconst PositiveDecimalStringStruct = define<string>(\n 'positive finite decimal string',\n (value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed > 0;\n },\n);\nconst NonNegativeFiniteNumberStruct = define<number>(\n 'non-negative finite number',\n (value) => typeof value === 'number' && Number.isFinite(value) && value >= 0,\n);\nconst NonNegativeMarginFractionStruct = define<number>(\n 'margin fraction in [0, 10000]',\n (value) =>\n typeof value === 'number' &&\n Number.isSafeInteger(value) &&\n value >= 0 &&\n value <= 10_000,\n);\nconst NonNegativeFinancialNumberStruct = union([\n NonNegativeFiniteNumberStruct,\n NonNegativeDecimalStringStruct,\n]);\nconst BaseResponseStruct = type({\n code: SafeIntegerStruct,\n message: optional(string()),\n});\nconst PositionStruct = type({\n marketId: NonNegativeIntegerStruct,\n symbol: string(),\n initialMarginFraction: NonNegativeDecimalStringStruct,\n openOrderCount: NonNegativeIntegerStruct,\n sign: SafeIntegerStruct,\n position: NonNegativeDecimalStringStruct,\n avgEntryPrice: NonNegativeDecimalStringStruct,\n positionValue: NonNegativeDecimalStringStruct,\n unrealizedPnl: SignedDecimalStringStruct,\n realizedPnl: SignedDecimalStringStruct,\n liquidationPrice: NonNegativeDecimalStringStruct,\n marginMode: optional(SafeIntegerStruct),\n});\nconst AccountStruct = type({\n code: SafeIntegerStruct,\n accountType: SafeIntegerStruct,\n index: NonNegativeIntegerStruct,\n l1Address: string(),\n cancelAllTime: NonNegativeIntegerStruct,\n totalOrderCount: NonNegativeIntegerStruct,\n pendingOrderCount: NonNegativeIntegerStruct,\n status: SafeIntegerStruct,\n collateral: NonNegativeDecimalStringStruct,\n availableBalance: NonNegativeDecimalStringStruct,\n positions: optional(array(PositionStruct)),\n});\n// The address-discovery endpoint is an identity lookup, not a financial read:\n// live responses can carry sparse balance fields (for example an empty\n// `availableBalance`). Validate only the fields its sole consumer needs. Full\n// account reads retain AccountStruct and its strict financial validation.\nconst AccountSummaryStruct = type({\n accountType: SafeIntegerStruct,\n index: NonNegativeIntegerStruct,\n l1Address: string(),\n});\nconst MarketBaseStruct = type({\n symbol: string(),\n marketId: NonNegativeIntegerStruct,\n marketType: string(),\n status: string(),\n takerFee: SignedDecimalStringStruct,\n makerFee: SignedDecimalStringStruct,\n minBaseAmount: NonNegativeDecimalStringStruct,\n minQuoteAmount: NonNegativeDecimalStringStruct,\n supportedSizeDecimals: NonNegativeIntegerStruct,\n supportedPriceDecimals: NonNegativeIntegerStruct,\n supportedQuoteDecimals: NonNegativeIntegerStruct,\n});\nconst hasValidMarketMinimums = (\n market: Pick<\n LighterOrderBookMeta,\n 'status' | 'minBaseAmount' | 'minQuoteAmount'\n >,\n): boolean =>\n market.status === 'inactive' ||\n [market.minBaseAmount, market.minQuoteAmount].every((value) => {\n const parsed = parseStrictDecimalString(value);\n return parsed !== null && parsed > 0;\n });\nconst MarketStruct = refine(\n MarketBaseStruct,\n 'positive minimum amounts for tradable markets',\n hasValidMarketMinimums,\n);\nconst MarketDetailBaseStruct = type({\n ...MarketBaseStruct.schema,\n lastTradePrice: NonNegativeFiniteNumberStruct,\n defaultInitialMarginFraction: optional(NonNegativeMarginFractionStruct),\n minInitialMarginFraction: optional(NonNegativeMarginFractionStruct),\n maintenanceMarginFraction: optional(NonNegativeMarginFractionStruct),\n dailyTradesCount: NonNegativeFiniteNumberStruct,\n dailyBaseTokenVolume: NonNegativeFiniteNumberStruct,\n dailyQuoteTokenVolume: NonNegativeFiniteNumberStruct,\n dailyPriceLow: NonNegativeFiniteNumberStruct,\n dailyPriceHigh: NonNegativeFiniteNumberStruct,\n dailyPriceChange: FiniteNumberStruct,\n openInterest: NonNegativeFiniteNumberStruct,\n dailyChart: record(string(), FiniteNumberStruct),\n});\nconst hasValidMarketMarginFractions = (market: {\n status: string;\n defaultInitialMarginFraction?: number;\n minInitialMarginFraction?: number;\n maintenanceMarginFraction?: number;\n}): boolean =>\n market.status === 'inactive' ||\n [\n market.defaultInitialMarginFraction,\n market.minInitialMarginFraction,\n market.maintenanceMarginFraction,\n ].every((value) => value === undefined || value > 0);\nconst MarketDetailStruct = refine(\n refine(\n MarketDetailBaseStruct,\n 'positive minimum amounts for tradable markets',\n hasValidMarketMinimums,\n ),\n 'positive margin fractions for tradable markets',\n hasValidMarketMarginFractions,\n);\nconst OrderStruct = type({\n orderIndex: NonNegativeIntegerStruct,\n clientOrderIndex: NonNegativeIntegerStruct,\n marketIndex: NonNegativeIntegerStruct,\n ownerAccountIndex: NonNegativeIntegerStruct,\n initialBaseAmount: PositiveDecimalStringStruct,\n remainingBaseAmount: NonNegativeDecimalStringStruct,\n filledBaseAmount: optional(NonNegativeDecimalStringStruct),\n price: PositiveDecimalStringStruct,\n isAsk: boolean(),\n type: string(),\n timeInForce: string(),\n reduceOnly: union([FiniteNumberStruct, boolean()]),\n status: string(),\n orderExpiry: SafeIntegerStruct,\n timestamp: NonNegativeIntegerStruct,\n triggerPrice: optional(NonNegativeDecimalStringStruct),\n orderId: optional(string()),\n parentOrderIndex: optional(NonNegativeIntegerStruct),\n parentOrderId: optional(string()),\n toCancelOrderId0: optional(string()),\n toTriggerOrderId0: optional(string()),\n toTriggerOrderId1: optional(string()),\n});\nconst TradeStruct = type({\n tradeId: NonNegativeIntegerStruct,\n txHash: string(),\n type: string(),\n marketId: NonNegativeIntegerStruct,\n size: PositiveDecimalStringStruct,\n price: PositiveDecimalStringStruct,\n usdAmount: PositiveDecimalStringStruct,\n askId: NonNegativeIntegerStruct,\n bidId: NonNegativeIntegerStruct,\n askAccountId: NonNegativeIntegerStruct,\n bidAccountId: NonNegativeIntegerStruct,\n isMakerAsk: boolean(),\n timestamp: NonNegativeIntegerStruct,\n askAccountPnl: optional(SignedDecimalStringStruct),\n bidAccountPnl: optional(SignedDecimalStringStruct),\n takerFee: optional(NonNegativeFinancialNumberStruct),\n makerFee: optional(NonNegativeFinancialNumberStruct),\n takerPositionSizeBefore: NonNegativeDecimalStringStruct,\n makerPositionSizeBefore: NonNegativeDecimalStringStruct,\n takerPositionSignChanged: boolean(),\n makerPositionSignChanged: boolean(),\n});\n\nconst ResponseStructs = {\n orderBooks: type({\n ...BaseResponseStruct.schema,\n orderBooks: array(MarketStruct),\n }),\n orderBookDetails: type({\n ...BaseResponseStruct.schema,\n orderBookDetails: array(MarketDetailStruct),\n }),\n account: type({\n ...BaseResponseStruct.schema,\n accounts: array(AccountStruct),\n }),\n accountsByAddress: type({\n ...BaseResponseStruct.schema,\n l1Address: string(),\n subAccounts: array(AccountSummaryStruct),\n }),\n apiKeys: type({\n ...BaseResponseStruct.schema,\n apiKeys: array(\n type({\n accountIndex: NonNegativeIntegerStruct,\n apiKeyIndex: NonNegativeIntegerStruct,\n nonce: NonNegativeIntegerStruct,\n publicKey: string(),\n }),\n ),\n }),\n nextNonce: type({\n ...BaseResponseStruct.schema,\n nonce: NonNegativeIntegerStruct,\n }),\n transaction: type({\n ...BaseResponseStruct.schema,\n hash: string(),\n accountIndex: NonNegativeIntegerStruct,\n apiKeyIndex: NonNegativeIntegerStruct,\n nonce: NonNegativeIntegerStruct,\n status: SafeIntegerStruct,\n }),\n sendTransaction: type({\n ...BaseResponseStruct.schema,\n txHash: string(),\n }),\n activeOrders: type({\n ...BaseResponseStruct.schema,\n orders: array(OrderStruct),\n }),\n inactiveOrders: type({\n ...BaseResponseStruct.schema,\n nextCursor: optional(string()),\n orders: array(OrderStruct),\n }),\n deposits: type({\n ...BaseResponseStruct.schema,\n deposits: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n status: string(),\n l1TxHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n withdrawals: type({\n ...BaseResponseStruct.schema,\n withdraws: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n status: string(),\n type: string(),\n l1TxHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n transfers: type({\n ...BaseResponseStruct.schema,\n transfers: array(\n type({\n id: string(),\n assetId: NonNegativeIntegerStruct,\n amount: PositiveDecimalStringStruct,\n fee: NonNegativeDecimalStringStruct,\n timestamp: NonNegativeIntegerStruct,\n type: TransferTypeStruct,\n fromL1Address: string(),\n toL1Address: string(),\n fromAccountIndex: NonNegativeIntegerStruct,\n toAccountIndex: NonNegativeIntegerStruct,\n txHash: string(),\n }),\n ),\n cursor: optional(string()),\n }),\n trades: type({\n ...BaseResponseStruct.schema,\n nextCursor: optional(string()),\n trades: array(TradeStruct),\n }),\n fundings: type({\n ...BaseResponseStruct.schema,\n positionFundings: array(\n type({\n timestamp: NonNegativeIntegerStruct,\n marketId: NonNegativeIntegerStruct,\n fundingId: NonNegativeIntegerStruct,\n change: SignedDecimalStringStruct,\n rate: SignedDecimalStringStruct,\n positionSize: NonNegativeDecimalStringStruct,\n positionSide: string(),\n }),\n ),\n }),\n pnl: type({\n ...BaseResponseStruct.schema,\n resolution: optional(string()),\n pnl: optional(\n array(\n type({\n timestamp: NonNegativeIntegerStruct,\n tradePnl: FiniteNumberStruct,\n inflow: FiniteNumberStruct,\n outflow: FiniteNumberStruct,\n volume: FiniteNumberStruct,\n }),\n ),\n ),\n }),\n candles: type({\n ...BaseResponseStruct.schema,\n r: optional(string()),\n c: optional(\n array(\n type({\n t: NonNegativeIntegerStruct,\n o: FiniteNumberStruct,\n h: FiniteNumberStruct,\n l: FiniteNumberStruct,\n c: FiniteNumberStruct,\n v: FiniteNumberStruct,\n }),\n ),\n ),\n }),\n} as const;\n\n/**\n * Convert a snake_case wire key to camelCase.\n *\n * @param key - Wire key (e.g. `min_base_amount`).\n * @returns camelCase key (e.g. `minBaseAmount`).\n */\nfunction toCamelKey(key: string): string {\n return key.replace(/_([a-z0-9])/gu, (_match, char: string) =>\n char.toUpperCase(),\n );\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n * The zkLighter wire format is snake_case; parsed shapes in this package\n * follow camelCase conventions (see types/lighter-types.ts).\n *\n * @param value - Parsed JSON value.\n * @returns The value with camelCase keys.\n */\nexport function convertKeysToCamelCase(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(convertKeysToCamelCase);\n }\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, entry]) => [\n toCamelKey(key),\n convertKeysToCamelCase(entry),\n ]),\n );\n }\n return value;\n}\n\n/**\n * Error thrown for non-2xx HTTP responses or API-level error codes.\n */\nexport class LighterApiError extends Error {\n readonly code: number | undefined;\n\n constructor(message: string, code?: number) {\n super(message);\n this.name = 'LighterApiError';\n this.code = code;\n }\n}\n\n/**\n * REST client for the zkLighter API.\n */\nexport class LighterClientService {\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #isTestnet: boolean;\n\n #marketsCache: LighterOrderBookMeta[] | null = null;\n\n #marketsCacheTime = 0;\n\n constructor(deps: PerpsPlatformDependencies, config: { isTestnet: boolean }) {\n this.#deps = deps;\n this.#isTestnet = config.isTestnet;\n }\n\n get network(): LighterNetwork {\n return this.#isTestnet ? 'testnet' : 'mainnet';\n }\n\n get baseUrl(): string {\n return getLighterHttpEndpoint(this.network);\n }\n\n /**\n * Fetch market metadata, cached for 5 minutes.\n *\n * @param forceRefresh - Skip the cache and refetch.\n * @returns Market metadata entries.\n */\n async getOrderBooks(forceRefresh = false): Promise<LighterOrderBookMeta[]> {\n const now = Date.now();\n if (\n !forceRefresh &&\n this.#marketsCache &&\n now - this.#marketsCacheTime < MARKETS_CACHE_TTL_MS\n ) {\n return this.#marketsCache;\n }\n\n const response = await this.#get<LighterOrderBooksResponse>(\n '/api/v1/orderBooks',\n ResponseStructs.orderBooks,\n );\n this.#marketsCache = response.orderBooks;\n this.#marketsCacheTime = now;\n return response.orderBooks;\n }\n\n /**\n * Fetch market stats for all markets.\n *\n * @returns Order book details entries.\n */\n async getOrderBookDetails(): Promise<LighterOrderBookDetailsResponse> {\n return await this.#get<LighterOrderBookDetailsResponse>(\n '/api/v1/orderBookDetails',\n ResponseStructs.orderBookDetails,\n );\n }\n\n /**\n * Fetch an account (including positions) by its Lighter index.\n *\n * @param accountIndex - The Lighter account index.\n * @returns Account payload.\n */\n async getAccountByIndex(\n accountIndex: number,\n ): Promise<LighterAccountResponse> {\n return await this.#get<LighterAccountResponse>(\n `/api/v1/account?by=index&value=${accountIndex}`,\n ResponseStructs.account,\n );\n }\n\n /**\n * Discover Lighter accounts owned by an L1 address.\n *\n * @param l1Address - The owning EVM address.\n * @returns Accounts payload.\n */\n async getAccountsByL1Address(\n l1Address: string,\n ): Promise<LighterAccountsByL1AddressResponse> {\n return await this.#get<LighterAccountsByL1AddressResponse>(\n `/api/v1/accountsByL1Address?l1_address=${l1Address}`,\n ResponseStructs.accountsByAddress,\n );\n }\n\n /**\n * Fetch registered API keys for an account.\n *\n * @param accountIndex - The Lighter account index.\n * @param apiKeyIndex - Key slot, or 255 for all slots.\n * @returns API keys payload.\n */\n async getApiKeys(\n accountIndex: number,\n apiKeyIndex = 255,\n ): Promise<LighterApiKeysResponse> {\n return await this.#get<LighterApiKeysResponse>(\n `/api/v1/apikeys?account_index=${accountIndex}&api_key_index=${apiKeyIndex}`,\n ResponseStructs.apiKeys,\n );\n }\n\n /**\n * Fetch the next nonce for a key slot.\n *\n * @param accountIndex - The Lighter account index.\n * @param apiKeyIndex - Key slot.\n * @returns Next nonce payload.\n */\n async getNextNonce(\n accountIndex: number,\n apiKeyIndex: number,\n ): Promise<LighterNextNonceResponse> {\n return await this.#get<LighterNextNonceResponse>(\n `/api/v1/nextNonce?account_index=${accountIndex}&api_key_index=${apiKeyIndex}`,\n ResponseStructs.nextNonce,\n );\n }\n\n /**\n * Look up a transaction by its exact hash (`GET /api/v1/tx`). Used to\n * resolve submission-acceptance ambiguity authoritatively: an exact-hash\n * match proves the signed payload reached the sequencer.\n *\n * Contract: a venue-confirmed \"transaction not found\" (API error code\n * 21500) resolves to NULL; transport failures and every other API error\n * RETHROW — they are ambiguity, never evidence of non-acceptance.\n *\n * @param txHash - The signed transaction hash.\n * @returns The venue's transaction payload, or null when the venue\n * confirms the hash is unknown.\n */\n async getTx(txHash: string): Promise<LighterTxLookupResponse | null> {\n try {\n return await this.#get<LighterTxLookupResponse>(\n `/api/v1/tx?by=hash&value=${encodeURIComponent(txHash)}`,\n ResponseStructs.transaction,\n );\n } catch (error) {\n if (error instanceof LighterApiError && error.code === 21500) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch active (open) orders for an account.\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer (`_createAuthToken`).\n * @param marketId - Optional market filter (255 = all markets).\n * @returns Active orders payload.\n */\n async getActiveOrders(\n accountIndex: number,\n authToken: string,\n marketId = 255,\n ): Promise<LighterActiveOrdersResponse> {\n return await this.#get<LighterActiveOrdersResponse>(\n `/api/v1/accountActiveOrders?account_index=${accountIndex}&market_id=${marketId}`,\n ResponseStructs.activeOrders,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch historical (inactive) orders: filled and canceled lifecycle\n * states, newest first (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param limit - Maximum entries per page.\n * @param cursor - Pagination cursor from a previous page's `nextCursor`.\n * @param marketId - Optional market filter (official `market_id` query\n * param) — sharply bounds history scans to one symbol.\n * @returns Inactive orders payload.\n */\n async getInactiveOrders(\n accountIndex: number,\n authToken: string,\n limit = 50,\n cursor?: string,\n marketId?: number,\n ): Promise<LighterInactiveOrdersResponse> {\n return await this.#get<LighterInactiveOrdersResponse>(\n `/api/v1/accountInactiveOrders?account_index=${accountIndex}&limit=${limit}${\n cursor === undefined ? '' : `&cursor=${encodeURIComponent(cursor)}`\n }${marketId === undefined ? '' : `&market_id=${marketId}`}`,\n ResponseStructs.inactiveOrders,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L1→L2 deposit history (auth token required). The venue requires\n * both the account index and its L1 address on this endpoint.\n *\n * @param accountIndex - The Lighter account index.\n * @param l1Address - The account's L1 address.\n * @param authToken - Auth token minted by the signer.\n * @returns Deposit history payload (newest first, cursor-paged).\n */\n async getDepositHistory(\n accountIndex: number,\n l1Address: string,\n authToken: string,\n ): Promise<LighterDepositHistoryResponse> {\n return await this.#get<LighterDepositHistoryResponse>(\n `/api/v1/deposit/history?account_index=${accountIndex}&l1_address=${l1Address}`,\n ResponseStructs.deposits,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L2→L1 withdrawal history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @returns Withdrawal history payload (newest first, cursor-paged).\n */\n async getWithdrawHistory(\n accountIndex: number,\n authToken: string,\n ): Promise<LighterWithdrawHistoryResponse> {\n return await this.#get<LighterWithdrawHistoryResponse>(\n `/api/v1/withdraw/history?account_index=${accountIndex}`,\n ResponseStructs.withdrawals,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch L2 transfer history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @returns Transfer history payload (newest first, cursor-paged).\n */\n async getTransferHistory(\n accountIndex: number,\n authToken: string,\n ): Promise<LighterTransferHistoryResponse> {\n return await this.#get<LighterTransferHistoryResponse>(\n `/api/v1/transfer/history?account_index=${accountIndex}`,\n ResponseStructs.transfers,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch account trade history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param query - Pagination, range, and market filters.\n * @returns Trades payload (newest first).\n */\n async getTrades(\n accountIndex: number,\n authToken: string,\n query: LighterTradesQuery,\n ): Promise<LighterTradesResponse> {\n const { limit, cursor, from, marketId } = query;\n return await this.#get<LighterTradesResponse>(\n `/api/v1/trades?sort_by=timestamp&sort_dir=desc&limit=${limit}&account_index=${accountIndex}&market_type=perp${\n cursor === undefined ? '' : `&cursor=${encodeURIComponent(cursor)}`\n }${from === undefined ? '' : `&from=${from}`}${\n marketId === undefined ? '' : `&market_id=${marketId}`\n }`,\n ResponseStructs.trades,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch user funding payment history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param limit - Max entries.\n * @returns Position fundings payload.\n */\n async getPositionFundings(\n accountIndex: number,\n authToken: string,\n limit = 50,\n ): Promise<LighterPositionFundingsResponse> {\n return await this.#get<LighterPositionFundingsResponse>(\n `/api/v1/positionFunding?account_index=${accountIndex}&market_id=255&limit=${limit}&sort_by=timestamp&side=all`,\n ResponseStructs.fundings,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch account PnL history (auth token required).\n *\n * @param accountIndex - The Lighter account index.\n * @param authToken - Auth token minted by the signer.\n * @param startTimestamp - Range start (ms).\n * @param endTimestamp - Range end (ms).\n * @param countBack - Records counted back from range end.\n * @returns PnL payload.\n */\n async getPnl(\n accountIndex: number,\n authToken: string,\n startTimestamp: number,\n endTimestamp: number,\n countBack: number,\n ): Promise<LighterPnlResponse> {\n return await this.#get<LighterPnlResponse>(\n `/api/v1/pnl?by=index&value=${accountIndex}&resolution=1d&count_back=${countBack}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}`,\n ResponseStructs.pnl,\n { authorization: authToken },\n );\n }\n\n /**\n * Fetch an OHLCV candle series for a market.\n *\n * @param marketId - Numeric Lighter market id.\n * @param resolution - Candle resolution (e.g. `1m`, `15m`, `1h`, `1d`).\n * @param startTimestamp - Range start (ms).\n * @param endTimestamp - Range end (ms).\n * @param countBack - Number of candles counted back from the range end.\n * @returns Candle series payload.\n */\n async getCandles(\n marketId: number,\n resolution: string,\n startTimestamp: number,\n endTimestamp: number,\n countBack: number,\n ): Promise<LighterCandlesResponse> {\n return await this.#get<LighterCandlesResponse>(\n `/api/v1/candles?market_id=${marketId}&resolution=${resolution}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}&count_back=${countBack}`,\n ResponseStructs.candles,\n );\n }\n\n /**\n * Submit a signed L2 transaction.\n *\n * @param txType - L2 transaction type code (see lighterConfig).\n * @param txInfo - Serialized signed transaction JSON.\n * @returns Send result payload.\n */\n async sendTx(txType: number, txInfo: string): Promise<LighterSendTxResponse> {\n const body = new URLSearchParams({\n tx_type: String(txType),\n tx_info: txInfo,\n });\n\n const response = await this.#request<LighterSendTxResponse>(\n '/api/v1/sendTx',\n {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n },\n ResponseStructs.sendTransaction,\n );\n return response;\n }\n\n readonly #get = async <Result extends { code: number; message?: string }>(\n path: string,\n responseStruct: Struct<Result, unknown>,\n headers?: Record<string, string>,\n ): Promise<Result> => {\n return await this.#request<Result>(\n path,\n { method: 'GET', headers },\n responseStruct,\n );\n };\n\n readonly #request = async <Result extends { code: number; message?: string }>(\n path: string,\n init: { method: string; headers?: Record<string, string>; body?: string },\n responseStruct: Struct<Result, unknown>,\n ): Promise<Result> => {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n LIGHTER_HTTP_TIMEOUT_MS,\n );\n\n try {\n const response = await fetch(url, {\n method: init.method,\n headers: init.headers,\n body: init.body,\n signal: controller.signal,\n });\n\n const payload: unknown = convertKeysToCamelCase(await response.json());\n assert(payload, BaseResponseStruct);\n\n // Lighter returns HTTP 200 with an application-level error code, and\n // 4xx/5xx with `{code, message}` bodies — treat both uniformly.\n if (!response.ok || payload.code !== 200) {\n throw new LighterApiError(\n payload.message ?? `Lighter API error (HTTP ${response.status})`,\n payload.code ?? response.status,\n );\n }\n try {\n assert(payload, responseStruct);\n } catch (error) {\n throw new LighterApiError(\n `${LIGHTER_DATA_INTEGRITY_PREFIX} response for ${path}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n return payload;\n } catch (error) {\n if (error instanceof LighterApiError) {\n throw error;\n }\n this.#deps.debugLogger?.log?.('LighterClientService request failed', {\n url,\n error,\n });\n throw new LighterApiError(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n clearTimeout(timeout);\n }\n };\n}\n"]}
|
|
@@ -22,7 +22,7 @@ export declare class TerminalMarketService {
|
|
|
22
22
|
metadata: Map<string, TerminalAssetMetadata>;
|
|
23
23
|
}>;
|
|
24
24
|
/**
|
|
25
|
-
* Fetch, authenticate by exact identity, and map a schema-
|
|
25
|
+
* Fetch, authenticate by exact identity, and map a schema-v3 atomic market
|
|
26
26
|
* snapshot. Accepted entries remain inside the source freshness window;
|
|
27
27
|
* rejected responses are never cached.
|
|
28
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalMarketService.d.ts","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,UAAU,EACV,0BAA0B,EAC1B,yBAAyB,EAEzB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"TerminalMarketService.d.ts","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,UAAU,EACV,0BAA0B,EAC1B,yBAAyB,EAEzB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAoG3B;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;;IAchC,YAAY,IAAI,EAAE,yBAAyB,EAE1C;IAED;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC;QAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;KAC9C,CAAC,CAqDD;IAED;;;;;;;OAOG;IACG,mBAAmB,CACvB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CAiDpC;IAoZD;;OAEG;IACH,UAAU,IAAI,IAAI,CAKjB;IA+HD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgB7C;CACF"}
|
|
@@ -7,7 +7,7 @@ import { ensureError } from '../utils/errorUtils.js';
|
|
|
7
7
|
import { formatChange } from '../utils/marketDataTransform.js';
|
|
8
8
|
import { clonePerpsMarketData } from '../utils/marketUtils.js';
|
|
9
9
|
const VALID_MARKET_TYPES = new Set(Object.values(MarketCategory));
|
|
10
|
-
const GLOBAL_SNAPSHOT_SCHEMA_VERSION =
|
|
10
|
+
const GLOBAL_SNAPSHOT_SCHEMA_VERSION = 3;
|
|
11
11
|
const GLOBAL_SNAPSHOT_CONSUMER_MAX_AGE_MS = 30_000;
|
|
12
12
|
const GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES = 1_048_576;
|
|
13
13
|
const GLOBAL_SNAPSHOT_PERCENT_TOLERANCE = 0.01;
|
|
@@ -17,7 +17,9 @@ const DECIMAL_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/u;
|
|
|
17
17
|
const NON_NEGATIVE_DECIMAL_PATTERN = /^(?:0|[1-9]\d*)(?:\.\d+)?$/u;
|
|
18
18
|
const DEX_PATTERN = /^(?:main|[a-z0-9][a-z0-9-]*)$/u;
|
|
19
19
|
const GlobalSnapshotMarketStruct = object({
|
|
20
|
+
id: string(),
|
|
20
21
|
symbol: string(),
|
|
22
|
+
network: string(),
|
|
21
23
|
provider: string(),
|
|
22
24
|
dex: string(),
|
|
23
25
|
name: nullable(string()),
|
|
@@ -145,7 +147,7 @@ export class TerminalMarketService {
|
|
|
145
147
|
return { markets, metadata };
|
|
146
148
|
}
|
|
147
149
|
/**
|
|
148
|
-
* Fetch, authenticate by exact identity, and map a schema-
|
|
150
|
+
* Fetch, authenticate by exact identity, and map a schema-v3 atomic market
|
|
149
151
|
* snapshot. Accepted entries remain inside the source freshness window;
|
|
150
152
|
* rejected responses are never cached.
|
|
151
153
|
*
|
|
@@ -345,6 +347,12 @@ export class TerminalMarketService {
|
|
|
345
347
|
}
|
|
346
348
|
#validateSnapshotMarket(market, identity, index, generatedAt) {
|
|
347
349
|
const invalid = (field) => new Error(`Terminal global snapshot market ${String(index)} has invalid ${field}`);
|
|
350
|
+
if (market.id.length === 0) {
|
|
351
|
+
throw invalid('id');
|
|
352
|
+
}
|
|
353
|
+
if (market.network !== identity.network) {
|
|
354
|
+
throw invalid('network');
|
|
355
|
+
}
|
|
348
356
|
if (!identity.enabledDexes.includes(market.dex)) {
|
|
349
357
|
throw invalid('dex');
|
|
350
358
|
}
|
|
@@ -452,6 +460,7 @@ export class TerminalMarketService {
|
|
|
452
460
|
const isHip3 = market.dex !== 'main';
|
|
453
461
|
const marketType = this.#marketTypeFor(market.dex, market.category);
|
|
454
462
|
return {
|
|
463
|
+
id: market.id,
|
|
455
464
|
symbol: market.symbol,
|
|
456
465
|
name: market.name ?? market.symbol,
|
|
457
466
|
...(market.description !== null && {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalMarketService.js","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Infer } from '@metamask/superstruct';\nimport {\n array,\n boolean,\n is,\n nullable,\n number,\n object,\n optional,\n string,\n tuple,\n type,\n union,\n} from '@metamask/superstruct';\nimport { bytesToHex, sha256, stringToBytes } from '@metamask/utils';\n\nimport { canonicalizeHyperLiquidDexes } from '../constants/hyperLiquidConfig.js';\nimport {\n PERPS_CONSTANTS,\n TERMINAL_API_CONFIG,\n} from '../constants/perpsConfig.js';\nimport type {\n MarketInfo,\n PerpsGlobalSnapshotRequest,\n PerpsGlobalSnapshotResult,\n PerpsMarketData,\n PerpsPlatformDependencies,\n TerminalAssetMetadata,\n} from '../types/index.js';\nimport { MarketCategory } from '../types/index.js';\nimport { ensureError } from '../utils/errorUtils.js';\nimport { formatChange } from '../utils/marketDataTransform.js';\nimport { clonePerpsMarketData } from '../utils/marketUtils.js';\n\nconst VALID_MARKET_TYPES = new Set<string>(Object.values(MarketCategory));\nconst GLOBAL_SNAPSHOT_SCHEMA_VERSION = 2;\nconst GLOBAL_SNAPSHOT_CONSUMER_MAX_AGE_MS = 30_000;\nconst GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES = 1_048_576;\nconst GLOBAL_SNAPSHOT_PERCENT_TOLERANCE = 0.01;\nconst GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS = 5_000;\nconst MINIMUM_EPOCH_MILLISECONDS = Date.UTC(2000, 0, 1);\nconst DECIMAL_PATTERN = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/u;\nconst NON_NEGATIVE_DECIMAL_PATTERN = /^(?:0|[1-9]\\d*)(?:\\.\\d+)?$/u;\nconst DEX_PATTERN = /^(?:main|[a-z0-9][a-z0-9-]*)$/u;\n\nconst GlobalSnapshotMarketStruct = object({\n symbol: string(),\n provider: string(),\n dex: string(),\n name: nullable(string()),\n description: nullable(string()),\n iconUrl: nullable(string()),\n szDecimals: number(),\n maxLeverage: number(),\n markPrice: string(),\n price: string(),\n midPrice: nullable(string()),\n oraclePrice: string(),\n change24h: string(),\n changePercent24h: number(),\n funding: string(),\n volume24h: string(),\n openInterest: string(),\n category: nullable(string()),\n keywords: nullable(array(string())),\n tags: nullable(array(string())),\n listedAt: nullable(number()),\n trend: array(tuple([number(), string()])),\n});\n\nconst GlobalSnapshotStruct = object({\n schemaVersion: number(),\n provider: string(),\n network: string(),\n enabledDexes: array(string()),\n fingerprint: string(),\n generatedAt: number(),\n receivedAt: number(),\n maxAgeMs: number(),\n complete: boolean(),\n perDexErrors: array(\n object({\n dex: string(),\n error: string(),\n }),\n ),\n markets: array(GlobalSnapshotMarketStruct),\n});\n\ntype GlobalSnapshotMarket = Infer<typeof GlobalSnapshotMarketStruct>;\ntype GlobalSnapshot = Infer<typeof GlobalSnapshotStruct>;\n\n/**\n * Runtime validation schema for a single market item returned by\n * `GET {terminalApi.marketDataUrl}`.\n *\n * Uses `type()` (loose object matching) so that extra fields the API sends\n * (e.g. `price`, `iconUrl`, `trend`) are silently accepted.\n * Each item is individually validated; items that fail validation are\n * filtered out and logged rather than rejecting the entire response.\n */\nconst TerminalPerpetualItemStruct = type({\n symbol: string(),\n name: optional(nullable(string())),\n description: optional(nullable(string())),\n szDecimals: optional(number()),\n maxLeverage: optional(number()),\n marginTableId: optional(number()),\n onlyIsolated: optional(boolean()),\n isDelisted: optional(boolean()),\n minimumOrderSize: optional(number()),\n keywords: optional(nullable(array(string()))),\n tags: optional(nullable(array(string()))),\n categories: optional(nullable(array(string()))),\n marketType: optional(nullable(string())),\n listedAt: optional(nullable(union([number(), string()]))),\n});\n\ntype TerminalPerpetualItem = Infer<typeof TerminalPerpetualItemStruct>;\n\ntype CacheEntry = {\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n timestamp: number;\n};\n\n/**\n * TerminalMarketService\n *\n * Fetches structured market metadata from the MetaMask Terminal API.\n * Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid\n * redundant network calls across polling cycles.\n *\n * Instance-based service with constructor injection of platform dependencies.\n */\nexport class TerminalMarketService {\n readonly #deps: PerpsPlatformDependencies;\n\n #cache: CacheEntry | null = null;\n\n readonly #globalSnapshotCache = new Map<string, PerpsGlobalSnapshotResult>();\n\n readonly #globalSnapshotInFlight = new Map<\n string,\n Promise<PerpsGlobalSnapshotResult>\n >();\n\n #globalSnapshotGeneration = 0;\n\n constructor(deps: PerpsPlatformDependencies) {\n this.#deps = deps;\n }\n\n /**\n * Fetch markets from the Terminal API.\n * Returns cached data when available and within TTL.\n *\n * @returns Object with mapped MarketInfo array and per-symbol metadata.\n */\n async fetchMarkets(): Promise<{\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n }> {\n if (\n this.#cache &&\n Date.now() - this.#cache.timestamp < TERMINAL_API_CONFIG.CacheTtlMs\n ) {\n return {\n markets: this.#cache.markets,\n metadata: this.#cache.metadata,\n };\n }\n\n const marketDataUrl =\n this.#deps.terminalApi?.marketDataUrl ?? this.#deps.terminalApiUrl;\n if (!marketDataUrl) {\n throw new Error('Terminal API market-data URL not configured');\n }\n\n const url = marketDataUrl;\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new Error('Terminal API fetch timed out')),\n TERMINAL_API_CONFIG.FetchTimeoutMs,\n );\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (!response.ok) {\n throw new Error(\n `Terminal API returned ${String(response.status)}: ${response.statusText}`,\n );\n }\n\n const body: unknown = await response.json();\n\n if (!Array.isArray(body)) {\n throw new Error(`Terminal API returned non-array body: ${typeof body}`);\n }\n\n const items = this.#validateItems(body);\n const markets = this.#mapToMarketInfo(items);\n const metadata = this.#extractMetadata(items);\n\n this.#cache = { markets, metadata, timestamp: Date.now() };\n return { markets, metadata };\n }\n\n /**\n * Fetch, authenticate by exact identity, and map a schema-v2 atomic market\n * snapshot. Accepted entries remain inside the source freshness window;\n * rejected responses are never cached.\n *\n * @param request - Exact provider/network/DEX identity expected by the client.\n * @returns UI-ready market data and its source-bounded expiry.\n */\n async fetchGlobalSnapshot(\n request: PerpsGlobalSnapshotRequest,\n ): Promise<PerpsGlobalSnapshotResult> {\n const identity = this.#validateRequestedIdentity(request);\n if (!this.#deps.terminalApi?.globalSnapshotUrl) {\n throw new Error('Terminal global snapshot URL not configured');\n }\n\n const url = this.#buildGlobalSnapshotUrl(\n this.#deps.terminalApi.globalSnapshotUrl,\n identity,\n );\n const cacheKey = [\n url,\n String(GLOBAL_SNAPSHOT_SCHEMA_VERSION),\n identity.provider,\n identity.network,\n identity.enabledDexes.join(','),\n ].join('|');\n const now = Date.now();\n const cached = this.#globalSnapshotCache.get(cacheKey);\n if (cached && now < cached.expiresAt) {\n return this.#cloneGlobalSnapshotResult(cached);\n }\n if (cached) {\n this.#globalSnapshotCache.delete(cacheKey);\n }\n\n const existing = this.#globalSnapshotInFlight.get(cacheKey);\n if (existing) {\n return this.#cloneGlobalSnapshotResult(await existing);\n }\n\n const generation = this.#globalSnapshotGeneration;\n const pending = this.#fetchAndValidateGlobalSnapshot(identity, url).then(\n (result) => {\n if (this.#globalSnapshotGeneration !== generation) {\n return result;\n }\n this.#globalSnapshotCache.set(cacheKey, result);\n return result;\n },\n );\n this.#globalSnapshotInFlight.set(cacheKey, pending);\n try {\n return this.#cloneGlobalSnapshotResult(await pending);\n } finally {\n if (this.#globalSnapshotInFlight.get(cacheKey) === pending) {\n this.#globalSnapshotInFlight.delete(cacheKey);\n }\n }\n }\n\n async #fetchAndValidateGlobalSnapshot(\n identity: PerpsGlobalSnapshotRequest,\n url: string,\n ): Promise<PerpsGlobalSnapshotResult> {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new Error('Terminal global snapshot timed out')),\n TERMINAL_API_CONFIG.FetchTimeoutMs,\n );\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(\n `Terminal global snapshot returned ${String(response.status)}: ${response.statusText}`,\n );\n }\n\n const declaredLength = response.headers?.get('content-length');\n if (\n declaredLength !== null &&\n declaredLength !== undefined &&\n /^\\d+$/u.test(declaredLength) &&\n Number(declaredLength) > GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES\n ) {\n throw new Error('Terminal global snapshot payload exceeds 1 MiB');\n }\n // React Native fetch does not consistently expose a streaming reader.\n // Reject declared oversize bodies before allocation, then enforce the same\n // byte cap after text() for servers that omit Content-Length.\n const text = await response.text();\n if (stringToBytes(text).byteLength > GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES) {\n throw new Error('Terminal global snapshot payload exceeds 1 MiB');\n }\n let body: unknown;\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n throw new Error('Terminal global snapshot returned invalid JSON');\n }\n if (!is(body, GlobalSnapshotStruct)) {\n throw new Error('Terminal global snapshot failed schema validation');\n }\n return this.#validateAndMapGlobalSnapshot(body, identity, Date.now());\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async #validateAndMapGlobalSnapshot(\n snapshot: GlobalSnapshot,\n identity: PerpsGlobalSnapshotRequest,\n now: number,\n ): Promise<PerpsGlobalSnapshotResult> {\n if (snapshot.schemaVersion !== GLOBAL_SNAPSHOT_SCHEMA_VERSION) {\n throw new Error('Terminal global snapshot schema version mismatch');\n }\n if (\n snapshot.provider !== identity.provider ||\n snapshot.network !== identity.network\n ) {\n throw new Error('Terminal global snapshot identity mismatch');\n }\n\n const responseDexes = this.#normalizeDexes(snapshot.enabledDexes);\n if (\n responseDexes.length !== identity.enabledDexes.length ||\n responseDexes.some((dex, index) => dex !== identity.enabledDexes[index])\n ) {\n throw new Error('Terminal global snapshot DEX mismatch');\n }\n const expectedFingerprint = await this.#createFingerprint(identity);\n if (snapshot.fingerprint !== expectedFingerprint) {\n throw new Error('Terminal global snapshot fingerprint mismatch');\n }\n if (!snapshot.complete || snapshot.perDexErrors.length > 0) {\n throw new Error('Terminal global snapshot is incomplete');\n }\n if (\n !this.#isNonNegativeSafeInteger(snapshot.generatedAt) ||\n !this.#isNonNegativeSafeInteger(snapshot.receivedAt) ||\n !this.#isPositiveSafeInteger(snapshot.maxAgeMs) ||\n snapshot.receivedAt > snapshot.generatedAt ||\n snapshot.generatedAt > now + GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS ||\n snapshot.receivedAt > now + GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS\n ) {\n throw new Error('Terminal global snapshot has invalid timestamps');\n }\n\n const trustedMaxAgeMs = Math.min(\n snapshot.maxAgeMs,\n GLOBAL_SNAPSHOT_CONSUMER_MAX_AGE_MS,\n );\n const expiresAt = snapshot.receivedAt + trustedMaxAgeMs;\n if (now >= expiresAt) {\n throw new Error('Terminal global snapshot is stale');\n }\n if (snapshot.markets.length === 0) {\n throw new Error('Terminal global snapshot has no markets');\n }\n\n const marketKeys = new Set<string>();\n const representedDexes = new Set<string>();\n const markets = snapshot.markets\n .map((market, index) => {\n this.#validateSnapshotMarket(\n market,\n identity,\n index,\n snapshot.generatedAt,\n );\n const key = `${market.dex}:${market.symbol}`;\n if (marketKeys.has(key)) {\n throw new Error(`Terminal global snapshot duplicates market ${key}`);\n }\n marketKeys.add(key);\n representedDexes.add(market.dex);\n return market;\n })\n .map((market) => this.#mapSnapshotMarket(market, expiresAt));\n if (identity.enabledDexes.some((dex) => !representedDexes.has(dex))) {\n throw new Error('Terminal global snapshot is missing a requested DEX');\n }\n if (markets.length === 0) {\n throw new Error('Terminal global snapshot has no tradable markets');\n }\n\n return { markets, expiresAt };\n }\n\n #validateRequestedIdentity(\n request: PerpsGlobalSnapshotRequest,\n ): PerpsGlobalSnapshotRequest {\n if (request.provider !== 'hyperliquid') {\n throw new Error('Terminal global snapshot provider is unsupported');\n }\n if (request.network !== 'mainnet' && request.network !== 'testnet') {\n throw new Error('Terminal global snapshot network is unsupported');\n }\n return {\n provider: request.provider,\n network: request.network,\n enabledDexes: this.#normalizeDexes(request.enabledDexes),\n };\n }\n\n #buildGlobalSnapshotUrl(\n baseUrl: string,\n identity: PerpsGlobalSnapshotRequest,\n ): string {\n const query = new URLSearchParams({\n provider: identity.provider,\n network: identity.network,\n dexes: identity.enabledDexes.join(','),\n });\n return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${query.toString()}`;\n }\n\n #normalizeDexes(dexes: string[]): string[] {\n if (!Array.isArray(dexes) || dexes.length === 0) {\n throw new Error('Terminal global snapshot requires at least one DEX');\n }\n const normalized = dexes.map((dex) => {\n if (typeof dex !== 'string' || !DEX_PATTERN.test(dex)) {\n throw new Error('Terminal global snapshot contains an invalid DEX');\n }\n return dex;\n });\n if (new Set(normalized).size !== normalized.length) {\n throw new Error('Terminal global snapshot contains duplicate DEXes');\n }\n if (!normalized.includes('main')) {\n throw new Error('Terminal global snapshot requires the main DEX');\n }\n return canonicalizeHyperLiquidDexes(normalized);\n }\n\n async #createFingerprint(\n identity: PerpsGlobalSnapshotRequest,\n ): Promise<string> {\n const canonicalIdentity = JSON.stringify({\n provider: identity.provider,\n network: identity.network,\n enabledDexes: identity.enabledDexes,\n });\n const digest = await sha256(stringToBytes(canonicalIdentity));\n return `sha256:${bytesToHex(digest).slice(2)}`;\n }\n\n #validateSnapshotMarket(\n market: GlobalSnapshotMarket,\n identity: PerpsGlobalSnapshotRequest,\n index: number,\n generatedAt: number,\n ): void {\n const invalid = (field: string): Error =>\n new Error(\n `Terminal global snapshot market ${String(index)} has invalid ${field}`,\n );\n if (!identity.enabledDexes.includes(market.dex)) {\n throw invalid('dex');\n }\n const expectedProvider = market.dex === 'main' ? 'hyperliquid' : market.dex;\n if (market.provider !== expectedProvider) {\n throw invalid('provider');\n }\n const expectedPrefix = market.dex === 'main' ? '' : `${market.dex}:`;\n if (\n market.symbol.length === 0 ||\n (expectedPrefix\n ? !market.symbol.startsWith(expectedPrefix)\n : market.symbol.includes(':'))\n ) {\n throw invalid('symbol');\n }\n if (\n !this.#isNonNegativeSafeInteger(market.szDecimals) ||\n !this.#isPositiveSafeInteger(market.maxLeverage) ||\n (market.listedAt !== null &&\n (!this.#isNonNegativeSafeInteger(market.listedAt) ||\n market.listedAt < MINIMUM_EPOCH_MILLISECONDS ||\n market.listedAt > generatedAt))\n ) {\n throw invalid('integer field');\n }\n\n const decimalFields: [string, string, boolean][] = [\n ['markPrice', market.markPrice, true],\n ['price', market.price, true],\n ['oraclePrice', market.oraclePrice, true],\n ['change24h', market.change24h, false],\n ['volume24h', market.volume24h, true],\n ['openInterest', market.openInterest, true],\n ['funding', market.funding, false],\n ];\n if (market.midPrice !== null) {\n decimalFields.push(['midPrice', market.midPrice, true]);\n }\n for (const [field, value, nonNegative] of decimalFields) {\n const pattern = nonNegative\n ? NON_NEGATIVE_DECIMAL_PATTERN\n : DECIMAL_PATTERN;\n if (!pattern.test(value) || !Number.isFinite(Number(value))) {\n throw invalid(field);\n }\n }\n if (market.price !== market.markPrice) {\n throw invalid('deprecated price alias');\n }\n if (\n Number(market.oraclePrice) <= 0 ||\n (market.midPrice !== null && Number(market.midPrice) <= 0)\n ) {\n throw invalid('reference price');\n }\n const price = Number(market.markPrice);\n const change24h = Number(market.change24h);\n const previousPrice = price - change24h;\n if (price <= 0 || previousPrice <= 0 || !Number.isFinite(previousPrice)) {\n throw invalid('mark/change coherence');\n }\n const derivedPercent = (change24h / previousPrice) * 100;\n if (\n !Number.isFinite(derivedPercent) ||\n !Number.isFinite(market.changePercent24h) ||\n Math.abs(market.changePercent24h - derivedPercent) >\n GLOBAL_SNAPSHOT_PERCENT_TOLERANCE\n ) {\n throw invalid('changePercent24h coherence');\n }\n for (const [field, values] of [\n ['keywords', market.keywords],\n ['tags', market.tags],\n ] as const) {\n if (\n values !== null &&\n (values.some((value) => value.length === 0) ||\n new Set(values).size !== values.length)\n ) {\n throw invalid(field);\n }\n }\n for (const [field, value] of [\n ['name', market.name],\n ['description', market.description],\n ['iconUrl', market.iconUrl],\n ['category', market.category],\n ] as const) {\n if (value !== null && value.length === 0) {\n throw invalid(field);\n }\n }\n let previousTrendTimestamp = -1;\n for (const [timestamp, trendPrice] of market.trend) {\n if (\n !this.#isNonNegativeSafeInteger(timestamp) ||\n timestamp < MINIMUM_EPOCH_MILLISECONDS ||\n timestamp > generatedAt ||\n timestamp <= previousTrendTimestamp ||\n !NON_NEGATIVE_DECIMAL_PATTERN.test(trendPrice) ||\n !Number.isFinite(Number(trendPrice)) ||\n Number(trendPrice) <= 0\n ) {\n throw invalid('trend');\n }\n previousTrendTimestamp = timestamp;\n }\n }\n\n #mapSnapshotMarket(\n market: GlobalSnapshotMarket,\n sourceExpiresAt: number,\n ): PerpsMarketData {\n const formatters = this.#deps.marketDataFormatters;\n // Keep both provider price semantics explicit in the wire contract. Core\n // maps markPrice to its UI price while retaining validation of midPrice.\n const price = Number(market.markPrice);\n const change24h = Number(market.change24h);\n const volume = Number(market.volume24h);\n const openInterest = Number(market.openInterest);\n const isHip3 = market.dex !== 'main';\n const marketType = this.#marketTypeFor(market.dex, market.category);\n\n return {\n symbol: market.symbol,\n name: market.name ?? market.symbol,\n ...(market.description !== null && {\n description: market.description,\n }),\n maxLeverage: `${String(market.maxLeverage)}x`,\n price: formatters.formatPerpsFiat(price, {\n ranges: formatters.priceRangesUniversal,\n }),\n change24h: formatChange(change24h, formatters),\n change24hPercent: formatters.formatPercentage(market.changePercent24h),\n volume: formatters.formatVolume(volume),\n openInterest: formatters.formatVolume(openInterest),\n fundingRate: Number(market.funding),\n marketSource: isHip3 ? market.dex : undefined,\n marketType,\n isHip3,\n isNewMarket: isHip3 && marketType === undefined,\n ...(market.keywords && { keywords: market.keywords }),\n ...(market.tags && { tags: market.tags }),\n ...(market.category && { categories: [market.category] }),\n ...(market.listedAt !== null && { listedAt: market.listedAt }),\n trend: market.trend,\n dataSource: 'terminal-global-snapshot-mark',\n sourceExpiresAt,\n };\n }\n\n #marketTypeFor(\n dex: string,\n category: string | null,\n ): TerminalAssetMetadata['marketType'] | undefined {\n if (dex === 'main') {\n return MarketCategory.CryptoCurrency;\n }\n if (category === 'stocks') {\n return MarketCategory.Stock;\n }\n if (category === 'pre_ipo') {\n return MarketCategory.PreIpo;\n }\n if (category && VALID_MARKET_TYPES.has(category)) {\n return category as TerminalAssetMetadata['marketType'];\n }\n return undefined;\n }\n\n #cloneGlobalSnapshotResult(\n result: PerpsGlobalSnapshotResult,\n ): PerpsGlobalSnapshotResult {\n return {\n expiresAt: result.expiresAt,\n markets: clonePerpsMarketData(result.markets),\n };\n }\n\n #isNonNegativeSafeInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isSafeInteger(value) && value >= 0\n );\n }\n\n #isPositiveSafeInteger(value: unknown): value is number {\n return this.#isNonNegativeSafeInteger(value) && value > 0;\n }\n\n /**\n * Invalidate the internal cache so the next fetch hits the network.\n */\n clearCache(): void {\n this.#cache = null;\n this.#globalSnapshotGeneration += 1;\n this.#globalSnapshotCache.clear();\n this.#globalSnapshotInFlight.clear();\n }\n\n /**\n * Validate raw API response items against the expected schema.\n * Items that fail validation are filtered out and logged rather than\n * rejecting the entire response.\n *\n * @param raw - The raw array from the API response body.\n * @returns Array of validated items.\n */\n #validateItems(raw: unknown[]): TerminalPerpetualItem[] {\n const valid: TerminalPerpetualItem[] = [];\n for (const item of raw) {\n if (is(item, TerminalPerpetualItemStruct)) {\n valid.push(item);\n } else {\n this.#deps.logger.error(\n ensureError(\n new Error('Terminal API item failed schema validation'),\n 'TerminalMarketService.validateItems',\n ),\n {\n tags: {\n feature: PERPS_CONSTANTS.FeatureName,\n source: 'terminal-api',\n },\n context: {\n name: 'TerminalMarketService.validateItems',\n data: {\n symbol:\n typeof item === 'object' &&\n item !== null &&\n Object.prototype.hasOwnProperty.call(item, 'symbol')\n ? (item as Record<string, unknown>).symbol\n : undefined,\n },\n },\n },\n );\n }\n }\n return valid;\n }\n\n /**\n * Map Terminal API items to the protocol-agnostic MarketInfo shape.\n *\n * @param items - Raw items from the API response.\n * @returns Array of MarketInfo objects.\n */\n #mapToMarketInfo(items: TerminalPerpetualItem[]): MarketInfo[] {\n return items\n .filter(\n (item) => typeof item.symbol === 'string' && item.symbol.length > 0,\n )\n .map((item) => ({\n name: item.symbol,\n szDecimals: item.szDecimals ?? 0,\n maxLeverage: item.maxLeverage ?? 1,\n marginTableId: item.marginTableId ?? 0,\n ...(item.onlyIsolated === true && { onlyIsolated: true as const }),\n ...(item.isDelisted === true && { isDelisted: true as const }),\n ...(item.minimumOrderSize !== undefined && {\n minimumOrderSize: item.minimumOrderSize,\n }),\n }));\n }\n\n /**\n * Extract per-symbol metadata for downstream merge into PerpsMarketData.\n *\n * @param items - Raw items from the API response.\n * @returns Map keyed by symbol with enrichment metadata.\n */\n #extractMetadata(\n items: TerminalPerpetualItem[],\n ): Map<string, TerminalAssetMetadata> {\n const map = new Map<string, TerminalAssetMetadata>();\n\n for (const item of items) {\n if (typeof item.symbol !== 'string' || item.symbol.length === 0) {\n continue;\n }\n\n const entry: TerminalAssetMetadata = {};\n\n if (typeof item.name === 'string' && item.name.length > 0) {\n entry.name = item.name;\n }\n\n if (typeof item.description === 'string' && item.description.length > 0) {\n entry.description = item.description;\n }\n\n if (Array.isArray(item.keywords) && item.keywords.length > 0) {\n entry.keywords = item.keywords;\n }\n if (Array.isArray(item.tags) && item.tags.length > 0) {\n entry.tags = item.tags;\n }\n if (Array.isArray(item.categories) && item.categories.length > 0) {\n entry.categories = item.categories;\n }\n if (\n typeof item.marketType === 'string' &&\n VALID_MARKET_TYPES.has(item.marketType)\n ) {\n entry.marketType =\n item.marketType as TerminalAssetMetadata['marketType'];\n }\n\n if (item.listedAt !== null && item.listedAt !== undefined) {\n const listedAtMs =\n typeof item.listedAt === 'number'\n ? item.listedAt\n : Date.parse(item.listedAt);\n if (isFinite(listedAtMs)) {\n entry.listedAt = listedAtMs;\n }\n }\n\n map.set(item.symbol, entry);\n }\n\n return map;\n }\n\n /**\n * Log a Terminal API error to Sentry without surfacing it to the user.\n *\n * @param error - The caught error.\n * @param method - The calling method name for context.\n */\n logError(error: unknown, method: string): void {\n this.#deps.logger.error(\n ensureError(error, `TerminalMarketService.${method}`),\n {\n tags: { feature: PERPS_CONSTANTS.FeatureName, source: 'terminal-api' },\n context: {\n name: `TerminalMarketService.${method}`,\n data: {\n url: method.includes('globalSnapshot')\n ? this.#deps.terminalApi?.globalSnapshotUrl\n : (this.#deps.terminalApi?.marketDataUrl ??\n this.#deps.terminalApiUrl),\n },\n },\n },\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TerminalMarketService.js","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Infer } from '@metamask/superstruct';\nimport {\n array,\n boolean,\n is,\n nullable,\n number,\n object,\n optional,\n string,\n tuple,\n type,\n union,\n} from '@metamask/superstruct';\nimport { bytesToHex, sha256, stringToBytes } from '@metamask/utils';\n\nimport { canonicalizeHyperLiquidDexes } from '../constants/hyperLiquidConfig.js';\nimport {\n PERPS_CONSTANTS,\n TERMINAL_API_CONFIG,\n} from '../constants/perpsConfig.js';\nimport type {\n MarketInfo,\n PerpsGlobalSnapshotRequest,\n PerpsGlobalSnapshotResult,\n PerpsMarketData,\n PerpsPlatformDependencies,\n TerminalAssetMetadata,\n} from '../types/index.js';\nimport { MarketCategory } from '../types/index.js';\nimport { ensureError } from '../utils/errorUtils.js';\nimport { formatChange } from '../utils/marketDataTransform.js';\nimport { clonePerpsMarketData } from '../utils/marketUtils.js';\n\nconst VALID_MARKET_TYPES = new Set<string>(Object.values(MarketCategory));\nconst GLOBAL_SNAPSHOT_SCHEMA_VERSION = 3;\nconst GLOBAL_SNAPSHOT_CONSUMER_MAX_AGE_MS = 30_000;\nconst GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES = 1_048_576;\nconst GLOBAL_SNAPSHOT_PERCENT_TOLERANCE = 0.01;\nconst GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS = 5_000;\nconst MINIMUM_EPOCH_MILLISECONDS = Date.UTC(2000, 0, 1);\nconst DECIMAL_PATTERN = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/u;\nconst NON_NEGATIVE_DECIMAL_PATTERN = /^(?:0|[1-9]\\d*)(?:\\.\\d+)?$/u;\nconst DEX_PATTERN = /^(?:main|[a-z0-9][a-z0-9-]*)$/u;\n\nconst GlobalSnapshotMarketStruct = object({\n id: string(),\n symbol: string(),\n network: string(),\n provider: string(),\n dex: string(),\n name: nullable(string()),\n description: nullable(string()),\n iconUrl: nullable(string()),\n szDecimals: number(),\n maxLeverage: number(),\n markPrice: string(),\n price: string(),\n midPrice: nullable(string()),\n oraclePrice: string(),\n change24h: string(),\n changePercent24h: number(),\n funding: string(),\n volume24h: string(),\n openInterest: string(),\n category: nullable(string()),\n keywords: nullable(array(string())),\n tags: nullable(array(string())),\n listedAt: nullable(number()),\n trend: array(tuple([number(), string()])),\n});\n\nconst GlobalSnapshotStruct = object({\n schemaVersion: number(),\n provider: string(),\n network: string(),\n enabledDexes: array(string()),\n fingerprint: string(),\n generatedAt: number(),\n receivedAt: number(),\n maxAgeMs: number(),\n complete: boolean(),\n perDexErrors: array(\n object({\n dex: string(),\n error: string(),\n }),\n ),\n markets: array(GlobalSnapshotMarketStruct),\n});\n\ntype GlobalSnapshotMarket = Infer<typeof GlobalSnapshotMarketStruct>;\ntype GlobalSnapshot = Infer<typeof GlobalSnapshotStruct>;\n\n/**\n * Runtime validation schema for a single market item returned by\n * `GET {terminalApi.marketDataUrl}`.\n *\n * Uses `type()` (loose object matching) so that extra fields the API sends\n * (e.g. `price`, `iconUrl`, `trend`) are silently accepted.\n * Each item is individually validated; items that fail validation are\n * filtered out and logged rather than rejecting the entire response.\n */\nconst TerminalPerpetualItemStruct = type({\n symbol: string(),\n name: optional(nullable(string())),\n description: optional(nullable(string())),\n szDecimals: optional(number()),\n maxLeverage: optional(number()),\n marginTableId: optional(number()),\n onlyIsolated: optional(boolean()),\n isDelisted: optional(boolean()),\n minimumOrderSize: optional(number()),\n keywords: optional(nullable(array(string()))),\n tags: optional(nullable(array(string()))),\n categories: optional(nullable(array(string()))),\n marketType: optional(nullable(string())),\n listedAt: optional(nullable(union([number(), string()]))),\n});\n\ntype TerminalPerpetualItem = Infer<typeof TerminalPerpetualItemStruct>;\n\ntype CacheEntry = {\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n timestamp: number;\n};\n\n/**\n * TerminalMarketService\n *\n * Fetches structured market metadata from the MetaMask Terminal API.\n * Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid\n * redundant network calls across polling cycles.\n *\n * Instance-based service with constructor injection of platform dependencies.\n */\nexport class TerminalMarketService {\n readonly #deps: PerpsPlatformDependencies;\n\n #cache: CacheEntry | null = null;\n\n readonly #globalSnapshotCache = new Map<string, PerpsGlobalSnapshotResult>();\n\n readonly #globalSnapshotInFlight = new Map<\n string,\n Promise<PerpsGlobalSnapshotResult>\n >();\n\n #globalSnapshotGeneration = 0;\n\n constructor(deps: PerpsPlatformDependencies) {\n this.#deps = deps;\n }\n\n /**\n * Fetch markets from the Terminal API.\n * Returns cached data when available and within TTL.\n *\n * @returns Object with mapped MarketInfo array and per-symbol metadata.\n */\n async fetchMarkets(): Promise<{\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n }> {\n if (\n this.#cache &&\n Date.now() - this.#cache.timestamp < TERMINAL_API_CONFIG.CacheTtlMs\n ) {\n return {\n markets: this.#cache.markets,\n metadata: this.#cache.metadata,\n };\n }\n\n const marketDataUrl =\n this.#deps.terminalApi?.marketDataUrl ?? this.#deps.terminalApiUrl;\n if (!marketDataUrl) {\n throw new Error('Terminal API market-data URL not configured');\n }\n\n const url = marketDataUrl;\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new Error('Terminal API fetch timed out')),\n TERMINAL_API_CONFIG.FetchTimeoutMs,\n );\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (!response.ok) {\n throw new Error(\n `Terminal API returned ${String(response.status)}: ${response.statusText}`,\n );\n }\n\n const body: unknown = await response.json();\n\n if (!Array.isArray(body)) {\n throw new Error(`Terminal API returned non-array body: ${typeof body}`);\n }\n\n const items = this.#validateItems(body);\n const markets = this.#mapToMarketInfo(items);\n const metadata = this.#extractMetadata(items);\n\n this.#cache = { markets, metadata, timestamp: Date.now() };\n return { markets, metadata };\n }\n\n /**\n * Fetch, authenticate by exact identity, and map a schema-v3 atomic market\n * snapshot. Accepted entries remain inside the source freshness window;\n * rejected responses are never cached.\n *\n * @param request - Exact provider/network/DEX identity expected by the client.\n * @returns UI-ready market data and its source-bounded expiry.\n */\n async fetchGlobalSnapshot(\n request: PerpsGlobalSnapshotRequest,\n ): Promise<PerpsGlobalSnapshotResult> {\n const identity = this.#validateRequestedIdentity(request);\n if (!this.#deps.terminalApi?.globalSnapshotUrl) {\n throw new Error('Terminal global snapshot URL not configured');\n }\n\n const url = this.#buildGlobalSnapshotUrl(\n this.#deps.terminalApi.globalSnapshotUrl,\n identity,\n );\n const cacheKey = [\n url,\n String(GLOBAL_SNAPSHOT_SCHEMA_VERSION),\n identity.provider,\n identity.network,\n identity.enabledDexes.join(','),\n ].join('|');\n const now = Date.now();\n const cached = this.#globalSnapshotCache.get(cacheKey);\n if (cached && now < cached.expiresAt) {\n return this.#cloneGlobalSnapshotResult(cached);\n }\n if (cached) {\n this.#globalSnapshotCache.delete(cacheKey);\n }\n\n const existing = this.#globalSnapshotInFlight.get(cacheKey);\n if (existing) {\n return this.#cloneGlobalSnapshotResult(await existing);\n }\n\n const generation = this.#globalSnapshotGeneration;\n const pending = this.#fetchAndValidateGlobalSnapshot(identity, url).then(\n (result) => {\n if (this.#globalSnapshotGeneration !== generation) {\n return result;\n }\n this.#globalSnapshotCache.set(cacheKey, result);\n return result;\n },\n );\n this.#globalSnapshotInFlight.set(cacheKey, pending);\n try {\n return this.#cloneGlobalSnapshotResult(await pending);\n } finally {\n if (this.#globalSnapshotInFlight.get(cacheKey) === pending) {\n this.#globalSnapshotInFlight.delete(cacheKey);\n }\n }\n }\n\n async #fetchAndValidateGlobalSnapshot(\n identity: PerpsGlobalSnapshotRequest,\n url: string,\n ): Promise<PerpsGlobalSnapshotResult> {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new Error('Terminal global snapshot timed out')),\n TERMINAL_API_CONFIG.FetchTimeoutMs,\n );\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(\n `Terminal global snapshot returned ${String(response.status)}: ${response.statusText}`,\n );\n }\n\n const declaredLength = response.headers?.get('content-length');\n if (\n declaredLength !== null &&\n declaredLength !== undefined &&\n /^\\d+$/u.test(declaredLength) &&\n Number(declaredLength) > GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES\n ) {\n throw new Error('Terminal global snapshot payload exceeds 1 MiB');\n }\n // React Native fetch does not consistently expose a streaming reader.\n // Reject declared oversize bodies before allocation, then enforce the same\n // byte cap after text() for servers that omit Content-Length.\n const text = await response.text();\n if (stringToBytes(text).byteLength > GLOBAL_SNAPSHOT_MAX_PAYLOAD_BYTES) {\n throw new Error('Terminal global snapshot payload exceeds 1 MiB');\n }\n let body: unknown;\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n throw new Error('Terminal global snapshot returned invalid JSON');\n }\n if (!is(body, GlobalSnapshotStruct)) {\n throw new Error('Terminal global snapshot failed schema validation');\n }\n return this.#validateAndMapGlobalSnapshot(body, identity, Date.now());\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async #validateAndMapGlobalSnapshot(\n snapshot: GlobalSnapshot,\n identity: PerpsGlobalSnapshotRequest,\n now: number,\n ): Promise<PerpsGlobalSnapshotResult> {\n if (snapshot.schemaVersion !== GLOBAL_SNAPSHOT_SCHEMA_VERSION) {\n throw new Error('Terminal global snapshot schema version mismatch');\n }\n if (\n snapshot.provider !== identity.provider ||\n snapshot.network !== identity.network\n ) {\n throw new Error('Terminal global snapshot identity mismatch');\n }\n\n const responseDexes = this.#normalizeDexes(snapshot.enabledDexes);\n if (\n responseDexes.length !== identity.enabledDexes.length ||\n responseDexes.some((dex, index) => dex !== identity.enabledDexes[index])\n ) {\n throw new Error('Terminal global snapshot DEX mismatch');\n }\n const expectedFingerprint = await this.#createFingerprint(identity);\n if (snapshot.fingerprint !== expectedFingerprint) {\n throw new Error('Terminal global snapshot fingerprint mismatch');\n }\n if (!snapshot.complete || snapshot.perDexErrors.length > 0) {\n throw new Error('Terminal global snapshot is incomplete');\n }\n if (\n !this.#isNonNegativeSafeInteger(snapshot.generatedAt) ||\n !this.#isNonNegativeSafeInteger(snapshot.receivedAt) ||\n !this.#isPositiveSafeInteger(snapshot.maxAgeMs) ||\n snapshot.receivedAt > snapshot.generatedAt ||\n snapshot.generatedAt > now + GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS ||\n snapshot.receivedAt > now + GLOBAL_SNAPSHOT_MAX_FUTURE_CLOCK_SKEW_MS\n ) {\n throw new Error('Terminal global snapshot has invalid timestamps');\n }\n\n const trustedMaxAgeMs = Math.min(\n snapshot.maxAgeMs,\n GLOBAL_SNAPSHOT_CONSUMER_MAX_AGE_MS,\n );\n const expiresAt = snapshot.receivedAt + trustedMaxAgeMs;\n if (now >= expiresAt) {\n throw new Error('Terminal global snapshot is stale');\n }\n if (snapshot.markets.length === 0) {\n throw new Error('Terminal global snapshot has no markets');\n }\n\n const marketKeys = new Set<string>();\n const representedDexes = new Set<string>();\n const markets = snapshot.markets\n .map((market, index) => {\n this.#validateSnapshotMarket(\n market,\n identity,\n index,\n snapshot.generatedAt,\n );\n const key = `${market.dex}:${market.symbol}`;\n if (marketKeys.has(key)) {\n throw new Error(`Terminal global snapshot duplicates market ${key}`);\n }\n marketKeys.add(key);\n representedDexes.add(market.dex);\n return market;\n })\n .map((market) => this.#mapSnapshotMarket(market, expiresAt));\n if (identity.enabledDexes.some((dex) => !representedDexes.has(dex))) {\n throw new Error('Terminal global snapshot is missing a requested DEX');\n }\n if (markets.length === 0) {\n throw new Error('Terminal global snapshot has no tradable markets');\n }\n\n return { markets, expiresAt };\n }\n\n #validateRequestedIdentity(\n request: PerpsGlobalSnapshotRequest,\n ): PerpsGlobalSnapshotRequest {\n if (request.provider !== 'hyperliquid') {\n throw new Error('Terminal global snapshot provider is unsupported');\n }\n if (request.network !== 'mainnet' && request.network !== 'testnet') {\n throw new Error('Terminal global snapshot network is unsupported');\n }\n return {\n provider: request.provider,\n network: request.network,\n enabledDexes: this.#normalizeDexes(request.enabledDexes),\n };\n }\n\n #buildGlobalSnapshotUrl(\n baseUrl: string,\n identity: PerpsGlobalSnapshotRequest,\n ): string {\n const query = new URLSearchParams({\n provider: identity.provider,\n network: identity.network,\n dexes: identity.enabledDexes.join(','),\n });\n return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${query.toString()}`;\n }\n\n #normalizeDexes(dexes: string[]): string[] {\n if (!Array.isArray(dexes) || dexes.length === 0) {\n throw new Error('Terminal global snapshot requires at least one DEX');\n }\n const normalized = dexes.map((dex) => {\n if (typeof dex !== 'string' || !DEX_PATTERN.test(dex)) {\n throw new Error('Terminal global snapshot contains an invalid DEX');\n }\n return dex;\n });\n if (new Set(normalized).size !== normalized.length) {\n throw new Error('Terminal global snapshot contains duplicate DEXes');\n }\n if (!normalized.includes('main')) {\n throw new Error('Terminal global snapshot requires the main DEX');\n }\n return canonicalizeHyperLiquidDexes(normalized);\n }\n\n async #createFingerprint(\n identity: PerpsGlobalSnapshotRequest,\n ): Promise<string> {\n const canonicalIdentity = JSON.stringify({\n provider: identity.provider,\n network: identity.network,\n enabledDexes: identity.enabledDexes,\n });\n const digest = await sha256(stringToBytes(canonicalIdentity));\n return `sha256:${bytesToHex(digest).slice(2)}`;\n }\n\n #validateSnapshotMarket(\n market: GlobalSnapshotMarket,\n identity: PerpsGlobalSnapshotRequest,\n index: number,\n generatedAt: number,\n ): void {\n const invalid = (field: string): Error =>\n new Error(\n `Terminal global snapshot market ${String(index)} has invalid ${field}`,\n );\n if (market.id.length === 0) {\n throw invalid('id');\n }\n if (market.network !== identity.network) {\n throw invalid('network');\n }\n if (!identity.enabledDexes.includes(market.dex)) {\n throw invalid('dex');\n }\n const expectedProvider = market.dex === 'main' ? 'hyperliquid' : market.dex;\n if (market.provider !== expectedProvider) {\n throw invalid('provider');\n }\n const expectedPrefix = market.dex === 'main' ? '' : `${market.dex}:`;\n if (\n market.symbol.length === 0 ||\n (expectedPrefix\n ? !market.symbol.startsWith(expectedPrefix)\n : market.symbol.includes(':'))\n ) {\n throw invalid('symbol');\n }\n if (\n !this.#isNonNegativeSafeInteger(market.szDecimals) ||\n !this.#isPositiveSafeInteger(market.maxLeverage) ||\n (market.listedAt !== null &&\n (!this.#isNonNegativeSafeInteger(market.listedAt) ||\n market.listedAt < MINIMUM_EPOCH_MILLISECONDS ||\n market.listedAt > generatedAt))\n ) {\n throw invalid('integer field');\n }\n\n const decimalFields: [string, string, boolean][] = [\n ['markPrice', market.markPrice, true],\n ['price', market.price, true],\n ['oraclePrice', market.oraclePrice, true],\n ['change24h', market.change24h, false],\n ['volume24h', market.volume24h, true],\n ['openInterest', market.openInterest, true],\n ['funding', market.funding, false],\n ];\n if (market.midPrice !== null) {\n decimalFields.push(['midPrice', market.midPrice, true]);\n }\n for (const [field, value, nonNegative] of decimalFields) {\n const pattern = nonNegative\n ? NON_NEGATIVE_DECIMAL_PATTERN\n : DECIMAL_PATTERN;\n if (!pattern.test(value) || !Number.isFinite(Number(value))) {\n throw invalid(field);\n }\n }\n if (market.price !== market.markPrice) {\n throw invalid('deprecated price alias');\n }\n if (\n Number(market.oraclePrice) <= 0 ||\n (market.midPrice !== null && Number(market.midPrice) <= 0)\n ) {\n throw invalid('reference price');\n }\n const price = Number(market.markPrice);\n const change24h = Number(market.change24h);\n const previousPrice = price - change24h;\n if (price <= 0 || previousPrice <= 0 || !Number.isFinite(previousPrice)) {\n throw invalid('mark/change coherence');\n }\n const derivedPercent = (change24h / previousPrice) * 100;\n if (\n !Number.isFinite(derivedPercent) ||\n !Number.isFinite(market.changePercent24h) ||\n Math.abs(market.changePercent24h - derivedPercent) >\n GLOBAL_SNAPSHOT_PERCENT_TOLERANCE\n ) {\n throw invalid('changePercent24h coherence');\n }\n for (const [field, values] of [\n ['keywords', market.keywords],\n ['tags', market.tags],\n ] as const) {\n if (\n values !== null &&\n (values.some((value) => value.length === 0) ||\n new Set(values).size !== values.length)\n ) {\n throw invalid(field);\n }\n }\n for (const [field, value] of [\n ['name', market.name],\n ['description', market.description],\n ['iconUrl', market.iconUrl],\n ['category', market.category],\n ] as const) {\n if (value !== null && value.length === 0) {\n throw invalid(field);\n }\n }\n let previousTrendTimestamp = -1;\n for (const [timestamp, trendPrice] of market.trend) {\n if (\n !this.#isNonNegativeSafeInteger(timestamp) ||\n timestamp < MINIMUM_EPOCH_MILLISECONDS ||\n timestamp > generatedAt ||\n timestamp <= previousTrendTimestamp ||\n !NON_NEGATIVE_DECIMAL_PATTERN.test(trendPrice) ||\n !Number.isFinite(Number(trendPrice)) ||\n Number(trendPrice) <= 0\n ) {\n throw invalid('trend');\n }\n previousTrendTimestamp = timestamp;\n }\n }\n\n #mapSnapshotMarket(\n market: GlobalSnapshotMarket,\n sourceExpiresAt: number,\n ): PerpsMarketData {\n const formatters = this.#deps.marketDataFormatters;\n // Keep both provider price semantics explicit in the wire contract. Core\n // maps markPrice to its UI price while retaining validation of midPrice.\n const price = Number(market.markPrice);\n const change24h = Number(market.change24h);\n const volume = Number(market.volume24h);\n const openInterest = Number(market.openInterest);\n const isHip3 = market.dex !== 'main';\n const marketType = this.#marketTypeFor(market.dex, market.category);\n\n return {\n id: market.id,\n symbol: market.symbol,\n name: market.name ?? market.symbol,\n ...(market.description !== null && {\n description: market.description,\n }),\n maxLeverage: `${String(market.maxLeverage)}x`,\n price: formatters.formatPerpsFiat(price, {\n ranges: formatters.priceRangesUniversal,\n }),\n change24h: formatChange(change24h, formatters),\n change24hPercent: formatters.formatPercentage(market.changePercent24h),\n volume: formatters.formatVolume(volume),\n openInterest: formatters.formatVolume(openInterest),\n fundingRate: Number(market.funding),\n marketSource: isHip3 ? market.dex : undefined,\n marketType,\n isHip3,\n isNewMarket: isHip3 && marketType === undefined,\n ...(market.keywords && { keywords: market.keywords }),\n ...(market.tags && { tags: market.tags }),\n ...(market.category && { categories: [market.category] }),\n ...(market.listedAt !== null && { listedAt: market.listedAt }),\n trend: market.trend,\n dataSource: 'terminal-global-snapshot-mark',\n sourceExpiresAt,\n };\n }\n\n #marketTypeFor(\n dex: string,\n category: string | null,\n ): TerminalAssetMetadata['marketType'] | undefined {\n if (dex === 'main') {\n return MarketCategory.CryptoCurrency;\n }\n if (category === 'stocks') {\n return MarketCategory.Stock;\n }\n if (category === 'pre_ipo') {\n return MarketCategory.PreIpo;\n }\n if (category && VALID_MARKET_TYPES.has(category)) {\n return category as TerminalAssetMetadata['marketType'];\n }\n return undefined;\n }\n\n #cloneGlobalSnapshotResult(\n result: PerpsGlobalSnapshotResult,\n ): PerpsGlobalSnapshotResult {\n return {\n expiresAt: result.expiresAt,\n markets: clonePerpsMarketData(result.markets),\n };\n }\n\n #isNonNegativeSafeInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isSafeInteger(value) && value >= 0\n );\n }\n\n #isPositiveSafeInteger(value: unknown): value is number {\n return this.#isNonNegativeSafeInteger(value) && value > 0;\n }\n\n /**\n * Invalidate the internal cache so the next fetch hits the network.\n */\n clearCache(): void {\n this.#cache = null;\n this.#globalSnapshotGeneration += 1;\n this.#globalSnapshotCache.clear();\n this.#globalSnapshotInFlight.clear();\n }\n\n /**\n * Validate raw API response items against the expected schema.\n * Items that fail validation are filtered out and logged rather than\n * rejecting the entire response.\n *\n * @param raw - The raw array from the API response body.\n * @returns Array of validated items.\n */\n #validateItems(raw: unknown[]): TerminalPerpetualItem[] {\n const valid: TerminalPerpetualItem[] = [];\n for (const item of raw) {\n if (is(item, TerminalPerpetualItemStruct)) {\n valid.push(item);\n } else {\n this.#deps.logger.error(\n ensureError(\n new Error('Terminal API item failed schema validation'),\n 'TerminalMarketService.validateItems',\n ),\n {\n tags: {\n feature: PERPS_CONSTANTS.FeatureName,\n source: 'terminal-api',\n },\n context: {\n name: 'TerminalMarketService.validateItems',\n data: {\n symbol:\n typeof item === 'object' &&\n item !== null &&\n Object.prototype.hasOwnProperty.call(item, 'symbol')\n ? (item as Record<string, unknown>).symbol\n : undefined,\n },\n },\n },\n );\n }\n }\n return valid;\n }\n\n /**\n * Map Terminal API items to the protocol-agnostic MarketInfo shape.\n *\n * @param items - Raw items from the API response.\n * @returns Array of MarketInfo objects.\n */\n #mapToMarketInfo(items: TerminalPerpetualItem[]): MarketInfo[] {\n return items\n .filter(\n (item) => typeof item.symbol === 'string' && item.symbol.length > 0,\n )\n .map((item) => ({\n name: item.symbol,\n szDecimals: item.szDecimals ?? 0,\n maxLeverage: item.maxLeverage ?? 1,\n marginTableId: item.marginTableId ?? 0,\n ...(item.onlyIsolated === true && { onlyIsolated: true as const }),\n ...(item.isDelisted === true && { isDelisted: true as const }),\n ...(item.minimumOrderSize !== undefined && {\n minimumOrderSize: item.minimumOrderSize,\n }),\n }));\n }\n\n /**\n * Extract per-symbol metadata for downstream merge into PerpsMarketData.\n *\n * @param items - Raw items from the API response.\n * @returns Map keyed by symbol with enrichment metadata.\n */\n #extractMetadata(\n items: TerminalPerpetualItem[],\n ): Map<string, TerminalAssetMetadata> {\n const map = new Map<string, TerminalAssetMetadata>();\n\n for (const item of items) {\n if (typeof item.symbol !== 'string' || item.symbol.length === 0) {\n continue;\n }\n\n const entry: TerminalAssetMetadata = {};\n\n if (typeof item.name === 'string' && item.name.length > 0) {\n entry.name = item.name;\n }\n\n if (typeof item.description === 'string' && item.description.length > 0) {\n entry.description = item.description;\n }\n\n if (Array.isArray(item.keywords) && item.keywords.length > 0) {\n entry.keywords = item.keywords;\n }\n if (Array.isArray(item.tags) && item.tags.length > 0) {\n entry.tags = item.tags;\n }\n if (Array.isArray(item.categories) && item.categories.length > 0) {\n entry.categories = item.categories;\n }\n if (\n typeof item.marketType === 'string' &&\n VALID_MARKET_TYPES.has(item.marketType)\n ) {\n entry.marketType =\n item.marketType as TerminalAssetMetadata['marketType'];\n }\n\n if (item.listedAt !== null && item.listedAt !== undefined) {\n const listedAtMs =\n typeof item.listedAt === 'number'\n ? item.listedAt\n : Date.parse(item.listedAt);\n if (isFinite(listedAtMs)) {\n entry.listedAt = listedAtMs;\n }\n }\n\n map.set(item.symbol, entry);\n }\n\n return map;\n }\n\n /**\n * Log a Terminal API error to Sentry without surfacing it to the user.\n *\n * @param error - The caught error.\n * @param method - The calling method name for context.\n */\n logError(error: unknown, method: string): void {\n this.#deps.logger.error(\n ensureError(error, `TerminalMarketService.${method}`),\n {\n tags: { feature: PERPS_CONSTANTS.FeatureName, source: 'terminal-api' },\n context: {\n name: `TerminalMarketService.${method}`,\n data: {\n url: method.includes('globalSnapshot')\n ? this.#deps.terminalApi?.globalSnapshotUrl\n : (this.#deps.terminalApi?.marketDataUrl ??\n this.#deps.terminalApiUrl),\n },\n },\n },\n );\n }\n}\n"]}
|