@solana/rpc-subscriptions-spec 2.0.0-experimental.fb655dd → 2.0.0-experimental.feaeef2

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.
@@ -20,7 +20,7 @@ function makeProxy(rpcConfig) {
20
20
  const notificationName = p.toString();
21
21
  const createRpcSubscription = Reflect.get(target, notificationName, receiver);
22
22
  if (p.toString().endsWith("Notifications") === false && !createRpcSubscription) {
23
- throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
23
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
24
24
  notificationName
25
25
  });
26
26
  }
@@ -82,7 +82,7 @@ function createPendingRpcSubscription(rpcConfig, { params, subscribeMethodName,
82
82
  }
83
83
  }
84
84
  if (subscriptionId == null) {
85
- throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);
85
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);
86
86
  }
87
87
  return {
88
88
  async *[Symbol.asyncIterator]() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
1
+ import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
2
2
  import { createRpcMessage, RpcError } from '@solana/rpc-spec-types';
3
3
 
4
4
  // src/rpc-subscriptions.ts
@@ -18,7 +18,7 @@ function makeProxy(rpcConfig) {
18
18
  const notificationName = p.toString();
19
19
  const createRpcSubscription = Reflect.get(target, notificationName, receiver);
20
20
  if (p.toString().endsWith("Notifications") === false && !createRpcSubscription) {
21
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
21
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
22
22
  notificationName
23
23
  });
24
24
  }
@@ -80,7 +80,7 @@ function createPendingRpcSubscription(rpcConfig, { params, subscribeMethodName,
80
80
  }
81
81
  }
82
82
  if (subscriptionId == null) {
83
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);
83
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);
84
84
  }
85
85
  return {
86
86
  async *[Symbol.asyncIterator]() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
1
+ import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
2
2
  import { createRpcMessage, RpcError } from '@solana/rpc-spec-types';
3
3
 
4
4
  // src/rpc-subscriptions.ts
@@ -18,7 +18,7 @@ function makeProxy(rpcConfig) {
18
18
  const notificationName = p.toString();
19
19
  const createRpcSubscription = Reflect.get(target, notificationName, receiver);
20
20
  if (p.toString().endsWith("Notifications") === false && !createRpcSubscription) {
21
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
21
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
22
22
  notificationName
23
23
  });
24
24
  }
@@ -80,7 +80,7 @@ function createPendingRpcSubscription(rpcConfig, { params, subscribeMethodName,
80
80
  }
81
81
  }
82
82
  if (subscriptionId == null) {
83
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);
83
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);
84
84
  }
