@oxyhq/services 5.16.35 → 5.16.36

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.
Files changed (228) hide show
  1. package/README.md +8 -26
  2. package/lib/commonjs/core/OxyServices.base.js.map +1 -1
  3. package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
  4. package/lib/commonjs/core/mixins/OxyServices.utility.js.map +1 -1
  5. package/lib/commonjs/crypto/README.md +142 -0
  6. package/lib/commonjs/crypto/core.js +147 -0
  7. package/lib/commonjs/crypto/core.js.map +1 -0
  8. package/lib/commonjs/crypto/index.js +16 -0
  9. package/lib/commonjs/crypto/index.js.map +1 -1
  10. package/lib/commonjs/crypto/keyManager.js +19 -22
  11. package/lib/commonjs/crypto/keyManager.js.map +1 -1
  12. package/lib/commonjs/crypto/signatureService.js +116 -28
  13. package/lib/commonjs/crypto/signatureService.js.map +1 -1
  14. package/lib/commonjs/index.js +0 -12
  15. package/lib/commonjs/index.js.map +1 -1
  16. package/lib/commonjs/models/interfaces.js +10 -11
  17. package/lib/commonjs/models/interfaces.js.map +1 -1
  18. package/lib/commonjs/node/index.js +10 -1
  19. package/lib/commonjs/node/index.js.map +1 -1
  20. package/lib/commonjs/node/signatureService.js +107 -0
  21. package/lib/commonjs/node/signatureService.js.map +1 -0
  22. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  23. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  24. package/lib/commonjs/ui/context/hooks/useLanguageManagement.js.map +1 -1
  25. package/lib/commonjs/ui/hooks/useLanguageManagement.js.map +1 -1
  26. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  27. package/lib/commonjs/ui/index.js +0 -2
  28. package/lib/commonjs/ui/index.js.map +1 -1
  29. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  30. package/lib/commonjs/ui/screens/OxyAuthScreen.js +11 -2
  31. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  32. package/lib/module/core/OxyServices.base.js.map +1 -1
  33. package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
  34. package/lib/module/core/mixins/OxyServices.utility.js.map +1 -1
  35. package/lib/module/crypto/README.md +142 -0
  36. package/lib/module/crypto/core.js +133 -0
  37. package/lib/module/crypto/core.js.map +1 -0
  38. package/lib/module/crypto/index.js +3 -9
  39. package/lib/module/crypto/index.js.map +1 -1
  40. package/lib/module/crypto/keyManager.js +19 -22
  41. package/lib/module/crypto/keyManager.js.map +1 -1
  42. package/lib/module/crypto/signatureService.js +113 -23
  43. package/lib/module/crypto/signatureService.js.map +1 -1
  44. package/lib/module/index.js +0 -2
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/models/interfaces.js +10 -11
  47. package/lib/module/models/interfaces.js.map +1 -1
  48. package/lib/module/node/index.js +3 -0
  49. package/lib/module/node/index.js.map +1 -1
  50. package/lib/module/node/signatureService.js +101 -0
  51. package/lib/module/node/signatureService.js.map +1 -0
  52. package/lib/module/ui/context/OxyContext.js.map +1 -1
  53. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  54. package/lib/module/ui/context/hooks/useLanguageManagement.js.map +1 -1
  55. package/lib/module/ui/hooks/useLanguageManagement.js.map +1 -1
  56. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  57. package/lib/module/ui/index.js +0 -1
  58. package/lib/module/ui/index.js.map +1 -1
  59. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  60. package/lib/module/ui/screens/OxyAuthScreen.js +11 -2
  61. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  62. package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
  63. package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
  64. package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
  65. package/lib/typescript/core/mixins/OxyServices.auth.d.ts +1 -1
  66. package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
  67. package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
  68. package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
  69. package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
  70. package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
  71. package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
  72. package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
  73. package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
  74. package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
  75. package/lib/typescript/core/mixins/OxyServices.user.d.ts +1 -2
  76. package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
  77. package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
  78. package/lib/typescript/core/mixins/index.d.ts +13 -13
  79. package/lib/typescript/core/mixins/index.d.ts.map +1 -1
  80. package/lib/typescript/core/services/SessionService.d.ts +1 -1
  81. package/lib/typescript/core/services/SessionService.d.ts.map +1 -1
  82. package/lib/typescript/crypto/core.d.ts +56 -0
  83. package/lib/typescript/crypto/core.d.ts.map +1 -0
  84. package/lib/typescript/crypto/index.d.ts +1 -9
  85. package/lib/typescript/crypto/index.d.ts.map +1 -1
  86. package/lib/typescript/crypto/keyManager.d.ts +13 -1
  87. package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
  88. package/lib/typescript/crypto/signatureService.d.ts +15 -9
  89. package/lib/typescript/crypto/signatureService.d.ts.map +1 -1
  90. package/lib/typescript/index.d.ts +1 -2
  91. package/lib/typescript/index.d.ts.map +1 -1
  92. package/lib/typescript/models/interfaces.d.ts +68 -15
  93. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  94. package/lib/typescript/node/index.d.ts +1 -0
  95. package/lib/typescript/node/index.d.ts.map +1 -1
  96. package/lib/typescript/node/signatureService.d.ts +55 -0
  97. package/lib/typescript/node/signatureService.d.ts.map +1 -0
  98. package/lib/typescript/ui/context/OxyContext.d.ts +1 -2
  99. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  100. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +1 -2
  101. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  102. package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts +1 -2
  103. package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts.map +1 -1
  104. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +1 -1
  105. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  106. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +1 -1
  107. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  108. package/lib/typescript/ui/hooks/useLanguageManagement.d.ts +1 -2
  109. package/lib/typescript/ui/hooks/useLanguageManagement.d.ts.map +1 -1
  110. package/lib/typescript/ui/hooks/useSessionManagement.d.ts +1 -2
  111. package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
  112. package/lib/typescript/ui/index.d.ts +1 -1
  113. package/lib/typescript/ui/index.d.ts.map +1 -1
  114. package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  115. package/lib/typescript/ui/stores/authStore.d.ts +1 -1
  116. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  117. package/lib/typescript/ui/utils/avatarUtils.d.ts +1 -1
  118. package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
  119. package/package.json +6 -1
  120. package/src/core/OxyServices.base.ts +1 -2
  121. package/src/core/mixins/OxyServices.auth.ts +1 -1
  122. package/src/core/mixins/OxyServices.user.ts +1 -2
  123. package/src/core/mixins/OxyServices.utility.ts +1 -2
  124. package/src/core/services/SessionService.ts +1 -1
  125. package/src/crypto/README.md +142 -0
  126. package/src/crypto/__tests__/core.test.ts +203 -0
  127. package/src/crypto/core.ts +142 -0
  128. package/src/crypto/index.ts +3 -10
  129. package/src/crypto/keyManager.ts +25 -21
  130. package/src/crypto/signatureService.ts +137 -36
  131. package/src/index.ts +2 -3
  132. package/src/models/interfaces.ts +73 -21
  133. package/src/node/index.ts +3 -0
  134. package/src/node/signatureService.ts +126 -0
  135. package/src/ui/context/OxyContext.tsx +1 -2
  136. package/src/ui/context/hooks/useAuthOperations.ts +1 -2
  137. package/src/ui/context/hooks/useLanguageManagement.ts +1 -2
  138. package/src/ui/hooks/auth/index.ts +2 -0
  139. package/src/ui/hooks/mutations/useAccountMutations.ts +1 -1
  140. package/src/ui/hooks/mutations/useServicesMutations.ts +1 -1
  141. package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
  142. package/src/ui/hooks/useLanguageManagement.ts +1 -2
  143. package/src/ui/hooks/useSessionManagement.ts +1 -2
  144. package/src/ui/index.ts +1 -2
  145. package/src/ui/screens/AccountSettingsScreen.tsx +6 -6
  146. package/src/ui/screens/AccountSwitcherScreen.tsx +1 -1
  147. package/src/ui/screens/OxyAuthScreen.tsx +11 -2
  148. package/src/ui/screens/ProfileScreen.tsx +1 -1
  149. package/src/ui/stores/authStore.ts +1 -1
  150. package/src/ui/types/navigation.ts +1 -1
  151. package/src/ui/utils/avatarUtils.ts +1 -1
  152. package/lib/commonjs/core/services/AuthService.js +0 -156
  153. package/lib/commonjs/core/services/AuthService.js.map +0 -1
  154. package/lib/commonjs/core/services/SessionTransportService.js +0 -64
  155. package/lib/commonjs/core/services/SessionTransportService.js.map +0 -1
  156. package/lib/commonjs/core/services/UserService.js +0 -123
  157. package/lib/commonjs/core/services/UserService.js.map +0 -1
  158. package/lib/commonjs/core/services/index.js +0 -34
  159. package/lib/commonjs/core/services/index.js.map +0 -1
  160. package/lib/commonjs/shared/crypto/messageBuilders.js +0 -79
  161. package/lib/commonjs/shared/crypto/messageBuilders.js.map +0 -1
  162. package/lib/commonjs/shared/crypto/platform.js +0 -118
  163. package/lib/commonjs/shared/crypto/platform.js.map +0 -1
  164. package/lib/commonjs/shared/crypto/signature.js +0 -191
  165. package/lib/commonjs/shared/crypto/signature.js.map +0 -1
  166. package/lib/commonjs/shared/index.js +0 -94
  167. package/lib/commonjs/shared/index.js.map +0 -1
  168. package/lib/commonjs/shared/models/index.js +0 -2
  169. package/lib/commonjs/shared/models/index.js.map +0 -1
  170. package/lib/commonjs/shared/transport/index.js +0 -260
  171. package/lib/commonjs/shared/transport/index.js.map +0 -1
  172. package/lib/commonjs/shared/utils/index.js +0 -82
  173. package/lib/commonjs/shared/utils/index.js.map +0 -1
  174. package/lib/module/core/services/AuthService.js +0 -151
  175. package/lib/module/core/services/AuthService.js.map +0 -1
  176. package/lib/module/core/services/SessionTransportService.js +0 -59
  177. package/lib/module/core/services/SessionTransportService.js.map +0 -1
  178. package/lib/module/core/services/UserService.js +0 -118
  179. package/lib/module/core/services/UserService.js.map +0 -1
  180. package/lib/module/core/services/index.js +0 -16
  181. package/lib/module/core/services/index.js.map +0 -1
  182. package/lib/module/shared/crypto/messageBuilders.js +0 -70
  183. package/lib/module/shared/crypto/messageBuilders.js.map +0 -1
  184. package/lib/module/shared/crypto/platform.js +0 -112
  185. package/lib/module/shared/crypto/platform.js.map +0 -1
  186. package/lib/module/shared/crypto/signature.js +0 -186
  187. package/lib/module/shared/crypto/signature.js.map +0 -1
  188. package/lib/module/shared/index.js +0 -30
  189. package/lib/module/shared/index.js.map +0 -1
  190. package/lib/module/shared/models/index.js +0 -2
  191. package/lib/module/shared/models/index.js.map +0 -1
  192. package/lib/module/shared/transport/index.js +0 -254
  193. package/lib/module/shared/transport/index.js.map +0 -1
  194. package/lib/module/shared/utils/index.js +0 -74
  195. package/lib/module/shared/utils/index.js.map +0 -1
  196. package/lib/typescript/core/services/AuthService.d.ts +0 -50
  197. package/lib/typescript/core/services/AuthService.d.ts.map +0 -1
  198. package/lib/typescript/core/services/SessionTransportService.d.ts +0 -31
  199. package/lib/typescript/core/services/SessionTransportService.d.ts.map +0 -1
  200. package/lib/typescript/core/services/UserService.d.ts +0 -39
  201. package/lib/typescript/core/services/UserService.d.ts.map +0 -1
  202. package/lib/typescript/core/services/index.d.ts +0 -13
  203. package/lib/typescript/core/services/index.d.ts.map +0 -1
  204. package/lib/typescript/shared/crypto/messageBuilders.d.ts +0 -38
  205. package/lib/typescript/shared/crypto/messageBuilders.d.ts.map +0 -1
  206. package/lib/typescript/shared/crypto/platform.d.ts +0 -54
  207. package/lib/typescript/shared/crypto/platform.d.ts.map +0 -1
  208. package/lib/typescript/shared/crypto/signature.d.ts +0 -72
  209. package/lib/typescript/shared/crypto/signature.d.ts.map +0 -1
  210. package/lib/typescript/shared/index.d.ts +0 -20
  211. package/lib/typescript/shared/index.d.ts.map +0 -1
  212. package/lib/typescript/shared/models/index.d.ts +0 -163
  213. package/lib/typescript/shared/models/index.d.ts.map +0 -1
  214. package/lib/typescript/shared/transport/index.d.ts +0 -73
  215. package/lib/typescript/shared/transport/index.d.ts.map +0 -1
  216. package/lib/typescript/shared/utils/index.d.ts +0 -28
  217. package/lib/typescript/shared/utils/index.d.ts.map +0 -1
  218. package/src/core/services/AuthService.ts +0 -153
  219. package/src/core/services/SessionTransportService.ts +0 -69
  220. package/src/core/services/UserService.ts +0 -125
  221. package/src/core/services/index.ts +0 -14
  222. package/src/shared/crypto/messageBuilders.ts +0 -89
  223. package/src/shared/crypto/platform.ts +0 -140
  224. package/src/shared/crypto/signature.ts +0 -235
  225. package/src/shared/index.ts +0 -28
  226. package/src/shared/models/index.ts +0 -173
  227. package/src/shared/transport/index.ts +0 -349
  228. package/src/shared/utils/index.ts +0 -73
