@edge-markets/connect-node 1.4.0 → 1.5.0

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
@@ -6,7 +6,7 @@ Server SDK for EDGE Connect token exchange and API calls.
6
6
 
7
7
  - 🔐 **Secure token exchange** - Exchange codes for tokens with PKCE
8
8
  - 🔄 **Token refresh** - Automatic refresh token handling
9
- - 📡 **Full API client** - User, balance, transfers
9
+ - 📡 **Full API client** - User, balance, transfers via `forUser()` pattern
10
10
  - 🛡️ **Typed errors** - Specific error classes for each scenario
11
11
  - 📝 **TypeScript first** - Complete type definitions
12
12
 
@@ -23,7 +23,7 @@ yarn add @edge-markets/connect-node
23
23
  ## Quick Start
24
24
 
25
25
  ```typescript
26
- import { EdgeConnectServer } from '@edgeboost/edge-connect-server'
26
+ import { EdgeConnectServer } from '@edge-markets/connect-node'
27
27
 
28
28
  // Create instance once (reuse for all requests)
29
29
  const edge = new EdgeConnectServer({
@@ -35,9 +35,10 @@ const edge = new EdgeConnectServer({
35
35
  // Exchange code from EdgeLink for tokens
36
36
  const tokens = await edge.exchangeCode(code, codeVerifier)
37
37
 
38
- // Make API calls
39
- const user = await edge.getUser(tokens.accessToken)
40
- const balance = await edge.getBalance(tokens.accessToken)
38
+ // Create a user-scoped client and make API calls
39
+ const client = edge.forUser(tokens.accessToken)
40
+ const user = await client.getUser()
41
+ const balance = await client.getBalance()
41
42
  ```
42
43
 
43
44
  ## ⚠️ Security