85
85
  return {
86
86
  async *[Symbol.asyncIterator]() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":";AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP;AAAA,EAEI;AAAA,EAGA;AAAA,OAGG;AAiDA,SAAS,sBAIZ,WAC6C;AAC7C,SAAO,UAAU,SAAS;AAC9B;AAEA,SAAS,UACL,WAC6C;AAC7C,SAAO,IAAI,MAAM,UAAU,KAAK;AAAA,IAC5B,iBAAiB;AACb,aAAO;AAAA,IACX;AAAA,IACA,iBAAiB;AACb,aAAO;AAAA,IACX;AAAA,IACA,IAAI,QAAQ,GAAG,UAAU;AACrB,aAAO,YAAa,WAAsB;AACtC,cAAM,mBAAmB,EAAE,SAAS;AACpC,cAAM,wBAAwB,QAAQ,IAAI,QAAQ,kBAAkB,QAAQ;AAC5E,YAAI,EAAE,SAAS,EAAE,SAAS,eAAe,MAAM,SAAS,CAAC,uBAAuB;AAC5E,gBAAM,IAAI,YAAY,qEAAqE;AAAA,YACvF;AAAA,UACJ,CAAC;AAAA,QACL;AACA,cAAM,aAAa,wBACb,sBAAsB,GAAG,SAAS,IAClC;AAAA,UACI,QAAQ;AAAA,UACR,qBAAqB,iBAAiB,QAAQ,kBAAkB,WAAW;AAAA,UAC3E,uBAAuB,iBAAiB,QAAQ,kBAAkB,aAAa;AAAA,QACnF;AACN,eAAO,6BAA6B,WAAW,UAAU;AAAA,MAC7D;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;AAEA,SAAS,wBAAwB,UAAkC,WAA6B;AAC5F,GAAC,YAAY;AACT,QAAI;AAEA,uBAAiB,KAAK;AAAS;AAAA,IACnC,QAAQ;AAAA,IAER,UAAE;AAEE,gBAAU;AAAA,IACd;AAAA,EACJ,GAAG;AACP;AAEA,SAAS,6BAKL,WACA,EAAE,QAAQ,qBAAqB,uBAAuB,oBAAoB,GAC7B;AAC7C,SAAO;AAAA,IACH,MAAM,UAAU,EAAE,YAAY,GAA+D;AACzF,kBAAY,eAAe;AAC3B,UAAI;AACJ,eAAS,gBAAgB;AACrB,YAAI,mBAAmB,QAAW;AAC9B,gBAAM,UAAU,iBAAiB,uBAAuB,CAAC,cAAc,CAAC;AACxE,qBAAW,qCAAqC,OAAO,EAAE,QAAQ,MAAM;AACnE,sCAA0B,MAAM;AAAA,UACpC,CAAC;AAAA,QACL,OAAO;AACH,oCAA0B,MAAM;AAAA,QACpC;AAAA,MACJ;AACA,kBAAY,iBAAiB,SAAS,aAAa;AAInD,YAAM,4BAA4B,IAAI,gBAAgB;AACtD,YAAM,mBAAmB,iBAAiB,qBAAqB,MAAM;AACrE,YAAM,aAAa,MAAM,UAAU,UAAU;AAAA,QACzC,SAAS;AAAA,QACT,QAAQ,0BAA0B;AAAA,MACtC,CAAC;AACD,eAAS,0BAA0B;AAC/B,oBAAY,oBAAoB,SAAS,aAAa;AAAA,MAC1D;AACA,8BAAwB,YAAY,uBAAuB;AAI3D,uBAAiB,WAAW,YAEzB;AACC,YAAI,QAAQ,WAAW,QAAQ,OAAO,iBAAiB,IAAI;AACvD,cAAI,WAAW,SAAS;AACpB,kBAAM,IAAI,SAAS,QAAQ,KAAK;AAAA,UACpC,OAAO;AACH,6BAAiB,QAAQ;AACzB;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AACA,UAAI,kBAAkB,MAAM;AACxB,cAAM,IAAI,YAAY,gEAAgE;AAAA,MAC1F;AAIA,aAAO;AAAA,QACH,QAAQ,OAAO,aAAa,IAAI;AAC5B,2BAAiB,WAAW,YAEzB;AACC,gBAAI,EAAE,YAAY,YAAY,QAAQ,OAAO,iBAAiB,gBAAgB;AAC1E;AAAA,YACJ;AACA,kBAAM,eAAe,QAAQ,OAAO;AACpC,kBAAM,sBACA,oBAAoB,cAAc,mBAAmB,IACrD;AAAA,UACV;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ;;;ACpKO,SAAS,0BACZ,QACgD;AAChD,SAAO,IAAI,MAAM,CAAC,GAAuD;AAAA,IACrE,iBAAiB;AACb,aAAO;AAAA,IACX;AAAA,IACA,iBAAiB;AACb,aAAO;AAAA,IACX;AAAA,IACA,OACO,MACL;AACE,YAAM,CAAC,GAAG,CAAC,IAAI;AACf,YAAM,mBAAmB,EAAE,SAAS;AACpC,aAAO,YACA,WAKgF;AACnF,cAAM,SAAS,QAAQ,wBACjB,QAAQ,sBAAsB,WAAW,gBAAgB,IACzD;AACN,cAAM,sBAAsB,QAAQ,sBAC9B,QAAQ,sBACR,CAAC,gBACG;AACV,cAAM,sBAAsB,QAAQ,uCAC9B,QAAQ,qCAAqC,gBAAgB,IAC7D;AACN,cAAM,wBAAwB,QAAQ,yCAChC,QAAQ,uCAAuC,gBAAgB,IAC/D;AACN,eAAO;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
@@ -20,7 +20,7 @@ function makeProxy(rpcConfig) {
20
20
  const notificationName = p.toString();
21
21
  const createRpcSubscription = Reflect.get(target, notificationName, receiver);
22
22
  if (p.toString().endsWith("Notifications") === false && !createRpcSubscription) {
23
- throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
23
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
24
24
  notificationName
25
25
  });
26
26
  }