@@ -4,26 +4,88 @@
4
4
  * Handles signing and verification of messages using ECDSA secp256k1.
5
5
  * Used for authenticating requests and proving identity ownership.
6
6
  *
7
- * Note: This service handles SIGNING (requires private key access via KeyManager).
8
- * For VERIFICATION, use the shared SignatureService from '../shared' instead.
7
+ * This service provides async methods for cross-platform compatibility (React Native + Node).
8
+ * For Node.js-only synchronous operations, use the node/signatureService module.
9
9
  */
10
10
 
11
- import { ec as EC } from 'elliptic';
12
11
  import { KeyManager } from './keyManager';
13
12
  import {
13
+ verifySignatureCore,
14
+ isValidPublicKey as validatePublicKey,
15
+ isTimestampFresh,
14
16
  buildAuthMessage,
15
17
  buildRegistrationMessage,
16
18
  buildRequestMessage,
17
- getCryptoAdapter,
18
- SignatureService as SharedSignatureService,
19
- isTimestampFresh,
20
- type SignedMessage,
21
- } from '../shared';
19
+ shortenPublicKey as shortenKey,
20
+ getEllipticCurve,
21
+ } from './core';
22
+
23
+ // Lazy import for expo-crypto
24
+ let ExpoCrypto: typeof import('expo-crypto') | null = null;
25
+
26
+ const ec = getEllipticCurve();
27
+
28
+ /**
29
+ * Check if we're in a React Native environment
30
+ */
31
+ function isReactNative(): boolean {
32
+ return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
33
+ }
34
+
35
+ /**
36
+ * Check if we're in a Node.js environment
37
+ */
38
+ function isNodeJS(): boolean {
39
+ return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
40
+ }
22
41
 
