@polyester/sdk 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/catalogs/readers.d.ts.map +1 -1
- package/dist/catalogs/readers.js +22 -0
- package/dist/catalogs/readers.js.map +1 -1
- package/dist/core-client.d.ts.map +1 -1
- package/dist/core-client.js +49 -15
- package/dist/core-client.js.map +1 -1
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js +3 -2
- package/dist/environment.js.map +1 -1
- package/dist/realtime/client.d.ts.map +1 -1
- package/dist/realtime/client.js +13 -5
- package/dist/realtime/client.js.map +1 -1
- package/dist/realtime/ready-gated-subscription.js +68 -0
- package/dist/realtime/ready-gated-subscription.js.map +1 -0
- package/dist/realtime/snapshot-then-stream.js +19 -10
- package/dist/realtime/snapshot-then-stream.js.map +1 -1
- package/dist/server-client.d.ts +3 -1
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +9 -4
- package/dist/server-client.js.map +1 -1
- package/dist/services/auth/session.d.ts.map +1 -1
- package/dist/services/auth/session.js +4 -1
- package/dist/services/auth/session.js.map +1 -1
- package/dist/services/auth/token-storage.js +2 -2
- package/dist/services/auth/token-storage.js.map +1 -1
- package/dist/services/balances/balances.js +5 -8
- package/dist/services/balances/balances.js.map +1 -1
- package/dist/services/candles/candles.js +9 -12
- package/dist/services/candles/candles.js.map +1 -1
- package/dist/services/heatmap/heatmap.js +5 -8
- package/dist/services/heatmap/heatmap.js.map +1 -1
- package/dist/services/lifecycle/lifecycle.schemas.d.ts +42 -42
- package/dist/services/lifecycle/lifecycle.schemas.js +1 -1
- package/dist/services/market-data/market-data.d.ts.map +1 -1
- package/dist/services/market-data/market-data.js +5 -8
- package/dist/services/market-data/market-data.js.map +1 -1
- package/dist/services/market-data/market-data.schemas.d.ts.map +1 -1
- package/dist/services/market-data/market-data.schemas.js +3 -2
- package/dist/services/market-data/market-data.schemas.js.map +1 -1
- package/dist/services/market-overview/market-overview.d.ts.map +1 -1
- package/dist/services/market-overview/market-overview.js +7 -13
- package/dist/services/market-overview/market-overview.js.map +1 -1
- package/dist/services/orderbook/orderbook.d.ts.map +1 -1
- package/dist/services/orderbook/orderbook.js +18 -11
- package/dist/services/orderbook/orderbook.js.map +1 -1
- package/dist/services/orders/orders-batch.schemas.d.ts +6 -22
- package/dist/services/orders/orders-batch.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-batch.schemas.js +23 -20
- package/dist/services/orders/orders-batch.schemas.js.map +1 -1
- package/dist/services/orders/orders-identifiers.schemas.js +6 -1
- package/dist/services/orders/orders-identifiers.schemas.js.map +1 -1
- package/dist/services/orders/orders-input.schemas.d.ts +11 -43
- package/dist/services/orders/orders-input.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-input.schemas.js +10 -11
- package/dist/services/orders/orders-input.schemas.js.map +1 -1
- package/dist/services/orders/orders-modify.schemas.d.ts +1 -25
- package/dist/services/orders/orders-modify.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-modify.schemas.js +2 -4
- package/dist/services/orders/orders-modify.schemas.js.map +1 -1
- package/dist/services/orders/orders-output.schemas.d.ts +165 -27
- package/dist/services/orders/orders-output.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-output.schemas.js +1 -1
- package/dist/services/orders/orders-output.schemas.js.map +1 -1
- package/dist/services/orders/orders-risk.schemas.d.ts +1 -20
- package/dist/services/orders/orders-risk.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-risk.schemas.js +52 -15
- package/dist/services/orders/orders-risk.schemas.js.map +1 -1
- package/dist/services/orders/orders.codecs.js +12 -1
- package/dist/services/orders/orders.codecs.js.map +1 -1
- package/dist/services/orders/orders.d.ts.map +1 -1
- package/dist/services/orders/orders.js +6 -9
- package/dist/services/orders/orders.js.map +1 -1
- package/dist/services/subaccounts/subaccounts.schemas.d.ts +3 -3
- package/dist/services/trades/trades.js +5 -8
- package/dist/services/trades/trades.js.map +1 -1
- package/dist/services/trailing-oneof-inputs.js +3 -3
- package/dist/services/trailing-oneof-inputs.js.map +1 -1
- package/dist/services/transfers/index.d.ts +2 -2
- package/dist/services/transfers/transfers.d.ts +1 -2
- package/dist/services/transfers/transfers.d.ts.map +1 -1
- package/dist/services/transfers/transfers.js +8 -13
- package/dist/services/transfers/transfers.js.map +1 -1
- package/dist/services/transfers/transfers.schemas.d.ts +5 -5
- package/dist/services/transfers/transfers.schemas.d.ts.map +1 -1
- package/dist/services/transfers/transfers.schemas.js +31 -33
- package/dist/services/transfers/transfers.schemas.js.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.d.ts +21 -8
- package/dist/services/triggers/trigger-input.schemas.d.ts.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.js +20 -43
- package/dist/services/triggers/trigger-input.schemas.js.map +1 -1
- package/dist/services/triggers/triggers-output.schemas.d.ts +13 -13
- package/dist/services/triggers/triggers-output.schemas.js +5 -5
- package/dist/services/triggers/triggers-output.schemas.js.map +1 -1
- package/dist/services/triggers/triggers.d.ts.map +1 -1
- package/dist/services/triggers/triggers.js +10 -23
- package/dist/services/triggers/triggers.js.map +1 -1
- package/dist/services/zipper/zipper.d.ts.map +1 -1
- package/dist/services/zipper/zipper.js +15 -18
- package/dist/services/zipper/zipper.js.map +1 -1
- package/dist/shared/connect-error-mapping.d.ts.map +1 -1
- package/dist/shared/connect-error-mapping.js +9 -2
- package/dist/shared/connect-error-mapping.js.map +1 -1
- package/dist/shared/decimal-surface.d.ts.map +1 -1
- package/dist/shared/decimal-surface.js +40 -17
- package/dist/shared/decimal-surface.js.map +1 -1
- package/dist/shared/transports.d.ts.map +1 -1
- package/dist/shared/transports.js +33 -11
- package/dist/shared/transports.js.map +1 -1
- package/dist/utils/base58-id.js +1 -2
- package/dist/utils/base58-id.js.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +4 -3
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/event-emitter.d.ts.map +1 -1
- package/dist/utils/event-emitter.js +6 -3
- package/dist/utils/event-emitter.js.map +1 -1
- package/dist/utils/jwt.d.ts.map +1 -1
- package/dist/utils/jwt.js +2 -2
- package/dist/utils/jwt.js.map +1 -1
- package/dist/utils/numbers.js +20 -3
- package/dist/utils/numbers.js.map +1 -1
- package/dist/utils/timestamp.js +27 -16
- package/dist/utils/timestamp.js.map +1 -1
- package/dist/utils/u128.js +6 -18
- package/dist/utils/u128.js.map +1 -1
- package/package.json +1 -1
|
@@ -117,7 +117,10 @@ var AuthSessionStore = class {
|
|
|
117
117
|
getEnvironmentBoundToken(tokenStorage) {
|
|
118
118
|
const token = tokenStorage.get();
|
|
119
119
|
if (!token) return null;
|
|
120
|
-
|
|
120
|
+
const session = this.#session.get();
|
|
121
|
+
if (!session) return token;
|
|
122
|
+
if (session.environmentFingerprint !== this.#environmentFingerprint) {
|
|
123
|
+
this.#session.clear();
|
|
121
124
|
tokenStorage.clear();
|
|
122
125
|
return null;
|
|
123
126
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":["#lastRawValue","#lastDecoded","#environmentFingerprint","#session"],"sources":["../../../src/services/auth/session.ts"],"sourcesContent":["import {\n setCookie,\n deleteCookie,\n getCookie,\n getCookieValue,\n shouldSecureCookies,\n type CookieGetter,\n} from \"../../utils/cookies.js\";\nimport {\n POLYESTER_AUTH_TOKEN_COOKIE_NAME,\n POLYESTER_SESSION_COOKIE_NAME,\n POLYESTER_LOGIN_COOKIE_MAX_AGE,\n} from \"./cookie-constants.js\";\nimport { SessionCodec } from \"./session-codec.js\";\nimport type { PolyesterEnvironment } from \"../../environment.js\";\nimport type { AuthTokenStorage, AuthTokenStorageSetOptions } from \"./token-storage.js\";\nimport type {\n ActiveAccountInfo,\n AuthLoginMethod,\n ServerSessionSnapshot,\n SessionData,\n} from \"./session.types.js\";\n\nexport type { ActiveAccountInfo, AuthLoginMethod, ServerSessionSnapshot, SessionData };\n\nexport interface SessionCookieOptions {\n maxAgeSeconds?: number | null;\n}\n\nexport interface CommitLoginSessionParams {\n accessToken: string;\n tokenOptions: AuthTokenStorageSetOptions;\n provider: SessionData[\"provider\"];\n loginMethod: AuthLoginMethod | null;\n primaryWallet: string;\n smartAccount: string;\n accountId: string;\n activeAccount?: ActiveAccountInfo;\n username?: string;\n}\n\nexport interface EnsureSessionParams {\n provider: SessionData[\"provider\"];\n loginMethod: AuthLoginMethod | null;\n primaryWallet: string;\n smartAccount: string;\n accountId: string;\n username?: string;\n}\n\nfunction resolveSessionCookieMaxAge(options?: SessionCookieOptions): number | undefined {\n if (!options) return POLYESTER_LOGIN_COOKIE_MAX_AGE;\n return options.maxAgeSeconds ?? undefined;\n}\n\n/**\n * Reads and writes the browser display-session cookie.\n */\nclass PolyesterSessionManager {\n /**\n * Replaces the current session state.\n */\n set(session: SessionData, options?: SessionCookieOptions): void {\n setCookie({\n name: POLYESTER_SESSION_COOKIE_NAME,\n value: SessionCodec.encode(session),\n options: {\n path: \"/\",\n maxAge: resolveSessionCookieMaxAge(options),\n secure: shouldSecureCookies(),\n sameSite: \"lax\",\n },\n });\n }\n\n // The session is re-read on every authenticated RPC; memoize the decode\n // (JSON.parse + schema validation) on the raw cookie value.\n #lastRawValue: string | null = null;\n #lastDecoded: SessionData | null = null;\n\n /**\n * Returns the current session state, or null when no session is active.\n */\n get(): SessionData | null {\n const value = getCookie(POLYESTER_SESSION_COOKIE_NAME);\n if (!value) {\n this.#lastRawValue = null;\n this.#lastDecoded = null;\n return null;\n }\n if (value === this.#lastRawValue) return this.#lastDecoded;\n\n const session = SessionCodec.decode(value);\n if (!session) {\n this.clear();\n this.#lastRawValue = null;\n this.#lastDecoded = null;\n return null;\n }\n\n this.#lastRawValue = value;\n this.#lastDecoded = session;\n return session;\n }\n\n /**\n * Clears the current session state.\n */\n clear(): void {\n deleteCookie(POLYESTER_SESSION_COOKIE_NAME);\n }\n}\n\nexport const polyesterSession = new PolyesterSessionManager();\n\nexport function emptyServerSessionSnapshot(): ServerSessionSnapshot {\n return {\n environmentFingerprint: null,\n hasDisplaySession: false,\n provider: null,\n loginMethod: null,\n accountAddresses: null,\n activeAccount: null,\n bearerToken: null,\n username: null,\n };\n}\n\n/**\n * Parses bearer authentication and display-only session cookies into a server snapshot.\n */\nexport function parseServerSessionSnapshot(\n cookies: CookieGetter,\n environment: PolyesterEnvironment,\n): ServerSessionSnapshot {\n const sessionValue = getCookieValue(cookies, POLYESTER_SESSION_COOKIE_NAME);\n const bearerToken = getCookieValue(cookies, POLYESTER_AUTH_TOKEN_COOKIE_NAME) ?? null;\n const session = sessionValue ? SessionCodec.decode(sessionValue) : null;\n\n if (!session) {\n return { ...emptyServerSessionSnapshot(), bearerToken };\n }\n\n if (session.environmentFingerprint !== environment.fingerprint) {\n return emptyServerSessionSnapshot();\n }\n\n return {\n environmentFingerprint: session.environmentFingerprint,\n hasDisplaySession: true,\n provider: session.provider,\n loginMethod: session.loginMethod,\n accountAddresses: {\n ownerAddress: session.primaryWallet,\n accountAddress: session.smartAccount,\n },\n activeAccount: session.activeAccount ?? null,\n bearerToken,\n username: session.username ?? null,\n };\n}\n\n/**\n * Owns environment-bound auth session transitions for browser clients.\n */\nexport class AuthSessionStore {\n #environmentFingerprint: string;\n #session: PolyesterSessionManager;\n\n constructor({ environmentFingerprint }: { environmentFingerprint: string }) {\n this.#environmentFingerprint = environmentFingerprint;\n this.#session = polyesterSession;\n }\n\n get(): SessionData | null {\n const session = this.#session.get();\n if (!session) return null;\n if (session.environmentFingerprint !== this.#environmentFingerprint) {\n this.#session.clear();\n return null;\n }\n return session;\n }\n\n getEnvironmentBoundToken(tokenStorage: AuthTokenStorage): string | null {\n const token = tokenStorage.get();\n if (!token) return null;\n\n if (!this.get()) {\n tokenStorage.clear();\n return null;\n }\n\n return token;\n }\n\n commitLogin(params: CommitLoginSessionParams, tokenStorage: AuthTokenStorage): void {\n tokenStorage.set(params.accessToken, params.tokenOptions);\n this.#session.set(\n {\n environmentFingerprint: this.#environmentFingerprint,\n provider: params.provider,\n loginMethod: params.loginMethod,\n primaryWallet: params.primaryWallet,\n smartAccount: params.smartAccount,\n activeAccount: {\n accountId: params.activeAccount?.accountId ?? params.accountId,\n isMain: params.activeAccount?.isMain ?? true,\n mainAccountId: params.accountId,\n smartAccountAddress: params.activeAccount?.smartAccountAddress,\n label: params.activeAccount?.label,\n },\n username: params.username,\n },\n { maxAgeSeconds: params.tokenOptions.maxAgeSeconds },\n );\n }\n\n ensureSession(params: EnsureSessionParams, options?: SessionCookieOptions): SessionData {\n const existingSession = this.get();\n if (existingSession) {\n const username = params.username || undefined;\n if (username === undefined || username === existingSession.username) {\n return existingSession;\n }\n\n const session = { ...existingSession, username };\n this.#session.set(session, options);\n return session;\n }\n\n const session: SessionData = {\n environmentFingerprint: this.#environmentFingerprint,\n provider: params.provider,\n loginMethod: params.loginMethod,\n primaryWallet: params.primaryWallet,\n smartAccount: params.smartAccount,\n activeAccount: {\n accountId: params.accountId,\n isMain: true,\n mainAccountId: params.accountId,\n },\n username: params.username,\n };\n this.#session.set(session, options);\n return session;\n }\n\n setUsername(username: string | null, options?: SessionCookieOptions): void {\n const session = this.get();\n if (!session) return;\n\n this.#session.set({ ...session, username: username || undefined }, options);\n }\n\n setActiveAccount(\n activeAccount: Omit<ActiveAccountInfo, \"mainAccountId\">,\n options?: SessionCookieOptions,\n ): void {\n const session = this.get();\n if (!session) return;\n\n const mainAccountId = session.activeAccount?.mainAccountId ?? activeAccount.accountId;\n const smartAccountAddress = activeAccount.isMain\n ? session.smartAccount\n : activeAccount.smartAccountAddress;\n const label = activeAccount.isMain ? undefined : activeAccount.label;\n this.#session.set(\n {\n ...session,\n activeAccount: { ...activeAccount, mainAccountId, smartAccountAddress, label },\n username: session.username,\n },\n options,\n );\n }\n\n clear(): void {\n this.#session.clear();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.js","names":["#lastRawValue","#lastDecoded","#environmentFingerprint","#session"],"sources":["../../../src/services/auth/session.ts"],"sourcesContent":["import {\n setCookie,\n deleteCookie,\n getCookie,\n getCookieValue,\n shouldSecureCookies,\n type CookieGetter,\n} from \"../../utils/cookies.js\";\nimport {\n POLYESTER_AUTH_TOKEN_COOKIE_NAME,\n POLYESTER_SESSION_COOKIE_NAME,\n POLYESTER_LOGIN_COOKIE_MAX_AGE,\n} from \"./cookie-constants.js\";\nimport { SessionCodec } from \"./session-codec.js\";\nimport type { PolyesterEnvironment } from \"../../environment.js\";\nimport type { AuthTokenStorage, AuthTokenStorageSetOptions } from \"./token-storage.js\";\nimport type {\n ActiveAccountInfo,\n AuthLoginMethod,\n ServerSessionSnapshot,\n SessionData,\n} from \"./session.types.js\";\n\nexport type { ActiveAccountInfo, AuthLoginMethod, ServerSessionSnapshot, SessionData };\n\nexport interface SessionCookieOptions {\n maxAgeSeconds?: number | null;\n}\n\nexport interface CommitLoginSessionParams {\n accessToken: string;\n tokenOptions: AuthTokenStorageSetOptions;\n provider: SessionData[\"provider\"];\n loginMethod: AuthLoginMethod | null;\n primaryWallet: string;\n smartAccount: string;\n accountId: string;\n activeAccount?: ActiveAccountInfo;\n username?: string;\n}\n\nexport interface EnsureSessionParams {\n provider: SessionData[\"provider\"];\n loginMethod: AuthLoginMethod | null;\n primaryWallet: string;\n smartAccount: string;\n accountId: string;\n username?: string;\n}\n\nfunction resolveSessionCookieMaxAge(options?: SessionCookieOptions): number | undefined {\n if (!options) return POLYESTER_LOGIN_COOKIE_MAX_AGE;\n return options.maxAgeSeconds ?? undefined;\n}\n\n/**\n * Reads and writes the browser display-session cookie.\n */\nclass PolyesterSessionManager {\n /**\n * Replaces the current session state.\n */\n set(session: SessionData, options?: SessionCookieOptions): void {\n setCookie({\n name: POLYESTER_SESSION_COOKIE_NAME,\n value: SessionCodec.encode(session),\n options: {\n path: \"/\",\n maxAge: resolveSessionCookieMaxAge(options),\n secure: shouldSecureCookies(),\n sameSite: \"lax\",\n },\n });\n }\n\n // The session is re-read on every authenticated RPC; memoize the decode\n // (JSON.parse + schema validation) on the raw cookie value.\n #lastRawValue: string | null = null;\n #lastDecoded: SessionData | null = null;\n\n /**\n * Returns the current session state, or null when no session is active.\n */\n get(): SessionData | null {\n const value = getCookie(POLYESTER_SESSION_COOKIE_NAME);\n if (!value) {\n this.#lastRawValue = null;\n this.#lastDecoded = null;\n return null;\n }\n if (value === this.#lastRawValue) return this.#lastDecoded;\n\n const session = SessionCodec.decode(value);\n if (!session) {\n this.clear();\n this.#lastRawValue = null;\n this.#lastDecoded = null;\n return null;\n }\n\n this.#lastRawValue = value;\n this.#lastDecoded = session;\n return session;\n }\n\n /**\n * Clears the current session state.\n */\n clear(): void {\n deleteCookie(POLYESTER_SESSION_COOKIE_NAME);\n }\n}\n\nexport const polyesterSession = new PolyesterSessionManager();\n\nexport function emptyServerSessionSnapshot(): ServerSessionSnapshot {\n return {\n environmentFingerprint: null,\n hasDisplaySession: false,\n provider: null,\n loginMethod: null,\n accountAddresses: null,\n activeAccount: null,\n bearerToken: null,\n username: null,\n };\n}\n\n/**\n * Parses bearer authentication and display-only session cookies into a server snapshot.\n */\nexport function parseServerSessionSnapshot(\n cookies: CookieGetter,\n environment: PolyesterEnvironment,\n): ServerSessionSnapshot {\n const sessionValue = getCookieValue(cookies, POLYESTER_SESSION_COOKIE_NAME);\n const bearerToken = getCookieValue(cookies, POLYESTER_AUTH_TOKEN_COOKIE_NAME) ?? null;\n const session = sessionValue ? SessionCodec.decode(sessionValue) : null;\n\n if (!session) {\n return { ...emptyServerSessionSnapshot(), bearerToken };\n }\n\n if (session.environmentFingerprint !== environment.fingerprint) {\n return emptyServerSessionSnapshot();\n }\n\n return {\n environmentFingerprint: session.environmentFingerprint,\n hasDisplaySession: true,\n provider: session.provider,\n loginMethod: session.loginMethod,\n accountAddresses: {\n ownerAddress: session.primaryWallet,\n accountAddress: session.smartAccount,\n },\n activeAccount: session.activeAccount ?? null,\n bearerToken,\n username: session.username ?? null,\n };\n}\n\n/**\n * Owns environment-bound auth session transitions for browser clients.\n */\nexport class AuthSessionStore {\n #environmentFingerprint: string;\n #session: PolyesterSessionManager;\n\n constructor({ environmentFingerprint }: { environmentFingerprint: string }) {\n this.#environmentFingerprint = environmentFingerprint;\n this.#session = polyesterSession;\n }\n\n get(): SessionData | null {\n const session = this.#session.get();\n if (!session) return null;\n if (session.environmentFingerprint !== this.#environmentFingerprint) {\n this.#session.clear();\n return null;\n }\n return session;\n }\n\n getEnvironmentBoundToken(tokenStorage: AuthTokenStorage): string | null {\n const token = tokenStorage.get();\n if (!token) return null;\n\n const session = this.#session.get();\n if (!session) return token;\n\n if (session.environmentFingerprint !== this.#environmentFingerprint) {\n this.#session.clear();\n tokenStorage.clear();\n return null;\n }\n\n return token;\n }\n\n commitLogin(params: CommitLoginSessionParams, tokenStorage: AuthTokenStorage): void {\n tokenStorage.set(params.accessToken, params.tokenOptions);\n this.#session.set(\n {\n environmentFingerprint: this.#environmentFingerprint,\n provider: params.provider,\n loginMethod: params.loginMethod,\n primaryWallet: params.primaryWallet,\n smartAccount: params.smartAccount,\n activeAccount: {\n accountId: params.activeAccount?.accountId ?? params.accountId,\n isMain: params.activeAccount?.isMain ?? true,\n mainAccountId: params.accountId,\n smartAccountAddress: params.activeAccount?.smartAccountAddress,\n label: params.activeAccount?.label,\n },\n username: params.username,\n },\n { maxAgeSeconds: params.tokenOptions.maxAgeSeconds },\n );\n }\n\n ensureSession(params: EnsureSessionParams, options?: SessionCookieOptions): SessionData {\n const existingSession = this.get();\n if (existingSession) {\n const username = params.username || undefined;\n if (username === undefined || username === existingSession.username) {\n return existingSession;\n }\n\n const session = { ...existingSession, username };\n this.#session.set(session, options);\n return session;\n }\n\n const session: SessionData = {\n environmentFingerprint: this.#environmentFingerprint,\n provider: params.provider,\n loginMethod: params.loginMethod,\n primaryWallet: params.primaryWallet,\n smartAccount: params.smartAccount,\n activeAccount: {\n accountId: params.accountId,\n isMain: true,\n mainAccountId: params.accountId,\n },\n username: params.username,\n };\n this.#session.set(session, options);\n return session;\n }\n\n setUsername(username: string | null, options?: SessionCookieOptions): void {\n const session = this.get();\n if (!session) return;\n\n this.#session.set({ ...session, username: username || undefined }, options);\n }\n\n setActiveAccount(\n activeAccount: Omit<ActiveAccountInfo, \"mainAccountId\">,\n options?: SessionCookieOptions,\n ): void {\n const session = this.get();\n if (!session) return;\n\n const mainAccountId = session.activeAccount?.mainAccountId ?? activeAccount.accountId;\n const smartAccountAddress = activeAccount.isMain\n ? session.smartAccount\n : activeAccount.smartAccountAddress;\n const label = activeAccount.isMain ? undefined : activeAccount.label;\n this.#session.set(\n {\n ...session,\n activeAccount: { ...activeAccount, mainAccountId, smartAccountAddress, label },\n username: session.username,\n },\n options,\n );\n }\n\n clear(): void {\n this.#session.clear();\n }\n}\n"],"mappings":"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"}
|
|
@@ -11,10 +11,10 @@ function createAuthTokenStorageSetOptions(token) {
|
|
|
11
11
|
expiresAt: null,
|
|
12
12
|
maxAgeSeconds: null
|
|
13
13
|
};
|
|
14
|
-
const nowSeconds =
|
|
14
|
+
const nowSeconds = Date.now() / 1e3;
|
|
15
15
|
return {
|
|
16
16
|
expiresAt: /* @__PURE__ */ new Date(exp * 1e3),
|
|
17
|
-
maxAgeSeconds: Math.max(0, exp - nowSeconds)
|
|
17
|
+
maxAgeSeconds: Math.max(0, Math.floor(exp - nowSeconds))
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-storage.js","names":[],"sources":["../../../src/services/auth/token-storage.ts"],"sourcesContent":["import { CookieManager } from \"../../utils/cookies.js\";\nimport { getJwtExpiration } from \"../../utils/jwt.js\";\nimport { POLYESTER_AUTH_TOKEN_COOKIE_NAME } from \"./cookie-constants.js\";\n\nexport interface AuthTokenStorageSetOptions {\n expiresAt: Date | null;\n maxAgeSeconds: number | null;\n}\n\nexport interface AuthTokenStorage {\n get(): string | null;\n set(token: string, options: AuthTokenStorageSetOptions): void;\n clear(): void;\n}\n\nexport interface CookieAuthTokenStorageOptions {\n cookieName?: string;\n path?: string;\n secure?: boolean;\n sameSite?: \"lax\" | \"strict\" | \"none\";\n}\n\n/**\n * Builds cookie write options for auth token storage.\n */\nexport function createAuthTokenStorageSetOptions(token: string): AuthTokenStorageSetOptions {\n const exp = getJwtExpiration(token);\n if (exp === null) {\n return { expiresAt: null, maxAgeSeconds: null };\n }\n\n const nowSeconds =
|
|
1
|
+
{"version":3,"file":"token-storage.js","names":[],"sources":["../../../src/services/auth/token-storage.ts"],"sourcesContent":["import { CookieManager } from \"../../utils/cookies.js\";\nimport { getJwtExpiration } from \"../../utils/jwt.js\";\nimport { POLYESTER_AUTH_TOKEN_COOKIE_NAME } from \"./cookie-constants.js\";\n\nexport interface AuthTokenStorageSetOptions {\n expiresAt: Date | null;\n maxAgeSeconds: number | null;\n}\n\nexport interface AuthTokenStorage {\n get(): string | null;\n set(token: string, options: AuthTokenStorageSetOptions): void;\n clear(): void;\n}\n\nexport interface CookieAuthTokenStorageOptions {\n cookieName?: string;\n path?: string;\n secure?: boolean;\n sameSite?: \"lax\" | \"strict\" | \"none\";\n}\n\n/**\n * Builds cookie write options for auth token storage.\n */\nexport function createAuthTokenStorageSetOptions(token: string): AuthTokenStorageSetOptions {\n const exp = getJwtExpiration(token);\n if (exp === null) {\n return { expiresAt: null, maxAgeSeconds: null };\n }\n\n const nowSeconds = Date.now() / 1000;\n return {\n expiresAt: new Date(exp * 1000),\n maxAgeSeconds: Math.max(0, Math.floor(exp - nowSeconds)),\n };\n}\n\n/**\n * Creates in-memory auth token storage.\n */\nexport function createMemoryAuthTokenStorage(initialToken?: string | null): AuthTokenStorage {\n let storedToken = initialToken ?? null;\n\n return {\n get: () => storedToken,\n set: (token: string) => {\n storedToken = token;\n },\n clear: () => {\n storedToken = null;\n },\n };\n}\n\n/**\n * Creates cookie-backed auth token storage.\n */\nexport function createCookieAuthTokenStorage(\n options: CookieAuthTokenStorageOptions = {},\n): AuthTokenStorage {\n const cookieName = options.cookieName ?? POLYESTER_AUTH_TOKEN_COOKIE_NAME;\n const path = options.path ?? \"/\";\n const cookie = new CookieManager({ name: cookieName });\n\n return {\n get: () => cookie.get(),\n set: (token: string, setOptions: AuthTokenStorageSetOptions) => {\n cookie.set(token, {\n path,\n secure: options.secure,\n sameSite: options.sameSite,\n maxAge: setOptions.maxAgeSeconds ?? undefined,\n expires: setOptions.expiresAt ?? undefined,\n });\n },\n clear: () => {\n cookie.clear({ path });\n },\n };\n}\n"],"mappings":";;;;;;;AAyBA,SAAgB,iCAAiC,OAA2C;CACxF,MAAM,MAAM,iBAAiB,KAAK;CAClC,IAAI,QAAQ,MACR,OAAO;EAAE,WAAW;EAAM,eAAe;CAAK;CAGlD,MAAM,aAAa,KAAK,IAAI,IAAI;CAChC,OAAO;EACH,2BAAW,IAAI,KAAK,MAAM,GAAI;EAC9B,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,UAAU,CAAC;CAC3D;AACJ;;;;AAKA,SAAgB,6BAA6B,cAAgD;CACzF,IAAI,cAAc,gBAAgB;CAElC,OAAO;EACH,WAAW;EACX,MAAM,UAAkB;GACpB,cAAc;EAClB;EACA,aAAa;GACT,cAAc;EAClB;CACJ;AACJ;;;;AAKA,SAAgB,6BACZ,UAAyC,CAAC,GAC1B;CAChB,MAAM,aAAa,QAAQ,cAAA;CAC3B,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,SAAS,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;CAErD,OAAO;EACH,WAAW,OAAO,IAAI;EACtB,MAAM,OAAe,eAA2C;GAC5D,OAAO,IAAI,OAAO;IACd;IACA,QAAQ,QAAQ;IAChB,UAAU,QAAQ;IAClB,QAAQ,WAAW,iBAAiB,KAAA;IACpC,SAAS,WAAW,aAAa,KAAA;GACrC,CAAC;EACL;EACA,aAAa;GACT,OAAO,MAAM,EAAE,KAAK,CAAC;EACzB;CACJ;AACJ"}
|
|
@@ -3,8 +3,7 @@ import { toConnectCallOptions } from "../../shared/request-options.js";
|
|
|
3
3
|
import { resolveAccountScopedInput } from "../subaccount-resolver.js";
|
|
4
4
|
import { accountScopeToSubaccountId } from "../../shared/account-scope.js";
|
|
5
5
|
import { AssetBalanceSchema, LedgerReadService } from "../../gen/ledger/read/v1/ledger_read_pb.js";
|
|
6
|
-
import {
|
|
7
|
-
import { createReadyGate } from "../../shared/decimal-surface.js";
|
|
6
|
+
import { connectReadyGatedProtoChannel } from "../../realtime/ready-gated-subscription.js";
|
|
8
7
|
import { BalanceHistoryInputSchema, BalancesListInputSchema, EquityHistoryInputSchema, createBalanceHistoryResponseSchema, createEquityHistoryResponseSchema, createLedgerBalanceSchema } from "./balances.schemas.js";
|
|
9
8
|
import { createClient } from "@connectrpc/connect";
|
|
10
9
|
import * as v from "valibot";
|
|
@@ -64,15 +63,13 @@ var BalancesService = class {
|
|
|
64
63
|
*/
|
|
65
64
|
subscribe(input) {
|
|
66
65
|
const channel = `private:ledger:balances:${input.accountId}:proto`;
|
|
67
|
-
|
|
68
|
-
return this.#realtime.connectProtoChannel({
|
|
66
|
+
return connectReadyGatedProtoChannel(this.#realtime, {
|
|
69
67
|
channel,
|
|
70
68
|
schema: AssetBalanceSchema,
|
|
69
|
+
ready: () => this.#scales.ready(),
|
|
71
70
|
onPublication: (data) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
input.onEvent(b);
|
|
75
|
-
});
|
|
71
|
+
const b = parse(this.#ledgerBalanceSchema, data);
|
|
72
|
+
input.onEvent(b);
|
|
76
73
|
},
|
|
77
74
|
onConnected: input.onOpen,
|
|
78
75
|
onDisconnected: input.onClose,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balances.js","names":["#client","Proto.LedgerReadService","#realtime","#resolver","#scales","#ledgerBalanceSchema","#balanceHistoryResponseSchema","#equityHistoryResponseSchema","Proto.AssetBalanceSchema"],"sources":["../../../src/services/balances/balances.ts"],"sourcesContent":["import * as Proto from \"../../gen/ledger/read/v1/ledger_read_pb.js\";\nimport { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport
|
|
1
|
+
{"version":3,"file":"balances.js","names":["#client","Proto.LedgerReadService","#realtime","#resolver","#scales","#ledgerBalanceSchema","#balanceHistoryResponseSchema","#equityHistoryResponseSchema","Proto.AssetBalanceSchema"],"sources":["../../../src/services/balances/balances.ts"],"sourcesContent":["import * as Proto from \"../../gen/ledger/read/v1/ledger_read_pb.js\";\nimport { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport * as v from \"valibot\";\nimport { parse } from \"../../shared/validation.js\";\nimport type { PolyesterRealtime } from \"../../realtime/index.js\";\nimport { connectReadyGatedProtoChannel } from \"../../realtime/ready-gated-subscription.js\";\nimport { type SubaccountResolver, resolveAccountScopedInput } from \"../subaccount-resolver.js\";\nimport {\n toConnectCallOptions,\n type PolyesterRequestOptions,\n} from \"../../shared/request-options.js\";\nimport { accountScopeToSubaccountId, type AccountScopedInput } from \"../../shared/account-scope.js\";\nimport type { BaseSubscribeInput } from \"../../shared/types.js\";\nimport type { SdkScales } from \"../../shared/decimal-surface.js\";\nimport {\n BalanceHistoryInputSchema,\n BalancesListInputSchema,\n EquityHistoryInputSchema,\n createBalanceHistoryResponseSchema,\n createEquityHistoryResponseSchema,\n createLedgerBalanceSchema,\n type LedgerBalance,\n type BalanceHistoryInput,\n type BalanceHistoryResponse,\n type EquityHistoryInput,\n type EquityHistoryResponse,\n} from \"./balances.schemas.js\";\n\ninterface SubscribeBalancesInput extends BaseSubscribeInput<LedgerBalance> {\n accountId: string;\n}\n\n/**\n * Reads and streams ledger balances plus balance and equity history for the authenticated account scope.\n */\nexport class BalancesService {\n #client: Client<typeof Proto.LedgerReadService>;\n #realtime: PolyesterRealtime;\n #resolver?: SubaccountResolver;\n #scales: SdkScales;\n #ledgerBalanceSchema: ReturnType<typeof createLedgerBalanceSchema>;\n #balanceHistoryResponseSchema: ReturnType<typeof createBalanceHistoryResponseSchema>;\n #equityHistoryResponseSchema: ReturnType<typeof createEquityHistoryResponseSchema>;\n\n constructor(\n transport: Transport,\n realtime: PolyesterRealtime,\n resolver: SubaccountResolver | undefined,\n scales: SdkScales,\n ) {\n this.#client = createClient(Proto.LedgerReadService, transport);\n this.#realtime = realtime;\n this.#resolver = resolver;\n this.#scales = scales;\n this.#ledgerBalanceSchema = createLedgerBalanceSchema();\n this.#balanceHistoryResponseSchema = createBalanceHistoryResponseSchema();\n this.#equityHistoryResponseSchema = createEquityHistoryResponseSchema(scales);\n }\n\n /**\n * Returns current asset balances for the resolved root account or subaccount, including trading, funding, reserved, and available amounts as decimal strings.\n */\n async list(\n input: AccountScopedInput = {},\n options?: PolyesterRequestOptions,\n ): Promise<LedgerBalance[]> {\n await this.#scales.ready();\n const resolved = resolveAccountScopedInput(input, this.#resolver);\n const validated = parse(BalancesListInputSchema, resolved);\n const res = await this.#client.getBalances(\n {\n subaccountId: accountScopeToSubaccountId(validated.account),\n },\n toConnectCallOptions(options),\n );\n return parse(v.array(this.#ledgerBalanceSchema), res.balances);\n }\n\n /**\n * Returns columnar balance history for the resolved account scope over a selected range, optionally filtered by a non-negative integer ledger asset ID and account buckets. Ledger 0 or omission includes all assets.\n */\n async getBalanceHistory(\n input: BalanceHistoryInput,\n options?: PolyesterRequestOptions,\n ): Promise<BalanceHistoryResponse> {\n await this.#scales.ready();\n const resolved = resolveAccountScopedInput(input, this.#resolver);\n const validated = parse(BalanceHistoryInputSchema, resolved);\n const res = await this.#client.getBalanceHistory(validated, toConnectCallOptions(options));\n return parse(this.#balanceHistoryResponseSchema, res);\n }\n\n /**\n * Returns equity history series for the resolved account scope over a selected range, optionally grouped by account or asset and filtered by account buckets.\n */\n async getEquityHistory(\n input: EquityHistoryInput,\n options?: PolyesterRequestOptions,\n ): Promise<EquityHistoryResponse> {\n await this.#scales.ready();\n const resolved = resolveAccountScopedInput(input, this.#resolver);\n const validated = parse(EquityHistoryInputSchema, resolved);\n const res = await this.#client.getEquityHistorySeries(\n validated,\n toConnectCallOptions(options),\n );\n return parse(this.#equityHistoryResponseSchema, res);\n }\n\n /**\n * Subscribes to private balance updates on private:ledger:balances:{accountId}:proto and emits every balance record as a decimal-string row. Records for assets unknown to the catalog route a CatalogLookupError to onError.\n */\n subscribe(input: SubscribeBalancesInput): () => void {\n const channel = `private:ledger:balances:${input.accountId}:proto`;\n return connectReadyGatedProtoChannel(this.#realtime, {\n channel,\n schema: Proto.AssetBalanceSchema,\n ready: () => this.#scales.ready(),\n onPublication: (data) => {\n const b = parse(this.#ledgerBalanceSchema, data);\n input.onEvent(b);\n },\n onConnected: input.onOpen,\n onDisconnected: input.onClose,\n onError: input.onError,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAmCA,IAAa,kBAAb,MAA6B;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YACI,WACA,UACA,UACA,QACF;EACE,KAAKA,UAAU,aAAaC,mBAAyB,SAAS;EAC9D,KAAKC,YAAY;EACjB,KAAKC,YAAY;EACjB,KAAKC,UAAU;EACf,KAAKC,uBAAuB,0BAA0B;EACtD,KAAKC,gCAAgC,mCAAmC;EACxE,KAAKC,+BAA+B,kCAAkC,MAAM;CAChF;;;;CAKA,MAAM,KACF,QAA4B,CAAC,GAC7B,SACwB;EACxB,MAAM,KAAKH,QAAQ,MAAM;EACzB,MAAM,WAAW,0BAA0B,OAAO,KAAKD,SAAS;EAChE,MAAM,YAAY,MAAM,yBAAyB,QAAQ;EACzD,MAAM,MAAM,MAAM,KAAKH,QAAQ,YAC3B,EACI,cAAc,2BAA2B,UAAU,OAAO,EAC9D,GACA,qBAAqB,OAAO,CAChC;EACA,OAAO,MAAM,EAAE,MAAM,KAAKK,oBAAoB,GAAG,IAAI,QAAQ;CACjE;;;;CAKA,MAAM,kBACF,OACA,SAC+B;EAC/B,MAAM,KAAKD,QAAQ,MAAM;EACzB,MAAM,WAAW,0BAA0B,OAAO,KAAKD,SAAS;EAChE,MAAM,YAAY,MAAM,2BAA2B,QAAQ;EAC3D,MAAM,MAAM,MAAM,KAAKH,QAAQ,kBAAkB,WAAW,qBAAqB,OAAO,CAAC;EACzF,OAAO,MAAM,KAAKM,+BAA+B,GAAG;CACxD;;;;CAKA,MAAM,iBACF,OACA,SAC8B;EAC9B,MAAM,KAAKF,QAAQ,MAAM;EACzB,MAAM,WAAW,0BAA0B,OAAO,KAAKD,SAAS;EAChE,MAAM,YAAY,MAAM,0BAA0B,QAAQ;EAC1D,MAAM,MAAM,MAAM,KAAKH,QAAQ,uBAC3B,WACA,qBAAqB,OAAO,CAChC;EACA,OAAO,MAAM,KAAKO,8BAA8B,GAAG;CACvD;;;;CAKA,UAAU,OAA2C;EACjD,MAAM,UAAU,2BAA2B,MAAM,UAAU;EAC3D,OAAO,8BAA8B,KAAKL,WAAW;GACjD;GACA,QAAQM;GACR,aAAa,KAAKJ,QAAQ,MAAM;GAChC,gBAAgB,SAAS;IACrB,MAAM,IAAI,MAAM,KAAKC,sBAAsB,IAAI;IAC/C,MAAM,QAAQ,CAAC;GACnB;GACA,aAAa,MAAM;GACnB,gBAAgB,MAAM;GACtB,SAAS,MAAM;EACnB,CAAC;CACL;AACJ"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { parse } from "../../shared/validation.js";
|
|
2
2
|
import { toConnectCallOptions } from "../../shared/request-options.js";
|
|
3
|
-
import { publicationHandlerErrorContext } from "../../shared/subscription-errors.js";
|
|
4
3
|
import { CandlePointSchema, MarketDataService } from "../../gen/marketdata/v1/marketdata_pb.js";
|
|
5
|
-
import {
|
|
4
|
+
import { connectReadyGatedProtoChannel } from "../../realtime/ready-gated-subscription.js";
|
|
6
5
|
import { TimeframeCodec } from "./candles.codecs.js";
|
|
7
6
|
import { CandlePointSchema as CandlePointSchema$1, ListCandlesInputSchema, TimeframeSchema, createCandleColumnarIntSchema, createCandleColumnarSchema, createCandleRowIntSchema, createCandleRowSchema } from "./candles.schemas.js";
|
|
8
7
|
import { createClient } from "@connectrpc/connect";
|
|
@@ -82,20 +81,18 @@ var CandlesService = class {
|
|
|
82
81
|
});
|
|
83
82
|
const protoTimeframe = TimeframeCodec.inputToProto[params.timeframe];
|
|
84
83
|
const channel = `public:spot:market:candles:${params.timeframe}:${params.symbolId}:proto`;
|
|
85
|
-
|
|
86
|
-
return this.#realtime.connectProtoChannel({
|
|
84
|
+
return connectReadyGatedProtoChannel(this.#realtime, {
|
|
87
85
|
channel,
|
|
88
86
|
schema: CandlePointSchema,
|
|
87
|
+
ready: () => this.#scales.ready(),
|
|
89
88
|
onPublication: (data) => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
timeframe: protoTimeframe
|
|
96
|
-
});
|
|
97
|
-
input.onEvent(candle);
|
|
89
|
+
const point = parse(CandlePointSchema$1, data);
|
|
90
|
+
const candle = parse(schema, {
|
|
91
|
+
...point,
|
|
92
|
+
symbolId: params.symbolId,
|
|
93
|
+
timeframe: protoTimeframe
|
|
98
94
|
});
|
|
95
|
+
input.onEvent(candle);
|
|
99
96
|
},
|
|
100
97
|
onConnected: input.onOpen,
|
|
101
98
|
onDisconnected: input.onClose,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candles.js","names":["#client","Proto.MarketDataService","#realtime","#scales","#rowSchema","#rowIntSchema","#columnarSchema","#columnarIntSchema","CandlePointSchema","#subscribeWithSchema","Proto.CandlePointSchema"],"sources":["../../../src/services/candles/candles.ts"],"sourcesContent":["import { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport
|
|
1
|
+
{"version":3,"file":"candles.js","names":["#client","Proto.MarketDataService","#realtime","#scales","#rowSchema","#rowIntSchema","#columnarSchema","#columnarIntSchema","CandlePointSchema","#subscribeWithSchema","Proto.CandlePointSchema"],"sources":["../../../src/services/candles/candles.ts"],"sourcesContent":["import { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport * as Proto from \"../../gen/marketdata/v1/marketdata_pb.js\";\nimport * as v from \"valibot\";\nimport { parse } from \"../../shared/validation.js\";\nimport type { PolyesterRealtime } from \"../../realtime/types.js\";\nimport { connectReadyGatedProtoChannel } from \"../../realtime/ready-gated-subscription.js\";\nimport type { BaseSubscribeInput } from \"../../shared/types.js\";\nimport {\n toConnectCallOptions,\n type PolyesterRequestOptions,\n} from \"../../shared/request-options.js\";\nimport type { SdkScales } from \"../../shared/decimal-surface.js\";\nimport {\n type CandleColumnar,\n createCandleRowSchema,\n createCandleRowIntSchema,\n createCandleColumnarSchema,\n createCandleColumnarIntSchema,\n CandlePointSchema,\n TimeframeSchema,\n type Candle,\n type CandleInt,\n type Timeframe,\n type CandleColumnarInt,\n type GetCandlesInput,\n type GetCandlesColumnsInput,\n ListCandlesInputSchema,\n} from \"./candles.schemas.js\";\nimport { TimeframeCodec } from \"./candles.codecs.js\";\n\ninterface SubscribeCandlesInput extends BaseSubscribeInput<Candle> {\n symbolId: number;\n timeframe: Timeframe;\n}\n\ninterface SubscribeCandlesIntsInput extends BaseSubscribeInput<CandleInt> {\n symbolId: number;\n timeframe: Timeframe;\n}\n\nconst SubscribeCandlesParamsSchema = v.object({\n symbolId: v.pipe(v.number(), v.integer(), v.gtValue(0)),\n timeframe: TimeframeSchema,\n});\n\n/**\n * Reads and streams public spot OHLCV candle data in row and columnar formats.\n */\nexport class CandlesService {\n #client: Client<typeof Proto.MarketDataService>;\n #realtime: PolyesterRealtime;\n #scales: SdkScales;\n #rowSchema: ReturnType<typeof createCandleRowSchema>;\n #rowIntSchema: ReturnType<typeof createCandleRowIntSchema>;\n #columnarSchema: ReturnType<typeof createCandleColumnarSchema>;\n #columnarIntSchema: ReturnType<typeof createCandleColumnarIntSchema>;\n\n constructor(transport: Transport, realtime: PolyesterRealtime, scales: SdkScales) {\n this.#client = createClient(Proto.MarketDataService, transport);\n this.#realtime = realtime;\n this.#scales = scales;\n this.#rowSchema = createCandleRowSchema(scales);\n this.#rowIntSchema = createCandleRowIntSchema(scales);\n this.#columnarSchema = createCandleColumnarSchema(scales);\n this.#columnarIntSchema = createCandleColumnarIntSchema(scales);\n }\n\n /**\n * Returns OHLCV candles for a symbol/timeframe request, mapped into row objects with symbol id and timeframe. The proto response is newest-first and may include incomplete/reference data depending on input flags.\n */\n async list(input: GetCandlesInput, options?: PolyesterRequestOptions): Promise<Candle[]> {\n const validatedInput = parse(ListCandlesInputSchema, input);\n await this.#scales.ready();\n const res = await this.#client.getCandles(validatedInput, toConnectCallOptions(options));\n const candles = parse(v.optional(v.array(CandlePointSchema), []), res.candles);\n return candles.map((c) =>\n parse(this.#rowSchema, {\n ...c,\n symbolId: res.symbolId,\n timeframe: res.timeframe,\n }),\n );\n }\n\n /**\n * Returns candle data in chart-friendly column arrays ordered oldest-first by bucket start time. This preserves decimal-string SDK formatting from the columnar schema.\n */\n async listColumnar(\n input: GetCandlesColumnsInput,\n options?: PolyesterRequestOptions,\n ): Promise<CandleColumnar> {\n const validatedInput = parse(ListCandlesInputSchema, input);\n await this.#scales.ready();\n const res = await this.#client.getCandlesColumns(\n validatedInput,\n toConnectCallOptions(options),\n );\n return parse(this.#columnarSchema, res);\n }\n\n /**\n * Returns the same columnar candle series keyed by numeric bucket-start seconds (`tsSec`) instead of `time`.\n */\n async listColumnarInts(\n input: GetCandlesColumnsInput,\n options?: PolyesterRequestOptions,\n ): Promise<CandleColumnarInt> {\n const validatedInput = parse(ListCandlesInputSchema, input);\n await this.#scales.ready();\n const res = await this.#client.getCandlesColumns(\n validatedInput,\n toConnectCallOptions(options),\n );\n return parse(this.#columnarIntSchema, res);\n }\n\n /**\n * Subscribes to live candle updates on public:spot:market:candles:{timeframe}:{symbolId}:proto and emits row-form candles.\n */\n subscribe(input: SubscribeCandlesInput): () => void {\n return this.#subscribeWithSchema(input, this.#rowSchema);\n }\n\n /**\n * Subscribes to the same live candle channel as subscribe and emits row candles parsed through the row-int schema.\n */\n subscribeInts(input: SubscribeCandlesIntsInput): () => void {\n return this.#subscribeWithSchema(input, this.#rowIntSchema);\n }\n\n #subscribeWithSchema(\n input: SubscribeCandlesInput | SubscribeCandlesIntsInput,\n schema: ReturnType<typeof createCandleRowSchema>,\n ): () => void {\n const params = parse(SubscribeCandlesParamsSchema, {\n symbolId: input.symbolId,\n timeframe: input.timeframe,\n });\n const protoTimeframe = TimeframeCodec.inputToProto[params.timeframe];\n const channel = `public:spot:market:candles:${params.timeframe}:${params.symbolId}:proto`;\n return connectReadyGatedProtoChannel(this.#realtime, {\n channel,\n schema: Proto.CandlePointSchema,\n ready: () => this.#scales.ready(),\n onPublication: (data) => {\n const point = parse(CandlePointSchema, data);\n const candle = parse(schema, {\n ...point,\n symbolId: params.symbolId,\n timeframe: protoTimeframe,\n });\n input.onEvent(candle);\n },\n onConnected: input.onOpen,\n onDisconnected: input.onClose,\n onError: input.onError,\n });\n }\n}\n"],"mappings":";;;;;;;;;AAwCA,MAAM,+BAA+B,EAAE,OAAO;CAC1C,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,QAAQ,CAAC,CAAC;CACtD,WAAW;AACf,CAAC;;;;AAKD,IAAa,iBAAb,MAA4B;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,WAAsB,UAA6B,QAAmB;EAC9E,KAAKA,UAAU,aAAaC,mBAAyB,SAAS;EAC9D,KAAKC,YAAY;EACjB,KAAKC,UAAU;EACf,KAAKC,aAAa,sBAAsB,MAAM;EAC9C,KAAKC,gBAAgB,yBAAyB,MAAM;EACpD,KAAKC,kBAAkB,2BAA2B,MAAM;EACxD,KAAKC,qBAAqB,8BAA8B,MAAM;CAClE;;;;CAKA,MAAM,KAAK,OAAwB,SAAsD;EACrF,MAAM,iBAAiB,MAAM,wBAAwB,KAAK;EAC1D,MAAM,KAAKJ,QAAQ,MAAM;EACzB,MAAM,MAAM,MAAM,KAAKH,QAAQ,WAAW,gBAAgB,qBAAqB,OAAO,CAAC;EAEvF,OADgB,MAAM,EAAE,SAAS,EAAE,MAAMQ,mBAAiB,GAAG,CAAC,CAAC,GAAG,IAAI,OACzD,CAAC,CAAC,KAAK,MAChB,MAAM,KAAKJ,YAAY;GACnB,GAAG;GACH,UAAU,IAAI;GACd,WAAW,IAAI;EACnB,CAAC,CACL;CACJ;;;;CAKA,MAAM,aACF,OACA,SACuB;EACvB,MAAM,iBAAiB,MAAM,wBAAwB,KAAK;EAC1D,MAAM,KAAKD,QAAQ,MAAM;EACzB,MAAM,MAAM,MAAM,KAAKH,QAAQ,kBAC3B,gBACA,qBAAqB,OAAO,CAChC;EACA,OAAO,MAAM,KAAKM,iBAAiB,GAAG;CAC1C;;;;CAKA,MAAM,iBACF,OACA,SAC0B;EAC1B,MAAM,iBAAiB,MAAM,wBAAwB,KAAK;EAC1D,MAAM,KAAKH,QAAQ,MAAM;EACzB,MAAM,MAAM,MAAM,KAAKH,QAAQ,kBAC3B,gBACA,qBAAqB,OAAO,CAChC;EACA,OAAO,MAAM,KAAKO,oBAAoB,GAAG;CAC7C;;;;CAKA,UAAU,OAA0C;EAChD,OAAO,KAAKE,qBAAqB,OAAO,KAAKL,UAAU;CAC3D;;;;CAKA,cAAc,OAA8C;EACxD,OAAO,KAAKK,qBAAqB,OAAO,KAAKJ,aAAa;CAC9D;CAEA,qBACI,OACA,QACU;EACV,MAAM,SAAS,MAAM,8BAA8B;GAC/C,UAAU,MAAM;GAChB,WAAW,MAAM;EACrB,CAAC;EACD,MAAM,iBAAiB,eAAe,aAAa,OAAO;EAC1D,MAAM,UAAU,8BAA8B,OAAO,UAAU,GAAG,OAAO,SAAS;EAClF,OAAO,8BAA8B,KAAKH,WAAW;GACjD;GACA,QAAQQ;GACR,aAAa,KAAKP,QAAQ,MAAM;GAChC,gBAAgB,SAAS;IACrB,MAAM,QAAQ,MAAMK,qBAAmB,IAAI;IAC3C,MAAM,SAAS,MAAM,QAAQ;KACzB,GAAG;KACH,UAAU,OAAO;KACjB,WAAW;IACf,CAAC;IACD,MAAM,QAAQ,MAAM;GACxB;GACA,aAAa,MAAM;GACnB,gBAAgB,MAAM;GACtB,SAAS,MAAM;EACnB,CAAC;CACL;AACJ"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { parse } from "../../shared/validation.js";
|
|
2
2
|
import { toConnectCallOptions } from "../../shared/request-options.js";
|
|
3
|
-
import {
|
|
4
|
-
import { createReadyGate } from "../../shared/decimal-surface.js";
|
|
3
|
+
import { connectReadyGatedProtoChannel } from "../../realtime/ready-gated-subscription.js";
|
|
5
4
|
import { HeatmapLiveBucketSchema, HeatmapService as HeatmapService$1, HeatmapTimeRangeSchema } from "../../gen/marketdata/v1/heatmap_pb.js";
|
|
6
5
|
import { HEATMAP_INTERVAL_VALUES } from "./heatmap.codecs.js";
|
|
7
6
|
import { GetOrderbookHeatmapInputSchema, createOrderbookHeatmapLiveBucketSchema, createOrderbookHeatmapResponseSchema } from "./heatmap.schemas.js";
|
|
@@ -58,15 +57,13 @@ var HeatmapService = class {
|
|
|
58
57
|
interval: input.interval
|
|
59
58
|
});
|
|
60
59
|
const channel = `public:spot:market:heatmap:${params.interval}:${params.symbolId}:proto`;
|
|
61
|
-
|
|
62
|
-
return this.#realtime.connectProtoChannel({
|
|
60
|
+
return connectReadyGatedProtoChannel(this.#realtime, {
|
|
63
61
|
channel,
|
|
64
62
|
schema: HeatmapLiveBucketSchema,
|
|
63
|
+
ready: () => this.#scales.ready(),
|
|
65
64
|
onPublication: (data) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
input.onEvent(bucket);
|
|
69
|
-
});
|
|
65
|
+
const bucket = parse(this.#liveBucketSchema, data);
|
|
66
|
+
input.onEvent(bucket);
|
|
70
67
|
},
|
|
71
68
|
onConnected: input.onOpen,
|
|
72
69
|
onDisconnected: input.onClose,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heatmap.js","names":["#client","HeatmapRpc","#realtime","#scales","#responseSchema","#liveBucketSchema","ProtoHeatmapLiveBucketSchema"],"sources":["../../../src/services/heatmap/heatmap.ts"],"sourcesContent":["import { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport { create } from \"@bufbuild/protobuf\";\nimport {
|
|
1
|
+
{"version":3,"file":"heatmap.js","names":["#client","HeatmapRpc","#realtime","#scales","#responseSchema","#liveBucketSchema","ProtoHeatmapLiveBucketSchema"],"sources":["../../../src/services/heatmap/heatmap.ts"],"sourcesContent":["import { createClient, type Client, type Transport } from \"@connectrpc/connect\";\nimport { create } from \"@bufbuild/protobuf\";\nimport {\n HeatmapService as HeatmapRpc,\n HeatmapLiveBucketSchema as ProtoHeatmapLiveBucketSchema,\n HeatmapTimeRangeSchema,\n} from \"../../gen/marketdata/v1/heatmap_pb.js\";\nimport type { PolyesterRealtime } from \"../../realtime/types.js\";\nimport { connectReadyGatedProtoChannel } from \"../../realtime/ready-gated-subscription.js\";\nimport type { BaseSubscribeInput } from \"../../shared/types.js\";\nimport {\n toConnectCallOptions,\n type PolyesterRequestOptions,\n} from \"../../shared/request-options.js\";\nimport type { SdkScales } from \"../../shared/decimal-surface.js\";\nimport { HEATMAP_INTERVAL_VALUES, type HeatmapIntervalValue } from \"./heatmap.codecs.js\";\nimport * as v from \"valibot\";\nimport { parse } from \"../../shared/validation.js\";\nimport {\n GetOrderbookHeatmapInputSchema,\n createOrderbookHeatmapLiveBucketSchema,\n createOrderbookHeatmapResponseSchema,\n type GetOrderbookHeatmapInput,\n type OrderbookHeatmapLiveBucket,\n type OrderbookHeatmapResponse,\n} from \"./heatmap.schemas.js\";\n\nexport interface OrderbookHeatmapProvider {\n getOrderbookHeatmap(\n input: GetOrderbookHeatmapInput,\n options?: PolyesterRequestOptions,\n ): Promise<OrderbookHeatmapResponse>;\n}\n\ninterface SubscribeHeatmapLiveInput extends BaseSubscribeInput<OrderbookHeatmapLiveBucket> {\n symbolId: number;\n interval: HeatmapIntervalValue;\n}\n\nconst SubscribeHeatmapLiveParamsSchema = v.object({\n symbolId: v.pipe(v.number(), v.integer(), v.gtValue(0)),\n interval: v.picklist(HEATMAP_INTERVAL_VALUES),\n});\n\n/**\n * Reads historical order book heatmap chains and streams live heatmap buckets.\n */\nexport class HeatmapService implements OrderbookHeatmapProvider {\n #client: Client<typeof HeatmapRpc>;\n #realtime: PolyesterRealtime;\n #scales: SdkScales;\n #responseSchema: ReturnType<typeof createOrderbookHeatmapResponseSchema>;\n #liveBucketSchema: ReturnType<typeof createOrderbookHeatmapLiveBucketSchema>;\n\n constructor(transport: Transport, realtime: PolyesterRealtime, scales: SdkScales) {\n this.#client = createClient(HeatmapRpc, transport);\n this.#realtime = realtime;\n this.#scales = scales;\n this.#responseSchema = createOrderbookHeatmapResponseSchema(scales);\n this.#liveBucketSchema = createOrderbookHeatmapLiveBucketSchema(scales);\n }\n\n /**\n * Fetches order book heatmap data for a symbol, interval, depth, and quantity mode using either an absolute time range or cursor pagination. The response includes a keyframe anchor, delta buckets, pagination metadata, and live-anchor fields when available.\n */\n async getOrderbookHeatmap(\n input: GetOrderbookHeatmapInput,\n options?: PolyesterRequestOptions,\n ): Promise<OrderbookHeatmapResponse> {\n const parsed = parse(GetOrderbookHeatmapInputSchema, input);\n await this.#scales.ready();\n\n const res = await this.#client.getOrderbookHeatmap(\n {\n symbolId: parsed.symbolId,\n interval: parsed.interval,\n depth: parsed.depth,\n quantityMode: parsed.quantityMode,\n limit: parsed.limit,\n pageToken: parsed.pageToken,\n timeRange:\n parsed.timeRange != null\n ? create(HeatmapTimeRangeSchema, {\n startTime: parsed.timeRange.startTime,\n endTime: parsed.timeRange.endTime,\n })\n : undefined,\n },\n toConnectCallOptions(options),\n );\n return parse(this.#responseSchema, res);\n }\n\n /**\n * Subscribes to live heatmap buckets on public:spot:market:heatmap:{interval}:{symbolId}:proto and emits parsed bid/ask delta buckets for the selected interval.\n */\n subscribeLive(input: SubscribeHeatmapLiveInput): () => void {\n const params = parse(SubscribeHeatmapLiveParamsSchema, {\n symbolId: input.symbolId,\n interval: input.interval,\n });\n const channel = `public:spot:market:heatmap:${params.interval}:${params.symbolId}:proto`;\n return connectReadyGatedProtoChannel(this.#realtime, {\n channel,\n schema: ProtoHeatmapLiveBucketSchema,\n ready: () => this.#scales.ready(),\n onPublication: (data) => {\n const bucket = parse(this.#liveBucketSchema, data);\n input.onEvent(bucket);\n },\n onConnected: input.onOpen,\n onDisconnected: input.onClose,\n onError: input.onError,\n });\n }\n}\n"],"mappings":";;;;;;;;;;AAuCA,MAAM,mCAAmC,EAAE,OAAO;CAC9C,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,QAAQ,CAAC,CAAC;CACtD,UAAU,EAAE,SAAS,uBAAuB;AAChD,CAAC;;;;AAKD,IAAa,iBAAb,MAAgE;CAC5D;CACA;CACA;CACA;CACA;CAEA,YAAY,WAAsB,UAA6B,QAAmB;EAC9E,KAAKA,UAAU,aAAaC,kBAAY,SAAS;EACjD,KAAKC,YAAY;EACjB,KAAKC,UAAU;EACf,KAAKC,kBAAkB,qCAAqC,MAAM;EAClE,KAAKC,oBAAoB,uCAAuC,MAAM;CAC1E;;;;CAKA,MAAM,oBACF,OACA,SACiC;EACjC,MAAM,SAAS,MAAM,gCAAgC,KAAK;EAC1D,MAAM,KAAKF,QAAQ,MAAM;EAEzB,MAAM,MAAM,MAAM,KAAKH,QAAQ,oBAC3B;GACI,UAAU,OAAO;GACjB,UAAU,OAAO;GACjB,OAAO,OAAO;GACd,cAAc,OAAO;GACrB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,WACI,OAAO,aAAa,OACd,OAAO,wBAAwB;IAC3B,WAAW,OAAO,UAAU;IAC5B,SAAS,OAAO,UAAU;GAC9B,CAAC,IACD,KAAA;EACd,GACA,qBAAqB,OAAO,CAChC;EACA,OAAO,MAAM,KAAKI,iBAAiB,GAAG;CAC1C;;;;CAKA,cAAc,OAA8C;EACxD,MAAM,SAAS,MAAM,kCAAkC;GACnD,UAAU,MAAM;GAChB,UAAU,MAAM;EACpB,CAAC;EACD,MAAM,UAAU,8BAA8B,OAAO,SAAS,GAAG,OAAO,SAAS;EACjF,OAAO,8BAA8B,KAAKF,WAAW;GACjD;GACA,QAAQI;GACR,aAAa,KAAKH,QAAQ,MAAM;GAChC,gBAAgB,SAAS;IACrB,MAAM,SAAS,MAAM,KAAKE,mBAAmB,IAAI;IACjD,MAAM,QAAQ,MAAM;GACxB;GACA,aAAa,MAAM;GACnB,gBAAgB,MAAM;GACtB,SAAS,MAAM;EACnB,CAAC;CACL;AACJ"}
|