@polyester/sdk 0.3.1 → 0.4.1

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.
Files changed (189) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +63 -17
  3. package/dist/account-signer/types.d.ts.map +1 -1
  4. package/dist/account-signer/types.js +6 -3
  5. package/dist/account-signer/types.js.map +1 -1
  6. package/dist/browser-client.d.ts +4 -2
  7. package/dist/browser-client.d.ts.map +1 -1
  8. package/dist/browser-client.js +3 -4
  9. package/dist/browser-client.js.map +1 -1
  10. package/dist/catalogs/client-catalog.d.ts.map +1 -1
  11. package/dist/catalogs/client-catalog.js +11 -4
  12. package/dist/catalogs/client-catalog.js.map +1 -1
  13. package/dist/catalogs/index.js +1 -1
  14. package/dist/catalogs/readers.d.ts.map +1 -1
  15. package/dist/catalogs/readers.js +3 -1
  16. package/dist/catalogs/readers.js.map +1 -1
  17. package/dist/catalogs/snapshot-validation.js +132 -0
  18. package/dist/catalogs/snapshot-validation.js.map +1 -0
  19. package/dist/catalogs/snapshot.d.ts.map +1 -1
  20. package/dist/catalogs/snapshot.js +16 -7
  21. package/dist/catalogs/snapshot.js.map +1 -1
  22. package/dist/catalogs/zipper-supply.d.ts.map +1 -1
  23. package/dist/catalogs/zipper-supply.js +10 -7
  24. package/dist/catalogs/zipper-supply.js.map +1 -1
  25. package/dist/core-client.d.ts +24 -17
  26. package/dist/core-client.d.ts.map +1 -1
  27. package/dist/core-client.js +21 -3
  28. package/dist/core-client.js.map +1 -1
  29. package/dist/environment.d.ts.map +1 -1
  30. package/dist/environment.js +32 -1
  31. package/dist/environment.js.map +1 -1
  32. package/dist/index.js +3 -3
  33. package/dist/realtime/client.js +13 -2
  34. package/dist/realtime/client.js.map +1 -1
  35. package/dist/realtime/snapshot-then-stream.js +1 -1
  36. package/dist/realtime/snapshot-then-stream.js.map +1 -1
  37. package/dist/realtime/types.d.ts +2 -0
  38. package/dist/realtime/types.d.ts.map +1 -1
  39. package/dist/server-client.d.ts +17 -8
  40. package/dist/server-client.d.ts.map +1 -1
  41. package/dist/server-client.js +8 -11
  42. package/dist/server-client.js.map +1 -1
  43. package/dist/services/accounts/accounts.js +3 -3
  44. package/dist/services/accounts/accounts.js.map +1 -1
  45. package/dist/services/address-book/address-book.js +28 -28
  46. package/dist/services/address-book/address-book.js.map +1 -1
  47. package/dist/services/address-book/address-book.schemas.d.ts.map +1 -1
  48. package/dist/services/address-book/address-book.schemas.js +2 -1
  49. package/dist/services/address-book/address-book.schemas.js.map +1 -1
  50. package/dist/services/api-keys/api-keys.d.ts.map +1 -1
  51. package/dist/services/api-keys/api-keys.js +12 -12
  52. package/dist/services/api-keys/api-keys.js.map +1 -1
  53. package/dist/services/auth/auth.d.ts +9 -3
  54. package/dist/services/auth/auth.d.ts.map +1 -1
  55. package/dist/services/auth/auth.js +11 -7
  56. package/dist/services/auth/auth.js.map +1 -1
  57. package/dist/services/auth/profile/profile.d.ts.map +1 -1
  58. package/dist/services/auth/profile/profile.js +7 -6
  59. package/dist/services/auth/profile/profile.js.map +1 -1
  60. package/dist/services/auth/session.d.ts +1 -1
  61. package/dist/services/auth/session.d.ts.map +1 -1
  62. package/dist/services/auth/session.js +6 -2
  63. package/dist/services/auth/session.js.map +1 -1
  64. package/dist/services/auth/session.types.d.ts +3 -2
  65. package/dist/services/auth/session.types.d.ts.map +1 -1
  66. package/dist/services/balances/balances.d.ts +1 -1
  67. package/dist/services/balances/balances.d.ts.map +1 -1
  68. package/dist/services/balances/balances.js +9 -8
  69. package/dist/services/balances/balances.js.map +1 -1
  70. package/dist/services/balances/balances.schemas.d.ts +1 -1
  71. package/dist/services/balances/balances.schemas.d.ts.map +1 -1
  72. package/dist/services/balances/balances.schemas.js +1 -1
  73. package/dist/services/balances/balances.schemas.js.map +1 -1
  74. package/dist/services/candles/candles.d.ts.map +1 -1
  75. package/dist/services/candles/candles.js +10 -9
  76. package/dist/services/candles/candles.js.map +1 -1
  77. package/dist/services/candles/candles.schemas.d.ts +11 -11
  78. package/dist/services/candles/candles.schemas.d.ts.map +1 -1
  79. package/dist/services/candles/candles.schemas.js +1 -2
  80. package/dist/services/candles/candles.schemas.js.map +1 -1
  81. package/dist/services/chain-analytics/chain-analytics.js +7 -7
  82. package/dist/services/chain-analytics/chain-analytics.js.map +1 -1
  83. package/dist/services/deposit/deposit.js +5 -5
  84. package/dist/services/deposit/deposit.js.map +1 -1
  85. package/dist/services/guard-signer/guard-signer.js +13 -13
  86. package/dist/services/guard-signer/guard-signer.js.map +1 -1
  87. package/dist/services/heatmap/heatmap.d.ts.map +1 -1
  88. package/dist/services/heatmap/heatmap.js +6 -5
  89. package/dist/services/heatmap/heatmap.js.map +1 -1
  90. package/dist/services/heatmap/heatmap.schemas.d.ts +17 -17
  91. package/dist/services/heatmap/heatmap.schemas.js +1 -1
  92. package/dist/services/heatmap/heatmap.schemas.js.map +1 -1
  93. package/dist/services/internal-transfers/internal-transfers.js +3 -3
  94. package/dist/services/internal-transfers/internal-transfers.js.map +1 -1
  95. package/dist/services/lifecycle/lifecycle.d.ts.map +1 -1
  96. package/dist/services/lifecycle/lifecycle.js +9 -8
  97. package/dist/services/lifecycle/lifecycle.js.map +1 -1
  98. package/dist/services/market-data/market-data.d.ts.map +1 -1
  99. package/dist/services/market-data/market-data.js +6 -5
  100. package/dist/services/market-data/market-data.js.map +1 -1
  101. package/dist/services/market-data/market-data.schemas.d.ts +2 -2
  102. package/dist/services/market-data/market-data.schemas.d.ts.map +1 -1
  103. package/dist/services/market-data/market-data.schemas.js +2 -6
  104. package/dist/services/market-data/market-data.schemas.js.map +1 -1
  105. package/dist/services/market-overview/market-overview.d.ts.map +1 -1
  106. package/dist/services/market-overview/market-overview.js +4 -3
  107. package/dist/services/market-overview/market-overview.js.map +1 -1
  108. package/dist/services/market-overview/market-overview.schemas.d.ts +3 -3
  109. package/dist/services/mfa/mfa.js +27 -27
  110. package/dist/services/mfa/mfa.js.map +1 -1
  111. package/dist/services/orderbook/orderbook.d.ts.map +1 -1
  112. package/dist/services/orderbook/orderbook.js +5 -4
  113. package/dist/services/orderbook/orderbook.js.map +1 -1
  114. package/dist/services/orderbook/orderbook.schemas.d.ts +1 -1
  115. package/dist/services/orders/orders-batch.schemas.d.ts +14 -14
  116. package/dist/services/orders/orders-batch.schemas.js +1 -1
  117. package/dist/services/orders/orders-input.schemas.d.ts +13 -4
  118. package/dist/services/orders/orders-input.schemas.d.ts.map +1 -1
  119. package/dist/services/orders/orders-input.schemas.js +8 -4
  120. package/dist/services/orders/orders-input.schemas.js.map +1 -1
  121. package/dist/services/orders/orders-modify.schemas.d.ts +22 -3
  122. package/dist/services/orders/orders-modify.schemas.d.ts.map +1 -1
  123. package/dist/services/orders/orders-modify.schemas.js +7 -3
  124. package/dist/services/orders/orders-modify.schemas.js.map +1 -1
  125. package/dist/services/orders/orders-output.schemas.d.ts +12 -12
  126. package/dist/services/orders/orders.d.ts +2 -2
  127. package/dist/services/orders/orders.d.ts.map +1 -1
  128. package/dist/services/orders/orders.js +44 -31
  129. package/dist/services/orders/orders.js.map +1 -1
  130. package/dist/services/policies/api-key-policies/api-key-policies.d.ts.map +1 -1
  131. package/dist/services/policies/api-key-policies/api-key-policies.js +11 -11
  132. package/dist/services/policies/api-key-policies/api-key-policies.js.map +1 -1
  133. package/dist/services/policies/subaccount-policies/subaccount-policies.d.ts.map +1 -1
  134. package/dist/services/policies/subaccount-policies/subaccount-policies.js +13 -12
  135. package/dist/services/policies/subaccount-policies/subaccount-policies.js.map +1 -1
  136. package/dist/services/social-verification/social-verification.d.ts.map +1 -1
  137. package/dist/services/social-verification/social-verification.js +7 -7
  138. package/dist/services/social-verification/social-verification.js.map +1 -1
  139. package/dist/services/subaccount-resolver.js +5 -3
  140. package/dist/services/subaccount-resolver.js.map +1 -1
  141. package/dist/services/subaccounts/subaccounts.d.ts +1 -1
  142. package/dist/services/subaccounts/subaccounts.d.ts.map +1 -1
  143. package/dist/services/subaccounts/subaccounts.js +34 -33
  144. package/dist/services/subaccounts/subaccounts.js.map +1 -1
  145. package/dist/services/subaccounts/subaccounts.schemas.d.ts +2 -2
  146. package/dist/services/subaccounts/subaccounts.schemas.js +1 -1
  147. package/dist/services/subaccounts/subaccounts.schemas.js.map +1 -1
  148. package/dist/services/trades/trades.d.ts.map +1 -1
  149. package/dist/services/trades/trades.js +5 -4
  150. package/dist/services/trades/trades.js.map +1 -1
  151. package/dist/services/trading-withdraws/trading-withdraws.js +8 -8
  152. package/dist/services/trading-withdraws/trading-withdraws.js.map +1 -1
  153. package/dist/services/transfers/transfers.d.ts +1 -1
  154. package/dist/services/transfers/transfers.d.ts.map +1 -1
  155. package/dist/services/transfers/transfers.js +5 -4
  156. package/dist/services/transfers/transfers.js.map +1 -1
  157. package/dist/services/triggers/trigger-input.schemas.d.ts +1 -1
  158. package/dist/services/triggers/triggers-output.schemas.d.ts +1 -1
  159. package/dist/services/triggers/triggers.d.ts.map +1 -1
  160. package/dist/services/triggers/triggers.js +21 -20
  161. package/dist/services/triggers/triggers.js.map +1 -1
  162. package/dist/services/whiteboard/whiteboard.js +15 -15
  163. package/dist/services/whiteboard/whiteboard.js.map +1 -1
  164. package/dist/services/zipper/zipper.js +3 -3
  165. package/dist/services/zipper/zipper.js.map +1 -1
  166. package/dist/shared/connect-error-mapping.d.ts +1 -1
  167. package/dist/shared/connect-error-mapping.js +27 -1
  168. package/dist/shared/connect-error-mapping.js.map +1 -1
  169. package/dist/shared/transports.js +7 -12
  170. package/dist/shared/transports.js.map +1 -1
  171. package/dist/shared/types.d.ts +12 -0
  172. package/dist/shared/types.d.ts.map +1 -1
  173. package/dist/shared/validation.js +19 -0
  174. package/dist/shared/validation.js.map +1 -0
  175. package/dist/utils/cookies.d.ts +8 -3
  176. package/dist/utils/cookies.d.ts.map +1 -1
  177. package/dist/utils/cookies.js +7 -1
  178. package/dist/utils/cookies.js.map +1 -1
  179. package/dist/utils/event-emitter.d.ts +1 -1
  180. package/dist/utils/event-emitter.d.ts.map +1 -1
  181. package/dist/utils/event-emitter.js +4 -2
  182. package/dist/utils/event-emitter.js.map +1 -1
  183. package/dist/utils/evm.js +2 -2
  184. package/dist/utils/evm.js.map +1 -1
  185. package/dist/utils/jwt.d.ts +2 -2
  186. package/dist/utils/jwt.d.ts.map +1 -1
  187. package/dist/utils/jwt.js +2 -2
  188. package/dist/utils/jwt.js.map +1 -1
  189. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # @polyester/sdk
