@coin-voyage/shared 2.2.4 → 2.2.5-beta.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.
@@ -1,10 +1,10 @@
1
1
  import { type PayOrder, PayOrderMode } from "../types";
2
- import type { ClaimFeesRequest, ClaimFeesResponse, CreateWebhookRequest, GetFeeBalancesResponse, PaymentDetails, PaymentDetailsParams, PayOrderParams, PayOrderQuoteParams, QuoteWithBalance, SwapDataRequest, SwapDataResponse, SwapQuoteRequest, UpdateWebhookRequest, WebhookResponse } from "../types/api";
2
+ import type { ClaimFeesRequest, ClaimFeesResponse, CreateWebhookRequest, GetFeeBalancesResponse, OrderStatusSocket, PaymentDetails, PaymentDetailsParams, PayOrderParams, PayOrderQuoteParams, QuoteWithBalance, SwapDataRequest, SwapDataResponse, SwapQuoteRequest, UpdateWebhookRequest, WebhookResponse } from "../types/api";
3
3
  import { type APIEnvironment } from "./config";
4
4
  import { type APIResponse } from "./fetcher";
5
5
  export declare class ApiClient {
6
6
  private readonly apiKey;
7
- private readonly environment?;
7
+ private readonly environment;
8
8
  private readonly sessionId?;
9
9
  private readonly version?;
10
10
  constructor({ apiKey, sessionId, environment, version, }: {
@@ -272,4 +272,19 @@ export declare class ApiClient {
272
272
  * @returns {Promise<APIResponse<SwapDataResponse>>} - Swap data wrapped in an API response.
273
273
  */
274
274
  swapData(params: SwapDataRequest): Promise<APIResponse<SwapDataResponse>>;
275
+ /**
276
+ * Opens a WebSocket connection to receive real-time order status events.
277
+ *
278
+ * Subscribe to an order's events after the connection is open:
279
+ * ```ts
280
+ * const socket = apiClient.subscribeOrderStatus()
281
+ * socket.onOpen(() => socket.subscribe(orderId)) // omit orderId to subscribe to all org orders
282
+ * socket.onMessage((msg) => {
283
+ * if (msg.type === 'event') console.log(msg.data)
284
+ * })
285
+ * ```
286
+ *
287
+ * @returns {OrderStatusSocket} - Handle for subscribing, receiving messages, and closing the connection.
288
+ */
289
+ subscribeOrderStatus(): OrderStatusSocket;
275
290
  }
@@ -1,6 +1,7 @@
1
1
  import { createHmac } from "crypto";
2
2
  import { now, zPayOrder, zPayOrderMetadata } from "../common";
3
3
  import { PayOrderMode } from "../types";
4
+ import { WS_URL } from "./config";
4
5
  import { fetchApi } from "./fetcher";
5
6
  export class ApiClient {
6
7
  constructor({ apiKey, sessionId, environment = "production", version, }) {
@@ -461,4 +462,82 @@ export class ApiClient {
461
462
  },
462
463
  });
463
464
  }
465
+ // ===================
466
+ // WebSocket
467
+ // ===================
468
+ /**
469
+ * Opens a WebSocket connection to receive real-time order status events.
470
+ *
471
+ * Subscribe to an order's events after the connection is open:
472
+ * ```ts
473
+ * const socket = apiClient.subscribeOrderStatus()
474
+ * socket.onOpen(() => socket.subscribe(orderId)) // omit orderId to subscribe to all org orders
475
+ * socket.onMessage((msg) => {
476
+ * if (msg.type === 'event') console.log(msg.data)
477
+ * })
478
+ * ```
479
+ *
480
+ * @returns {OrderStatusSocket} - Handle for subscribing, receiving messages, and closing the connection.
481
+ */
482
+ subscribeOrderStatus() {
483
+ const ws = new WebSocket(WS_URL[this.environment]);
484
+ const messageListeners = [];
485
+ const pendingMessages = [];
486
+ ws.addEventListener("open", () => {
487
+ ws.send(JSON.stringify({ type: "connect", data: { api_key: this.apiKey } }));
488
+ });
489
+ ws.addEventListener("message", (event) => {
490
+ try {
491
+ const msg = JSON.parse(event.data);
492
+ if (msg.type === "connected") {
493
+ for (const pending of pendingMessages)
494
+ ws.send(pending);
495
+ pendingMessages.length = 0;
496
+ }
497
+ for (const listener of messageListeners)
498
+ listener(msg);
499
+ }
500
+ catch {
501
+ // ignore malformed messages
502
+ }
503
+ });
504
+ const send = (msg) => {
505
+ const data = JSON.stringify(msg);
506
+ if (ws.readyState === WebSocket.OPEN) {
507
+ ws.send(data);
508
+ }
509
+ else {
510
+ pendingMessages.push(data);
511
+ }
512
+ };
513
+ return {
514
+ subscribe(orderId) {
515
+ send({ type: "subscribe", data: { order_id: orderId } });
516
+ },
517
+ subscribeOrg() {
518
+ send({ type: "subscribe", data: {} });
519
+ },
520
+ unsubscribe(orderId) {
521
+ send({ type: "unsubscribe", data: orderId ? { order_id: orderId } : {} });
522
+ },
523
+ unsubscribeOrg() {
524
+ send({ type: "unsubscribe", data: {} });
525
+ },
526
+ onMessage(callback) {
527
+ messageListeners.push(callback);
528
+ },
529
+ onOpen(callback) {
530
+ ws.addEventListener("open", callback);
531
+ },
532
+ onClose(callback) {
533
+ ws.addEventListener("close", callback);
534
+ },
535
+ onError(callback) {
536
+ ws.addEventListener("error", callback);
537
+ },
538
+ close() {
539
+ ws.close();
540
+ },
541
+ };
542
+ }
464
543
  }
@@ -1,2 +1,3 @@
1
1
  export declare const API_URL: Record<string, string>;
2
+ export declare const WS_URL: Record<string, string>;
2
3
  export type APIEnvironment = keyof typeof API_URL;
@@ -3,3 +3,8 @@ export const API_URL = {
3
3
  development: "https://acc-api.coinvoyage.io/v2",
4
4
  local: "http://localhost:8000/v2",
5
5
  };
6
+ export const WS_URL = {
7
+ production: "wss://api.coinvoyage.io/v2/ws",
8
+ development: "wss://acc-api.coinvoyage.io/v2/ws",
9
+ local: "ws://localhost:8000/v2/ws",
10
+ };
@@ -1,7 +1,7 @@
1
1
  import { API_URL } from "./config";
2
2
  export async function fetchApi(opts) {
3
3
  try {
4
- const baseUrl = API_URL[opts.environment ?? "production"];
4
+ const baseUrl = API_URL[opts.environment || "production"];
5
5
  const response = await fetch(`${baseUrl}${opts.path}`, {
6
6
  ...opts.options,
7
7
  headers: {
@@ -1,5 +1,6 @@
1
1
  import { FiatCurrency } from "../common/currencies";
2
2
  import { ChainId, ChainType, PayOrderStatus } from "./enums";
3
+ import { PayOrderEvent } from "./events";
3
4
  import { Currency, CurrencyAmount, CurrencyBase, CurrencyWithAmount, PaymentData, PayOrderMetadata, QuoteWithCurrency } from "./model";
4
5
  export type PayOrderParams = {
5
6
  /**
@@ -127,3 +128,46 @@ export type SwapDataResponse = {
127
128
  refund_address: string;
128
129
  expires_at: string;
129
130
  };
131
+ declare enum WsMessageType {
132
+ Connected = "connected",
133
+ Subscription = "subscription",
134
+ Event = "event",
135
+ Error = "error"
136
+ }
137
+ export type WsConnectedMessage = {
138
+ type: WsMessageType.Connected;
139
+ data: {
140
+ status: "authenticated";
141
+ };
142
+ };
143
+ export type WsSubscriptionMessage = {
144
+ type: WsMessageType.Subscription;
145
+ data: {
146
+ order_id?: string;
147
+ scope: "order" | "organization";
148
+ status: "subscribed" | "unsubscribed";
149
+ };
150
+ };
151
+ export type WsEventMessage = {
152
+ type: WsMessageType.Event;
153
+ data: PayOrderEvent;
154
+ };
155
+ export type WsErrorMessage = {
156
+ type: WsMessageType.Error;
157
+ data: {
158
+ message: string;
159
+ };
160
+ };
161
+ export type WsServerMessage = WsConnectedMessage | WsSubscriptionMessage | WsEventMessage | WsErrorMessage;
162
+ export type OrderStatusSocket = {
163
+ subscribe: (orderId: string) => void;
164
+ subscribeOrg: () => void;
165
+ unsubscribe: (orderId?: string) => void;
166
+ unsubscribeOrg: () => void;
167
+ onMessage: (callback: (msg: WsServerMessage) => void) => void;
168
+ onOpen: (callback: () => void) => void;
169
+ onClose: (callback: (event: CloseEvent) => void) => void;
170
+ onError: (callback: (event: Event) => void) => void;
171
+ close: () => void;
172
+ };
173
+ export {};
package/dist/types/api.js CHANGED
@@ -1 +1,9 @@
1
+ // ======== WebSocket ========
2
+ var WsMessageType;
3
+ (function (WsMessageType) {
4
+ WsMessageType["Connected"] = "connected";
5
+ WsMessageType["Subscription"] = "subscription";
6
+ WsMessageType["Event"] = "event";
7
+ WsMessageType["Error"] = "error";
8
+ })(WsMessageType || (WsMessageType = {}));
1
9
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coin-voyage/shared",
3
3
  "description": "Shared utilities for Coin Voyage",
4
- "version": "2.2.4",
4
+ "version": "2.2.5-beta.1",
5
5
  "private": false,
6
6
  "sideEffects": false,
7
7
  "exports": {