@edge-markets/connect-react-native 1.2.0 → 1.3.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/dist/index.d.mts CHANGED
@@ -1,23 +1,10 @@
1
- import { EdgeEnvironment, EdgeLinkSuccess, EdgeLinkExit, EdgeScope } from '@edge-markets/connect';
2
- export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
1
+ import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, PKCEPair } from '@edge-markets/connect';
2
+ export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
3
3
 
4
- interface EdgeLinkConfig {
5
- clientId: string;
6
- environment: EdgeEnvironment;
4
+ interface EdgeLinkConfig extends EdgeLinkConfigBase {
7
5
  redirectUri: string;
8
- onSuccess: (result: EdgeLinkSuccess) => void;
9
- onExit?: (metadata: EdgeLinkExit) => void;
10
- onEvent?: (event: EdgeLinkEvent) => void;
11
- scopes?: EdgeScope[];
12
- linkUrl?: string;
13
6
  useExternalBrowser?: boolean;
14
7
  }
15
- interface EdgeLinkEvent {
16
- eventName: EdgeLinkEventName;
17
- timestamp: number;
18
- metadata?: Record<string, unknown>;
19
- }
20
- type EdgeLinkEventName = 'OPEN' | 'CLOSE' | 'HANDOFF' | 'SUCCESS' | 'ERROR' | 'REDIRECT';
21
8
  declare class EdgeLink {
22
9
  private readonly config;
23
10
  private pkce;
@@ -155,6 +142,8 @@ declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
155
142
  interface UseEdgeLinkHandlerConfig {
156
143
  /** Your redirect URI prefix */
157
144
  redirectUri: string;
145
+ /** PKCE code verifier from the EdgeLink instance that initiated the flow */
146
+ codeVerifier: string;
158
147
  /** Called on successful auth */
159
148
  onSuccess: (result: EdgeLinkSuccess) => void;
160
149
  /** Called on error or user exit */
@@ -188,12 +177,8 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
188
177
  */
189
178
  declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
190
179
 
191
- interface PKCEPair {
192
- verifier: string;
193
- challenge: string;
194
- }
195
180
  declare function generatePKCE(): Promise<PKCEPair>;
196
- declare function generateState(): string;
181
+ declare function generateState(): Promise<string>;
197
182
  declare function isSecureCryptoAvailable(): Promise<boolean>;
198
183
 
199
- export { EdgeLink, type EdgeLinkConfig, type EdgeLinkEvent, type EdgeLinkEventName, type PKCEPair, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
184
+ export { EdgeLink, type EdgeLinkConfig, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
package/dist/index.d.ts CHANGED
@@ -1,23 +1,10 @@
1
- import { EdgeEnvironment, EdgeLinkSuccess, EdgeLinkExit, EdgeScope } from '@edge-markets/connect';
2
- export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
1
+ import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, PKCEPair } from '@edge-markets/connect';
2
+ export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
3
3
 
4
- interface EdgeLinkConfig {
5
- clientId: string;
6
- environment: EdgeEnvironment;
4
+ interface EdgeLinkConfig extends EdgeLinkConfigBase {
7
5
  redirectUri: string;
8
- onSuccess: (result: EdgeLinkSuccess) => void;
9
- onExit?: (metadata: EdgeLinkExit) => void;
10
- onEvent?: (event: EdgeLinkEvent) => void;
11
- scopes?: EdgeScope[];
12
- linkUrl?: string;
13
6
  useExternalBrowser?: boolean;
14
7
  }
15
- interface EdgeLinkEvent {
16
- eventName: EdgeLinkEventName;
17
- timestamp: number;
18
- metadata?: Record<string, unknown>;
19
- }
20
- type EdgeLinkEventName = 'OPEN' | 'CLOSE' | 'HANDOFF' | 'SUCCESS' | 'ERROR' | 'REDIRECT';
21
8
  declare class EdgeLink {
22
9
  private readonly config;
23
10
  private pkce;
@@ -155,6 +142,8 @@ declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
155
142
  interface UseEdgeLinkHandlerConfig {
156
143
  /** Your redirect URI prefix */
157
144
  redirectUri: string;
145
+ /** PKCE code verifier from the EdgeLink instance that initiated the flow */
146
+ codeVerifier: string;
158
147
  /** Called on successful auth */
159
148
  onSuccess: (result: EdgeLinkSuccess) => void;
160
149
  /** Called on error or user exit */
@@ -188,12 +177,8 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
188
177
  */
189
178
  declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
190
179
 
191
- interface PKCEPair {
192
- verifier: string;
193
- challenge: string;
194
- }
195
180
  declare function generatePKCE(): Promise<PKCEPair>;
196
- declare function generateState(): string;
181
+ declare function generateState(): Promise<string>;
197
182
  declare function isSecureCryptoAvailable(): Promise<boolean>;
198
183
 
199
- export { EdgeLink, type EdgeLinkConfig, type EdgeLinkEvent, type EdgeLinkEventName, type PKCEPair, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
184
+ export { EdgeLink, type EdgeLinkConfig, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
package/dist/index.js CHANGED
@@ -233,13 +233,9 @@ async function getRandomBytes(byteLength) {
233
233
  return ExpoRandom.getRandomBytes(byteLength);
234
234
  } catch {
235
235
  }
236
- console.warn(
237
- "[EdgeLink] Using Math.random fallback - NOT CRYPTOGRAPHICALLY SECURE!\nInstall react-native-get-random-values or expo-random for production."
236
+ throw new Error(
237
+ "[EdgeLink] No cryptographically secure random source available. Install react-native-get-random-values (and import it before EdgeLink) or expo-random."
238
238
  );
239
- for (let i = 0; i < byteLength; i++) {
240
- array[i] = Math.floor(Math.random() * 256);
241
- }
242
- return array;
243
239
  }
244
240
  async function generateRandomHex(byteLength) {
245
241
  const bytes = await getRandomBytes(byteLength);
@@ -281,16 +277,9 @@ async function generatePKCE() {
281
277
  const challenge = base64UrlEncode(hash);
282
278
  return { verifier, challenge };
283
279
  }
284
- function generateState() {
285
- const array = new Uint8Array(32);
286
- if (typeof globalThis.crypto?.getRandomValues === "function") {
287
- globalThis.crypto.getRandomValues(array);
288
- } else {
289
- for (let i = 0; i < 32; i++) {
290
- array[i] = Math.floor(Math.random() * 256);
291
- }
292
- }
293
- return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
280
+ async function generateState() {
281
+ const bytes = await getRandomBytes(32);
282
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
294
283
  }
295
284
  async function isSecureCryptoAvailable() {
296
285
  if (typeof globalThis.crypto?.getRandomValues === "function") {
@@ -395,7 +384,7 @@ var EdgeLink = class {
395
384
  this.isOpen = true;
396
385
  try {
397
386
  this.pkce = await generatePKCE();
398
- this.state = generateState();
387
+ this.state = await generateState();
399
388
  this.setupLinkListener();
400
389
  const url = this.buildLinkUrl();
401
390
  this.emitEvent("HANDOFF", { url });
@@ -630,7 +619,6 @@ function useEdgeLinkHandler(config) {
630
619
  const state = parsed.searchParams.get("state");
631
620
  const error = parsed.searchParams.get("error");
632
621
  const errorDescription = parsed.searchParams.get("error_description");
633
- const codeVerifier = parsed.searchParams.get("code_verifier");
634
622
  if (error) {
635
623
  config.onError?.({
636
624
  code: error,
@@ -641,8 +629,7 @@ function useEdgeLinkHandler(config) {
641
629
  if (code && state) {
642
630
  config.onSuccess({
643
631
  code,
644
- codeVerifier: codeVerifier || "",
645
- // Might be empty if not passed in URL
632
+ codeVerifier: config.codeVerifier,
646
633
  state
647
634
  });
648
635
  return true;
package/dist/index.mjs CHANGED
@@ -198,13 +198,9 @@ async function getRandomBytes(byteLength) {
198
198
  return ExpoRandom.getRandomBytes(byteLength);
199
199
  } catch {
200
200
  }
201
- console.warn(
202
- "[EdgeLink] Using Math.random fallback - NOT CRYPTOGRAPHICALLY SECURE!\nInstall react-native-get-random-values or expo-random for production."
201
+ throw new Error(
202
+ "[EdgeLink] No cryptographically secure random source available. Install react-native-get-random-values (and import it before EdgeLink) or expo-random."
203
203
  );
204
- for (let i = 0; i < byteLength; i++) {
205
- array[i] = Math.floor(Math.random() * 256);
206
- }
207
- return array;
208
204
  }
209
205
  async function generateRandomHex(byteLength) {
210
206
  const bytes = await getRandomBytes(byteLength);
@@ -246,16 +242,9 @@ async function generatePKCE() {
246
242
  const challenge = base64UrlEncode(hash);
247
243
  return { verifier, challenge };
248
244
  }
249
- function generateState() {
250
- const array = new Uint8Array(32);
251
- if (typeof globalThis.crypto?.getRandomValues === "function") {
252
- globalThis.crypto.getRandomValues(array);
253
- } else {
254
- for (let i = 0; i < 32; i++) {
255
- array[i] = Math.floor(Math.random() * 256);
256
- }
257
- }
258
- return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
245
+ async function generateState() {
246
+ const bytes = await getRandomBytes(32);
247
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
259
248
  }
260
249
  async function isSecureCryptoAvailable() {
261
250
  if (typeof globalThis.crypto?.getRandomValues === "function") {
@@ -360,7 +349,7 @@ var EdgeLink = class {
360
349
  this.isOpen = true;
361
350
  try {
362
351
  this.pkce = await generatePKCE();
363
- this.state = generateState();
352
+ this.state = await generateState();
364
353
  this.setupLinkListener();
365
354
  const url = this.buildLinkUrl();
366
355
  this.emitEvent("HANDOFF", { url });
@@ -595,7 +584,6 @@ function useEdgeLinkHandler(config) {
595
584
  const state = parsed.searchParams.get("state");
596
585
  const error = parsed.searchParams.get("error");
597
586
  const errorDescription = parsed.searchParams.get("error_description");
598
- const codeVerifier = parsed.searchParams.get("code_verifier");
599
587
  if (error) {
600
588
  config.onError?.({
601
589
  code: error,
@@ -606,8 +594,7 @@ function useEdgeLinkHandler(config) {
606
594
  if (code && state) {
607
595
  config.onSuccess({
608
596
  code,
609
- codeVerifier: codeVerifier || "",
610
- // Might be empty if not passed in URL
597
+ codeVerifier: config.codeVerifier,
611
598
  state
612
599
  });
613
600
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edge-markets/connect-react-native",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "React Native SDK for EDGE Connect authentication flow for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -30,7 +30,7 @@
30
30
  "author": "EdgeBoost",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@edge-markets/connect": "^1.0.0"
33
+ "@edge-markets/connect": "1.3.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18.0.0",