23
- const ec = new EC('secp256k1');
42
+ /**
43
+ * Initialize expo-crypto module
44
+ */
45
+ async function initExpoCrypto(): Promise<typeof import('expo-crypto')> {
46
+ if (!ExpoCrypto) {
47
+ ExpoCrypto = await import('expo-crypto');
48
+ }
49
+ return ExpoCrypto;
50
+ }
24
51
 
25
- // Re-export shared types
26
- export type { SignedMessage } from '../shared';
52
+ /**
53
+ * Compute SHA-256 hash of a string
54
+ */
55
+ async function sha256(message: string): Promise<string> {
56
+ // In React Native, always use expo-crypto
57
+ if (isReactNative() || !isNodeJS()) {
58
+ const Crypto = await initExpoCrypto();
59
+ return Crypto.digestStringAsync(
60
+ Crypto.CryptoDigestAlgorithm.SHA256,
61
+ message
62
+ );
63
+ }
64
+
65
+ // In Node.js, use Node's crypto module
66
+ // Use Function constructor to prevent Metro bundler from statically analyzing this require
67
+ // This ensures the require is only evaluated in Node.js runtime, not during Metro bundling
68
+ try {
69
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
70
+ const getCrypto = new Function('return require("crypto")');
71
+ const crypto = getCrypto();
72
+ return crypto.createHash('sha256').update(message).digest('hex');
73
+ } catch (error) {
74
+ // Fallback to expo-crypto if Node crypto fails
75
+ const Crypto = await initExpoCrypto();
76
+ return Crypto.digestStringAsync(
77
+ Crypto.CryptoDigestAlgorithm.SHA256,
78
+ message
79
+ );
80
+ }
81
+ }
82
+
83
+ export interface SignedMessage {
84
+ message: string;
85
+ signature: string;
86
+ publicKey: string;
87
+ timestamp: number;
88
+ }
27
89
 
