@canton-network/core-rpc-transport 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -26,6 +26,43 @@ var WindowTransport = class {
26
26
  constructor(win, options = {}) {
27
27
  this.win = win;
28
28
  this.options = options;
29
+ __publicField(this, "notificationHandlers", /* @__PURE__ */ new Set());
30
+ __publicField(this, "notificationListener");
31
+ /**
32
+ * Subscribe to wallet-pushed JSON-RPC notifications: SPLICE_WALLET_REQUEST
33
+ * frames with no `id` (JSON-RPC 2.0 §4.1). The window listener must be
34
+ * always-on for the transport's lifetime — CIP-103 events arrive between
35
+ * requests, where a per-request listener can never observe them.
36
+ */
37
+ __publicField(this, "onNotification", (handler) => {
38
+ this.notificationHandlers.add(handler);
39
+ if (!this.notificationListener) {
40
+ this.notificationListener = (event) => {
41
+ if (!coreTypes.isSpliceMessageEvent(event) || event.data.type !== coreTypes.WalletEvent.SPLICE_WALLET_REQUEST) {
42
+ return;
43
+ }
44
+ if (event.data.request.id != null) {
45
+ return;
46
+ }
47
+ if (this.options.target && event.data.target !== this.options.target) {
48
+ return;
49
+ }
50
+ const { method, params } = event.data.request;
51
+ this.notificationHandlers.forEach((h) => h(method, params));
52
+ };
53
+ this.win.addEventListener("message", this.notificationListener);
54
+ }
55
+ return () => {
56
+ this.notificationHandlers.delete(handler);
57
+ if (this.notificationHandlers.size === 0 && this.notificationListener) {
58
+ this.win.removeEventListener(
59
+ "message",
60
+ this.notificationListener
61
+ );
62
+ this.notificationListener = void 0;
63
+ }
64
+ };
65
+ });
29
66
  __publicField(this, "submit", async (payload) => {
30
67
  const message = {
31
68
  request: jsonRpcRequest(uuid.v4(), payload),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["uuidv4","WalletEvent","isSpliceMessageEvent","ErrorResponse","ResponsePayload"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { v4 as uuidv4 } from 'uuid'\nimport {\n RequestPayload,\n ResponsePayload,\n JsonRpcRequest,\n SpliceMessage,\n WalletEvent,\n isSpliceMessageEvent,\n SuccessResponse,\n ErrorResponse,\n JsonRpcResponse,\n} from '@canton-network/core-types'\n\nexport const jsonRpcRequest = (\n id: string | number | null,\n payload: RequestPayload\n): JsonRpcRequest => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport const jsonRpcResponse = (\n id: string | number | null,\n payload: ResponsePayload\n): JsonRpcResponse => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport interface RpcTransport {\n submit: (payload: RequestPayload) => Promise<ResponsePayload>\n}\n\nexport type WindowTransportOptions = {\n /**\n * Optional routing key for browser-extension messaging. When set, extensions\n * should ignore messages that do not match their own identifier.\n */\n target?: string | undefined\n}\n\nexport class WindowTransport implements RpcTransport {\n constructor(\n private win: Window,\n private options: WindowTransportOptions = {}\n ) {}\n\n submit = async (payload: RequestPayload) => {\n const message: SpliceMessage = {\n request: jsonRpcRequest(uuidv4(), payload),\n type: WalletEvent.SPLICE_WALLET_REQUEST,\n target: this.options.target,\n }\n\n this.win.postMessage(message, '*')\n\n return new Promise<SuccessResponse>((resolve, reject) => {\n const listener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_RESPONSE ||\n event.data.response.id !== message.request.id\n ) {\n return\n }\n\n window.removeEventListener('message', listener)\n if ('error' in event.data.response) {\n reject(event.data.response.error)\n } else {\n resolve(event.data.response)\n }\n }\n\n window.addEventListener('message', listener)\n })\n }\n\n submitResponse = (id: string | number | null, payload: ResponsePayload) => {\n const message: SpliceMessage = {\n response: jsonRpcResponse(id, payload),\n type: WalletEvent.SPLICE_WALLET_RESPONSE,\n }\n this.win.postMessage(message, '*')\n }\n}\n\nexport class HttpTransport implements RpcTransport {\n constructor(\n private url: URL,\n private accessToken?: string\n ) {}\n\n protected async handleErrorResponse(response: Response): Promise<never> {\n const body = await response.text()\n\n // if the response uses the RPC error format, throw it as is\n try {\n if (ErrorResponse.safeParse(JSON.parse(body)).success) {\n throw JSON.parse(body)\n }\n } catch {\n // ignore JSON parse errors\n }\n\n throw {\n error: {\n code: response.status,\n message: response.statusText,\n data: body,\n },\n }\n }\n\n async submit(payload: RequestPayload): Promise<ResponsePayload> {\n const request: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: payload.method,\n params: payload.params,\n id: uuidv4(),\n }\n\n const header = this.accessToken\n ? { Authorization: `Bearer ${this.accessToken}` }\n : undefined\n\n const response = await fetch(this.url.href, {\n method: 'POST',\n headers: {\n ...header,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n return this.handleErrorResponse(response)\n }\n\n const json = await response.json()\n const parsed = ResponsePayload.parse(json)\n\n if ('error' in parsed) {\n throw parsed\n }\n\n return parsed\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["isSpliceMessageEvent","WalletEvent","uuidv4","ErrorResponse","ResponsePayload"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { v4 as uuidv4 } from 'uuid'\nimport {\n RequestPayload,\n ResponsePayload,\n JsonRpcRequest,\n SpliceMessage,\n WalletEvent,\n isSpliceMessageEvent,\n SuccessResponse,\n ErrorResponse,\n JsonRpcResponse,\n} from '@canton-network/core-types'\n\nexport const jsonRpcRequest = (\n id: string | number | null,\n payload: RequestPayload\n): JsonRpcRequest => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport const jsonRpcResponse = (\n id: string | number | null,\n payload: ResponsePayload\n): JsonRpcResponse => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport interface RpcTransport {\n submit: (payload: RequestPayload) => Promise<ResponsePayload>\n}\n\n/**\n * Handler for wallet-pushed JSON-RPC notifications (CIP-103 events such as\n * txChanged / accountsChanged / statusChanged / connected).\n */\nexport type NotificationHandler = (method: string, params?: unknown) => void\n\nexport type WindowTransportOptions = {\n /**\n * Optional routing key for browser-extension messaging. When set, extensions\n * should ignore messages that do not match their own identifier.\n */\n target?: string | undefined\n}\n\nexport class WindowTransport implements RpcTransport {\n private notificationHandlers = new Set<NotificationHandler>()\n private notificationListener: ((event: MessageEvent) => void) | undefined\n\n constructor(\n private win: Window,\n private options: WindowTransportOptions = {}\n ) {}\n\n /**\n * Subscribe to wallet-pushed JSON-RPC notifications: SPLICE_WALLET_REQUEST\n * frames with no `id` (JSON-RPC 2.0 §4.1). The window listener must be\n * always-on for the transport's lifetime — CIP-103 events arrive between\n * requests, where a per-request listener can never observe them.\n */\n onNotification = (handler: NotificationHandler): (() => void) => {\n this.notificationHandlers.add(handler)\n if (!this.notificationListener) {\n this.notificationListener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_REQUEST\n ) {\n return\n }\n // Requests submitted by this transport always carry a uuid id,\n // so an id-less request can only be a wallet-originated\n // notification — this also keeps the dApp's own outgoing\n // frames (posted to the same window) out of the event path.\n if (event.data.request.id != null) {\n return\n }\n // Same gating as extension detection: a transport constructed\n // from an announced provider's routing key only accepts frames\n // stamped with that key, so multi-wallet pages do not\n // cross-deliver events between providers.\n if (\n this.options.target &&\n event.data.target !== this.options.target\n ) {\n return\n }\n const { method, params } = event.data.request\n this.notificationHandlers.forEach((h) => h(method, params))\n }\n this.win.addEventListener('message', this.notificationListener)\n }\n return () => {\n this.notificationHandlers.delete(handler)\n // Drop the DOM listener with the last subscriber so an abandoned\n // transport leaves nothing attached to the window; a later\n // subscribe re-installs it.\n if (\n this.notificationHandlers.size === 0 &&\n this.notificationListener\n ) {\n this.win.removeEventListener(\n 'message',\n this.notificationListener\n )\n this.notificationListener = undefined\n }\n }\n }\n\n submit = async (payload: RequestPayload) => {\n const message: SpliceMessage = {\n request: jsonRpcRequest(uuidv4(), payload),\n type: WalletEvent.SPLICE_WALLET_REQUEST,\n target: this.options.target,\n }\n\n this.win.postMessage(message, '*')\n\n return new Promise<SuccessResponse>((resolve, reject) => {\n const listener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_RESPONSE ||\n event.data.response.id !== message.request.id\n ) {\n return\n }\n\n window.removeEventListener('message', listener)\n if ('error' in event.data.response) {\n reject(event.data.response.error)\n } else {\n resolve(event.data.response)\n }\n }\n\n window.addEventListener('message', listener)\n })\n }\n\n submitResponse = (id: string | number | null, payload: ResponsePayload) => {\n const message: SpliceMessage = {\n response: jsonRpcResponse(id, payload),\n type: WalletEvent.SPLICE_WALLET_RESPONSE,\n }\n this.win.postMessage(message, '*')\n }\n}\n\nexport class HttpTransport implements RpcTransport {\n constructor(\n private url: URL,\n private accessToken?: string\n ) {}\n\n protected async handleErrorResponse(response: Response): Promise<never> {\n const body = await response.text()\n\n // if the response uses the RPC error format, throw it as is\n try {\n if (ErrorResponse.safeParse(JSON.parse(body)).success) {\n throw JSON.parse(body)\n }\n } catch {\n // ignore JSON parse errors\n }\n\n throw {\n error: {\n code: response.status,\n message: response.statusText,\n data: body,\n },\n }\n }\n\n async submit(payload: RequestPayload): Promise<ResponsePayload> {\n const request: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: payload.method,\n params: payload.params,\n id: uuidv4(),\n }\n\n const header = this.accessToken\n ? { Authorization: `Bearer ${this.accessToken}` }\n : undefined\n\n const response = await fetch(this.url.href, {\n method: 'POST',\n headers: {\n ...header,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n return this.handleErrorResponse(response)\n }\n\n const json = await response.json()\n const parsed = ResponsePayload.parse(json)\n\n if ('error' in parsed) {\n throw parsed\n }\n\n return parsed\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,11 @@ export declare const jsonRpcResponse: (id: string | number | null, payload: Resp
4
4
  export interface RpcTransport {
5
5
  submit: (payload: RequestPayload) => Promise<ResponsePayload>;
6
6
  }
7
+ /**
8
+ * Handler for wallet-pushed JSON-RPC notifications (CIP-103 events such as
9
+ * txChanged / accountsChanged / statusChanged / connected).
10
+ */
11
+ export type NotificationHandler = (method: string, params?: unknown) => void;
7
12
  export type WindowTransportOptions = {
8
13
  /**
9
14
  * Optional routing key for browser-extension messaging. When set, extensions
@@ -14,7 +19,16 @@ export type WindowTransportOptions = {
14
19
  export declare class WindowTransport implements RpcTransport {
15
20
  private win;
16
21
  private options;
22
+ private notificationHandlers;
23
+ private notificationListener;
17
24
  constructor(win: Window, options?: WindowTransportOptions);
25
+ /**
26
+ * Subscribe to wallet-pushed JSON-RPC notifications: SPLICE_WALLET_REQUEST
27
+ * frames with no `id` (JSON-RPC 2.0 §4.1). The window listener must be
28
+ * always-on for the transport's lifetime — CIP-103 events arrive between
29
+ * requests, where a per-request listener can never observe them.
30
+ */
31
+ onNotification: (handler: NotificationHandler) => (() => void);
18
32
  submit: (payload: RequestPayload) => Promise<{
19
33
  result?: unknown;
20
34
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,cAAc,EACd,eAAe,EACf,cAAc,EAMd,eAAe,EAClB,MAAM,4BAA4B,CAAA;AAEnC,eAAO,MAAM,cAAc,GACvB,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,SAAS,cAAc,KACxB,cAMF,CAAA;AAED,eAAO,MAAM,eAAe,GACxB,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,SAAS,eAAe,KACzB,eAMF,CAAA;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAChE;AAED,MAAM,MAAM,sBAAsB,GAAG;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,CAAA;AAED,qBAAa,eAAgB,YAAW,YAAY;IAE5C,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,OAAO;gBADP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,sBAA2B;IAGhD,MAAM,GAAU,SAAS,cAAc;;OA6BtC;IAED,cAAc,GAAI,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,SAAS,eAAe,UAMrE;CACJ;AAED,qBAAa,aAAc,YAAW,YAAY;IAE1C,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,WAAW,CAAC;gBADZ,GAAG,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,MAAM,YAAA;cAGhB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAqBjE,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAkClE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,cAAc,EACd,eAAe,EACf,cAAc,EAMd,eAAe,EAClB,MAAM,4BAA4B,CAAA;AAEnC,eAAO,MAAM,cAAc,GACvB,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,SAAS,cAAc,KACxB,cAMF,CAAA;AAED,eAAO,MAAM,eAAe,GACxB,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,SAAS,eAAe,KACzB,eAMF,CAAA;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAChE;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;AAE5E,MAAM,MAAM,sBAAsB,GAAG;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,CAAA;AAED,qBAAa,eAAgB,YAAW,YAAY;IAK5C,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,OAAO;IALnB,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,oBAAoB,CAA6C;gBAG7D,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,sBAA2B;IAGhD;;;;;OAKG;IACH,cAAc,GAAI,SAAS,mBAAmB,KAAG,CAAC,MAAM,IAAI,CAAC,CAgD5D;IAED,MAAM,GAAU,SAAS,cAAc;;OA6BtC;IAED,cAAc,GAAI,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,SAAS,eAAe,UAMrE;CACJ;AAED,qBAAa,aAAc,YAAW,YAAY;IAE1C,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,WAAW,CAAC;gBADZ,GAAG,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,MAAM,YAAA;cAGhB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAqBjE,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAkClE"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { v4 } from 'uuid';
2
- import { ErrorResponse, ResponsePayload, WalletEvent, isSpliceMessageEvent } from '@canton-network/core-types';
2
+ import { ErrorResponse, ResponsePayload, isSpliceMessageEvent, WalletEvent } from '@canton-network/core-types';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -24,6 +24,43 @@ var WindowTransport = class {
24
24
  constructor(win, options = {}) {
25
25
  this.win = win;
26
26
  this.options = options;
27
+ __publicField(this, "notificationHandlers", /* @__PURE__ */ new Set());
28
+ __publicField(this, "notificationListener");
29
+ /**
30
+ * Subscribe to wallet-pushed JSON-RPC notifications: SPLICE_WALLET_REQUEST
31
+ * frames with no `id` (JSON-RPC 2.0 §4.1). The window listener must be
32
+ * always-on for the transport's lifetime — CIP-103 events arrive between
33
+ * requests, where a per-request listener can never observe them.
34
+ */
35
+ __publicField(this, "onNotification", (handler) => {
36
+ this.notificationHandlers.add(handler);
37
+ if (!this.notificationListener) {
38
+ this.notificationListener = (event) => {
39
+ if (!isSpliceMessageEvent(event) || event.data.type !== WalletEvent.SPLICE_WALLET_REQUEST) {
40
+ return;
41
+ }
42
+ if (event.data.request.id != null) {
43
+ return;
44
+ }
45
+ if (this.options.target && event.data.target !== this.options.target) {
46
+ return;
47
+ }
48
+ const { method, params } = event.data.request;
49
+ this.notificationHandlers.forEach((h) => h(method, params));
50
+ };
51
+ this.win.addEventListener("message", this.notificationListener);
52
+ }
53
+ return () => {
54
+ this.notificationHandlers.delete(handler);
55
+ if (this.notificationHandlers.size === 0 && this.notificationListener) {
56
+ this.win.removeEventListener(
57
+ "message",
58
+ this.notificationListener
59
+ );
60
+ this.notificationListener = void 0;
61
+ }
62
+ };
63
+ });
27
64
  __publicField(this, "submit", async (payload) => {
28
65
  const message = {
29
66
  request: jsonRpcRequest(v4(), payload),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { v4 as uuidv4 } from 'uuid'\nimport {\n RequestPayload,\n ResponsePayload,\n JsonRpcRequest,\n SpliceMessage,\n WalletEvent,\n isSpliceMessageEvent,\n SuccessResponse,\n ErrorResponse,\n JsonRpcResponse,\n} from '@canton-network/core-types'\n\nexport const jsonRpcRequest = (\n id: string | number | null,\n payload: RequestPayload\n): JsonRpcRequest => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport const jsonRpcResponse = (\n id: string | number | null,\n payload: ResponsePayload\n): JsonRpcResponse => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport interface RpcTransport {\n submit: (payload: RequestPayload) => Promise<ResponsePayload>\n}\n\nexport type WindowTransportOptions = {\n /**\n * Optional routing key for browser-extension messaging. When set, extensions\n * should ignore messages that do not match their own identifier.\n */\n target?: string | undefined\n}\n\nexport class WindowTransport implements RpcTransport {\n constructor(\n private win: Window,\n private options: WindowTransportOptions = {}\n ) {}\n\n submit = async (payload: RequestPayload) => {\n const message: SpliceMessage = {\n request: jsonRpcRequest(uuidv4(), payload),\n type: WalletEvent.SPLICE_WALLET_REQUEST,\n target: this.options.target,\n }\n\n this.win.postMessage(message, '*')\n\n return new Promise<SuccessResponse>((resolve, reject) => {\n const listener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_RESPONSE ||\n event.data.response.id !== message.request.id\n ) {\n return\n }\n\n window.removeEventListener('message', listener)\n if ('error' in event.data.response) {\n reject(event.data.response.error)\n } else {\n resolve(event.data.response)\n }\n }\n\n window.addEventListener('message', listener)\n })\n }\n\n submitResponse = (id: string | number | null, payload: ResponsePayload) => {\n const message: SpliceMessage = {\n response: jsonRpcResponse(id, payload),\n type: WalletEvent.SPLICE_WALLET_RESPONSE,\n }\n this.win.postMessage(message, '*')\n }\n}\n\nexport class HttpTransport implements RpcTransport {\n constructor(\n private url: URL,\n private accessToken?: string\n ) {}\n\n protected async handleErrorResponse(response: Response): Promise<never> {\n const body = await response.text()\n\n // if the response uses the RPC error format, throw it as is\n try {\n if (ErrorResponse.safeParse(JSON.parse(body)).success) {\n throw JSON.parse(body)\n }\n } catch {\n // ignore JSON parse errors\n }\n\n throw {\n error: {\n code: response.status,\n message: response.statusText,\n data: body,\n },\n }\n }\n\n async submit(payload: RequestPayload): Promise<ResponsePayload> {\n const request: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: payload.method,\n params: payload.params,\n id: uuidv4(),\n }\n\n const header = this.accessToken\n ? { Authorization: `Bearer ${this.accessToken}` }\n : undefined\n\n const response = await fetch(this.url.href, {\n method: 'POST',\n headers: {\n ...header,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n return this.handleErrorResponse(response)\n }\n\n const json = await response.json()\n const parsed = ResponsePayload.parse(json)\n\n if ('error' in parsed) {\n throw parsed\n }\n\n return parsed\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { v4 as uuidv4 } from 'uuid'\nimport {\n RequestPayload,\n ResponsePayload,\n JsonRpcRequest,\n SpliceMessage,\n WalletEvent,\n isSpliceMessageEvent,\n SuccessResponse,\n ErrorResponse,\n JsonRpcResponse,\n} from '@canton-network/core-types'\n\nexport const jsonRpcRequest = (\n id: string | number | null,\n payload: RequestPayload\n): JsonRpcRequest => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport const jsonRpcResponse = (\n id: string | number | null,\n payload: ResponsePayload\n): JsonRpcResponse => {\n return {\n jsonrpc: '2.0',\n id, // id should be set based on the request context\n ...payload,\n }\n}\n\nexport interface RpcTransport {\n submit: (payload: RequestPayload) => Promise<ResponsePayload>\n}\n\n/**\n * Handler for wallet-pushed JSON-RPC notifications (CIP-103 events such as\n * txChanged / accountsChanged / statusChanged / connected).\n */\nexport type NotificationHandler = (method: string, params?: unknown) => void\n\nexport type WindowTransportOptions = {\n /**\n * Optional routing key for browser-extension messaging. When set, extensions\n * should ignore messages that do not match their own identifier.\n */\n target?: string | undefined\n}\n\nexport class WindowTransport implements RpcTransport {\n private notificationHandlers = new Set<NotificationHandler>()\n private notificationListener: ((event: MessageEvent) => void) | undefined\n\n constructor(\n private win: Window,\n private options: WindowTransportOptions = {}\n ) {}\n\n /**\n * Subscribe to wallet-pushed JSON-RPC notifications: SPLICE_WALLET_REQUEST\n * frames with no `id` (JSON-RPC 2.0 §4.1). The window listener must be\n * always-on for the transport's lifetime — CIP-103 events arrive between\n * requests, where a per-request listener can never observe them.\n */\n onNotification = (handler: NotificationHandler): (() => void) => {\n this.notificationHandlers.add(handler)\n if (!this.notificationListener) {\n this.notificationListener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_REQUEST\n ) {\n return\n }\n // Requests submitted by this transport always carry a uuid id,\n // so an id-less request can only be a wallet-originated\n // notification — this also keeps the dApp's own outgoing\n // frames (posted to the same window) out of the event path.\n if (event.data.request.id != null) {\n return\n }\n // Same gating as extension detection: a transport constructed\n // from an announced provider's routing key only accepts frames\n // stamped with that key, so multi-wallet pages do not\n // cross-deliver events between providers.\n if (\n this.options.target &&\n event.data.target !== this.options.target\n ) {\n return\n }\n const { method, params } = event.data.request\n this.notificationHandlers.forEach((h) => h(method, params))\n }\n this.win.addEventListener('message', this.notificationListener)\n }\n return () => {\n this.notificationHandlers.delete(handler)\n // Drop the DOM listener with the last subscriber so an abandoned\n // transport leaves nothing attached to the window; a later\n // subscribe re-installs it.\n if (\n this.notificationHandlers.size === 0 &&\n this.notificationListener\n ) {\n this.win.removeEventListener(\n 'message',\n this.notificationListener\n )\n this.notificationListener = undefined\n }\n }\n }\n\n submit = async (payload: RequestPayload) => {\n const message: SpliceMessage = {\n request: jsonRpcRequest(uuidv4(), payload),\n type: WalletEvent.SPLICE_WALLET_REQUEST,\n target: this.options.target,\n }\n\n this.win.postMessage(message, '*')\n\n return new Promise<SuccessResponse>((resolve, reject) => {\n const listener = (event: MessageEvent) => {\n if (\n !isSpliceMessageEvent(event) ||\n event.data.type !== WalletEvent.SPLICE_WALLET_RESPONSE ||\n event.data.response.id !== message.request.id\n ) {\n return\n }\n\n window.removeEventListener('message', listener)\n if ('error' in event.data.response) {\n reject(event.data.response.error)\n } else {\n resolve(event.data.response)\n }\n }\n\n window.addEventListener('message', listener)\n })\n }\n\n submitResponse = (id: string | number | null, payload: ResponsePayload) => {\n const message: SpliceMessage = {\n response: jsonRpcResponse(id, payload),\n type: WalletEvent.SPLICE_WALLET_RESPONSE,\n }\n this.win.postMessage(message, '*')\n }\n}\n\nexport class HttpTransport implements RpcTransport {\n constructor(\n private url: URL,\n private accessToken?: string\n ) {}\n\n protected async handleErrorResponse(response: Response): Promise<never> {\n const body = await response.text()\n\n // if the response uses the RPC error format, throw it as is\n try {\n if (ErrorResponse.safeParse(JSON.parse(body)).success) {\n throw JSON.parse(body)\n }\n } catch {\n // ignore JSON parse errors\n }\n\n throw {\n error: {\n code: response.status,\n message: response.statusText,\n data: body,\n },\n }\n }\n\n async submit(payload: RequestPayload): Promise<ResponsePayload> {\n const request: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: payload.method,\n params: payload.params,\n id: uuidv4(),\n }\n\n const header = this.accessToken\n ? { Authorization: `Bearer ${this.accessToken}` }\n : undefined\n\n const response = await fetch(this.url.href, {\n method: 'POST',\n headers: {\n ...header,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n return this.handleErrorResponse(response)\n }\n\n const json = await response.json()\n const parsed = ResponsePayload.parse(json)\n\n if ('error' in parsed) {\n throw parsed\n }\n\n return parsed\n }\n}\n"]}
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@canton-network/core-rpc-transport",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "type": "module",
5
5
  "description": "RPC transport implementations",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Digital Asset (Switzerland) GmbH and/or its affiliates",
8
- "packageManager": "yarn@4.9.4",
9
8
  "main": "./dist/index.cjs",
10
9
  "module": "./dist/index.js",
11
10
  "types": "./dist/index.d.ts",
@@ -22,20 +21,20 @@
22
21
  "dev": "tsup --watch --onSuccess \"tsc\"",
23
22
  "flatpack": "yarn pack --out \"$FLATPACK_OUTDIR\"",
24
23
  "clean": "tsc -b --clean; rm -rf dist",
25
- "test": "vitest run --project node --project browser --passWithNoTests",
26
- "test:coverage": "vitest run --project node --project browser --coverage --passWithNoTests"
24
+ "test": "vitest run --project node --project browser",
25
+ "test:coverage": "vitest run --project node --project browser --coverage"
27
26
  },
28
27
  "dependencies": {
29
- "@canton-network/core-types": "^1.5.0",
28
+ "@canton-network/core-types": "^1.6.1",
30
29
  "uuid": "^14.0.0"
31
30
  },
32
31
  "devDependencies": {
33
- "@vitest/browser-playwright": "^4.1.2",
34
- "@vitest/coverage-v8": "^4.1.2",
35
- "playwright": "^1.58.2",
32
+ "@vitest/browser-playwright": "^4.1.8",
33
+ "@vitest/coverage-v8": "^4.1.8",
34
+ "playwright": "^1.60.0",
36
35
  "tsup": "^8.5.1",
37
36
  "typescript": "^5.9.3",
38
- "vitest": "^4.1.2"
37
+ "vitest": "^4.1.8"
39
38
  },
40
39
  "files": [
41
40
  "dist/**"
@@ -47,5 +46,9 @@
47
46
  "type": "git",
48
47
  "url": "git+https://github.com/canton-network/wallet.git",
49
48
  "directory": "core/rpc-transport"
49
+ },
50
+ "homepage": "https://github.com/canton-network/wallet/tree/main/core/rpc-transport#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/canton-network/wallet/issues"
50
53
  }
51
54
  }