@@ -82,7 +82,7 @@ function createPendingRpcSubscription(rpcConfig, { params, subscribeMethodName,
82
82
  }
83
83
  }
84
84
  if (subscriptionId == null) {
85
- throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);
85
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);
86
86
  }
87
87
  return {
88
88
  async *[Symbol.asyncIterator]() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
1
+ import { SolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID } from '@solana/errors';
2
2
  import { createRpcMessage, RpcError } from '@solana/rpc-spec-types';
3
3
 
4
4
  // src/rpc-subscriptions.ts
@@ -18,7 +18,7 @@ function makeProxy(rpcConfig) {
18
18
  const notificationName = p.toString();
19
19
  const createRpcSubscription = Reflect.get(target, notificationName, receiver);
20
20
  if (p.toString().endsWith("Notifications") === false && !createRpcSubscription) {
21
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
21
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {
22
22
  notificationName
23
23
  });
24
24
  }
@@ -80,7 +80,7 @@ function createPendingRpcSubscription(rpcConfig, { params, subscribeMethodName,
80
80
  }
81
81
  }
82
82
  if (subscriptionId == null) {
83
- throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);
83
+ throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);
84
84
  }
85
85
  return {
86
86
  async *[Symbol.asyncIterator]() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS_EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport {\n Callable,\n createRpcMessage,\n Flatten,\n OverloadImplementations,\n RpcError,\n RpcResponse,\n UnionToIntersection,\n} from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsApi } from './rpc-subscriptions-api';\nimport {\n PendingRpcSubscriptionsRequest,\n RpcSubscribeOptions,\n RpcSubscriptionsRequest,\n} from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<\n TRpcMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: TRpcSubscriptionsTransport;\n}>;\n\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\ntype RpcNotification<TNotification> = Readonly<{\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\nexport function createSubscriptionRpc<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return makeProxy(rpcConfig);\n}\n\nfunction makeProxy<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport extends RpcSubscriptionsTransport>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscription = Reflect.get(target, notificationName, receiver);\n if (p.toString().endsWith('Notifications') === false && !createRpcSubscription) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_REQUEST, {\n notificationName,\n });\n }\n const newRequest = createRpcSubscription\n ? createRpcSubscription(...rawParams)\n : {\n params: rawParams,\n subscribeMethodName: notificationName.replace(/Notifications$/, 'Subscribe'),\n unsubscribeMethodName: notificationName.replace(/Notifications$/, 'Unsubscribe'),\n };\n return createPendingRpcSubscription(rpcConfig, newRequest);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nfunction createPendingRpcSubscription<\n TRpcSubscriptionsApiMethods,\n TRpcSubscriptionsTransport extends RpcSubscriptionsTransport,\n TNotification,\n>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods, TRpcSubscriptionsTransport>,\n { params, subscribeMethodName, unsubscribeMethodName, responseTransformer }: RpcSubscriptionsRequest<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n abortSignal.throwIfAborted();\n let subscriptionId: number | undefined;\n function handleCleanup() {\n if (subscriptionId !== undefined) {\n const payload = createRpcMessage(unsubscribeMethodName, [subscriptionId]);\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload).finally(() => {\n connectionAbortController.abort();\n });\n } else {\n connectionAbortController.abort();\n }\n }\n abortSignal.addEventListener('abort', handleCleanup);\n /**\n * STEP 1: Send the subscribe message.\n */\n const connectionAbortController = new AbortController();\n const subscribeMessage = createRpcMessage(subscribeMethodName, params);\n const connection = await rpcConfig.transport({\n payload: subscribeMessage,\n signal: connectionAbortController.signal,\n });\n function handleConnectionCleanup() {\n abortSignal.removeEventListener('abort', handleCleanup);\n }\n registerIterableCleanup(connection, handleConnectionCleanup);\n /**\n * STEP 2: Wait for the acknowledgement from the server with the subscription id.\n */\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if ('id' in message && message.id === subscribeMessage.id) {\n if ('error' in message) {\n throw new RpcError(message.error);\n } else {\n subscriptionId = message.result as RpcSubscriptionId;\n break;\n }\n }\n }\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n /**\n * STEP 3: Return an iterable that yields notifications for this subscription id.\n */\n return {\n async *[Symbol.asyncIterator]() {\n for await (const message of connection as AsyncIterable<\n RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>\n >) {\n if (!('params' in message) || message.params.subscription !== subscriptionId) {\n continue;\n }\n const notification = message.params.result as TNotification;\n yield responseTransformer\n ? responseTransformer(notification, subscribeMethodName)\n : notification;\n }\n },\n };\n },\n };\n}\n","import { Callable } from '@solana/rpc-spec-types';\n\nimport { RpcSubscriptionsRequest } from './rpc-subscriptions-request';\n\nexport type RpcSubscriptionsApiConfig = Readonly<{\n parametersTransformer?: <T extends unknown[]>(params: T, notificationName: string) => unknown[];\n responseTransformer?: <T>(response: unknown, notificationName: string) => T;\n subscribeNotificationNameTransformer?: (notificationName: string) => string;\n unsubscribeNotificationNameTransformer?: (notificationName: string) => string;\n}>;\n\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsRequest<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config?: RpcSubscriptionsApiConfig,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const notificationName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...rawParams: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsRequest<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const params = config?.parametersTransformer\n ? config?.parametersTransformer(rawParams, notificationName)\n : rawParams;\n const responseTransformer = config?.responseTransformer\n ? config?.responseTransformer<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>>\n : (rawResponse: unknown) =>\n rawResponse as ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>;\n const subscribeMethodName = config?.subscribeNotificationNameTransformer\n ? config?.subscribeNotificationNameTransformer(notificationName)\n : notificationName;\n const unsubscribeMethodName = config?.unsubscribeNotificationNameTransformer\n ? config?.unsubscribeNotificationNameTransformer(notificationName)\n : notificationName;\n return {\n params,\n responseTransformer,\n subscribeMethodName,\n unsubscribeMethodName,\n };\n };\n },\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/rpc-subscriptions-spec",
3
- "version": "2.0.0-experimental.fb655dd",
3
+ "version": "2.0.0-experimental.feaeef2",
4
4
  "description": "A generic implementation of JSON RPC Subscriptions using proxies",
5
5
  "exports": {
6
6
  "browser": {
@@ -46,8 +46,8 @@
46
46
  "maintained node versions"
47
47
  ],
48
48
  "dependencies": {
49
- "@solana/errors": "2.0.0-experimental.fb655dd",
50
- "@solana/rpc-spec-types": "2.0.0-experimental.fb655dd"
49
+ "@solana/errors": "2.0.0-experimental.feaeef2",
50
+ "@solana/rpc-spec-types": "2.0.0-experimental.feaeef2"
51
51
  },
52
52
  "bundlewatch": {
53
53
  "defaultCompression": "gzip",