28
90
  export interface AuthChallenge {
29
91
  challenge: string;
@@ -34,23 +96,39 @@ export interface AuthChallenge {
34
96
  export class SignatureService {
35
97
  /**
36
98
  * Generate a random challenge string (for offline use)
37
- * Uses shared crypto adapter
99
+ * Uses expo-crypto in React Native, crypto.randomBytes in Node.js
38
100
  */
39
101
  static async generateChallenge(): Promise<string> {
40
- const adapter = await getCryptoAdapter();
41
- const randomBytes = await adapter.randomBytes(32);
42
- return Array.from(randomBytes)
43
- .map((b: number) => b.toString(16).padStart(2, '0'))
44
- .join('');
102
+ if (isReactNative() || !isNodeJS()) {
103
+ // Use expo-crypto for React Native (expo-random is deprecated)
104
+ const Crypto = await initExpoCrypto();
105
+ const randomBytes = await Crypto.getRandomBytesAsync(32);
106
+ return Array.from(randomBytes)
107
+ .map((b: number) => b.toString(16).padStart(2, '0'))
108
+ .join('');
109
+ }
110
+
111
+ // Node.js fallback
112
+ try {
113
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
114
+ const getCrypto = new Function('return require("crypto")');
115
+ const crypto = getCrypto();
116
+ return crypto.randomBytes(32).toString('hex');
117
+ } catch (error) {
118
+ // Fallback to expo-crypto if Node crypto fails
119
+ const Crypto = await initExpoCrypto();
120
+ const randomBytes = await Crypto.getRandomBytesAsync(32);
121
+ return Array.from(randomBytes)
122
+ .map((b: number) => b.toString(16).padStart(2, '0'))
123
+ .join('');
124
+ }
45
125
  }
46
126
 
47
127
  /**
48
128
  * Hash a message using SHA-256
49
- * Uses shared crypto adapter
50
129
  */
51
130
  static async hashMessage(message: string): Promise<string> {
52
- const adapter = await getCryptoAdapter();
53
- return adapter.sha256(message);
131
+ return sha256(message);
54
132
  }
55
133
 
56
134
  /**
@@ -63,8 +141,7 @@ export class SignatureService {
63
141
  throw new Error('No identity found. Please create or import an identity first.');
64
142
  }
65
143
 
66
- const adapter = await getCryptoAdapter();
67
- const messageHash = await adapter.sha256(message);
144
+ const messageHash = await sha256(message);
68
145
  const signature = keyPair.sign(messageHash);
69
146
  return signature.toDER('hex');
70
147
  }
@@ -75,18 +152,43 @@ export class SignatureService {
75
152
  */
76
153
  static async signWithKey(message: string, privateKey: string): Promise<string> {
77
154
  const keyPair = ec.keyFromPrivate(privateKey);
78
- const adapter = await getCryptoAdapter();
79
- const messageHash = await adapter.sha256(message);
155
+ const messageHash = await sha256(message);
80
156
  const signature = keyPair.sign(messageHash);
81
157
  return signature.toDER('hex');
82
158
  }
83
159
 
84
160
  /**
85
161
  * Verify a signature against a message and public key
86
- * Uses shared SignatureService for verification
87
162
  */
88
163
  static async verify(message: string, signature: string, publicKey: string): Promise<boolean> {
89
- return SharedSignatureService.verify(message, signature, publicKey);
164
+ try {
165
+ const messageHash = await sha256(message);
166
+ return verifySignatureCore(messageHash, signature, publicKey);
167
+ } catch {
168
+ return false;
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Synchronous verification (for Node.js backend)
174
+ * Uses crypto module directly for hashing
175
+ * Note: This method should only be used in Node.js environments
176
+ */
177
+ static verifySync(message: string, signature: string, publicKey: string): boolean {
178
+ try {
179
+ if (!isNodeJS()) {
180
+ // In React Native, use async verify instead
181
+ throw new Error('verifySync should only be used in Node.js. Use verify() in React Native.');
182
+ }
183
+ // Use Function constructor to prevent Metro bundler from statically analyzing this require
184
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
185
+ const getCrypto = new Function('return require("crypto")');
186
+ const crypto = getCrypto();
187
+ const messageHash = crypto.createHash('sha256').update(message).digest('hex');
188
+ return verifySignatureCore(messageHash, signature, publicKey);
189
+ } catch {
190
+ return false;
191
+ }
90
192
  }
91
193
 
92
194
  /**
@@ -113,7 +215,6 @@ export class SignatureService {
113
215
  /**
114
216
  * Verify a signed message object
115
217
  * Checks both signature validity and timestamp freshness
116
- * Uses shared SignatureService for verification
117
218
  */
118
219
  static async verifySignedMessage(
119
220
  signedMessage: SignedMessage,
@@ -128,7 +229,7 @@ export class SignatureService {
128
229
 
129
230
  // Verify signature
130
231
  const messageWithTimestamp = `${message}:${timestamp}`;
131
- return SharedSignatureService.verify(messageWithTimestamp, signature, publicKey);
232
+ return SignatureService.verify(messageWithTimestamp, signature, publicKey);
132
233
  }
133
234
 
134
235
  /**
@@ -154,7 +255,6 @@ export class SignatureService {
154
255
 
155
256
  /**
156
257
  * Verify a challenge response
157
- * Uses shared SignatureService for verification
158
258
  */
159
259
  static async verifyChallengeResponse(
160
260
  originalChallenge: string,
@@ -162,13 +262,14 @@ export class SignatureService {
162
262
  maxAgeMs: number = 5 * 60 * 1000
163
263
  ): Promise<boolean> {
164
264
  const { challenge: signature, publicKey, timestamp } = response;
165
- return SharedSignatureService.verifyChallengeResponse(
166
- publicKey,
167
- originalChallenge,
168
- signature,
169
- timestamp,
170
- maxAgeMs
171
- );
265
+
266
+ // Check timestamp freshness
267
+ if (!isTimestampFresh(timestamp, maxAgeMs)) {
268
+ return false;
269
+ }
270
+
271
+ const message = buildAuthMessage(publicKey, originalChallenge, timestamp);
272
+ return SignatureService.verify(message, signature, publicKey);
172
273
  }
173
274
 
174
275
  /**
package/src/index.ts CHANGED
@@ -48,12 +48,11 @@ export {
48
48
  } from './utils/languageUtils';
49
49
  export type { LanguageMetadata } from './utils/languageUtils';
50
50
 
51
- // Shared models and utilities (bundled for external consumers)
52
- export * from './shared';
53
-
54
51
  // Type exports
55
52
  export type {
56
53
  OxyConfig,
54
+ User,
55
+ LoginResponse,
57
56
  Notification,
58
57
  Wallet,
59
58
  Transaction,
@@ -1,12 +1,3 @@
1
- /**
2
- * Services Package Interfaces
3
- *
4
- * Package-specific interfaces. For shared models (User, Session, etc.),
5
- * import directly from the shared module:
6
- *
7
- * import { User, LoginResponse, Session } from '../shared';
8
- */
9
-
10
1
  export interface OxyConfig {
11
2
  baseURL: string;
12
3
  cloudURL?: string;
@@ -30,8 +21,65 @@ export interface OxyConfig {
30
21
  onRequestError?: (url: string, method: string, error: Error) => void;
31
22
  }
32
23
 
33
- // Note: User and LoginResponse are in the shared module
34
- // Import them directly: import { User, LoginResponse } from '../shared';
24
+ /**
25
+ * User Model
26
+ *
27
+ * IMPORTANT:
28
+ * - id: MongoDB ObjectId (24 hex characters) - PRIMARY IDENTIFIER for all internal operations
29
+ * - publicKey: Cryptographic public key (130 hex characters) - LOOKUP KEY for authentication and identity operations
30
+ *
31
+ * Never use publicKey as an ID. Always use id (ObjectId) for:
32
+ * - Database queries
33
+ * - Session userId
34
+ * - Token userId
35
+ * - Socket room names
36
+ * - API route parameters (unless explicitly doing publicKey lookup)
37
+ */
38
+ export interface User {
39
+ id: string; // MongoDB ObjectId - PRIMARY IDENTIFIER (always 24 hex chars)
40
+ publicKey: string; // Cryptographic public key - LOOKUP KEY (130 hex chars for secp256k1)
41
+ username: string;
42
+ email?: string;
43
+ // Avatar file id (asset id)
44
+ avatar?: string;
45
+ // Privacy and security settings
46
+ privacySettings?: {
47
+ [key: string]: unknown;
48
+ };
49
+ name?: {
50
+ first?: string;
51
+ last?: string;
52
+ full?: string; // virtual, not stored in DB, returned by API
53
+ [key: string]: unknown;
54
+ };
55
+ bio?: string;
56
+ karma?: number;
57
+ location?: string;
58
+ website?: string;
59
+ createdAt?: string;
60
+ updatedAt?: string;
61
+ links?: Array<{
62
+ title?: string;
63
+ description?: string;
64
+ image?: string;
65
+ link: string;
66
+ }>;
67
+ // Social counts
68
+ _count?: {
69
+ followers?: number;
70
+ following?: number;
71
+ };
72
+ accountExpiresAfterInactivityDays?: number | null; // Days of inactivity before account expires (null = never expire)
73
+ [key: string]: unknown;
74
+ }
75
+
76
+ export interface LoginResponse {
77
+ accessToken?: string;
78
+ refreshToken?: string;
79
+ token?: string; // For backwards compatibility
80
+ user: User;
81
+ message?: string;
82
+ }
35
83
 
36
84
  export interface Notification {
37
85
  id: string;
@@ -104,8 +152,17 @@ export interface TransactionResponse {
104
152
  transaction: Transaction;
105
153
  }
106
154
 
107
- // Note: PaginationInfo and SearchProfilesResponse are in the shared module
108
- // Import them directly: import { PaginationInfo, SearchProfilesResponse } from '../shared';
155
+ export interface PaginationInfo {
156
+ total: number;
157
+ limit: number;
158
+ offset: number;
159
+ hasMore: boolean;
160
+ }
161
+
162
+ export interface SearchProfilesResponse {
163
+ data: User[];
164
+ pagination: PaginationInfo;
165
+ }
109
166
 
110
167
  export interface KarmaRule {
111
168
  id: string;
@@ -318,6 +375,8 @@ export interface AssetUrlResponse {
318
375
 
319
376
  export interface AssetDeleteSummary {
320
377
  fileId: string;
378
+ wouldDelete: boolean;
379
+ affectedApps: string[];
321
380
  remainingLinks: number;
322
381
  variants: string[];
323
382
  }
@@ -435,7 +494,6 @@ export interface AssetUploadProgress {
435
494
  }
436
495
 
437
496
  // Device Session interfaces
438
- // Note: User type should be imported from the shared module
439
497
  export interface DeviceSession {
440
498
  sessionId: string;
441
499
  deviceId: string;
@@ -444,13 +502,7 @@ export interface DeviceSession {
444
502
  lastActive: string;
445
503
  expiresAt: string;
446
504
  isCurrent: boolean;
447
- user?: {
448
- id: string;
449
- publicKey: string;
450
- username: string;
451
- avatar?: string;
452
- [key: string]: unknown;
453
- }; // Partial User - import full User type from '../shared' if needed
505
+ user?: User;
454
506
  createdAt?: string;
455
507
  }
456
508
 
package/src/node/index.ts CHANGED
@@ -13,5 +13,8 @@ export { OxyServices, OXY_CLOUD_URL, oxyClient };
13
13
  export { Models }; // Export all models as a namespace
14
14
  export * from '../models/interfaces'; // Export all models directly
15
15
 
16
+ // ------------- Node-Specific Crypto Exports -------------
17
+ export { SignatureService } from './signatureService';
18
+
16
19
  // Default export for consistency or specific use cases if needed
17
20
  export default OxyServices;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Node.js Signature Service
3
+ *
4
+ * Provides synchronous signature operations for Node.js backend.
5
+ * Uses Node's crypto module for hashing and the shared core for verification.
6
+ */
7
+
8
+ import crypto from 'crypto';
9
+ import {
10
+ verifySignatureCore,
11
+ isValidPublicKey,
12
+ isTimestampFresh,
13
+ buildAuthMessage,
14
+ buildRegistrationMessage,
15
+ buildRequestMessage,
16
+ shortenPublicKey,
17
+ CHALLENGE_TTL_MS,
18
+ MAX_SIGNATURE_AGE_MS,
19
+ } from '../crypto/core';
20
+
21
+ export class SignatureService {
22
+ /**
23
+ * Generate a random challenge string
24
+ */
25
+ static generateChallenge(): string {
26
+ return crypto.randomBytes(32).toString('hex');
27
+ }
28
+
29
+ /**
30
+ * Compute SHA-256 hash of a message (synchronous)
31
+ */
32
+ static hashMessage(message: string): string {
33
+ return crypto.createHash('sha256').update(message).digest('hex');
34
+ }
35
+
36
+ /**
37
+ * Verify an ECDSA signature (synchronous)
38
+ *
39
+ * @param message - The original message that was signed
40
+ * @param signature - The signature in DER format (hex encoded)
41
+ * @param publicKey - The public key (hex encoded, uncompressed)
42
+ * @returns true if the signature is valid
43
+ */
44
+ static verifySignature(message: string, signature: string, publicKey: string): boolean {
45
+ const messageHash = SignatureService.hashMessage(message);
46
+ return verifySignatureCore(messageHash, signature, publicKey);
47
+ }
48
+
49
+ /**
50
+ * Verify an authentication challenge response
51
+ *
52
+ * @param publicKey - The user's public key
53
+ * @param challenge - The original challenge string
54
+ * @param signature - The signature of the auth message
55
+ * @param timestamp - The timestamp when the signature was created
56
+ * @returns true if the challenge response is valid
57
+ */
58
+ static verifyChallengeResponse(
59
+ publicKey: string,
60
+ challenge: string,
61
+ signature: string,
62
+ timestamp: number
63
+ ): boolean {
64
+ // Check timestamp is not too old
65
+ if (!isTimestampFresh(timestamp, CHALLENGE_TTL_MS)) {
66
+ return false;
67
+ }
68
+
69
+ // Build the message and verify signature
70
+ const message = buildAuthMessage(publicKey, challenge, timestamp);
71
+ return SignatureService.verifySignature(message, signature, publicKey);
72
+ }
73
+
74
+ /**
75
+ * Verify a registration signature
76
+ * Signature format: oxy:register:{publicKey}:{timestamp}
77
+ */
78
+ static verifyRegistrationSignature(
79
+ publicKey: string,
80
+ signature: string,
81
+ timestamp: number
82
+ ): boolean {
83
+ // Check timestamp freshness
84
+ if (!isTimestampFresh(timestamp, MAX_SIGNATURE_AGE_MS)) {
85
+ return false;
86
+ }
87
+
88
+ const message = buildRegistrationMessage(publicKey, timestamp);
89
+ return SignatureService.verifySignature(message, signature, publicKey);
90
+ }
91
+
92
+ /**
93
+ * Verify a signed request
94
+ * Used for authenticated API operations
95
+ */
96
+ static verifyRequestSignature(
97
+ publicKey: string,
98
+ data: Record<string, unknown>,
99
+ signature: string,
100
+ timestamp: number
101
+ ): boolean {
102
+ // Check timestamp freshness
103
+ if (!isTimestampFresh(timestamp, MAX_SIGNATURE_AGE_MS)) {
104
+ return false;
105
+ }
106
+
107
+ const message = buildRequestMessage(publicKey, timestamp, data);
108
+ return SignatureService.verifySignature(message, signature, publicKey);
109
+ }
110
+
111
+ /**
112
+ * Validate that a string is a valid public key
113
+ */
114
+ static isValidPublicKey(publicKey: string): boolean {
115
+ return isValidPublicKey(publicKey);
116
+ }
117
+
118
+ /**
119
+ * Get a shortened display version of a public key
120
+ */
121
+ static shortenPublicKey(publicKey: string): string {
122
+ return shortenPublicKey(publicKey);
123
+ }
124
+ }
125
+
126
+ export default SignatureService;
@@ -11,8 +11,7 @@ import {
11
11
  } from 'react';
12
12
  import { Platform } from 'react-native';
13
13
  import { OxyServices } from '../../core';
14
- import type { ApiError } from '../../models/interfaces';
15
- import type { User } from '../../shared';
14
+ import type { User, ApiError } from '../../models/interfaces';
16
15
  import type { ClientSession } from '../../models/session';
17
16
  import { toast } from '../../lib/sonner';
18
17
  import { useAuthStore, type AuthState } from '../stores/authStore';
@@ -1,6 +1,5 @@
1
1
  import { useCallback } from 'react';
2
- import type { ApiError } from '../../../models/interfaces';
3
- import type { User } from '../../../shared';
2
+ import type { ApiError, User } from '../../../models/interfaces';
4
3
  import type { AuthState } from '../../stores/authStore';
5
4
  import type { ClientSession, SessionLoginResponse } from '../../../models/session';
6
5
  import { DeviceManager } from '../../../utils/deviceManager';
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useEffect, useMemo, useState } from 'react';
2
- import type { ApiError } from '../../../models/interfaces';
3
- import type { User } from '../../../shared';
2
+ import type { ApiError, User } from '../../../models/interfaces';
4
3
  import {
5
4
  getLanguageMetadata,
6
5
  getLanguageName,
@@ -4,3 +4,5 @@
4
4
  export { useUsernameValidation, USERNAME_MIN_LENGTH, USERNAME_REGEX, USERNAME_FORMAT_ERROR, USERNAME_DEBOUNCE_MS } from './useUsernameValidation';
5
5
  export type { UsernameValidationResult } from './useUsernameValidation';
6
6
 
7
+
8
+
@@ -1,5 +1,5 @@
1
1
  import { useMutation, useQueryClient } from '@tanstack/react-query';
2
- import type { User } from '../../../shared';
2
+ import type { User } from '../../../models/interfaces';
3
3
  import { queryKeys, invalidateAccountQueries, invalidateUserQueries } from '../queries/queryKeys';
4
4
  import { useOxy } from '../../context/OxyContext';
5
5
  import { toast } from '../../../lib/sonner';
@@ -1,5 +1,5 @@
1
1
  import { useMutation, useQueryClient } from '@tanstack/react-query';
2
- import type { User } from '../../../shared';
2
+ import type { User } from '../../../models/interfaces';
3
3
  import { queryKeys, invalidateSessionQueries } from '../queries/queryKeys';
4
4
  import { useOxy } from '../../context/OxyContext';
5
5
  import { toast } from '../../../lib/sonner';
@@ -1,5 +1,5 @@
1
1
  import { useQuery, useQueries } from '@tanstack/react-query';
2
- import type { User } from '../../../shared';
2
+ import type { User } from '../../../models/interfaces';
3
3
  import type { OxyServices } from '../../../core';
4
4
  import { queryKeys } from './queryKeys';
5
5
  import { useOxy } from '../../context/OxyContext';
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useEffect, useMemo, useState } from 'react';
2
- import type { ApiError } from '../../models/interfaces';
3
- import type { User } from '../../shared';
2
+ import type { ApiError, User } from '../../models/interfaces';
4
3
  import {
5
4
  getLanguageMetadata,
6
5
  getLanguageName,
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useMemo, useRef, useState } from 'react';
2
- import type { ApiError } from '../../models/interfaces';
3
- import type { User } from '../../shared';
2
+ import type { ApiError, User } from '../../models/interfaces';
4
3
  import type { ClientSession } from '../../models/session';
5
4
  import { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual } from '../../utils/sessionUtils';
6
5
  import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch } from '../utils/sessionHelpers';
package/src/ui/index.ts CHANGED
@@ -81,5 +81,4 @@ export {
81
81
 
82
82
  // Re-export core services for convenience in UI context
83
83
  export { OxyServices } from '../core';
84
- // Note: User and LoginResponse are available from the shared module (exported from main index)
85
- export type { ApiError } from '../models/interfaces';
84
+ export type { User, LoginResponse, ApiError } from '../models/interfaces';
@@ -233,7 +233,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
233
233
 
234
234
  // Handle locations - convert single location to array format
235
235
  if (finalUser.locations && Array.isArray(finalUser.locations)) {
236
- setLocations(finalUser.locations.map((loc: any, index: number) => ({
236
+ setLocations(finalUser.locations.map((loc, index) => ({
237
237
  id: loc.id || `existing-${index}`,
238
238
  name: loc.name,
239
239
  label: loc.label,
@@ -252,17 +252,17 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
252
252
 
253
253
  // Handle links - simple and direct like other fields
254
254
  if (finalUser.linksMetadata && Array.isArray(finalUser.linksMetadata)) {
255
- const urls = finalUser.linksMetadata.map((l: any) => l.url);
255
+ const urls = finalUser.linksMetadata.map(l => l.url);
256
256
  setLinks(urls);
257
- const metadataWithIds = finalUser.linksMetadata.map((link: any, index: number) => ({
257
+ const metadataWithIds = finalUser.linksMetadata.map((link, index) => ({
258
258
  ...link,
259
259
  id: link.id || `existing-${index}`
260
260
  }));
261
261
  setLinksMetadata(metadataWithIds);
262
262
  } else if (Array.isArray(finalUser.links)) {
263
- const simpleLinks = finalUser.links.map((l: any) => typeof l === 'string' ? l : l.link).filter(Boolean);
263
+ const simpleLinks = finalUser.links.map(l => typeof l === 'string' ? l : l.link).filter(Boolean);
264
264
  setLinks(simpleLinks);
265
- const linksWithMetadata = simpleLinks.map((url: string, index: number) => ({
265
+ const linksWithMetadata = simpleLinks.map((url, index) => ({
266
266
  url,
267
267
  title: url.replace(/^https?:\/\//, '').replace(/\/$/, ''),
268
268
  description: `Link to ${url}`,
@@ -553,7 +553,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
553
553
  }
554
554
 
555
555
  if (currentUser.linksMetadata && Array.isArray(currentUser.linksMetadata)) {
556
- setLinksMetadata(currentUser.linksMetadata.map((link: any, index: number) => ({
556
+ setLinksMetadata(currentUser.linksMetadata.map((link, index) => ({
557
557
  ...link,
558
558
  id: link.id || `existing-${index}`
559
559
  })));
@@ -15,7 +15,7 @@ import {
15
15
  import type { BaseScreenProps } from '../types/navigation';
16
16
  import type { ClientSession } from '../../models/session';
17
17
  import { fontFamilies } from '../styles/fonts';
18
- import type { User } from '../../shared';
18
+ import type { User } from '../../models/interfaces';
19
19
  import { toast } from '../../lib/sonner';
20
20
  import { confirmAction } from '../utils/confirmAction';
21
21
  import OxyIcon from '../components/icon/OxyIcon';