@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 +29 -25
- package/dist/index.d.mts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +39 -2
- package/dist/index.mjs +39 -2
- package/package.json +2 -2
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 '@
|
|
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
|
-
//
|
|
39
|
-
const
|
|
40
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
159
|
-
const user = await edge.getUser(accessToken)
|
|
168
|
+
const user = await client.getUser()
|
|
160
169
|
// Returns: { id, email, firstName, lastName, createdAt }
|
|
161
170
|
|
|
162
|
-
|
|
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
|
|
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
|
|
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
|
|
191
|
+
const status = await client.getTransfer(transferId)
|
|
184
192
|
|
|
185
193
|
// List transfers
|
|
186
|
-
const { transfers, total } = await
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
490
|
-
|
|
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
|
-
|
|
459
|
-
|
|
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.
|
|
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.
|
|
24
|
+
"@edge-markets/connect": "^1.4.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsup": "^8.0.0",
|