2
2
 
3
+ ## 0.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#56](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/56) [`1e34fde`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/1e34fde8be60b78006ee2c0c23595c0561ab5d6a) Thanks [@huntabyte](https://github.com/huntabyte)! - Repair the published TypeScript declarations so public contract and service callback types retain their precise inferred shapes.
8
+
9
+ ## 0.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Standardize market-data limits as positive integers, reject string and invalid candle or trade limits, and require a valid orderbook heatmap limit before sending requests.
14
+
15
+ ### Patch Changes
16
+
17
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Return exact nanosecond timestamp strings and epoch-millisecond timestamps from single-order cancel and modify operations.
18
+
19
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Preserve server-side bearer authentication when the display-session cookie is missing or invalid, and discard it when an explicit display session belongs to another environment.
20
+
21
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Clarify that single-order cancellation acknowledges the request and requires lifecycle reconciliation, while missing targets remain not-found errors.
22
+
23
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Document that realtime callers must wait for `onOpen` before issuing writes whose events they need to observe.
24
+
25
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Allow transfer history to be listed without an input object and return an SDK validation error for null account-scoped inputs.
26
+
27
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Accept Next.js-style cookie getters when creating server clients.
28
+
29
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Reject malformed client, environment, account signer, and catalog configuration with SDK error types before constructing clients or marking catalog snapshots fresh.
30
+
31
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Isolate synchronously thrown auth event listener errors so one failing listener cannot reject a completed auth operation or prevent later listeners from running.
32
+
33
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Return login nonce expiration timestamps as JSON-safe epoch-millisecond numbers instead of raw protobuf timestamp objects.
34
+
35
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Route private realtime subscription authentication failures through `onError` when provided, and throw from `subscribe()` when no error observer exists.
36
+
37
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Return `null` from `orders.getDetails` when the backend reports that the requested order was not found.
38
+
39
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - fix(auth): prevent malformed hex credentials from appearing in configuration error messages.
40
+
41
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Return `false` from `isJwtValid` for non-string values instead of throwing.
42
+
43
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Validate subaccount activity limits and balance-history ledger IDs as non-negative integers before serializing requests.
44
+
45
+ - [#54](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/54) [`b1d07ad`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/b1d07ad58e7f691cbf0df32e5905bd679c1adfd6) Thanks [@huntabyte](https://github.com/huntabyte)! - Translate schema validation, authentication, RPC, and network failures into the documented `PolyesterError` hierarchy.
46
+
3
47
  ## 0.3.1
4
48
 
5
49
  ### Patch Changes
package/README.md CHANGED
@@ -59,8 +59,30 @@ if (client.hasUsableBearerToken) {
59
59
  }
60
60
  ```
61
61
 
62
- The parsed cookie session is display data for hydrating UI. It is not proof of
63
- authentication, so the backend still authorizes every call.
62
+ Framework cookie stores are accepted too. Await asynchronous helpers before
63
+ passing the store. For example, with current Next.js versions:
64
+
65
+ ```ts
66
+ import { cookies } from "next/headers";
67
+ import {
68
+ createPolyesterServerClientFromCookies,
69
+ POLYESTER_TESTNET_ENVIRONMENT,
70
+ } from "@polyester/sdk";
71
+
72
+ const client = createPolyesterServerClientFromCookies({
73
+ cookies: await cookies(),
74
+ environment: POLYESTER_TESTNET_ENVIRONMENT,
75
+ });
76
+ ```
77
+
78
+ This factory accepts a `Request`, a `{ [name]: value }` record, or a synchronous
79
+ `.get(name)` store that returns either the cookie value or an object containing
80
+ the value.
81
+
82
+ The `polyester_auth_token` bearer cookie is read independently from the
83
+ `polyester_session_3` cookie. The latter contains unsigned display data for UI
84
+ hydration; it is not proof of authentication. The backend still verifies the
85
+ bearer token and authorizes every call.
64
86
 
65
87
  For machine clients, pass an Ed25519 API key provider instead of a cookie
66
88
  session:
@@ -80,28 +102,52 @@ const client = new PolyesterClient({
80
102
 
81
103
  ## Realtime
82
104
 
83
- Subscriptions return their own unsubscribe function. No event emitter, no
84
- cleanup bookkeeping.
105
+ Subscriptions start connecting immediately and return their own unsubscribe
106
+ function. The return value does not mean the channel is open. Wait for the first
107
+ `onOpen` callback to avoid the initial startup gap. This does not guarantee
108
+ delivery across a later disconnect; applications that require continuity must
109
+ reconcile after connection gaps. `onOpen` can run again after a successful
110
+ reconnect, so keep one-time writes outside the callback itself.
85
111
 
86
112
  ```ts
87
- const unsubscribe = client.orders.subscribe({
88
- accountId,
89
- onEvent: (order) => console.log(order.orderId, order.status),
90
- onError: (ctx) => console.warn(ctx.channel, ctx.error),
113
+ const unsubscribe = await new Promise<() => void>((resolve, reject) => {
114
+ let stop = () => {};
115
+ let pending = true;
116
+
117
+ stop = client.orders.subscribe({
118
+ accountId,
119
+ onOpen: () => {
120
+ if (!pending) return;
121
+ pending = false;
122
+ resolve(stop);
123
+ },
124
+ onEvent: (order) => console.log(order.orderId, order.status),
125
+ onError: (ctx) => {
126
+ console.warn(ctx.channel, ctx.error);
127
+ if (!pending) return;
128
+ pending = false;
129
+ stop();
130
+ reject(ctx.error);
131
+ },
132
+ });
91
133
  });
134
+
135
+ await client.orders.create(order);
92
136
  ```
93
137
 
138
+ Call `unsubscribe()` when the subscription is no longer needed.
139
+
94
140
  ## Entry points
95
141
 
96
- | Import | Contains |
97
- | --- | --- |
98
- | `@polyester/sdk` | clients, environments, errors, types |
99
- | `@polyester/sdk/errors` | error classes and codes on their own |
100
- | `@polyester/sdk/account-signer` | `createPolyesterAccountSigner` |
101
- | `@polyester/sdk/smart-account` | UserOperations and on-chain smart account calls |
102
- | `@polyester/sdk/catalogs` | symbol catalog and decimal scales |
103
- | `@polyester/sdk/server-session` | cookie parsing without the client graph |
104
- | `@polyester/sdk/unstable/gen` | raw protobuf types and service descriptors |
142
+ | Import | Contains |
143
+ | ------------------------------- | ----------------------------------------------- |
144
+ | `@polyester/sdk` | clients, environments, errors, types |
145
+ | `@polyester/sdk/errors` | error classes and codes on their own |
146
+ | `@polyester/sdk/account-signer` | `createPolyesterAccountSigner` |
147
+ | `@polyester/sdk/smart-account` | UserOperations and on-chain smart account calls |
148
+ | `@polyester/sdk/catalogs` | symbol catalog and decimal scales |
149
+ | `@polyester/sdk/server-session` | cookie parsing without the client graph |
150
+ | `@polyester/sdk/unstable/gen` | raw protobuf types and service descriptors |
105
151
 
106
152
  `account-signer` and `smart-account` are separate subpaths on purpose. Both pull
107
153
  in a large viem graph, and keeping them out of the root barrel means the app
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/account-signer/types.ts"],"mappings":";;KAGY;;;;;;;UAQK;;WAEJ;;WAGA,gBAAgB;;WAGhB,eAAe;;EAGxB,YAAY,kBAAkB,QAAQ;;;;;;KAO9B,6BAA6B,uBAAuB,QAAQ;;;;;KAM5D,sBAAsB,gBAAgB;;;;iBAKlC,uBACZ,QAAQ,sBACT,UAAU;;;;iBAsBS,qBAClB,QAAQ,kCACT,QAAQ"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/account-signer/types.ts"],"mappings":";;KAIY;;;;;;;UAQK;;WAEJ;;WAGA,gBAAgB;;WAGhB,eAAe;;EAGxB,YAAY,kBAAkB,QAAQ;;;;;;KAO9B,6BAA6B,uBAAuB,QAAQ;;;;;KAM5D,sBAAsB,gBAAgB;;;;iBAKlC,uBACZ,QAAQ,sBACT,UAAU;;;;iBA4BS,qBAClB,QAAQ,kCACT,QAAQ"}
@@ -1,3 +1,4 @@
1
+ import { ConfigurationError } from "../shared/errors.js";
1
2
  import { isEvmAddress } from "../utils/evm.js";
2
3
  //#region src/account-signer/types.ts
3
4
  /**
@@ -10,9 +11,11 @@ function isAccountSignerFactory(config) {
10
11
  * Asserts that a value implements the account signer contract.
11
12
  */
12
13
  function assertAccountSigner(value) {
13
- if (!value.environmentFingerprint) throw new Error("Account signer must include an environmentFingerprint.");
14
- if (!isEvmAddress(value.accountAddress)) throw new Error("Account signer must include a valid accountAddress.");
15
- if (value.ownerAddress && !isEvmAddress(value.ownerAddress)) throw new Error("Account signer ownerAddress must be a valid address.");
14
+ if (typeof value !== "object" || value === null) throw new ConfigurationError("Account signer must be an object or factory function.");
15
+ if (!value.environmentFingerprint) throw new ConfigurationError("Account signer must include an environmentFingerprint.");
16
+ if (!isEvmAddress(value.accountAddress)) throw new ConfigurationError("Account signer must include a valid accountAddress.");
17
+ if (value.ownerAddress && !isEvmAddress(value.ownerAddress)) throw new ConfigurationError("Account signer ownerAddress must be a valid address.");
18
+ if (typeof value.signMessage !== "function") throw new ConfigurationError("Account signer must include a signMessage function.");
16
19
  }
17
20
  /**
18
21
  * Helper to resolve an account signer from config.
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/account-signer/types.ts"],"sourcesContent":["import type { Hex } from \"viem\";\nimport { isEvmAddress } from \"../utils/evm.js\";\n\nexport type HexAddress = `0x${string}`;\n\n/**\n * Minimal account signer interface for SDK operations.\n *\n * The SDK authenticates the Polyester smart account address. The owner address\n * is optional metadata about the EOA or custody provider that controls it.\n */\nexport interface AccountSigner {\n /** Fingerprint of the PolyesterEnvironment this signer was created for */\n readonly environmentFingerprint: string;\n\n /** The smart account address (used for authentication and trading) */\n readonly accountAddress: HexAddress;\n\n /** The owner/EOA address (optional metadata about the controlling signer) */\n readonly ownerAddress?: HexAddress;\n\n /** Sign a message and return the signature */\n signMessage(message: string): Promise<Hex>;\n}\n\n/**\n * Factory function type for lazy account signer initialization.\n * Useful when the signer might not be available at client creation time.\n */\nexport type AccountSignerFactory = () => AccountSigner | null | Promise<AccountSigner | null>;\n\n/**\n * Account signer configuration for the client.\n * Can be a signer instance or a factory for lazy initialization.\n */\nexport type AccountSignerConfig = AccountSigner | AccountSignerFactory;\n\n/**\n * Helper to check if an account signer config is a factory function.\n */\nexport function isAccountSignerFactory(\n config: AccountSignerConfig,\n): config is AccountSignerFactory {\n return typeof config === \"function\";\n}\n\n/**\n * Asserts that a value implements the account signer contract.\n */\nexport function assertAccountSigner(value: AccountSigner): void {\n if (!value.environmentFingerprint) {\n throw new Error(\"Account signer must include an environmentFingerprint.\");\n }\n if (!isEvmAddress(value.accountAddress)) {\n throw new Error(\"Account signer must include a valid accountAddress.\");\n }\n if (value.ownerAddress && !isEvmAddress(value.ownerAddress)) {\n throw new Error(\"Account signer ownerAddress must be a valid address.\");\n }\n}\n\n/**\n * Helper to resolve an account signer from config.\n */\nexport async function resolveAccountSigner(\n config: AccountSignerConfig | undefined,\n): Promise<AccountSigner | null> {\n if (!config) return null;\n const accountSigner = isAccountSignerFactory(config) ? await config() : config;\n if (accountSigner) assertAccountSigner(accountSigner);\n return accountSigner;\n}\n"],"mappings":";;;;;AAwCA,SAAgB,uBACZ,QAC8B;CAC9B,OAAO,OAAO,WAAW;AAC7B;;;;AAKA,SAAgB,oBAAoB,OAA4B;CAC5D,IAAI,CAAC,MAAM,wBACP,MAAM,IAAI,MAAM,wDAAwD;CAE5E,IAAI,CAAC,aAAa,MAAM,cAAc,GAClC,MAAM,IAAI,MAAM,qDAAqD;CAEzE,IAAI,MAAM,gBAAgB,CAAC,aAAa,MAAM,YAAY,GACtD,MAAM,IAAI,MAAM,sDAAsD;AAE9E;;;;AAKA,eAAsB,qBAClB,QAC6B;CAC7B,IAAI,CAAC,QAAQ,OAAO;CACpB,MAAM,gBAAgB,uBAAuB,MAAM,IAAI,MAAM,OAAO,IAAI;CACxE,IAAI,eAAe,oBAAoB,aAAa;CACpD,OAAO;AACX"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/account-signer/types.ts"],"sourcesContent":["import type { Hex } from \"viem\";\nimport { isEvmAddress } from \"../utils/evm.js\";\nimport { ConfigurationError } from \"../shared/errors.js\";\n\nexport type HexAddress = `0x${string}`;\n\n/**\n * Minimal account signer interface for SDK operations.\n *\n * The SDK authenticates the Polyester smart account address. The owner address\n * is optional metadata about the EOA or custody provider that controls it.\n */\nexport interface AccountSigner {\n /** Fingerprint of the PolyesterEnvironment this signer was created for */\n readonly environmentFingerprint: string;\n\n /** The smart account address (used for authentication and trading) */\n readonly accountAddress: HexAddress;\n\n /** The owner/EOA address (optional metadata about the controlling signer) */\n readonly ownerAddress?: HexAddress;\n\n /** Sign a message and return the signature */\n signMessage(message: string): Promise<Hex>;\n}\n\n/**\n * Factory function type for lazy account signer initialization.\n * Useful when the signer might not be available at client creation time.\n */\nexport type AccountSignerFactory = () => AccountSigner | null | Promise<AccountSigner | null>;\n\n/**\n * Account signer configuration for the client.\n * Can be a signer instance or a factory for lazy initialization.\n */\nexport type AccountSignerConfig = AccountSigner | AccountSignerFactory;\n\n/**\n * Helper to check if an account signer config is a factory function.\n */\nexport function isAccountSignerFactory(\n config: AccountSignerConfig,\n): config is AccountSignerFactory {\n return typeof config === \"function\";\n}\n\n/**\n * Asserts that a value implements the account signer contract.\n */\nexport function assertAccountSigner(value: AccountSigner): void {\n if (typeof value !== \"object\" || value === null) {\n throw new ConfigurationError(\"Account signer must be an object or factory function.\");\n }\n if (!value.environmentFingerprint) {\n throw new ConfigurationError(\"Account signer must include an environmentFingerprint.\");\n }\n if (!isEvmAddress(value.accountAddress)) {\n throw new ConfigurationError(\"Account signer must include a valid accountAddress.\");\n }\n if (value.ownerAddress && !isEvmAddress(value.ownerAddress)) {\n throw new ConfigurationError(\"Account signer ownerAddress must be a valid address.\");\n }\n if (typeof value.signMessage !== \"function\") {\n throw new ConfigurationError(\"Account signer must include a signMessage function.\");\n }\n}\n\n/**\n * Helper to resolve an account signer from config.\n */\nexport async function resolveAccountSigner(\n config: AccountSignerConfig | undefined,\n): Promise<AccountSigner | null> {\n if (!config) return null;\n const accountSigner = isAccountSignerFactory(config) ? await config() : config;\n if (accountSigner) assertAccountSigner(accountSigner);\n return accountSigner;\n}\n"],"mappings":";;;;;;AAyCA,SAAgB,uBACZ,QAC8B;CAC9B,OAAO,OAAO,WAAW;AAC7B;;;;AAKA,SAAgB,oBAAoB,OAA4B;CAC5D,IAAI,OAAO,UAAU,YAAY,UAAU,MACvC,MAAM,IAAI,mBAAmB,uDAAuD;CAExF,IAAI,CAAC,MAAM,wBACP,MAAM,IAAI,mBAAmB,wDAAwD;CAEzF,IAAI,CAAC,aAAa,MAAM,cAAc,GAClC,MAAM,IAAI,mBAAmB,qDAAqD;CAEtF,IAAI,MAAM,gBAAgB,CAAC,aAAa,MAAM,YAAY,GACtD,MAAM,IAAI,mBAAmB,sDAAsD;CAEvF,IAAI,OAAO,MAAM,gBAAgB,YAC7B,MAAM,IAAI,mBAAmB,qDAAqD;AAE1F;;;;AAKA,eAAsB,qBAClB,QAC6B;CAC7B,IAAI,CAAC,QAAQ,OAAO;CACpB,MAAM,gBAAgB,uBAAuB,MAAM,IAAI,MAAM,OAAO,IAAI;CACxE,IAAI,eAAe,oBAAoB,aAAa;CACpD,OAAO;AACX"}
@@ -4,7 +4,9 @@ import { PolyesterClient, PolyesterClientBaseConfig } from "./core-client.js";
4
4
  import { AuthTokenStorage } from "./services/auth/token-storage.js";
5
5
  import { AccountSignerAuthService } from "./services/auth/account-signer-auth.js";
6
6
  //#region src/browser-client.d.ts
7
- interface PolyesterBrowserClientConfig extends Omit<PolyesterClientBaseConfig, "auth"> {
7
+ type BrowserClientBaseConfig<TConfig> = TConfig extends PolyesterClientBaseConfig ? Omit<TConfig, "auth"> : never;
8
+ /** Configuration for the browser Polyester client. */
9
+ type PolyesterBrowserClientConfig = BrowserClientBaseConfig<PolyesterClientBaseConfig> & {
8
10
  /**
9
11
  * Account signer interface for authentication.
10
12
  * Pass a signer object or a factory function for lazy initialization.
@@ -15,7 +17,7 @@ interface PolyesterBrowserClientConfig extends Omit<PolyesterClientBaseConfig, "
15
17
  * Use createCookieAuthTokenStorage() to opt into reload/SSR persistence.
16
18
  */
17
19
  tokenStorage?: AuthTokenStorage;
18
- }
20
+ };
19
21
  /**
20
22
  * A client for interacting with the Polyester DEX in the browser.
21
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"browser-client.d.ts","names":[],"sources":["../src/browser-client.ts"],"mappings":";;;;;;UAUiB,qCAAqC,KAAK;;;;;EAKvD,gBAAgB;;;;;EAKhB,eAAe;;;;;cAMN,+BAA+B;MAI3B,QAAQ;EAIT,YAAA,QAAQ;;;;;YA0CD,4BAA4B;;;;EAiB/C,iBAAiB,eAAe"}
1
+ {"version":3,"file":"browser-client.d.ts","names":[],"sources":["../src/browser-client.ts"],"mappings":";;;;;;KAeK,wBAAwB,WAAW,gBAAgB,4BAClD,KAAK;;KAIC,+BAA+B,wBAAwB;;;;;EAK/D,gBAAgB;;;;;EAKhB,eAAe;;;;;cAMN,+BAA+B;MAI3B,QAAQ;EAIT,YAAA,QAAQ;;;;;YAyCD,4BAA4B;;;;EAiB/C,iBAAiB,eAAe"}
@@ -1,4 +1,4 @@
1
- import { PolyesterClient } from "./core-client.js";
1
+ import { PolyesterClient, parsePolyesterClientConfig, pickPolyesterCatalogConfig } from "./core-client.js";
2
2
  import { AuthSessionStore } from "./services/auth/session.js";
3
3
  import { createMemoryAuthTokenStorage } from "./services/auth/token-storage.js";
4
4
  import { AccountSignerAuthService } from "./services/auth/account-signer-auth.js";
@@ -11,6 +11,7 @@ var PolyesterBrowserClient = class extends PolyesterClient {
11
11
  return super.auth;
12
12
  }
13
13
  constructor(config) {
14
+ config = parsePolyesterClientConfig(config);
14
15
  const tokenStorage = config.tokenStorage ?? createMemoryAuthTokenStorage();
15
16
  const sessionStore = new AuthSessionStore({ environmentFingerprint: config.environment.fingerprint });
16
17
  const getToken = () => sessionStore.getEnvironmentBoundToken(tokenStorage);
@@ -22,9 +23,7 @@ var PolyesterBrowserClient = class extends PolyesterClient {
22
23
  getToken
23
24
  },
24
25
  wireFormat: config.wireFormat,
25
- catalog: config.catalog,
26
- catalogSnapshot: config.catalogSnapshot,
27
- catalogCell: config.catalogCell,
26
+ ...pickPolyesterCatalogConfig(config),
28
27
  transports: config.transports,
29
28
  realtimeClient: config.realtimeClient,
30
29
  realtime: {
@@ -1 +1 @@
1
- {"version":3,"file":"browser-client.js","names":[],"sources":["../src/browser-client.ts"],"sourcesContent":["import { PolyesterClient, type PolyesterClientBaseConfig } from \"./core-client.js\";\nimport { AccountSignerAuthService } from \"./services/auth/account-signer-auth.js\";\nimport type { AccountSignerConfig, AccountSigner } from \"./account-signer/types.js\";\nimport type { SubaccountResolver } from \"./services/subaccount-resolver.js\";\nimport {\n createMemoryAuthTokenStorage,\n type AuthTokenStorage,\n} from \"./services/auth/token-storage.js\";\nimport { AuthSessionStore } from \"./services/auth/session.js\";\n\nexport interface PolyesterBrowserClientConfig extends Omit<PolyesterClientBaseConfig, \"auth\"> {\n /**\n * Account signer interface for authentication.\n * Pass a signer object or a factory function for lazy initialization.\n */\n accountSigner?: AccountSignerConfig;\n /**\n * Storage for browser bearer tokens. Defaults to per-client memory storage.\n * Use createCookieAuthTokenStorage() to opt into reload/SSR persistence.\n */\n tokenStorage?: AuthTokenStorage;\n}\n\n/**\n * A client for interacting with the Polyester DEX in the browser.\n */\nexport class PolyesterBrowserClient extends PolyesterClient {\n // The base class builds `auth` through the `createAuth` runtime factory we\n // pass below, so the lazily-constructed instance is always an\n // AccountSignerAuthService — this override only narrows the type.\n override get auth(): AccountSignerAuthService {\n return super.auth as AccountSignerAuthService;\n }\n\n constructor(config: PolyesterBrowserClientConfig) {\n const tokenStorage = config.tokenStorage ?? createMemoryAuthTokenStorage();\n const sessionStore = new AuthSessionStore({\n environmentFingerprint: config.environment.fingerprint,\n });\n const getToken = () => sessionStore.getEnvironmentBoundToken(tokenStorage);\n\n super(\n {\n environment: config.environment,\n interceptors: config.interceptors,\n auth: { kind: \"jwt\", getToken },\n wireFormat: config.wireFormat,\n catalog: config.catalog,\n catalogSnapshot: config.catalogSnapshot,\n catalogCell: config.catalogCell,\n transports: config.transports,\n realtimeClient: config.realtimeClient,\n realtime: {\n hasAuth: () => !!getToken(),\n ...config.realtime,\n },\n },\n {\n createAuth: ({ transports, realtime, subaccounts, environment }) =>\n new AccountSignerAuthService({\n transports,\n accountSignerConfig: config.accountSigner,\n environment,\n subaccounts,\n realtime,\n tokenStorage,\n sessionStore,\n }),\n },\n );\n }\n\n /**\n * Creates a resolver that defaults subaccountId to the active subaccount.\n * The getter is called lazily when service methods are invoked.\n */\n protected override createSubaccountResolver(): SubaccountResolver {\n return {\n getDefaultSubaccountId: () => {\n const state = this.auth.getState();\n if (state.activeAccount && !state.activeAccount.isMain) {\n return state.activeAccount.accountId;\n }\n return null;\n },\n getActiveAccountId: () => this.auth.getState().activeAccount?.accountId ?? null,\n getMainAccountId: () => this.auth.getState().mainAccountId ?? null,\n };\n }\n\n /**\n * Sets the account signer used for authenticated browser requests.\n */\n setAccountSigner(accountSigner: AccountSigner | null): void {\n this.auth.setAccountSigner(accountSigner);\n }\n}\n"],"mappings":";;;;;;;;AA0BA,IAAa,yBAAb,cAA4C,gBAAgB;CAIxD,IAAa,OAAiC;EAC1C,OAAO,MAAM;CACjB;CAEA,YAAY,QAAsC;EAC9C,MAAM,eAAe,OAAO,gBAAgB,6BAA6B;EACzE,MAAM,eAAe,IAAI,iBAAiB,EACtC,wBAAwB,OAAO,YAAY,YAC/C,CAAC;EACD,MAAM,iBAAiB,aAAa,yBAAyB,YAAY;EAEzE,MACI;GACI,aAAa,OAAO;GACpB,cAAc,OAAO;GACrB,MAAM;IAAE,MAAM;IAAO;GAAS;GAC9B,YAAY,OAAO;GACnB,SAAS,OAAO;GAChB,iBAAiB,OAAO;GACxB,aAAa,OAAO;GACpB,YAAY,OAAO;GACnB,gBAAgB,OAAO;GACvB,UAAU;IACN,eAAe,CAAC,CAAC,SAAS;IAC1B,GAAG,OAAO;GACd;EACJ,GACA,EACI,aAAa,EAAE,YAAY,UAAU,aAAa,kBAC9C,IAAI,yBAAyB;GACzB;GACA,qBAAqB,OAAO;GAC5B;GACA;GACA;GACA;GACA;EACJ,CAAC,EACT,CACJ;CACJ;;;;;CAMA,2BAAkE;EAC9D,OAAO;GACH,8BAA8B;IAC1B,MAAM,QAAQ,KAAK,KAAK,SAAS;IACjC,IAAI,MAAM,iBAAiB,CAAC,MAAM,cAAc,QAC5C,OAAO,MAAM,cAAc;IAE/B,OAAO;GACX;GACA,0BAA0B,KAAK,KAAK,SAAS,CAAC,CAAC,eAAe,aAAa;GAC3E,wBAAwB,KAAK,KAAK,SAAS,CAAC,CAAC,iBAAiB;EAClE;CACJ;;;;CAKA,iBAAiB,eAA2C;EACxD,KAAK,KAAK,iBAAiB,aAAa;CAC5C;AACJ"}
1
+ {"version":3,"file":"browser-client.js","names":[],"sources":["../src/browser-client.ts"],"sourcesContent":["import {\n parsePolyesterClientConfig,\n pickPolyesterCatalogConfig,\n PolyesterClient,\n type PolyesterClientBaseConfig,\n} from \"./core-client.js\";\nimport { AccountSignerAuthService } from \"./services/auth/account-signer-auth.js\";\nimport type { AccountSignerConfig, AccountSigner } from \"./account-signer/types.js\";\nimport type { SubaccountResolver } from \"./services/subaccount-resolver.js\";\nimport {\n createMemoryAuthTokenStorage,\n type AuthTokenStorage,\n} from \"./services/auth/token-storage.js\";\nimport { AuthSessionStore } from \"./services/auth/session.js\";\n\ntype BrowserClientBaseConfig<TConfig> = TConfig extends PolyesterClientBaseConfig\n ? Omit<TConfig, \"auth\">\n : never;\n\n/** Configuration for the browser Polyester client. */\nexport type PolyesterBrowserClientConfig = BrowserClientBaseConfig<PolyesterClientBaseConfig> & {\n /**\n * Account signer interface for authentication.\n * Pass a signer object or a factory function for lazy initialization.\n */\n accountSigner?: AccountSignerConfig;\n /**\n * Storage for browser bearer tokens. Defaults to per-client memory storage.\n * Use createCookieAuthTokenStorage() to opt into reload/SSR persistence.\n */\n tokenStorage?: AuthTokenStorage;\n};\n\n/**\n * A client for interacting with the Polyester DEX in the browser.\n */\nexport class PolyesterBrowserClient extends PolyesterClient {\n // The base class builds `auth` through the `createAuth` runtime factory we\n // pass below, so the lazily-constructed instance is always an\n // AccountSignerAuthService — this override only narrows the type.\n override get auth(): AccountSignerAuthService {\n return super.auth as AccountSignerAuthService;\n }\n\n constructor(config: PolyesterBrowserClientConfig) {\n config = parsePolyesterClientConfig(config);\n const tokenStorage = config.tokenStorage ?? createMemoryAuthTokenStorage();\n const sessionStore = new AuthSessionStore({\n environmentFingerprint: config.environment.fingerprint,\n });\n const getToken = () => sessionStore.getEnvironmentBoundToken(tokenStorage);\n\n super(\n {\n environment: config.environment,\n interceptors: config.interceptors,\n auth: { kind: \"jwt\", getToken },\n wireFormat: config.wireFormat,\n ...pickPolyesterCatalogConfig(config),\n transports: config.transports,\n realtimeClient: config.realtimeClient,\n realtime: {\n hasAuth: () => !!getToken(),\n ...config.realtime,\n },\n },\n {\n createAuth: ({ transports, realtime, subaccounts, environment }) =>\n new AccountSignerAuthService({\n transports,\n accountSignerConfig: config.accountSigner,\n environment,\n subaccounts,\n realtime,\n tokenStorage,\n sessionStore,\n }),\n },\n );\n }\n\n /**\n * Creates a resolver that defaults subaccountId to the active subaccount.\n * The getter is called lazily when service methods are invoked.\n */\n protected override createSubaccountResolver(): SubaccountResolver {\n return {\n getDefaultSubaccountId: () => {\n const state = this.auth.getState();\n if (state.activeAccount && !state.activeAccount.isMain) {\n return state.activeAccount.accountId;\n }\n return null;\n },\n getActiveAccountId: () => this.auth.getState().activeAccount?.accountId ?? null,\n getMainAccountId: () => this.auth.getState().mainAccountId ?? null,\n };\n }\n\n /**\n * Sets the account signer used for authenticated browser requests.\n */\n setAccountSigner(accountSigner: AccountSigner | null): void {\n this.auth.setAccountSigner(accountSigner);\n }\n}\n"],"mappings":";;;;;;;;AAoCA,IAAa,yBAAb,cAA4C,gBAAgB;CAIxD,IAAa,OAAiC;EAC1C,OAAO,MAAM;CACjB;CAEA,YAAY,QAAsC;EAC9C,SAAS,2BAA2B,MAAM;EAC1C,MAAM,eAAe,OAAO,gBAAgB,6BAA6B;EACzE,MAAM,eAAe,IAAI,iBAAiB,EACtC,wBAAwB,OAAO,YAAY,YAC/C,CAAC;EACD,MAAM,iBAAiB,aAAa,yBAAyB,YAAY;EAEzE,MACI;GACI,aAAa,OAAO;GACpB,cAAc,OAAO;GACrB,MAAM;IAAE,MAAM;IAAO;GAAS;GAC9B,YAAY,OAAO;GACnB,GAAG,2BAA2B,MAAM;GACpC,YAAY,OAAO;GACnB,gBAAgB,OAAO;GACvB,UAAU;IACN,eAAe,CAAC,CAAC,SAAS;IAC1B,GAAG,OAAO;GACd;EACJ,GACA,EACI,aAAa,EAAE,YAAY,UAAU,aAAa,kBAC9C,IAAI,yBAAyB;GACzB;GACA,qBAAqB,OAAO;GAC5B;GACA;GACA;GACA;GACA;EACJ,CAAC,EACT,CACJ;CACJ;;;;;CAMA,2BAAkE;EAC9D,OAAO;GACH,8BAA8B;IAC1B,MAAM,QAAQ,KAAK,KAAK,SAAS;IACjC,IAAI,MAAM,iBAAiB,CAAC,MAAM,cAAc,QAC5C,OAAO,MAAM,cAAc;IAE/B,OAAO;GACX;GACA,0BAA0B,KAAK,KAAK,SAAS,CAAC,CAAC,eAAe,aAAa;GAC3E,wBAAwB,KAAK,KAAK,SAAS,CAAC,CAAC,iBAAiB;EAClE;CACJ;;;;CAKA,iBAAiB,eAA2C;EACxD,KAAK,KAAK,iBAAiB,aAAa;CAC5C;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"client-catalog.d.ts","names":[],"sources":["../../src/catalogs/client-catalog.ts"],"mappings":";;iBAWgB,uBAAuB,UAAS,gCAAqC"}
1
+ {"version":3,"file":"client-catalog.d.ts","names":[],"sources":["../../src/catalogs/client-catalog.ts"],"mappings":";;iBAagB,uBAAuB,UAAS,gCAAqC"}
@@ -1,16 +1,22 @@
1
+ import { ConfigurationError } from "../shared/errors.js";
1
2
  import { CatalogNotReadyError } from "./types.js";
3
+ import { parseCatalogSnapshot } from "./snapshot-validation.js";
2
4
  import { createReader } from "./readers.js";
3
5
  import { buildCatalogSnapshot } from "./snapshot.js";
4
6
  //#region src/catalogs/client-catalog.ts
5
7
  function createPolyesterCatalog(options = {}) {
8
+ if (typeof options !== "object" || options === null || Array.isArray(options)) throw new ConfigurationError("Catalog options must be an object.");
6
9
  const cell = options.cell;
7
10
  let local = void 0;
8
- const getCurrent = () => cell ? cell.get() : local;
11
+ const getCurrent = () => {
12
+ const current = cell ? cell.get() : local;
13
+ return current === void 0 ? void 0 : parseCatalogSnapshot(current);
14
+ };
9
15
  const setCurrent = (snapshot) => {
10
16
  if (cell) cell.set(snapshot);
11
17
  else local = snapshot;
12
18
  };
13
- if (options.snapshot && !getCurrent()) setCurrent(options.snapshot);
19
+ if (options.snapshot !== void 0 && !getCurrent()) setCurrent(parseCatalogSnapshot(options.snapshot));
14
20
  const initial = getCurrent();
15
21
  let stateValue = initial ? {
16
22
  status: "fresh",
@@ -24,10 +30,11 @@ function createPolyesterCatalog(options = {}) {
24
30
  });
25
31
  const currentSource = () => getCurrent()?.source ?? "empty";
26
32
  function setSnapshot(snapshot) {
27
- setCurrent(snapshot);
33
+ const parsed = parseCatalogSnapshot(snapshot);
34
+ setCurrent(parsed);
28
35
  stateValue = {
29
36
  status: "fresh",
30
- source: snapshot.source
37
+ source: parsed.source
31
38
  };
32
39
  }
33
40
  function refresh() {
@@ -1 +1 @@
1
- {"version":3,"file":"client-catalog.js","names":[],"sources":["../../src/catalogs/client-catalog.ts"],"sourcesContent":["import { createReader } from \"./readers.js\";\nimport { buildCatalogSnapshot } from \"./snapshot.js\";\nimport type {\n CatalogSnapshot,\n CatalogState,\n CatalogStateSource,\n ClientCatalog,\n CreatePolyesterCatalogOptions,\n} from \"./types.js\";\nimport { CatalogNotReadyError } from \"./types.js\";\n\nexport function createPolyesterCatalog(options: CreatePolyesterCatalogOptions = {}): ClientCatalog {\n const cell = options.cell;\n let local: CatalogSnapshot | undefined = undefined;\n const getCurrent = (): CatalogSnapshot | undefined => (cell ? cell.get() : local);\n const setCurrent = (snapshot: CatalogSnapshot): void => {\n if (cell) cell.set(snapshot);\n else local = snapshot;\n };\n if (options.snapshot && !getCurrent()) setCurrent(options.snapshot);\n\n const initial = getCurrent();\n let stateValue: CatalogState = initial\n ? { status: \"fresh\", source: initial.source }\n : { status: \"empty\" };\n let refreshInFlight: Promise<CatalogSnapshot> | undefined;\n\n const reader = createReader(() => {\n const current = getCurrent();\n if (!current) throw new CatalogNotReadyError();\n return current;\n });\n\n const currentSource = (): CatalogStateSource => getCurrent()?.source ?? \"empty\";\n\n function setSnapshot(snapshot: CatalogSnapshot): void {\n setCurrent(snapshot);\n stateValue = { status: \"fresh\", source: snapshot.source };\n }\n\n function refresh(): Promise<CatalogSnapshot> {\n if (options.refresh === false || options.refresh === undefined) {\n const current = getCurrent();\n if (!current) return Promise.reject(new CatalogNotReadyError());\n return Promise.resolve(current);\n }\n if (refreshInFlight) return refreshInFlight;\n\n stateValue = { status: \"refreshing\", previousSource: currentSource() };\n refreshInFlight = Promise.all([options.refresh.market(), options.refresh.zipper()])\n .then(([marketSeed, zipperSeed]) => {\n const snapshot = buildCatalogSnapshot({\n market: marketSeed,\n zipper: zipperSeed,\n source: \"api\",\n version: (getCurrent()?.version ?? 0) + 1,\n });\n setSnapshot(snapshot);\n return snapshot;\n })\n .catch((error) => {\n stateValue = { status: \"stale\", source: currentSource(), error };\n throw error;\n })\n .finally(() => {\n refreshInFlight = undefined;\n });\n\n return refreshInFlight;\n }\n\n function ready(): Promise<CatalogSnapshot | null> {\n const current = getCurrent();\n if (current) return Promise.resolve(current);\n if (refreshInFlight) return refreshInFlight.catch(() => getCurrent() ?? null);\n return Promise.resolve(null);\n }\n\n function ensureReady(): Promise<CatalogSnapshot> {\n const current = getCurrent();\n if (current) return Promise.resolve(current);\n return refreshInFlight ?? refresh();\n }\n\n return {\n ...reader,\n state: () => stateValue,\n ready,\n ensureReady,\n refresh,\n setSnapshot,\n };\n}\n"],"mappings":";;;;AAWA,SAAgB,uBAAuB,UAAyC,CAAC,GAAkB;CAC/F,MAAM,OAAO,QAAQ;CACrB,IAAI,QAAqC,KAAA;CACzC,MAAM,mBAAiD,OAAO,KAAK,IAAI,IAAI;CAC3E,MAAM,cAAc,aAAoC;EACpD,IAAI,MAAM,KAAK,IAAI,QAAQ;OACtB,QAAQ;CACjB;CACA,IAAI,QAAQ,YAAY,CAAC,WAAW,GAAG,WAAW,QAAQ,QAAQ;CAElE,MAAM,UAAU,WAAW;CAC3B,IAAI,aAA2B,UACzB;EAAE,QAAQ;EAAS,QAAQ,QAAQ;CAAO,IAC1C,EAAE,QAAQ,QAAQ;CACxB,IAAI;CAEJ,MAAM,SAAS,mBAAmB;EAC9B,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,SAAS,MAAM,IAAI,qBAAqB;EAC7C,OAAO;CACX,CAAC;CAED,MAAM,sBAA0C,WAAW,CAAC,EAAE,UAAU;CAExE,SAAS,YAAY,UAAiC;EAClD,WAAW,QAAQ;EACnB,aAAa;GAAE,QAAQ;GAAS,QAAQ,SAAS;EAAO;CAC5D;CAEA,SAAS,UAAoC;EACzC,IAAI,QAAQ,YAAY,SAAS,QAAQ,YAAY,KAAA,GAAW;GAC5D,MAAM,UAAU,WAAW;GAC3B,IAAI,CAAC,SAAS,OAAO,QAAQ,OAAO,IAAI,qBAAqB,CAAC;GAC9D,OAAO,QAAQ,QAAQ,OAAO;EAClC;EACA,IAAI,iBAAiB,OAAO;EAE5B,aAAa;GAAE,QAAQ;GAAc,gBAAgB,cAAc;EAAE;EACrE,kBAAkB,QAAQ,IAAI,CAAC,QAAQ,QAAQ,OAAO,GAAG,QAAQ,QAAQ,OAAO,CAAC,CAAC,CAAC,CAC9E,MAAM,CAAC,YAAY,gBAAgB;GAChC,MAAM,WAAW,qBAAqB;IAClC,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU,WAAW,CAAC,EAAE,WAAW,KAAK;GAC5C,CAAC;GACD,YAAY,QAAQ;GACpB,OAAO;EACX,CAAC,CAAC,CACD,OAAO,UAAU;GACd,aAAa;IAAE,QAAQ;IAAS,QAAQ,cAAc;IAAG;GAAM;GAC/D,MAAM;EACV,CAAC,CAAC,CACD,cAAc;GACX,kBAAkB,KAAA;EACtB,CAAC;EAEL,OAAO;CACX;CAEA,SAAS,QAAyC;EAC9C,MAAM,UAAU,WAAW;EAC3B,IAAI,SAAS,OAAO,QAAQ,QAAQ,OAAO;EAC3C,IAAI,iBAAiB,OAAO,gBAAgB,YAAY,WAAW,KAAK,IAAI;EAC5E,OAAO,QAAQ,QAAQ,IAAI;CAC/B;CAEA,SAAS,cAAwC;EAC7C,MAAM,UAAU,WAAW;EAC3B,IAAI,SAAS,OAAO,QAAQ,QAAQ,OAAO;EAC3C,OAAO,mBAAmB,QAAQ;CACtC;CAEA,OAAO;EACH,GAAG;EACH,aAAa;EACb;EACA;EACA;EACA;CACJ;AACJ"}
1
+ {"version":3,"file":"client-catalog.js","names":[],"sources":["../../src/catalogs/client-catalog.ts"],"sourcesContent":["import { createReader } from \"./readers.js\";\nimport { buildCatalogSnapshot } from \"./snapshot.js\";\nimport type {\n CatalogSnapshot,\n CatalogState,\n CatalogStateSource,\n ClientCatalog,\n CreatePolyesterCatalogOptions,\n} from \"./types.js\";\nimport { CatalogNotReadyError } from \"./types.js\";\nimport { ConfigurationError } from \"../shared/errors.js\";\nimport { parseCatalogSnapshot } from \"./snapshot-validation.js\";\n\nexport function createPolyesterCatalog(options: CreatePolyesterCatalogOptions = {}): ClientCatalog {\n if (typeof options !== \"object\" || options === null || Array.isArray(options)) {\n throw new ConfigurationError(\"Catalog options must be an object.\");\n }\n const cell = options.cell;\n let local: CatalogSnapshot | undefined = undefined;\n const getCurrent = (): CatalogSnapshot | undefined => {\n const current = cell ? cell.get() : local;\n return current === undefined ? undefined : parseCatalogSnapshot(current);\n };\n const setCurrent = (snapshot: CatalogSnapshot): void => {\n if (cell) cell.set(snapshot);\n else local = snapshot;\n };\n if (options.snapshot !== undefined && !getCurrent()) {\n setCurrent(parseCatalogSnapshot(options.snapshot));\n }\n\n const initial = getCurrent();\n let stateValue: CatalogState = initial\n ? { status: \"fresh\", source: initial.source }\n : { status: \"empty\" };\n let refreshInFlight: Promise<CatalogSnapshot> | undefined;\n\n const reader = createReader(() => {\n const current = getCurrent();\n if (!current) throw new CatalogNotReadyError();\n return current;\n });\n\n const currentSource = (): CatalogStateSource => getCurrent()?.source ?? \"empty\";\n\n function setSnapshot(snapshot: CatalogSnapshot): void {\n const parsed = parseCatalogSnapshot(snapshot);\n setCurrent(parsed);\n stateValue = { status: \"fresh\", source: parsed.source };\n }\n\n function refresh(): Promise<CatalogSnapshot> {\n if (options.refresh === false || options.refresh === undefined) {\n const current = getCurrent();\n if (!current) return Promise.reject(new CatalogNotReadyError());\n return Promise.resolve(current);\n }\n if (refreshInFlight) return refreshInFlight;\n\n stateValue = { status: \"refreshing\", previousSource: currentSource() };\n refreshInFlight = Promise.all([options.refresh.market(), options.refresh.zipper()])\n .then(([marketSeed, zipperSeed]) => {\n const snapshot = buildCatalogSnapshot({\n market: marketSeed,\n zipper: zipperSeed,\n source: \"api\",\n version: (getCurrent()?.version ?? 0) + 1,\n });\n setSnapshot(snapshot);\n return snapshot;\n })\n .catch((error) => {\n stateValue = { status: \"stale\", source: currentSource(), error };\n throw error;\n })\n .finally(() => {\n refreshInFlight = undefined;\n });\n\n return refreshInFlight;\n }\n\n function ready(): Promise<CatalogSnapshot | null> {\n const current = getCurrent();\n if (current) return Promise.resolve(current);\n if (refreshInFlight) return refreshInFlight.catch(() => getCurrent() ?? null);\n return Promise.resolve(null);\n }\n\n function ensureReady(): Promise<CatalogSnapshot> {\n const current = getCurrent();\n if (current) return Promise.resolve(current);\n return refreshInFlight ?? refresh();\n }\n\n return {\n ...reader,\n state: () => stateValue,\n ready,\n ensureReady,\n refresh,\n setSnapshot,\n };\n}\n"],"mappings":";;;;;;AAaA,SAAgB,uBAAuB,UAAyC,CAAC,GAAkB;CAC/F,IAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,MAAM,QAAQ,OAAO,GACxE,MAAM,IAAI,mBAAmB,oCAAoC;CAErE,MAAM,OAAO,QAAQ;CACrB,IAAI,QAAqC,KAAA;CACzC,MAAM,mBAAgD;EAClD,MAAM,UAAU,OAAO,KAAK,IAAI,IAAI;EACpC,OAAO,YAAY,KAAA,IAAY,KAAA,IAAY,qBAAqB,OAAO;CAC3E;CACA,MAAM,cAAc,aAAoC;EACpD,IAAI,MAAM,KAAK,IAAI,QAAQ;OACtB,QAAQ;CACjB;CACA,IAAI,QAAQ,aAAa,KAAA,KAAa,CAAC,WAAW,GAC9C,WAAW,qBAAqB,QAAQ,QAAQ,CAAC;CAGrD,MAAM,UAAU,WAAW;CAC3B,IAAI,aAA2B,UACzB;EAAE,QAAQ;EAAS,QAAQ,QAAQ;CAAO,IAC1C,EAAE,QAAQ,QAAQ;CACxB,IAAI;CAEJ,MAAM,SAAS,mBAAmB;EAC9B,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,SAAS,MAAM,IAAI,qBAAqB;EAC7C,OAAO;CACX,CAAC;CAED,MAAM,sBAA0C,WAAW,CAAC,EAAE,UAAU;CAExE,SAAS,YAAY,UAAiC;EAClD,MAAM,SAAS,qBAAqB,QAAQ;EAC5C,WAAW,MAAM;EACjB,aAAa;GAAE,QAAQ;GAAS,QAAQ,OAAO;EAAO;CAC1D;CAEA,SAAS,UAAoC;EACzC,IAAI,QAAQ,YAAY,SAAS,QAAQ,YAAY,KAAA,GAAW;GAC5D,MAAM,UAAU,WAAW;GAC3B,IAAI,CAAC,SAAS,OAAO,QAAQ,OAAO,IAAI,qBAAqB,CAAC;GAC9D,OAAO,QAAQ,QAAQ,OAAO;EAClC;EACA,IAAI,iBAAiB,OAAO;EAE5B,aAAa;GAAE,QAAQ;GAAc,gBAAgB,cAAc;EAAE;EACrE,kBAAkB,QAAQ,IAAI,CAAC,QAAQ,QAAQ,OAAO,GAAG,QAAQ,QAAQ,OAAO,CAAC,CAAC,CAAC,CAC9E,MAAM,CAAC,YAAY,gBAAgB;GAChC,MAAM,WAAW,qBAAqB;IAClC,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU,WAAW,CAAC,EAAE,WAAW,KAAK;GAC5C,CAAC;GACD,YAAY,QAAQ;GACpB,OAAO;EACX,CAAC,CAAC,CACD,OAAO,UAAU;GACd,aAAa;IAAE,QAAQ;IAAS,QAAQ,cAAc;IAAG;GAAM;GAC/D,MAAM;EACV,CAAC,CAAC,CACD,cAAc;GACX,kBAAkB,KAAA;EACtB,CAAC;EAEL,OAAO;CACX;CAEA,SAAS,QAAyC;EAC9C,MAAM,UAAU,WAAW;EAC3B,IAAI,SAAS,OAAO,QAAQ,QAAQ,OAAO;EAC3C,IAAI,iBAAiB,OAAO,gBAAgB,YAAY,WAAW,KAAK,IAAI;EAC5E,OAAO,QAAQ,QAAQ,IAAI;CAC/B;CAEA,SAAS,cAAwC;EAC7C,MAAM,UAAU,WAAW;EAC3B,IAAI,SAAS,OAAO,QAAQ,QAAQ,OAAO;EAC3C,OAAO,mBAAmB,QAAQ;CACtC;CAEA,OAAO;EACH,GAAG;EACH,aAAa;EACb;EACA;EACA;EACA;CACJ;AACJ"}
@@ -1,7 +1,7 @@
1
1
  import { CatalogConversionError, CatalogLookupError, CatalogNotReadyError, CatalogValidationFailedError } from "./types.js";
2
2
  import { UNKNOWN_ASSET_LABEL, UNKNOWN_LEDGER_ASSET_ID, isUnknownLedgerAsset, isUnknownZipperAsset, unknownLedgerAsset, unknownZipperAsset } from "./unknown-asset.js";
3
- import { createCatalogSnapshotReader } from "./readers.js";
4
3
  import { PAIR_STATUSES } from "../shared/catalog-config.js";
4
+ import { createCatalogSnapshotReader } from "./readers.js";
5
5
  import { buildCatalogSnapshot } from "./snapshot.js";
6
6
  import { createPolyesterCatalog } from "./client-catalog.js";
7
7
  import { patchZipperCatalogSupply } from "./zipper-supply.js";
@@ -1 +1 @@
1
- {"version":3,"file":"readers.d.ts","names":[],"sources":["../../src/catalogs/readers.ts"],"mappings":";;iBAiwBgB,4BAA4B,UAAU,kBAAkB"}
1
+ {"version":3,"file":"readers.d.ts","names":[],"sources":["../../src/catalogs/readers.ts"],"mappings":";;iBAkwBgB,4BAA4B,UAAU,kBAAkB"}
@@ -2,6 +2,7 @@ import { scaledToDecimal, scaledToDisplay, significantDecimalPlaces, tryDecimalT
2
2
  import { CatalogConversionError, CatalogLookupError, CatalogValidationFailedError } from "./types.js";
3
3
  import { indexesFor } from "./indexes.js";
4
4
  import { resolveLedgerAssetByLedgerId, resolveZipperAssetByLedgerId } from "./unknown-asset.js";
5
+ import { parseCatalogSnapshot } from "./snapshot-validation.js";
5
6
  function isListed(pair, nowMs) {
6
7
  if (pair.listingAt === null || pair.listingAt > nowMs) return false;
7
8
  if (pair.status === "disabled") return false;
@@ -537,7 +538,8 @@ function createReader(getSnapshot) {
537
538
  return new SnapshotCatalogReader(getSnapshot);
538
539
  }
539
540
  function createCatalogSnapshotReader(snapshot) {
540
- return createReader(() => snapshot);
541
+ const parsed = parseCatalogSnapshot(snapshot);
542
+ return createReader(() => parsed);
541
543
  }
542
544
  //#endregion
543
545
  export { createCatalogSnapshotReader, createReader };
@@ -1 +1 @@
1
- {"version":3,"file":"readers.js","names":[],"sources":["../../src/catalogs/readers.ts"],"sourcesContent":["import type {\n AssetConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport {\n scaledToDecimal,\n scaledToDisplay,\n significantDecimalPlaces,\n tryDecimalToScaled,\n tryNormalizeDecimalInput,\n tryToScaledBigInt,\n type DecimalToScaledFailure,\n type ScaledIntegerLike,\n} from \"./decimal.js\";\nimport { indexesFor } from \"./indexes.js\";\nimport type { EnrichedPairConfig } from \"./market-data-catalog.js\";\nimport {\n resolveLedgerAssetByLedgerId,\n resolveZipperAssetByLedgerId,\n UNKNOWN_LEDGER_ASSET_ID,\n} from \"./unknown-asset.js\";\nimport type { ZipperContractName, ZipperEnrichedAssetConfig } from \"./zipper-catalog.js\";\nimport {\n CatalogConversionError,\n CatalogLookupError,\n CatalogValidationFailedError,\n type AssetCatalogKey,\n type CatalogLookupDomain,\n type CatalogReader,\n type CatalogSnapshot,\n type CatalogValidationError,\n type CatalogValidationResult,\n type ChainCatalogKey,\n type LedgerCatalogReader,\n type MarketCatalogReader,\n type OrdersCatalogReader,\n type PairCatalogKey,\n type ParsedCatalogAmount,\n type SpotOrderConstraints,\n type SpotOrderDecimalInput,\n type ZipperAssetChainRoute,\n type ZipperCatalogReader,\n} from \"./types.js\";\n\n/** Price ticks are always quoted at 6 decimal places. */\nexport const PRICE_SCALE = 6;\n\ntype SnapshotGetter = () => CatalogSnapshot;\n\nfunction isListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n if (pair.listingAt === null || pair.listingAt > nowMs) return false;\n if (pair.status === \"disabled\") return false;\n if (pair.delistingAt !== null && pair.delistingAt < nowMs) return false;\n return true;\n}\n\nfunction isEverListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n return pair.listingAt !== null && pair.listingAt < nowMs;\n}\n\nfunction requireFound<T>(\n domain: CatalogLookupDomain,\n lookup: string,\n value: string | number,\n found: T | null,\n): T {\n if (found === null) throw new CatalogLookupError(domain, lookup, value);\n return found;\n}\n\ntype ResolvedKey<TByName extends string, TById extends string> =\n | { lookup: TByName; value: string }\n | { lookup: TById; value: number };\n\nfunction resolvePairKey(key: PairCatalogKey): ResolvedKey<\"symbol\", \"symbolId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"symbolId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"symbolId\", value: key.symbolId };\n}\n\nfunction resolveAssetKey(key: AssetCatalogKey): ResolvedKey<\"symbol\", \"ledgerId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"ledgerId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"ledgerId\", value: key.ledgerId };\n}\n\nfunction resolveChainKey(key: ChainCatalogKey): ResolvedKey<\"chainCode\", \"chainId\"> {\n if (typeof key === \"string\") return { lookup: \"chainCode\", value: key };\n if (typeof key === \"number\") return { lookup: \"chainId\", value: key };\n if (\"code\" in key) return { lookup: \"chainCode\", value: key.code };\n return { lookup: \"chainId\", value: key.chainId };\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/** Shared conversion core used by the market and ledger readers. */\nclass DecimalConverter {\n constructor(\n readonly field: string,\n readonly scale: number,\n readonly displayDecimals: number,\n ) {}\n\n parse(decimal: string): ParsedCatalogAmount {\n const result = tryDecimalToScaled(decimal, this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return {\n scaledValue: result.scaled.toString(),\n decimal: scaledToDecimal(result.scaled, this.scale),\n display: scaledToDisplay(result.scaled, this.scale, this.displayDecimals),\n scale: this.scale,\n };\n }\n\n normalizeInput(raw: string): string {\n const normalized = tryNormalizeDecimalInput(raw, this.scale);\n if (normalized === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a non-negative decimal number: ${raw}`,\n );\n }\n return normalized;\n }\n\n toDecimalString(scaled: ScaledIntegerLike): string {\n return scaledToDecimal(this.toBigInt(scaled), this.scale);\n }\n\n toDisplayString(scaled: ScaledIntegerLike): string {\n return scaledToDisplay(this.toBigInt(scaled), this.scale, this.displayDecimals);\n }\n\n formatDecimal(decimal: string): string {\n const result = tryDecimalToScaled(decimal.trim(), this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return scaledToDisplay(result.scaled, this.scale, this.displayDecimals);\n }\n\n private toBigInt(scaled: ScaledIntegerLike): bigint {\n const value = tryToScaledBigInt(scaled);\n if (value === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a raw scaled integer: ${String(scaled)}`,\n );\n }\n return value;\n }\n}\n\nfunction priceConverter(pair: EnrichedPairConfig): DecimalConverter {\n const tickDecimals = significantDecimalPlaces(pair.tickSize);\n const displayDecimals = tickDecimals > 0 ? tickDecimals : PRICE_SCALE;\n return new DecimalConverter(\"price\", PRICE_SCALE, displayDecimals);\n}\n\nfunction quantityConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quantity\",\n pair.baseAsset.quantityScale,\n pair.baseAsset.quantityDisplayDecimals,\n );\n}\n\nfunction quoteAmountConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quoteAmount\",\n pair.quoteAsset.quantityScale,\n pair.quoteAsset.quantityDisplayDecimals,\n );\n}\n\nfunction ledgerAmountConverter(asset: AssetConfig): DecimalConverter {\n return new DecimalConverter(\"amount\", asset.quantityScale, asset.quantityDisplayDecimals);\n}\n\nclass MarketReader implements MarketCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listAssets(): readonly AssetConfig[] {\n return this.getSnapshot().market.assets;\n }\n\n getAsset(asset: AssetCatalogKey): AssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"market\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"market\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return resolveLedgerAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[] {\n const pairs = this.getSnapshot().market.pairs;\n if (!filter) return pairs;\n const nowMs = filter.atMs ?? Date.now();\n return pairs.filter((pair) => {\n if (filter.listed !== undefined && isListed(pair, nowMs) !== filter.listed)\n return false;\n if (filter.everListed !== undefined && isEverListed(pair, nowMs) !== filter.everListed)\n return false;\n return true;\n });\n }\n\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null {\n const key = resolvePairKey(pair);\n return key.lookup === \"symbol\"\n ? this.getPairBySymbol(key.value)\n : this.getPairBySymbolId(key.value);\n }\n\n requirePair(pair: PairCatalogKey): EnrichedPairConfig {\n const key = resolvePairKey(pair);\n return requireFound(\"market\", key.lookup, key.value, this.getPair(pair));\n }\n\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbol.get(pairSymbol) ?? null;\n }\n\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig {\n return requireFound(\"market\", \"symbol\", pairSymbol, this.getPairBySymbol(pairSymbol));\n }\n\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbolId.get(pairSymbolId) ?? null;\n }\n\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig {\n return requireFound(\n \"market\",\n \"symbolId\",\n pairSymbolId,\n this.getPairBySymbolId(pairSymbolId),\n );\n }\n\n getSymbolIdByPairSymbol(pairSymbol: string): number | null {\n return this.getPairBySymbol(pairSymbol)?.symbolId ?? null;\n }\n\n requireSymbolIdByPairSymbol(pairSymbol: string): number {\n return this.requirePairBySymbol(pairSymbol).symbolId;\n }\n\n getPairSymbolBySymbolId(pairSymbolId: number): string | null {\n return this.getPairBySymbolId(pairSymbolId)?.symbol ?? null;\n }\n\n requirePairSymbolBySymbolId(pairSymbolId: number): string {\n return this.requirePairBySymbolId(pairSymbolId).symbol;\n }\n\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return priceConverter(this.requirePair(pair)).parse(price);\n }\n\n normalizePriceInput(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).normalizeInput(price);\n }\n\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDecimalString(priceTicks);\n }\n\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDisplayString(priceTicks);\n }\n\n formatPrice(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).formatDecimal(price);\n }\n\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quantityConverter(this.requirePair(pair)).parse(quantity);\n }\n\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).normalizeInput(quantity);\n }\n\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDecimalString(quantityScaled);\n }\n\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDisplayString(quantityScaled);\n }\n\n formatQuantity(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).formatDecimal(quantity);\n }\n\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quoteAmountConverter(this.requirePair(pair)).parse(amount);\n }\n\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).normalizeInput(amount);\n }\n\n quoteAmountScaledToDecimalString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDecimalString(amountScaled);\n }\n\n quoteAmountScaledToDisplayString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDisplayString(amountScaled);\n }\n\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).formatDecimal(amount);\n }\n}\n\nclass LedgerReader implements LedgerCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.market.getAssetByLedgerId(ledgerAssetId);\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return this.market.getAssetBySymbol(assetSymbol);\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"ledger\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getLedgerIdBySymbol(assetSymbol: string): number | null {\n return this.getAssetBySymbol(assetSymbol)?.ledgerId ?? null;\n }\n\n requireLedgerIdBySymbol(assetSymbol: string): number {\n return this.requireAssetBySymbol(assetSymbol).ledgerId;\n }\n\n requireSymbolByLedgerId(ledgerAssetId: number): string {\n return this.requireAssetByLedgerId(ledgerAssetId).symbol;\n }\n\n isKnownAssetId(ledgerAssetId: number): boolean {\n if (!Number.isInteger(ledgerAssetId) || ledgerAssetId <= 0) return false;\n if (ledgerAssetId === UNKNOWN_LEDGER_ASSET_ID) return false;\n return this.market.lookupAssetByLedgerId(ledgerAssetId) !== null;\n }\n\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount {\n return ledgerAmountConverter(this.requireAsset(asset)).parse(amount);\n }\n\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).normalizeInput(amount);\n }\n\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDecimalString(amountScaled);\n }\n\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDisplayString(amountScaled);\n }\n\n formatAmount(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).formatDecimal(amount);\n }\n\n private requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n const found =\n key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n return requireFound(\"ledger\", key.lookup, key.value, found);\n }\n}\n\nclass OrdersReader implements OrdersCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints {\n const config = this.market.requirePair(pair);\n return {\n symbolId: config.symbolId,\n symbol: config.symbol,\n status: config.status,\n tickSize: config.tickSize,\n stepSize: config.stepSize,\n minQtyBase: config.minQtyBase,\n minNotionalQuote: config.minNotionalQuote,\n priceScale: PRICE_SCALE,\n quantityScale: config.baseAsset.quantityScale,\n quoteAmountScale: config.quoteAsset.quantityScale,\n priceDisplayDecimals: priceConverter(config).displayDecimals,\n quantityDisplayDecimals: config.baseAsset.quantityDisplayDecimals,\n quoteAmountDisplayDecimals: config.quoteAsset.quantityDisplayDecimals,\n };\n }\n\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult {\n const pair = this.market.requirePair(input.pair);\n const errors: CatalogValidationError[] = [];\n\n const quantityScaled = this.validateQuantity(pair, input.quantity, errors);\n const priceTicks =\n input.price === undefined ? null : this.validatePrice(pair, input.price, errors);\n\n if (quantityScaled !== null && priceTicks !== null) {\n this.validateMinNotional(pair, quantityScaled, priceTicks, errors);\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void {\n const result = this.validateSpotOrderDecimalInput(input);\n if (!result.valid) throw new CatalogValidationFailedError(result.errors);\n }\n\n private validateQuantity(\n pair: EnrichedPairConfig,\n quantity: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const scale = pair.baseAsset.quantityScale;\n const parsed = tryDecimalToScaled(quantity, scale);\n if (!parsed.ok) {\n errors.push({\n field: \"quantity\",\n rule: \"parse\",\n message: conversionFailureMessage(\"quantity\", quantity, parsed.failure),\n actual: quantity,\n });\n return null;\n }\n\n const step = this.requireConstraintScaled(pair.stepSize, scale, \"stepSize\");\n if (step > 0n && parsed.scaled % step !== 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"stepSize\",\n message: `quantity must be a multiple of the pair step size ${pair.stepSize}`,\n expected: pair.stepSize,\n actual: quantity,\n });\n }\n\n const minQty = this.requireConstraintScaled(pair.minQtyBase, scale, \"minQtyBase\");\n if (parsed.scaled < minQty || parsed.scaled === 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"minQty\",\n message: `quantity is below the pair minimum of ${pair.minQtyBase}`,\n expected: pair.minQtyBase,\n actual: quantity,\n });\n }\n\n return parsed.scaled;\n }\n\n private validatePrice(\n pair: EnrichedPairConfig,\n price: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const parsed = tryDecimalToScaled(price, PRICE_SCALE);\n if (!parsed.ok) {\n errors.push({\n field: \"price\",\n rule: \"parse\",\n message: conversionFailureMessage(\"price\", price, parsed.failure),\n actual: price,\n });\n return null;\n }\n\n const tick = this.requireConstraintScaled(pair.tickSize, PRICE_SCALE, \"tickSize\");\n if (tick > 0n && parsed.scaled % tick !== 0n) {\n errors.push({\n field: \"price\",\n rule: \"tickSize\",\n message: `price must be a multiple of the pair tick size ${pair.tickSize}`,\n expected: pair.tickSize,\n actual: price,\n });\n }\n\n return parsed.scaled;\n }\n\n private validateMinNotional(\n pair: EnrichedPairConfig,\n quantityScaled: bigint,\n priceTicks: bigint,\n errors: CatalogValidationError[],\n ): void {\n const notionalScale = pair.baseAsset.quantityScale + PRICE_SCALE;\n const minNotional = this.requireConstraintScaled(\n pair.minNotionalQuote,\n notionalScale,\n \"minNotionalQuote\",\n );\n const notional = quantityScaled * priceTicks;\n if (notional < minNotional) {\n errors.push({\n field: \"notional\",\n rule: \"minNotional\",\n message: `order notional is below the pair minimum of ${pair.minNotionalQuote}`,\n expected: pair.minNotionalQuote,\n actual: scaledToDecimal(notional, notionalScale),\n });\n }\n }\n\n /** Pair constraint strings come from the catalog itself, so failures are data bugs. */\n private requireConstraintScaled(decimal: string, scale: number, field: string): bigint {\n const result = tryDecimalToScaled(decimal, scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, decimal, result.failure),\n );\n }\n return result.scaled;\n }\n}\n\nclass ZipperReader implements ZipperCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listChains(): readonly ZipperChainConfig[] {\n return this.getSnapshot().zipper.chains;\n }\n\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null {\n const key = resolveChainKey(chain);\n return key.lookup === \"chainCode\"\n ? this.getChainByCode(key.value)\n : this.getChainById(key.value);\n }\n\n requireChain(chain: ChainCatalogKey): ZipperChainConfig {\n const key = resolveChainKey(chain);\n return requireFound(\"zipper\", key.lookup, key.value, this.getChain(chain));\n }\n\n getChainByCode(chainCode: string): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainByCode.get(chainCode) ?? null;\n }\n\n requireChainByCode(chainCode: string): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainCode\", chainCode, this.getChainByCode(chainCode));\n }\n\n getChainById(chainId: number): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainById.get(chainId) ?? null;\n }\n\n requireChainById(chainId: number): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainId\", chainId, this.getChainById(chainId));\n }\n\n getChainIdByCode(chainCode: string): number | null {\n return this.getChainByCode(chainCode)?.chainId ?? null;\n }\n\n requireChainIdByCode(chainCode: string): number {\n return this.requireChainByCode(chainCode).chainId;\n }\n\n listAssets(): readonly ZipperEnrichedAssetConfig[] {\n return this.getSnapshot().zipper.assets;\n }\n\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"zipper\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return resolveZipperAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByUAssetId.get(uAssetId) ?? null;\n }\n\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"uAssetId\", uAssetId, this.getAssetByUAssetId(uAssetId));\n }\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null {\n const zipperAsset = this.getAsset(asset);\n const zipperChain = this.getChain(chain);\n if (!zipperAsset || !zipperChain) return null;\n const route = zipperAsset.chains.find(\n (candidate) => candidate.chainId === zipperChain.chainId,\n );\n return route ? { asset: zipperAsset, chain: route } : null;\n }\n\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute {\n const route = this.getAssetChain(asset, chain);\n if (!route) {\n throw new CatalogLookupError(\n \"zipper\",\n \"assetChain\",\n `${formatKey(resolveAssetKey(asset))}:${formatKey(resolveChainKey(chain))}`,\n );\n }\n return route;\n }\n\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null {\n return indexesFor(this.getSnapshot()).zipperRouteByZippedAssetId.get(zippedAssetId) ?? null;\n }\n\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute {\n return requireFound(\n \"zipper\",\n \"zippedAssetId\",\n zippedAssetId,\n this.getAssetChainByZippedAssetId(zippedAssetId),\n );\n }\n\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null {\n return this.getAssetChain(asset, chain)?.chain.zippedAssetId ?? null;\n }\n\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number {\n return this.requireAssetChain(asset, chain).chain.zippedAssetId;\n }\n\n listContracts(): readonly ZipperChainContractConfig[] {\n return this.getSnapshot().zipper.contracts;\n }\n\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return this.getContractByName(contractName);\n }\n\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig {\n return this.requireContractByName(contractName);\n }\n\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return indexesFor(this.getSnapshot()).zipperContractByName.get(contractName) ?? null;\n }\n\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig {\n return requireFound(\n \"zipper\",\n \"contractName\",\n contractName,\n this.getContractByName(contractName),\n );\n }\n}\n\nfunction formatKey(key: { lookup: string; value: string | number }): string {\n return String(key.value);\n}\n\nclass SnapshotCatalogReader implements CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n readonly snapshot: () => CatalogSnapshot;\n\n constructor(getSnapshot: SnapshotGetter) {\n const market = new MarketReader(getSnapshot);\n this.market = market;\n this.ledger = new LedgerReader(market);\n this.orders = new OrdersReader(market);\n this.zipper = new ZipperReader(getSnapshot);\n this.snapshot = () => getSnapshot();\n }\n}\n\nexport function createReader(getSnapshot: () => CatalogSnapshot): CatalogReader {\n return new SnapshotCatalogReader(getSnapshot);\n}\n\nexport function createCatalogSnapshotReader(snapshot: CatalogSnapshot): CatalogReader {\n return createReader(() => snapshot);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"readers.js","names":[],"sources":["../../src/catalogs/readers.ts"],"sourcesContent":["import type {\n AssetConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport {\n scaledToDecimal,\n scaledToDisplay,\n significantDecimalPlaces,\n tryDecimalToScaled,\n tryNormalizeDecimalInput,\n tryToScaledBigInt,\n type DecimalToScaledFailure,\n type ScaledIntegerLike,\n} from \"./decimal.js\";\nimport { indexesFor } from \"./indexes.js\";\nimport type { EnrichedPairConfig } from \"./market-data-catalog.js\";\nimport {\n resolveLedgerAssetByLedgerId,\n resolveZipperAssetByLedgerId,\n UNKNOWN_LEDGER_ASSET_ID,\n} from \"./unknown-asset.js\";\nimport type { ZipperContractName, ZipperEnrichedAssetConfig } from \"./zipper-catalog.js\";\nimport {\n CatalogConversionError,\n CatalogLookupError,\n CatalogValidationFailedError,\n type AssetCatalogKey,\n type CatalogLookupDomain,\n type CatalogReader,\n type CatalogSnapshot,\n type CatalogValidationError,\n type CatalogValidationResult,\n type ChainCatalogKey,\n type LedgerCatalogReader,\n type MarketCatalogReader,\n type OrdersCatalogReader,\n type PairCatalogKey,\n type ParsedCatalogAmount,\n type SpotOrderConstraints,\n type SpotOrderDecimalInput,\n type ZipperAssetChainRoute,\n type ZipperCatalogReader,\n} from \"./types.js\";\nimport { parseCatalogSnapshot } from \"./snapshot-validation.js\";\n\n/** Price ticks are always quoted at 6 decimal places. */\nexport const PRICE_SCALE = 6;\n\ntype SnapshotGetter = () => CatalogSnapshot;\n\nfunction isListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n if (pair.listingAt === null || pair.listingAt > nowMs) return false;\n if (pair.status === \"disabled\") return false;\n if (pair.delistingAt !== null && pair.delistingAt < nowMs) return false;\n return true;\n}\n\nfunction isEverListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n return pair.listingAt !== null && pair.listingAt < nowMs;\n}\n\nfunction requireFound<T>(\n domain: CatalogLookupDomain,\n lookup: string,\n value: string | number,\n found: T | null,\n): T {\n if (found === null) throw new CatalogLookupError(domain, lookup, value);\n return found;\n}\n\ntype ResolvedKey<TByName extends string, TById extends string> =\n | { lookup: TByName; value: string }\n | { lookup: TById; value: number };\n\nfunction resolvePairKey(key: PairCatalogKey): ResolvedKey<\"symbol\", \"symbolId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"symbolId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"symbolId\", value: key.symbolId };\n}\n\nfunction resolveAssetKey(key: AssetCatalogKey): ResolvedKey<\"symbol\", \"ledgerId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"ledgerId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"ledgerId\", value: key.ledgerId };\n}\n\nfunction resolveChainKey(key: ChainCatalogKey): ResolvedKey<\"chainCode\", \"chainId\"> {\n if (typeof key === \"string\") return { lookup: \"chainCode\", value: key };\n if (typeof key === \"number\") return { lookup: \"chainId\", value: key };\n if (\"code\" in key) return { lookup: \"chainCode\", value: key.code };\n return { lookup: \"chainId\", value: key.chainId };\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/** Shared conversion core used by the market and ledger readers. */\nclass DecimalConverter {\n constructor(\n readonly field: string,\n readonly scale: number,\n readonly displayDecimals: number,\n ) {}\n\n parse(decimal: string): ParsedCatalogAmount {\n const result = tryDecimalToScaled(decimal, this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return {\n scaledValue: result.scaled.toString(),\n decimal: scaledToDecimal(result.scaled, this.scale),\n display: scaledToDisplay(result.scaled, this.scale, this.displayDecimals),\n scale: this.scale,\n };\n }\n\n normalizeInput(raw: string): string {\n const normalized = tryNormalizeDecimalInput(raw, this.scale);\n if (normalized === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a non-negative decimal number: ${raw}`,\n );\n }\n return normalized;\n }\n\n toDecimalString(scaled: ScaledIntegerLike): string {\n return scaledToDecimal(this.toBigInt(scaled), this.scale);\n }\n\n toDisplayString(scaled: ScaledIntegerLike): string {\n return scaledToDisplay(this.toBigInt(scaled), this.scale, this.displayDecimals);\n }\n\n formatDecimal(decimal: string): string {\n const result = tryDecimalToScaled(decimal.trim(), this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return scaledToDisplay(result.scaled, this.scale, this.displayDecimals);\n }\n\n private toBigInt(scaled: ScaledIntegerLike): bigint {\n const value = tryToScaledBigInt(scaled);\n if (value === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a raw scaled integer: ${String(scaled)}`,\n );\n }\n return value;\n }\n}\n\nfunction priceConverter(pair: EnrichedPairConfig): DecimalConverter {\n const tickDecimals = significantDecimalPlaces(pair.tickSize);\n const displayDecimals = tickDecimals > 0 ? tickDecimals : PRICE_SCALE;\n return new DecimalConverter(\"price\", PRICE_SCALE, displayDecimals);\n}\n\nfunction quantityConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quantity\",\n pair.baseAsset.quantityScale,\n pair.baseAsset.quantityDisplayDecimals,\n );\n}\n\nfunction quoteAmountConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quoteAmount\",\n pair.quoteAsset.quantityScale,\n pair.quoteAsset.quantityDisplayDecimals,\n );\n}\n\nfunction ledgerAmountConverter(asset: AssetConfig): DecimalConverter {\n return new DecimalConverter(\"amount\", asset.quantityScale, asset.quantityDisplayDecimals);\n}\n\nclass MarketReader implements MarketCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listAssets(): readonly AssetConfig[] {\n return this.getSnapshot().market.assets;\n }\n\n getAsset(asset: AssetCatalogKey): AssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"market\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"market\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return resolveLedgerAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[] {\n const pairs = this.getSnapshot().market.pairs;\n if (!filter) return pairs;\n const nowMs = filter.atMs ?? Date.now();\n return pairs.filter((pair) => {\n if (filter.listed !== undefined && isListed(pair, nowMs) !== filter.listed)\n return false;\n if (filter.everListed !== undefined && isEverListed(pair, nowMs) !== filter.everListed)\n return false;\n return true;\n });\n }\n\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null {\n const key = resolvePairKey(pair);\n return key.lookup === \"symbol\"\n ? this.getPairBySymbol(key.value)\n : this.getPairBySymbolId(key.value);\n }\n\n requirePair(pair: PairCatalogKey): EnrichedPairConfig {\n const key = resolvePairKey(pair);\n return requireFound(\"market\", key.lookup, key.value, this.getPair(pair));\n }\n\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbol.get(pairSymbol) ?? null;\n }\n\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig {\n return requireFound(\"market\", \"symbol\", pairSymbol, this.getPairBySymbol(pairSymbol));\n }\n\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbolId.get(pairSymbolId) ?? null;\n }\n\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig {\n return requireFound(\n \"market\",\n \"symbolId\",\n pairSymbolId,\n this.getPairBySymbolId(pairSymbolId),\n );\n }\n\n getSymbolIdByPairSymbol(pairSymbol: string): number | null {\n return this.getPairBySymbol(pairSymbol)?.symbolId ?? null;\n }\n\n requireSymbolIdByPairSymbol(pairSymbol: string): number {\n return this.requirePairBySymbol(pairSymbol).symbolId;\n }\n\n getPairSymbolBySymbolId(pairSymbolId: number): string | null {\n return this.getPairBySymbolId(pairSymbolId)?.symbol ?? null;\n }\n\n requirePairSymbolBySymbolId(pairSymbolId: number): string {\n return this.requirePairBySymbolId(pairSymbolId).symbol;\n }\n\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return priceConverter(this.requirePair(pair)).parse(price);\n }\n\n normalizePriceInput(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).normalizeInput(price);\n }\n\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDecimalString(priceTicks);\n }\n\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDisplayString(priceTicks);\n }\n\n formatPrice(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).formatDecimal(price);\n }\n\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quantityConverter(this.requirePair(pair)).parse(quantity);\n }\n\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).normalizeInput(quantity);\n }\n\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDecimalString(quantityScaled);\n }\n\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDisplayString(quantityScaled);\n }\n\n formatQuantity(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).formatDecimal(quantity);\n }\n\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quoteAmountConverter(this.requirePair(pair)).parse(amount);\n }\n\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).normalizeInput(amount);\n }\n\n quoteAmountScaledToDecimalString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDecimalString(amountScaled);\n }\n\n quoteAmountScaledToDisplayString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDisplayString(amountScaled);\n }\n\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).formatDecimal(amount);\n }\n}\n\nclass LedgerReader implements LedgerCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.market.getAssetByLedgerId(ledgerAssetId);\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return this.market.getAssetBySymbol(assetSymbol);\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"ledger\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getLedgerIdBySymbol(assetSymbol: string): number | null {\n return this.getAssetBySymbol(assetSymbol)?.ledgerId ?? null;\n }\n\n requireLedgerIdBySymbol(assetSymbol: string): number {\n return this.requireAssetBySymbol(assetSymbol).ledgerId;\n }\n\n requireSymbolByLedgerId(ledgerAssetId: number): string {\n return this.requireAssetByLedgerId(ledgerAssetId).symbol;\n }\n\n isKnownAssetId(ledgerAssetId: number): boolean {\n if (!Number.isInteger(ledgerAssetId) || ledgerAssetId <= 0) return false;\n if (ledgerAssetId === UNKNOWN_LEDGER_ASSET_ID) return false;\n return this.market.lookupAssetByLedgerId(ledgerAssetId) !== null;\n }\n\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount {\n return ledgerAmountConverter(this.requireAsset(asset)).parse(amount);\n }\n\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).normalizeInput(amount);\n }\n\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDecimalString(amountScaled);\n }\n\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDisplayString(amountScaled);\n }\n\n formatAmount(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).formatDecimal(amount);\n }\n\n private requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n const found =\n key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n return requireFound(\"ledger\", key.lookup, key.value, found);\n }\n}\n\nclass OrdersReader implements OrdersCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints {\n const config = this.market.requirePair(pair);\n return {\n symbolId: config.symbolId,\n symbol: config.symbol,\n status: config.status,\n tickSize: config.tickSize,\n stepSize: config.stepSize,\n minQtyBase: config.minQtyBase,\n minNotionalQuote: config.minNotionalQuote,\n priceScale: PRICE_SCALE,\n quantityScale: config.baseAsset.quantityScale,\n quoteAmountScale: config.quoteAsset.quantityScale,\n priceDisplayDecimals: priceConverter(config).displayDecimals,\n quantityDisplayDecimals: config.baseAsset.quantityDisplayDecimals,\n quoteAmountDisplayDecimals: config.quoteAsset.quantityDisplayDecimals,\n };\n }\n\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult {\n const pair = this.market.requirePair(input.pair);\n const errors: CatalogValidationError[] = [];\n\n const quantityScaled = this.validateQuantity(pair, input.quantity, errors);\n const priceTicks =\n input.price === undefined ? null : this.validatePrice(pair, input.price, errors);\n\n if (quantityScaled !== null && priceTicks !== null) {\n this.validateMinNotional(pair, quantityScaled, priceTicks, errors);\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void {\n const result = this.validateSpotOrderDecimalInput(input);\n if (!result.valid) throw new CatalogValidationFailedError(result.errors);\n }\n\n private validateQuantity(\n pair: EnrichedPairConfig,\n quantity: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const scale = pair.baseAsset.quantityScale;\n const parsed = tryDecimalToScaled(quantity, scale);\n if (!parsed.ok) {\n errors.push({\n field: \"quantity\",\n rule: \"parse\",\n message: conversionFailureMessage(\"quantity\", quantity, parsed.failure),\n actual: quantity,\n });\n return null;\n }\n\n const step = this.requireConstraintScaled(pair.stepSize, scale, \"stepSize\");\n if (step > 0n && parsed.scaled % step !== 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"stepSize\",\n message: `quantity must be a multiple of the pair step size ${pair.stepSize}`,\n expected: pair.stepSize,\n actual: quantity,\n });\n }\n\n const minQty = this.requireConstraintScaled(pair.minQtyBase, scale, \"minQtyBase\");\n if (parsed.scaled < minQty || parsed.scaled === 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"minQty\",\n message: `quantity is below the pair minimum of ${pair.minQtyBase}`,\n expected: pair.minQtyBase,\n actual: quantity,\n });\n }\n\n return parsed.scaled;\n }\n\n private validatePrice(\n pair: EnrichedPairConfig,\n price: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const parsed = tryDecimalToScaled(price, PRICE_SCALE);\n if (!parsed.ok) {\n errors.push({\n field: \"price\",\n rule: \"parse\",\n message: conversionFailureMessage(\"price\", price, parsed.failure),\n actual: price,\n });\n return null;\n }\n\n const tick = this.requireConstraintScaled(pair.tickSize, PRICE_SCALE, \"tickSize\");\n if (tick > 0n && parsed.scaled % tick !== 0n) {\n errors.push({\n field: \"price\",\n rule: \"tickSize\",\n message: `price must be a multiple of the pair tick size ${pair.tickSize}`,\n expected: pair.tickSize,\n actual: price,\n });\n }\n\n return parsed.scaled;\n }\n\n private validateMinNotional(\n pair: EnrichedPairConfig,\n quantityScaled: bigint,\n priceTicks: bigint,\n errors: CatalogValidationError[],\n ): void {\n const notionalScale = pair.baseAsset.quantityScale + PRICE_SCALE;\n const minNotional = this.requireConstraintScaled(\n pair.minNotionalQuote,\n notionalScale,\n \"minNotionalQuote\",\n );\n const notional = quantityScaled * priceTicks;\n if (notional < minNotional) {\n errors.push({\n field: \"notional\",\n rule: \"minNotional\",\n message: `order notional is below the pair minimum of ${pair.minNotionalQuote}`,\n expected: pair.minNotionalQuote,\n actual: scaledToDecimal(notional, notionalScale),\n });\n }\n }\n\n /** Pair constraint strings come from the catalog itself, so failures are data bugs. */\n private requireConstraintScaled(decimal: string, scale: number, field: string): bigint {\n const result = tryDecimalToScaled(decimal, scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, decimal, result.failure),\n );\n }\n return result.scaled;\n }\n}\n\nclass ZipperReader implements ZipperCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listChains(): readonly ZipperChainConfig[] {\n return this.getSnapshot().zipper.chains;\n }\n\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null {\n const key = resolveChainKey(chain);\n return key.lookup === \"chainCode\"\n ? this.getChainByCode(key.value)\n : this.getChainById(key.value);\n }\n\n requireChain(chain: ChainCatalogKey): ZipperChainConfig {\n const key = resolveChainKey(chain);\n return requireFound(\"zipper\", key.lookup, key.value, this.getChain(chain));\n }\n\n getChainByCode(chainCode: string): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainByCode.get(chainCode) ?? null;\n }\n\n requireChainByCode(chainCode: string): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainCode\", chainCode, this.getChainByCode(chainCode));\n }\n\n getChainById(chainId: number): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainById.get(chainId) ?? null;\n }\n\n requireChainById(chainId: number): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainId\", chainId, this.getChainById(chainId));\n }\n\n getChainIdByCode(chainCode: string): number | null {\n return this.getChainByCode(chainCode)?.chainId ?? null;\n }\n\n requireChainIdByCode(chainCode: string): number {\n return this.requireChainByCode(chainCode).chainId;\n }\n\n listAssets(): readonly ZipperEnrichedAssetConfig[] {\n return this.getSnapshot().zipper.assets;\n }\n\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"zipper\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return resolveZipperAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByUAssetId.get(uAssetId) ?? null;\n }\n\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"uAssetId\", uAssetId, this.getAssetByUAssetId(uAssetId));\n }\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null {\n const zipperAsset = this.getAsset(asset);\n const zipperChain = this.getChain(chain);\n if (!zipperAsset || !zipperChain) return null;\n const route = zipperAsset.chains.find(\n (candidate) => candidate.chainId === zipperChain.chainId,\n );\n return route ? { asset: zipperAsset, chain: route } : null;\n }\n\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute {\n const route = this.getAssetChain(asset, chain);\n if (!route) {\n throw new CatalogLookupError(\n \"zipper\",\n \"assetChain\",\n `${formatKey(resolveAssetKey(asset))}:${formatKey(resolveChainKey(chain))}`,\n );\n }\n return route;\n }\n\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null {\n return indexesFor(this.getSnapshot()).zipperRouteByZippedAssetId.get(zippedAssetId) ?? null;\n }\n\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute {\n return requireFound(\n \"zipper\",\n \"zippedAssetId\",\n zippedAssetId,\n this.getAssetChainByZippedAssetId(zippedAssetId),\n );\n }\n\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null {\n return this.getAssetChain(asset, chain)?.chain.zippedAssetId ?? null;\n }\n\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number {\n return this.requireAssetChain(asset, chain).chain.zippedAssetId;\n }\n\n listContracts(): readonly ZipperChainContractConfig[] {\n return this.getSnapshot().zipper.contracts;\n }\n\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return this.getContractByName(contractName);\n }\n\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig {\n return this.requireContractByName(contractName);\n }\n\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return indexesFor(this.getSnapshot()).zipperContractByName.get(contractName) ?? null;\n }\n\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig {\n return requireFound(\n \"zipper\",\n \"contractName\",\n contractName,\n this.getContractByName(contractName),\n );\n }\n}\n\nfunction formatKey(key: { lookup: string; value: string | number }): string {\n return String(key.value);\n}\n\nclass SnapshotCatalogReader implements CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n readonly snapshot: () => CatalogSnapshot;\n\n constructor(getSnapshot: SnapshotGetter) {\n const market = new MarketReader(getSnapshot);\n this.market = market;\n this.ledger = new LedgerReader(market);\n this.orders = new OrdersReader(market);\n this.zipper = new ZipperReader(getSnapshot);\n this.snapshot = () => getSnapshot();\n }\n}\n\nexport function createReader(getSnapshot: () => CatalogSnapshot): CatalogReader {\n return new SnapshotCatalogReader(getSnapshot);\n}\n\nexport function createCatalogSnapshotReader(snapshot: CatalogSnapshot): CatalogReader {\n const parsed = parseCatalogSnapshot(snapshot);\n return createReader(() => parsed);\n}\n"],"mappings":"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"}