@edge-markets/connect-node 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/README.md CHANGED
@@ -175,7 +175,7 @@ const balance = await client.getBalance()
175
175
  ### Transfers
176
176
 
177
177
  ```typescript
178
- // Initiate transfer (requires OTP verification)
178
+ // 1. Initiate the transfer — returns a pending transfer that requires verification.
179
179
  const transfer = await client.initiateTransfer({
180
180
  type: 'debit', // 'debit' = pull from user, 'credit' = push to user
181
181
  amount: '100.00',
@@ -183,12 +183,22 @@ const transfer = await client.initiateTransfer({
183
183
  })
184
184
  // Returns: { transferId, status: 'pending_verification', otpMethod }
185
185
 
186
- // Verify with OTP
187
- const result = await client.verifyTransfer(transfer.transferId, userOtp)
188
- // Returns: { transferId, status: 'completed' | 'failed' }
186
+ // 2. Create an EDGE-hosted verification session. The returned `verificationUrl`
187
+ // is a single-use, short-lived URL you embed in an iframe or popup on your
188
+ // frontend. The user enters their OTP inside the EDGE-hosted UI — OTP secrets
189
+ // never touch your infrastructure.
190
+ const session = await client.createVerificationSession(transfer.transferId, {
191
+ origin: 'https://your-site.example.com',
192
+ })
193
+ // Returns: { sessionId, verificationUrl, expiresAt }
194
+
195
+ // 3. Listen for the postMessage event from the iframe (or poll
196
+ // getVerificationSessionStatus) to learn when verification completes.
197
+ // A `transfer.completed` webhook will be delivered to your configured
198
+ // webhook URL once the transfer settles.
189
199
 
190
200
  // Get transfer status
191
- const status = await client.getTransfer(transferId)
201
+ const status = await client.getTransfer(transfer.transferId)
192
202
 
193
203
  // List transfers
194
204
  const { transfers, total } = await client.listTransfers({
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { EdgeEnvironment, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, CreateVerificationSessionRequest, VerificationSession, VerificationSessionStatusResponse, EdgeTokens } from '@edge-markets/connect';
2
- export { Balance, CreateVerificationSessionRequest, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, Transfer, TransferList, TransferListItem, TransferStatus, TransferType, User, VerificationSession, VerificationSessionStatus, VerificationSessionStatusResponse, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
1
+ import * as node_https from 'node:https';
2
+ import { EdgeEnvironment, TransferCategory, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, CreateVerificationSessionRequest, VerificationSession, VerificationSessionStatusResponse, EdgeTokens } from '@edge-markets/connect';
3
+ export { Balance, CreateVerificationSessionRequest, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeIdentityVerificationError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, SdkGeolocation, TRANSFER_CATEGORIES, Transfer, TransferCategory, TransferList, TransferListItem, TransferStatus, TransferType, User, UserAddress, VerificationSession, VerificationSessionStatus, VerificationSessionStatusResponse, VerifyIdentityAddress, VerifyIdentityOptions, VerifyIdentityResult, VerifyIdentityScores, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isIdentityVerificationError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
3
4
 
4
5
  interface RequestInfo {
5
6
  method: string;
@@ -40,11 +41,20 @@ interface EdgeConnectServerConfig {
40
41
  partnerKeyId: string;
41
42
  strictResponseEncryption?: boolean;
42
43
  };
44
+ mtls?: MtlsConfig;
45
+ }
46
+ interface MtlsConfig {
47
+ enabled: boolean;
48
+ cert: string;
49
+ key: string;
50
+ ca?: string;
43
51
  }
44
52
  interface TransferOptions {
45
53
  type: 'debit' | 'credit';
46
54
  amount: string;
47
55
  idempotencyKey: string;
56
+ /** Optional transaction category for settlement window determination */
57
+ category?: TransferCategory;
48
58
  }
49
59
 
50
60
  /**
@@ -61,7 +71,6 @@ declare class EdgeUserClient {
61
71
  verifyIdentity(options: VerifyIdentityOptions): Promise<VerifyIdentityResult>;
62
72
  getBalance(): Promise<Balance>;
63
73
  initiateTransfer(options: TransferOptions): Promise<Transfer>;
64
- verifyTransfer(transferId: string, otp: string): Promise<Transfer>;
65
74
  getTransfer(transferId: string): Promise<Transfer>;
66
75
  listTransfers(params?: ListTransfersParams): Promise<TransferList>;
67
76
  revokeConsent(): Promise<{
@@ -86,9 +95,16 @@ declare class EdgeConnectServer {
86
95
  private readonly oauthBaseUrl;
87
96
  private readonly timeout;
88
97
  private readonly retryConfig;
98
+ private readonly httpsAgent;
99
+ private readonly dispatcher;
89
100
  static getInstance(config: EdgeConnectServerConfig): EdgeConnectServer;
90
101
  static clearInstances(): void;
91
102
  constructor(config: EdgeConnectServerConfig);
103
+ /**
104
+ * Returns the `node:https.Agent` configured with mTLS client certificates.
105
+ * Use this with axios, got, or other HTTP clients. Returns `undefined` if mTLS is not configured.
106
+ */
107
+ getHttpsAgent(): node_https.Agent | undefined;
92
108
  /**
93
109
  * Create a user-scoped client for making authenticated API calls.
94
110
  *
@@ -108,4 +124,4 @@ declare class EdgeConnectServer {
108
124
  private handleApiErrorFromBody;
109
125
  }
110
126
 
111
- export { EdgeConnectServer, type EdgeConnectServerConfig, EdgeUserClient, type RequestInfo, type ResponseInfo, type RetryConfig, type TransferOptions };
127
+ export { EdgeConnectServer, type EdgeConnectServerConfig, EdgeUserClient, type MtlsConfig, type RequestInfo, type ResponseInfo, type RetryConfig, type TransferOptions };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { EdgeEnvironment, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, CreateVerificationSessionRequest, VerificationSession, VerificationSessionStatusResponse, EdgeTokens } from '@edge-markets/connect';
2
- export { Balance, CreateVerificationSessionRequest, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, Transfer, TransferList, TransferListItem, TransferStatus, TransferType, User, VerificationSession, VerificationSessionStatus, VerificationSessionStatusResponse, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
1
+ import * as node_https from 'node:https';
2
+ import { EdgeEnvironment, TransferCategory, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, CreateVerificationSessionRequest, VerificationSession, VerificationSessionStatusResponse, EdgeTokens } from '@edge-markets/connect';
3
+ export { Balance, CreateVerificationSessionRequest, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeIdentityVerificationError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, SdkGeolocation, TRANSFER_CATEGORIES, Transfer, TransferCategory, TransferList, TransferListItem, TransferStatus, TransferType, User, UserAddress, VerificationSession, VerificationSessionStatus, VerificationSessionStatusResponse, VerifyIdentityAddress, VerifyIdentityOptions, VerifyIdentityResult, VerifyIdentityScores, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isIdentityVerificationError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
3
4
 
4
5
  interface RequestInfo {
5
6
  method: string;
@@ -40,11 +41,20 @@ interface EdgeConnectServerConfig {
40
41
  partnerKeyId: string;
41
42
  strictResponseEncryption?: boolean;
42
43
  };
44
+ mtls?: MtlsConfig;
45
+ }
46
+ interface MtlsConfig {
47
+ enabled: boolean;
48
+ cert: string;
49
+ key: string;
50
+ ca?: string;
43
51
  }
44
52
  interface TransferOptions {
45
53
  type: 'debit' | 'credit';
46
54
  amount: string;
47
55
  idempotencyKey: string;
56
+ /** Optional transaction category for settlement window determination */
57
+ category?: TransferCategory;
48
58
  }
49
59
 
50
60
  /**
@@ -61,7 +71,6 @@ declare class EdgeUserClient {
61
71
  verifyIdentity(options: VerifyIdentityOptions): Promise<VerifyIdentityResult>;
62
72
  getBalance(): Promise<Balance>;
63
73
  initiateTransfer(options: TransferOptions): Promise<Transfer>;
64
- verifyTransfer(transferId: string, otp: string): Promise<Transfer>;
65
74
  getTransfer(transferId: string): Promise<Transfer>;
66
75
  listTransfers(params?: ListTransfersParams): Promise<TransferList>;
67
76
  revokeConsent(): Promise<{
@@ -86,9 +95,16 @@ declare class EdgeConnectServer {
86
95
  private readonly oauthBaseUrl;
87
96
  private readonly timeout;
88
97
  private readonly retryConfig;
98
+ private readonly httpsAgent;
99
+ private readonly dispatcher;
89
100
  static getInstance(config: EdgeConnectServerConfig): EdgeConnectServer;
90
101
  static clearInstances(): void;
91
102
  constructor(config: EdgeConnectServerConfig);
103
+ /**
104
+ * Returns the `node:https.Agent` configured with mTLS client certificates.
105
+ * Use this with axios, got, or other HTTP clients. Returns `undefined` if mTLS is not configured.
106
+ */
107
+ getHttpsAgent(): node_https.Agent | undefined;
92
108
  /**
93
109
  * Create a user-scoped client for making authenticated API calls.
94
110
  *
@@ -108,4 +124,4 @@ declare class EdgeConnectServer {
108
124
  private handleApiErrorFromBody;
109
125
  }
110
126
 
111
- export { EdgeConnectServer, type EdgeConnectServerConfig, EdgeUserClient, type RequestInfo, type ResponseInfo, type RetryConfig, type TransferOptions };
127
+ export { EdgeConnectServer, type EdgeConnectServerConfig, EdgeUserClient, type MtlsConfig, type RequestInfo, type ResponseInfo, type RetryConfig, type TransferOptions };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -25,16 +35,19 @@ __export(index_exports, {
25
35
  EdgeConnectServer: () => EdgeConnectServer,
26
36
  EdgeConsentRequiredError: () => import_connect3.EdgeConsentRequiredError,
27
37
  EdgeError: () => import_connect3.EdgeError,
38
+ EdgeIdentityVerificationError: () => import_connect3.EdgeIdentityVerificationError,
28
39
  EdgeInsufficientScopeError: () => import_connect3.EdgeInsufficientScopeError,
29
40
  EdgeNetworkError: () => import_connect3.EdgeNetworkError,
30
41
  EdgeNotFoundError: () => import_connect3.EdgeNotFoundError,
31
42
  EdgeTokenExchangeError: () => import_connect3.EdgeTokenExchangeError,
32
43
  EdgeUserClient: () => EdgeUserClient,
44
+ TRANSFER_CATEGORIES: () => import_connect4.TRANSFER_CATEGORIES,
33
45
  getEnvironmentConfig: () => import_connect4.getEnvironmentConfig,
34
46
  isApiError: () => import_connect3.isApiError,
35
47
  isAuthenticationError: () => import_connect3.isAuthenticationError,
36
48
  isConsentRequiredError: () => import_connect3.isConsentRequiredError,
37
49
  isEdgeError: () => import_connect3.isEdgeError,
50
+ isIdentityVerificationError: () => import_connect3.isIdentityVerificationError,
38
51
  isNetworkError: () => import_connect3.isNetworkError,
39
52
  isProductionEnvironment: () => import_connect4.isProductionEnvironment
40
53
  });
@@ -85,6 +98,9 @@ function validateTransferOptions(options) {
85
98
  } else if (options.idempotencyKey.length > 255) {
86
99
  errors.idempotencyKey = ["Must be 255 characters or less"];
87
100
  }
101
+ if (options.category && !["sportsbook", "casino", "dfs", "sweepstakes"].includes(options.category)) {
102
+ errors.category = ["Must be one of: sportsbook, casino, dfs, sweepstakes"];
103
+ }
88
104
  if (Object.keys(errors).length > 0) {
89
105
  throw new import_connect.EdgeValidationError("Invalid transfer options", errors);
90
106
  }
@@ -113,16 +129,11 @@ var EdgeUserClient = class {
113
129
  amount: options.amount,
114
130
  idempotencyKey: options.idempotencyKey
115
131
  };
132
+ if (options.category) {
133
+ body.category = options.category;
134
+ }
116
135
  return this.server._apiRequest("POST", "/transfer", this.accessToken, body);
117
136
  }
118
- async verifyTransfer(transferId, otp) {
119
- return this.server._apiRequest(
120
- "POST",
121
- `/transfer/${encodeURIComponent(transferId)}/verify`,
122
- this.accessToken,
123
- { otp }
124
- );
125
- }
126
137
  async getTransfer(transferId) {
127
138
  return this.server._apiRequest("GET", `/transfer/${encodeURIComponent(transferId)}`, this.accessToken);
128
139
  }
@@ -239,6 +250,37 @@ function fromBase64Url(value) {
239
250
  return Buffer.from(normalized, "base64");
240
251
  }
241
252
 
253
+ // src/mtls.ts
254
+ var import_node_https = __toESM(require("https"));
255
+ function createHttpsAgent(config) {
256
+ return new import_node_https.default.Agent({
257
+ cert: config.cert,
258
+ key: config.key,
259
+ rejectUnauthorized: true,
260
+ ...config.ca ? { ca: config.ca } : {}
261
+ });
262
+ }
263
+ function createUndiciDispatcher(config) {
264
+ const moduleName = "undici";
265
+ const { Agent } = require(moduleName);
266
+ return new Agent({
267
+ connect: {
268
+ cert: config.cert,
269
+ key: config.key,
270
+ rejectUnauthorized: true,
271
+ ...config.ca ? { ca: config.ca } : {}
272
+ }
273
+ });
274
+ }
275
+ function validateMtlsConfig(config) {
276
+ if (!config.cert?.trim()) {
277
+ throw new Error("EdgeConnectServer: mTLS cert is required when enabled");
278
+ }
279
+ if (!config.key?.trim()) {
280
+ throw new Error("EdgeConnectServer: mTLS key is required when enabled");
281
+ }
282
+ }
283
+
242
284
  // src/types.ts
243
285
  var DEFAULT_TIMEOUT = 3e4;
244
286
  var USER_AGENT = "@edge-markets/connect-node/1.0.0";
@@ -254,6 +296,28 @@ var instances = /* @__PURE__ */ new Map();
254
296
  function getInstanceKey(config) {
255
297
  return `${config.clientId}:${config.environment}`;
256
298
  }
299
+ var MTLS_ENFORCED_HOSTS = /* @__PURE__ */ new Set(["connect-staging.edgeboost.io", "api.edgeboost.com"]);
300
+ function isMtlsEnforcedHost(host) {
301
+ if (MTLS_ENFORCED_HOSTS.has(host)) {
302
+ return true;
303
+ }
304
+ for (const enforced of MTLS_ENFORCED_HOSTS) {
305
+ if (host.endsWith("." + enforced)) {
306
+ return true;
307
+ }
308
+ }
309
+ return false;
310
+ }
311
+ function environmentRequiresMtls(environment, apiBaseUrl) {
312
+ if (environment === "staging" || environment === "production") {
313
+ return true;
314
+ }
315
+ try {
316
+ return isMtlsEnforcedHost(new URL(apiBaseUrl).host);
317
+ } catch {
318
+ return false;
319
+ }
320
+ }
257
321
  var EdgeConnectServer = class _EdgeConnectServer {
258
322
  static getInstance(config) {
259
323
  const key = getInstanceKey(config);
@@ -285,6 +349,22 @@ var EdgeConnectServer = class _EdgeConnectServer {
285
349
  ...DEFAULT_RETRY_CONFIG,
286
350
  ...config.retry
287
351
  };
352
+ if (config.mtls?.enabled) {
353
+ validateMtlsConfig(config.mtls);
354
+ this.httpsAgent = createHttpsAgent(config.mtls);
355
+ this.dispatcher = createUndiciDispatcher(config.mtls);
356
+ } else if (environmentRequiresMtls(config.environment, this.apiBaseUrl)) {
357
+ console.warn(
358
+ `[EdgeConnectServer] environment='${config.environment}' is served from an mTLS-enforced host (${this.apiBaseUrl}) but no mtls config was provided. Requests will fail at the TLS handshake with a connection reset. Pass mtls: { enabled: true, cert, key, ca? } to EdgeConnectServer or coordinate with EDGE DevRel to issue a partner client certificate.`
359
+ );
360
+ }
361
+ }
362
+ /**
363
+ * Returns the `node:https.Agent` configured with mTLS client certificates.
364
+ * Use this with axios, got, or other HTTP clients. Returns `undefined` if mTLS is not configured.
365
+ */
366
+ getHttpsAgent() {
367
+ return this.httpsAgent;
288
368
  }
289
369
  /**
290
370
  * Create a user-scoped client for making authenticated API calls.
@@ -309,14 +389,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
309
389
  redirect_uri: redirectUri || this.config.redirectUri || ""
310
390
  };
311
391
  try {
312
- const response = await this.fetchWithTimeout(tokenUrl, {
313
- method: "POST",
314
- headers: {
315
- "Content-Type": "application/json",
316
- "User-Agent": USER_AGENT
392
+ const response = await this.fetchWithTimeout(
393
+ tokenUrl,
394
+ {
395
+ method: "POST",
396
+ headers: {
397
+ "Content-Type": "application/json",
398
+ "User-Agent": USER_AGENT
399
+ },
400
+ body: JSON.stringify(body)
317
401
  },
318
- body: JSON.stringify(body)
319
- });
402
+ this.dispatcher
403
+ );
320
404
  if (!response.ok) {
321
405
  const error = await response.json().catch(() => ({}));
322
406
  throw this.handleTokenError(error, response.status);
@@ -337,14 +421,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
337
421
  client_secret: this.config.clientSecret
338
422
  };
339
423
  try {
340
- const response = await this.fetchWithTimeout(tokenUrl, {
341
- method: "POST",
342
- headers: {
343
- "Content-Type": "application/json",
344
- "User-Agent": USER_AGENT
424
+ const response = await this.fetchWithTimeout(
425
+ tokenUrl,
426
+ {
427
+ method: "POST",
428
+ headers: {
429
+ "Content-Type": "application/json",
430
+ "User-Agent": USER_AGENT
431
+ },
432
+ body: JSON.stringify(body)
345
433
  },
346
- body: JSON.stringify(body)
347
- });
434
+ this.dispatcher
435
+ );
348
436
  if (!response.ok) {
349
437
  const error = await response.json().catch(() => ({}));
350
438
  throw new import_connect2.EdgeAuthenticationError(
@@ -384,11 +472,15 @@ var EdgeConnectServer = class _EdgeConnectServer {
384
472
  requestBody = { jwe: encryptMle(body, this.config.clientId, mleConfig) };
385
473
  }
386
474
  }
387
- const response = await this.fetchWithTimeout(url, {
388
- method,
389
- headers: requestHeaders,
390
- body: requestBody !== void 0 ? JSON.stringify(requestBody) : void 0
391
- });
475
+ const response = await this.fetchWithTimeout(
476
+ url,
477
+ {
478
+ method,
479
+ headers: requestHeaders,
480
+ body: requestBody !== void 0 ? JSON.stringify(requestBody) : void 0
481
+ },
482
+ this.dispatcher
483
+ );
392
484
  const rawResponseBody = await response.json().catch(() => ({}));
393
485
  let responseBody = rawResponseBody;
394
486
  if (mleEnabled && typeof rawResponseBody?.jwe === "string") {
@@ -447,14 +539,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
447
539
  async sleep(ms) {
448
540
  return new Promise((resolve) => setTimeout(resolve, ms));
449
541
  }
450
- async fetchWithTimeout(url, options) {
542
+ async fetchWithTimeout(url, options, dispatcher) {
451
543
  const controller = new AbortController();
452
544
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
453
545
  try {
454
- return await fetch(url, {
546
+ const fetchOptions = {
455
547
  ...options,
456
548
  signal: controller.signal
457
- });
549
+ };
550
+ if (dispatcher) {
551
+ fetchOptions.dispatcher = dispatcher;
552
+ }
553
+ return await fetch(url, fetchOptions);
458
554
  } finally {
459
555
  clearTimeout(timeoutId);
460
556
  }
@@ -552,16 +648,19 @@ var import_connect4 = require("@edge-markets/connect");
552
648
  EdgeConnectServer,
553
649
  EdgeConsentRequiredError,
554
650
  EdgeError,
651
+ EdgeIdentityVerificationError,
555
652
  EdgeInsufficientScopeError,
556
653
  EdgeNetworkError,
557
654
  EdgeNotFoundError,
558
655
  EdgeTokenExchangeError,
559
656
  EdgeUserClient,
657
+ TRANSFER_CATEGORIES,
560
658
  getEnvironmentConfig,
561
659
  isApiError,
562
660
  isAuthenticationError,
563
661
  isConsentRequiredError,
564
662
  isEdgeError,
663
+ isIdentityVerificationError,
565
664
  isNetworkError,
566
665
  isProductionEnvironment
567
666
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/edge-connect-server.ts
2
9
  import {
3
10
  EdgeApiError,
@@ -54,6 +61,9 @@ function validateTransferOptions(options) {
54
61
  } else if (options.idempotencyKey.length > 255) {
55
62
  errors.idempotencyKey = ["Must be 255 characters or less"];
56
63
  }
64
+ if (options.category && !["sportsbook", "casino", "dfs", "sweepstakes"].includes(options.category)) {
65
+ errors.category = ["Must be one of: sportsbook, casino, dfs, sweepstakes"];
66
+ }
57
67
  if (Object.keys(errors).length > 0) {
58
68
  throw new EdgeValidationError("Invalid transfer options", errors);
59
69
  }
@@ -82,16 +92,11 @@ var EdgeUserClient = class {
82
92
  amount: options.amount,
83
93
  idempotencyKey: options.idempotencyKey
84
94
  };
95
+ if (options.category) {
96
+ body.category = options.category;
97
+ }
85
98
  return this.server._apiRequest("POST", "/transfer", this.accessToken, body);
86
99
  }
87
- async verifyTransfer(transferId, otp) {
88
- return this.server._apiRequest(
89
- "POST",
90
- `/transfer/${encodeURIComponent(transferId)}/verify`,
91
- this.accessToken,
92
- { otp }
93
- );
94
- }
95
100
  async getTransfer(transferId) {
96
101
  return this.server._apiRequest("GET", `/transfer/${encodeURIComponent(transferId)}`, this.accessToken);
97
102
  }
@@ -208,6 +213,37 @@ function fromBase64Url(value) {
208
213
  return Buffer.from(normalized, "base64");
209
214
  }
210
215
 
216
+ // src/mtls.ts
217
+ import https from "https";
218
+ function createHttpsAgent(config) {
219
+ return new https.Agent({
220
+ cert: config.cert,
221
+ key: config.key,
222
+ rejectUnauthorized: true,
223
+ ...config.ca ? { ca: config.ca } : {}
224
+ });
225
+ }
226
+ function createUndiciDispatcher(config) {
227
+ const moduleName = "undici";
228
+ const { Agent } = __require(moduleName);
229
+ return new Agent({
230
+ connect: {
231
+ cert: config.cert,
232
+ key: config.key,
233
+ rejectUnauthorized: true,
234
+ ...config.ca ? { ca: config.ca } : {}
235
+ }
236
+ });
237
+ }
238
+ function validateMtlsConfig(config) {
239
+ if (!config.cert?.trim()) {
240
+ throw new Error("EdgeConnectServer: mTLS cert is required when enabled");
241
+ }
242
+ if (!config.key?.trim()) {
243
+ throw new Error("EdgeConnectServer: mTLS key is required when enabled");
244
+ }
245
+ }
246
+
211
247
  // src/types.ts
212
248
  var DEFAULT_TIMEOUT = 3e4;
213
249
  var USER_AGENT = "@edge-markets/connect-node/1.0.0";
@@ -223,6 +259,28 @@ var instances = /* @__PURE__ */ new Map();
223
259
  function getInstanceKey(config) {
224
260
  return `${config.clientId}:${config.environment}`;
225
261
  }
262
+ var MTLS_ENFORCED_HOSTS = /* @__PURE__ */ new Set(["connect-staging.edgeboost.io", "api.edgeboost.com"]);
263
+ function isMtlsEnforcedHost(host) {
264
+ if (MTLS_ENFORCED_HOSTS.has(host)) {
265
+ return true;
266
+ }
267
+ for (const enforced of MTLS_ENFORCED_HOSTS) {
268
+ if (host.endsWith("." + enforced)) {
269
+ return true;
270
+ }
271
+ }
272
+ return false;
273
+ }
274
+ function environmentRequiresMtls(environment, apiBaseUrl) {
275
+ if (environment === "staging" || environment === "production") {
276
+ return true;
277
+ }
278
+ try {
279
+ return isMtlsEnforcedHost(new URL(apiBaseUrl).host);
280
+ } catch {
281
+ return false;
282
+ }
283
+ }
226
284
  var EdgeConnectServer = class _EdgeConnectServer {
227
285
  static getInstance(config) {
228
286
  const key = getInstanceKey(config);
@@ -254,6 +312,22 @@ var EdgeConnectServer = class _EdgeConnectServer {
254
312
  ...DEFAULT_RETRY_CONFIG,
255
313
  ...config.retry
256
314
  };
315
+ if (config.mtls?.enabled) {
316
+ validateMtlsConfig(config.mtls);
317
+ this.httpsAgent = createHttpsAgent(config.mtls);
318
+ this.dispatcher = createUndiciDispatcher(config.mtls);
319
+ } else if (environmentRequiresMtls(config.environment, this.apiBaseUrl)) {
320
+ console.warn(
321
+ `[EdgeConnectServer] environment='${config.environment}' is served from an mTLS-enforced host (${this.apiBaseUrl}) but no mtls config was provided. Requests will fail at the TLS handshake with a connection reset. Pass mtls: { enabled: true, cert, key, ca? } to EdgeConnectServer or coordinate with EDGE DevRel to issue a partner client certificate.`
322
+ );
323
+ }
324
+ }
325
+ /**
326
+ * Returns the `node:https.Agent` configured with mTLS client certificates.
327
+ * Use this with axios, got, or other HTTP clients. Returns `undefined` if mTLS is not configured.
328
+ */
329
+ getHttpsAgent() {
330
+ return this.httpsAgent;
257
331
  }
258
332
  /**
259
333
  * Create a user-scoped client for making authenticated API calls.
@@ -278,14 +352,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
278
352
  redirect_uri: redirectUri || this.config.redirectUri || ""
279
353
  };
280
354
  try {
281
- const response = await this.fetchWithTimeout(tokenUrl, {
282
- method: "POST",
283
- headers: {
284
- "Content-Type": "application/json",
285
- "User-Agent": USER_AGENT
355
+ const response = await this.fetchWithTimeout(
356
+ tokenUrl,
357
+ {
358
+ method: "POST",
359
+ headers: {
360
+ "Content-Type": "application/json",
361
+ "User-Agent": USER_AGENT
362
+ },
363
+ body: JSON.stringify(body)
286
364
  },
287
- body: JSON.stringify(body)
288
- });
365
+ this.dispatcher
366
+ );
289
367
  if (!response.ok) {
290
368
  const error = await response.json().catch(() => ({}));
291
369
  throw this.handleTokenError(error, response.status);
@@ -306,14 +384,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
306
384
  client_secret: this.config.clientSecret
307
385
  };
308
386
  try {
309
- const response = await this.fetchWithTimeout(tokenUrl, {
310
- method: "POST",
311
- headers: {
312
- "Content-Type": "application/json",
313
- "User-Agent": USER_AGENT
387
+ const response = await this.fetchWithTimeout(
388
+ tokenUrl,
389
+ {
390
+ method: "POST",
391
+ headers: {
392
+ "Content-Type": "application/json",
393
+ "User-Agent": USER_AGENT
394
+ },
395
+ body: JSON.stringify(body)
314
396
  },
315
- body: JSON.stringify(body)
316
- });
397
+ this.dispatcher
398
+ );
317
399
  if (!response.ok) {
318
400
  const error = await response.json().catch(() => ({}));
319
401
  throw new EdgeAuthenticationError(
@@ -353,11 +435,15 @@ var EdgeConnectServer = class _EdgeConnectServer {
353
435
  requestBody = { jwe: encryptMle(body, this.config.clientId, mleConfig) };
354
436
  }
355
437
  }
356
- const response = await this.fetchWithTimeout(url, {
357
- method,
358
- headers: requestHeaders,
359
- body: requestBody !== void 0 ? JSON.stringify(requestBody) : void 0
360
- });
438
+ const response = await this.fetchWithTimeout(
439
+ url,
440
+ {
441
+ method,
442
+ headers: requestHeaders,
443
+ body: requestBody !== void 0 ? JSON.stringify(requestBody) : void 0
444
+ },
445
+ this.dispatcher
446
+ );
361
447
  const rawResponseBody = await response.json().catch(() => ({}));
362
448
  let responseBody = rawResponseBody;
363
449
  if (mleEnabled && typeof rawResponseBody?.jwe === "string") {
@@ -416,14 +502,18 @@ var EdgeConnectServer = class _EdgeConnectServer {
416
502
  async sleep(ms) {
417
503
  return new Promise((resolve) => setTimeout(resolve, ms));
418
504
  }
419
- async fetchWithTimeout(url, options) {
505
+ async fetchWithTimeout(url, options, dispatcher) {
420
506
  const controller = new AbortController();
421
507
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
422
508
  try {
423
- return await fetch(url, {
509
+ const fetchOptions = {
424
510
  ...options,
425
511
  signal: controller.signal
426
- });
512
+ };
513
+ if (dispatcher) {
514
+ fetchOptions.dispatcher = dispatcher;
515
+ }
516
+ return await fetch(url, fetchOptions);
427
517
  } finally {
428
518
  clearTimeout(timeoutId);
429
519
  }
@@ -517,6 +607,7 @@ import {
517
607
  EdgeAuthenticationError as EdgeAuthenticationError2,
518
608
  EdgeConsentRequiredError as EdgeConsentRequiredError2,
519
609
  EdgeError as EdgeError2,
610
+ EdgeIdentityVerificationError as EdgeIdentityVerificationError2,
520
611
  EdgeInsufficientScopeError as EdgeInsufficientScopeError2,
521
612
  EdgeNetworkError as EdgeNetworkError2,
522
613
  EdgeNotFoundError as EdgeNotFoundError2,
@@ -525,25 +616,29 @@ import {
525
616
  isAuthenticationError,
526
617
  isConsentRequiredError,
527
618
  isEdgeError,
619
+ isIdentityVerificationError,
528
620
  isNetworkError
529
621
  } from "@edge-markets/connect";
530
- import { getEnvironmentConfig as getEnvironmentConfig2, isProductionEnvironment } from "@edge-markets/connect";
622
+ import { TRANSFER_CATEGORIES, getEnvironmentConfig as getEnvironmentConfig2, isProductionEnvironment } from "@edge-markets/connect";
531
623
  export {
532
624
  EdgeApiError2 as EdgeApiError,
533
625
  EdgeAuthenticationError2 as EdgeAuthenticationError,
534
626
  EdgeConnectServer,
535
627
  EdgeConsentRequiredError2 as EdgeConsentRequiredError,
536
628
  EdgeError2 as EdgeError,
629
+ EdgeIdentityVerificationError2 as EdgeIdentityVerificationError,
537
630
  EdgeInsufficientScopeError2 as EdgeInsufficientScopeError,
538
631
  EdgeNetworkError2 as EdgeNetworkError,
539
632
  EdgeNotFoundError2 as EdgeNotFoundError,
540
633
  EdgeTokenExchangeError2 as EdgeTokenExchangeError,
541
634
  EdgeUserClient,
635
+ TRANSFER_CATEGORIES,
542
636
  getEnvironmentConfig2 as getEnvironmentConfig,
543
637
  isApiError,
544
638
  isAuthenticationError,
545
639
  isConsentRequiredError,
546
640
  isEdgeError,
641
+ isIdentityVerificationError,
547
642
  isNetworkError,
548
643
  isProductionEnvironment
549
644
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edge-markets/connect-node",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "Server SDK for EDGE Connect token exchange and API calls",
5
5
  "author": "Edge Markets",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@edge-markets/connect": "^1.4.0"
24
+ "@edge-markets/connect": "^1.5.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsup": "^8.0.0",