@dubsdotapp/expo 0.2.20 → 0.2.21
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 +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +270 -226
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/src/hooks/useAuth.ts +10 -3
- package/src/index.ts +2 -0
- package/src/types.ts +4 -0
- package/src/utils/device.ts +55 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dubsdotapp/expo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.21",
|
|
4
4
|
"description": "React Native SDK for the Dubs betting platform",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -31,11 +31,15 @@
|
|
|
31
31
|
"@solana/web3.js": "^1.90.0",
|
|
32
32
|
"react": ">=18.0.0",
|
|
33
33
|
"react-native": ">=0.72.0",
|
|
34
|
-
"expo-secure-store": ">=13.0.0"
|
|
34
|
+
"expo-secure-store": ">=13.0.0",
|
|
35
|
+
"expo-device": ">=6.0.0"
|
|
35
36
|
},
|
|
36
37
|
"peerDependenciesMeta": {
|
|
37
38
|
"expo-secure-store": {
|
|
38
39
|
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"expo-device": {
|
|
42
|
+
"optional": true
|
|
39
43
|
}
|
|
40
44
|
},
|
|
41
45
|
"optionalDependencies": {
|
|
@@ -45,6 +49,7 @@
|
|
|
45
49
|
"@solana/web3.js": "^1.95.0",
|
|
46
50
|
"@types/react": "^18.2.0",
|
|
47
51
|
"react": "^18.2.0",
|
|
52
|
+
"expo-device": "^7.0.0",
|
|
48
53
|
"react-native": "^0.73.0",
|
|
49
54
|
"tsup": "^8.0.0",
|
|
50
55
|
"typescript": "^5.3.0"
|
package/src/hooks/useAuth.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { useState, useCallback, useRef, useContext } from 'react';
|
|
|
2
2
|
import bs58 from 'bs58';
|
|
3
3
|
import { useDubs } from '../provider';
|
|
4
4
|
import { AuthContext } from '../auth-context';
|
|
5
|
+
import { getDeviceInfo } from '../utils/device';
|
|
5
6
|
import type { AuthStatus, DubsUser } from '../types';
|
|
6
7
|
|
|
7
8
|
export interface UseAuthResult {
|
|
@@ -52,11 +53,12 @@ export function useAuth(): UseAuthResult {
|
|
|
52
53
|
const [token, setToken] = useState<string | null>(null);
|
|
53
54
|
const [error, setError] = useState<Error | null>(null);
|
|
54
55
|
|
|
55
|
-
// Stash nonce+signature between authenticate → register (single-sign flow)
|
|
56
|
+
// Stash nonce+signature+deviceInfo between authenticate → register (single-sign flow)
|
|
56
57
|
const pendingAuth = useRef<{
|
|
57
58
|
walletAddress: string;
|
|
58
59
|
nonce: string;
|
|
59
60
|
signature: string;
|
|
61
|
+
deviceInfo?: import('../utils/device').DeviceInfo;
|
|
60
62
|
} | null>(null);
|
|
61
63
|
|
|
62
64
|
const reset = useCallback(() => {
|
|
@@ -82,6 +84,10 @@ export function useAuth(): UseAuthResult {
|
|
|
82
84
|
|
|
83
85
|
const walletAddress = wallet.publicKey.toBase58();
|
|
84
86
|
|
|
87
|
+
// 0. Collect device info
|
|
88
|
+
const deviceInfo = await getDeviceInfo();
|
|
89
|
+
console.log('[useAuth] Device info:', JSON.stringify(deviceInfo, null, 2));
|
|
90
|
+
|
|
85
91
|
// 1. Get nonce
|
|
86
92
|
const { nonce, message } = await client.getNonce(walletAddress);
|
|
87
93
|
|
|
@@ -94,11 +100,11 @@ export function useAuth(): UseAuthResult {
|
|
|
94
100
|
|
|
95
101
|
// 3. Verify with server
|
|
96
102
|
setStatus('verifying');
|
|
97
|
-
const result = await client.authenticate({ walletAddress, signature, nonce });
|
|
103
|
+
const result = await client.authenticate({ walletAddress, signature, nonce, deviceInfo });
|
|
98
104
|
|
|
99
105
|
if (result.needsRegistration) {
|
|
100
106
|
// Stash credentials for register() — nonce is NOT consumed
|
|
101
|
-
pendingAuth.current = { walletAddress, nonce, signature };
|
|
107
|
+
pendingAuth.current = { walletAddress, nonce, signature, deviceInfo };
|
|
102
108
|
setStatus('needsRegistration');
|
|
103
109
|
return;
|
|
104
110
|
}
|
|
@@ -130,6 +136,7 @@ export function useAuth(): UseAuthResult {
|
|
|
130
136
|
username,
|
|
131
137
|
referralCode,
|
|
132
138
|
avatarUrl,
|
|
139
|
+
deviceInfo: pending.deviceInfo,
|
|
133
140
|
});
|
|
134
141
|
|
|
135
142
|
pendingAuth.current = null;
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -295,10 +295,13 @@ export interface NonceResult {
|
|
|
295
295
|
message: string;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
export type { DeviceInfo } from './utils/device';
|
|
299
|
+
|
|
298
300
|
export interface AuthenticateParams {
|
|
299
301
|
walletAddress: string;
|
|
300
302
|
signature: string;
|
|
301
303
|
nonce: string;
|
|
304
|
+
deviceInfo?: import('./utils/device').DeviceInfo;
|
|
302
305
|
}
|
|
303
306
|
|
|
304
307
|
export interface AuthenticateResult {
|
|
@@ -314,6 +317,7 @@ export interface RegisterParams {
|
|
|
314
317
|
username: string;
|
|
315
318
|
referralCode?: string;
|
|
316
319
|
avatarUrl?: string;
|
|
320
|
+
deviceInfo?: import('./utils/device').DeviceInfo;
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
export interface RegisterResult {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export interface DeviceInfo {
|
|
4
|
+
platform: string;
|
|
5
|
+
modelName: string | null;
|
|
6
|
+
brand: string | null;
|
|
7
|
+
manufacturer: string | null;
|
|
8
|
+
osName: string | null;
|
|
9
|
+
osVersion: string | null;
|
|
10
|
+
deviceType: number | null;
|
|
11
|
+
deviceName: string | null;
|
|
12
|
+
totalMemory: number | null;
|
|
13
|
+
modelId: string | null;
|
|
14
|
+
designName: string | null;
|
|
15
|
+
productName: string | null;
|
|
16
|
+
isDevice: boolean | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function getDeviceInfo(): Promise<DeviceInfo> {
|
|
20
|
+
try {
|
|
21
|
+
const Device = require('expo-device');
|
|
22
|
+
return {
|
|
23
|
+
platform: Platform.OS,
|
|
24
|
+
modelName: Device.modelName,
|
|
25
|
+
brand: Device.brand,
|
|
26
|
+
manufacturer: Device.manufacturer,
|
|
27
|
+
osName: Device.osName,
|
|
28
|
+
osVersion: Device.osVersion,
|
|
29
|
+
deviceType: Device.deviceType,
|
|
30
|
+
deviceName: Device.deviceName,
|
|
31
|
+
totalMemory: Device.totalMemory,
|
|
32
|
+
modelId: Device.modelId,
|
|
33
|
+
designName: Device.designName,
|
|
34
|
+
productName: Device.productName,
|
|
35
|
+
isDevice: Device.isDevice,
|
|
36
|
+
};
|
|
37
|
+
} catch {
|
|
38
|
+
// expo-device not installed — return minimal info
|
|
39
|
+
return {
|
|
40
|
+
platform: Platform.OS,
|
|
41
|
+
modelName: null,
|
|
42
|
+
brand: null,
|
|
43
|
+
manufacturer: null,
|
|
44
|
+
osName: null,
|
|
45
|
+
osVersion: null,
|
|
46
|
+
deviceType: null,
|
|
47
|
+
deviceName: null,
|
|
48
|
+
totalMemory: null,
|
|
49
|
+
modelId: null,
|
|
50
|
+
designName: null,
|
|
51
|
+
productName: null,
|
|
52
|
+
isDevice: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|