@@ -56,8 +57,11 @@ interface EdgeConnectServerConfig {
56
57
 
57
58
  // Optional
58
59
  apiBaseUrl?: string // Custom API URL (dev only)
59
- authDomain?: string // Custom Cognito domain (dev only)
60
+ oauthBaseUrl?: string // Custom OAuth URL (dev only)
60
61
  timeout?: number // Request timeout (default: 30000ms)
62
+ retry?: RetryConfig // Retry configuration
63
+ onRequest?: (info) => void // Hook called before each request
64
+ onResponse?: (info) => void // Hook called after each response
61
65
 
62
66
  // Optional: Message Level Encryption (Connect endpoints only)
63
67
  mle?: {
@@ -152,15 +156,19 @@ async function getValidAccessToken(userId: string): Promise<string> {
152
156
 
153
157
  ## API Methods
154
158
 
159
+ All user-scoped API methods live on `EdgeUserClient`, created via `edge.forUser(accessToken)`:
160
+
161
+ ```typescript
162
+ const client = edge.forUser(accessToken)
163
+ ```
164
+
155
165
  ### User & Balance
156
166
 
157
167
  ```typescript
158
- // Get user profile
159
- const user = await edge.getUser(accessToken)
168
+ const user = await client.getUser()
160
169
  // Returns: { id, email, firstName, lastName, createdAt }
161
170
 
162
- // Get balance
163
- const balance = await edge.getBalance(accessToken)
171
+ const balance = await client.getBalance()
164
172
  // Returns: { userId, availableBalance, currency, asOf }
165
173
  ```
166
174
 
@@ -168,7 +176,7 @@ const balance = await edge.getBalance(accessToken)
168
176
 
169
177
  ```typescript
170
178
  // Initiate transfer (requires OTP verification)
171
- const transfer = await edge.initiateTransfer(accessToken, {
179
+ const transfer = await client.initiateTransfer({
172
180
  type: 'debit', // 'debit' = pull from user, 'credit' = push to user
173
181
  amount: '100.00',
174
182
  idempotencyKey: `txn_${userId}_${Date.now()}`,
@@ -176,14 +184,14 @@ const transfer = await edge.initiateTransfer(accessToken, {
176
184
  // Returns: { transferId, status: 'pending_verification', otpMethod }
177
185
 
178
186
  // Verify with OTP
179
- const result = await edge.verifyTransfer(accessToken, transfer.transferId, userOtp)
187
+ const result = await client.verifyTransfer(transfer.transferId, userOtp)
180
188
  // Returns: { transferId, status: 'completed' | 'failed' }
181
189
 
182
190
  // Get transfer status
183
- const status = await edge.getTransfer(accessToken, transferId)
191
+ const status = await client.getTransfer(transferId)
184
192
 
185
193
  // List transfers
186
- const { transfers, total } = await edge.listTransfers(accessToken, {
194
+ const { transfers, total } = await client.listTransfers({
187
195
  status: 'completed',
188
196
  limit: 10,
189
197
  offset: 0,
@@ -194,7 +202,7 @@ const { transfers, total } = await edge.listTransfers(accessToken, {
194
202
 
195
203
  ```typescript
196
204
  // Revoke consent (disconnect user)
197
- await edge.revokeConsent(accessToken)
205
+ await client.revokeConsent()
198
206
 
199
207
  // Clean up stored tokens
200
208
  await db.edgeConnections.delete(userId)
@@ -212,7 +220,8 @@ import {
212
220
  } from '@edge-markets/connect-node'
213
221
 
214
222
  try {
215
- const balance = await edge.getBalance(accessToken)
223
+ const client = edge.forUser(accessToken)
224
+ const balance = await client.getBalance()
216
225
  } catch (error) {
217
226
  if (error instanceof EdgeAuthenticationError) {
218
227
  // Token expired - try refresh or reconnect
@@ -273,7 +282,8 @@ export class EdgeService {
273
282
 
274
283
  async getBalance(accessToken: string) {
275
284
  try {
276
- return await this.edge.getBalance(accessToken)
285
+ const client = this.edge.forUser(accessToken)
286
+ return await client.getBalance()
277
287
  } catch (error) {
278
288
  if (error instanceof EdgeConsentRequiredError) {
279
289
  this.logger.warn('User consent required')
@@ -323,7 +333,8 @@ app.post('/api/edge/exchange', async (req, res) => {
323
333
  app.get('/api/edge/balance', async (req, res) => {
324
334
  try {
325
335
  const accessToken = await getAccessTokenForUser(req.user.id)
326
- const balance = await edge.getBalance(accessToken)
336
+ const client = edge.forUser(accessToken)
337
+ const balance = await client.getBalance()
327
338
  res.json(balance)
328
339
  } catch (error) {
329
340
  // Handle errors...
@@ -339,10 +350,3 @@ app.get('/api/edge/balance', async (req, res) => {
339
350
  ## License
340
351
 
341
352
  MIT
342
-
343
-
344
-
345
-
346
-
347
-
348
-
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { EdgeEnvironment, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, EdgeTokens } from '@edge-markets/connect';
2
- export { Balance, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, Transfer, TransferList, TransferListItem, TransferStatus, TransferType, User, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
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';
3
3
 
4
4
  interface RequestInfo {
5
5
  method: string;
@@ -67,6 +67,17 @@ declare class EdgeUserClient {
67
67
  revokeConsent(): Promise<{
68
68
  revoked: boolean;
69
69
  }>;
70
+ /**
71
+ * Creates an EDGE-hosted transfer verification session.
72
+ * Returns a `verificationUrl` to open in an iframe or popup.
73
+ * The handoff token is single-use and expires in 120 seconds.
74
+ */
75
+ createVerificationSession(transferId: string, options: CreateVerificationSessionRequest): Promise<VerificationSession>;
76
+ /**
77
+ * Polls the status of a verification session.
78
+ * Use as an alternative to postMessage events.
79
+ */
80
+ getVerificationSessionStatus(transferId: string, sessionId: string): Promise<VerificationSessionStatusResponse>;
70
81
  }
71
82
 
72
83
  declare class EdgeConnectServer {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { EdgeEnvironment, User, VerifyIdentityOptions, VerifyIdentityResult, Balance, Transfer, ListTransfersParams, TransferList, EdgeTokens } from '@edge-markets/connect';
2
- export { Balance, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeInsufficientScopeError, EdgeNetworkError, EdgeNotFoundError, EdgeTokenExchangeError, EdgeTokens, ListTransfersParams, Transfer, TransferList, TransferListItem, TransferStatus, TransferType, User, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isEdgeError, isNetworkError, isProductionEnvironment } from '@edge-markets/connect';
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';
3
3
 
4
4
  interface RequestInfo {
5
5
  method: string;
@@ -67,6 +67,17 @@ declare class EdgeUserClient {
67
67
  revokeConsent(): Promise<{
68
68
  revoked: boolean;
69
69
  }>;
70
+ /**
71
+ * Creates an EDGE-hosted transfer verification session.
72
+ * Returns a `verificationUrl` to open in an iframe or popup.
73
+ * The handoff token is single-use and expires in 120 seconds.
74
+ */
75
+ createVerificationSession(transferId: string, options: CreateVerificationSessionRequest): Promise<VerificationSession>;
76
+ /**
77
+ * Polls the status of a verification session.
78
+ * Use as an alternative to postMessage events.
79
+ */
80
+ getVerificationSessionStatus(transferId: string, sessionId: string): Promise<VerificationSessionStatusResponse>;
70
81
  }
71
82
 
72
83
  declare class EdgeConnectServer {
package/dist/index.js CHANGED
@@ -138,6 +138,30 @@ var EdgeUserClient = class {
138
138
  async revokeConsent() {
139
139
  return this.server._apiRequest("DELETE", "/consent", this.accessToken);
140
140
  }
141
+ /**
142
+ * Creates an EDGE-hosted transfer verification session.
143
+ * Returns a `verificationUrl` to open in an iframe or popup.
144
+ * The handoff token is single-use and expires in 120 seconds.
145
+ */
146
+ async createVerificationSession(transferId, options) {
147
+ return this.server._apiRequest(
148
+ "POST",
149
+ `/transfer/${encodeURIComponent(transferId)}/verification-session`,
150
+ this.accessToken,
151
+ { origin: options.origin }
152
+ );
153
+ }
154
+ /**
155
+ * Polls the status of a verification session.
156
+ * Use as an alternative to postMessage events.
157
+ */
158
+ async getVerificationSessionStatus(transferId, sessionId) {
159
+ return this.server._apiRequest(
160
+ "GET",
161
+ `/transfer/${encodeURIComponent(transferId)}/verification-session/${encodeURIComponent(sessionId)}`,
162
+ this.accessToken
163
+ );
164
+ }
141
165
  };
142
166
 
143
167
  // src/mle.ts
@@ -486,8 +510,21 @@ var EdgeConnectServer = class _EdgeConnectServer {
486
510
  }
487
511
  }
488
512
  if (status === 404) {
489
- const resourceType = path.includes("/transfer") ? "Transfer" : "Resource";
490
- const resourceId = path.split("/").pop() || "unknown";
513
+ let resourceType = "Resource";
514
+ let resourceId = path.split("/").pop() || "unknown";
515
+ if (path.includes("/verification-session/")) {
516
+ resourceType = "VerificationSession";
517
+ const parts = path.split("/");
518
+ const vsIdx = parts.indexOf("verification-session");
519
+ resourceId = vsIdx >= 0 && parts[vsIdx + 1] ? parts[vsIdx + 1] : "unknown";
520
+ } else if (path.includes("/verification-session")) {
521
+ resourceType = "Transfer";
522
+ const parts = path.split("/");
523
+ const txIdx = parts.indexOf("transfer");
524
+ resourceId = txIdx >= 0 && parts[txIdx + 1] ? parts[txIdx + 1] : "unknown";
525
+ } else if (path.includes("/transfer")) {
526
+ resourceType = "Transfer";
527
+ }
491
528
  return new import_connect2.EdgeNotFoundError(resourceType, resourceId);
492
529
  }
493
530
  if (status === 422 && error.error === "identity_verification_failed") {
package/dist/index.mjs CHANGED
@@ -107,6 +107,30 @@ var EdgeUserClient = class {
107
107
  async revokeConsent() {
108
108
  return this.server._apiRequest("DELETE", "/consent", this.accessToken);
109
109
  }
110
+ /**
111
+ * Creates an EDGE-hosted transfer verification session.
112
+ * Returns a `verificationUrl` to open in an iframe or popup.
113
+ * The handoff token is single-use and expires in 120 seconds.
114
+ */
115
+ async createVerificationSession(transferId, options) {
116
+ return this.server._apiRequest(
117
+ "POST",
118
+ `/transfer/${encodeURIComponent(transferId)}/verification-session`,
119
+ this.accessToken,
120
+ { origin: options.origin }
121
+ );
122
+ }
123
+ /**
124
+ * Polls the status of a verification session.
125
+ * Use as an alternative to postMessage events.
126
+ */
127
+ async getVerificationSessionStatus(transferId, sessionId) {
128
+ return this.server._apiRequest(
129
+ "GET",
130
+ `/transfer/${encodeURIComponent(transferId)}/verification-session/${encodeURIComponent(sessionId)}`,
131
+ this.accessToken
132
+ );
133
+ }
110
134
  };
111
135
 
112
136
  // src/mle.ts
@@ -455,8 +479,21 @@ var EdgeConnectServer = class _EdgeConnectServer {
455
479
  }
456
480
  }
457
481
  if (status === 404) {
458
- const resourceType = path.includes("/transfer") ? "Transfer" : "Resource";
459
- const resourceId = path.split("/").pop() || "unknown";
482
+ let resourceType = "Resource";
483
+ let resourceId = path.split("/").pop() || "unknown";
484
+ if (path.includes("/verification-session/")) {
485
+ resourceType = "VerificationSession";
486
+ const parts = path.split("/");
487
+ const vsIdx = parts.indexOf("verification-session");
488
+ resourceId = vsIdx >= 0 && parts[vsIdx + 1] ? parts[vsIdx + 1] : "unknown";
489
+ } else if (path.includes("/verification-session")) {
490
+ resourceType = "Transfer";
491
+ const parts = path.split("/");
492
+ const txIdx = parts.indexOf("transfer");
493
+ resourceId = txIdx >= 0 && parts[txIdx + 1] ? parts[txIdx + 1] : "unknown";
494
+ } else if (path.includes("/transfer")) {
495
+ resourceType = "Transfer";
496
+ }
460
497
  return new EdgeNotFoundError(resourceType, resourceId);
461
498
  }
462
499
  if (status === 422 && error.error === "identity_verification_failed") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edge-markets/connect-node",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
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.3.0"
24
+ "@edge-markets/connect": "^1.4.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsup": "^8.0.0",