@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 +15 -5
- package/dist/index.d.mts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.js +129 -30
- package/dist/index.mjs +126 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -175,7 +175,7 @@ const balance = await client.getBalance()
|
|
|
175
175
|
### Transfers
|
|
176
176
|
|
|
177
177
|
```typescript
|
|
178
|
-
// Initiate transfer
|
|
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
|
-
//
|
|
187
|
-
|
|
188
|
-
//
|
|
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
|
|
2
|
-
|
|
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
|
|
2
|
-
|
|
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(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
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(
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
-
|
|
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(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
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(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
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(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
-
|
|
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(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
24
|
+
"@edge-markets/connect": "^1.5.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsup": "^8.0.0",
|