toss-expo-sdk 0.1.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.
Files changed (116) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +292 -0
  3. package/lib/module/ble.js +103 -0
  4. package/lib/module/ble.js.map +1 -0
  5. package/lib/module/client/TossClient.js +324 -0
  6. package/lib/module/client/TossClient.js.map +1 -0
  7. package/lib/module/client/index.js +4 -0
  8. package/lib/module/client/index.js.map +1 -0
  9. package/lib/module/contexts/WalletContext.js +99 -0
  10. package/lib/module/contexts/WalletContext.js.map +1 -0
  11. package/lib/module/discovery.js +434 -0
  12. package/lib/module/discovery.js.map +1 -0
  13. package/lib/module/errors.js +47 -0
  14. package/lib/module/errors.js.map +1 -0
  15. package/lib/module/examples/offlinePaymentFlow.js +234 -0
  16. package/lib/module/examples/offlinePaymentFlow.js.map +1 -0
  17. package/lib/module/index.js +32 -0
  18. package/lib/module/index.js.map +1 -0
  19. package/lib/module/intent.js +223 -0
  20. package/lib/module/intent.js.map +1 -0
  21. package/lib/module/intentManager.js +145 -0
  22. package/lib/module/intentManager.js.map +1 -0
  23. package/lib/module/internal/arciumHelper.js +50 -0
  24. package/lib/module/internal/arciumHelper.js.map +1 -0
  25. package/lib/module/nfc.js +54 -0
  26. package/lib/module/nfc.js.map +1 -0
  27. package/lib/module/noise.js +14 -0
  28. package/lib/module/noise.js.map +1 -0
  29. package/lib/module/package.json +1 -0
  30. package/lib/module/qr.js +57 -0
  31. package/lib/module/qr.js.map +1 -0
  32. package/lib/module/reconciliation.js +329 -0
  33. package/lib/module/reconciliation.js.map +1 -0
  34. package/lib/module/services/authService.js +205 -0
  35. package/lib/module/services/authService.js.map +1 -0
  36. package/lib/module/storage/secureStorage.js +89 -0
  37. package/lib/module/storage/secureStorage.js.map +1 -0
  38. package/lib/module/storage.js +16 -0
  39. package/lib/module/storage.js.map +1 -0
  40. package/lib/module/sync.js +64 -0
  41. package/lib/module/sync.js.map +1 -0
  42. package/lib/module/types/tossUser.js +41 -0
  43. package/lib/module/types/tossUser.js.map +1 -0
  44. package/lib/module/utils/nonceUtils.js +38 -0
  45. package/lib/module/utils/nonceUtils.js.map +1 -0
  46. package/lib/typescript/package.json +1 -0
  47. package/lib/typescript/src/__tests__/index.test.d.ts +1 -0
  48. package/lib/typescript/src/__tests__/index.test.d.ts.map +1 -0
  49. package/lib/typescript/src/__tests__/reconciliation.test.d.ts +6 -0
  50. package/lib/typescript/src/__tests__/reconciliation.test.d.ts.map +1 -0
  51. package/lib/typescript/src/ble.d.ts +10 -0
  52. package/lib/typescript/src/ble.d.ts.map +1 -0
  53. package/lib/typescript/src/client/TossClient.d.ts +110 -0
  54. package/lib/typescript/src/client/TossClient.d.ts.map +1 -0
  55. package/lib/typescript/src/client/index.d.ts +3 -0
  56. package/lib/typescript/src/client/index.d.ts.map +1 -0
  57. package/lib/typescript/src/contexts/WalletContext.d.ts +20 -0
  58. package/lib/typescript/src/contexts/WalletContext.d.ts.map +1 -0
  59. package/lib/typescript/src/discovery.d.ts +188 -0
  60. package/lib/typescript/src/discovery.d.ts.map +1 -0
  61. package/lib/typescript/src/errors.d.ts +27 -0
  62. package/lib/typescript/src/errors.d.ts.map +1 -0
  63. package/lib/typescript/src/examples/offlinePaymentFlow.d.ts +48 -0
  64. package/lib/typescript/src/examples/offlinePaymentFlow.d.ts.map +1 -0
  65. package/lib/typescript/src/index.d.ts +13 -0
  66. package/lib/typescript/src/index.d.ts.map +1 -0
  67. package/lib/typescript/src/intent.d.ts +84 -0
  68. package/lib/typescript/src/intent.d.ts.map +1 -0
  69. package/lib/typescript/src/intentManager.d.ts +46 -0
  70. package/lib/typescript/src/intentManager.d.ts.map +1 -0
  71. package/lib/typescript/src/internal/arciumHelper.d.ts +19 -0
  72. package/lib/typescript/src/internal/arciumHelper.d.ts.map +1 -0
  73. package/lib/typescript/src/nfc.d.ts +7 -0
  74. package/lib/typescript/src/nfc.d.ts.map +1 -0
  75. package/lib/typescript/src/noise.d.ts +5 -0
  76. package/lib/typescript/src/noise.d.ts.map +1 -0
  77. package/lib/typescript/src/qr.d.ts +6 -0
  78. package/lib/typescript/src/qr.d.ts.map +1 -0
  79. package/lib/typescript/src/reconciliation.d.ts +65 -0
  80. package/lib/typescript/src/reconciliation.d.ts.map +1 -0
  81. package/lib/typescript/src/services/authService.d.ts +55 -0
  82. package/lib/typescript/src/services/authService.d.ts.map +1 -0
  83. package/lib/typescript/src/storage/secureStorage.d.ts +7 -0
  84. package/lib/typescript/src/storage/secureStorage.d.ts.map +1 -0
  85. package/lib/typescript/src/storage.d.ts +4 -0
  86. package/lib/typescript/src/storage.d.ts.map +1 -0
  87. package/lib/typescript/src/sync.d.ts +40 -0
  88. package/lib/typescript/src/sync.d.ts.map +1 -0
  89. package/lib/typescript/src/types/tossUser.d.ts +39 -0
  90. package/lib/typescript/src/types/tossUser.d.ts.map +1 -0
  91. package/lib/typescript/src/utils/nonceUtils.d.ts +8 -0
  92. package/lib/typescript/src/utils/nonceUtils.d.ts.map +1 -0
  93. package/package.json +176 -0
  94. package/src/__tests__/index.test.tsx +1 -0
  95. package/src/__tests__/reconciliation.test.tsx +361 -0
  96. package/src/ble.ts +138 -0
  97. package/src/client/TossClient.ts +435 -0
  98. package/src/client/index.ts +2 -0
  99. package/src/contexts/WalletContext.tsx +127 -0
  100. package/src/discovery.ts +542 -0
  101. package/src/errors.ts +51 -0
  102. package/src/examples/offlinePaymentFlow.ts +331 -0
  103. package/src/index.tsx +61 -0
  104. package/src/intent.ts +328 -0
  105. package/src/intentManager.ts +164 -0
  106. package/src/internal/arciumHelper.ts +58 -0
  107. package/src/nfc.ts +57 -0
  108. package/src/noise.ts +9 -0
  109. package/src/qr.tsx +65 -0
  110. package/src/reconciliation.ts +421 -0
  111. package/src/services/authService.ts +238 -0
  112. package/src/storage/secureStorage.ts +100 -0
  113. package/src/storage.ts +17 -0
  114. package/src/sync.ts +101 -0
  115. package/src/types/tossUser.ts +81 -0
  116. package/src/utils/nonceUtils.ts +56 -0
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+
3
+ import { Connection, PublicKey } from '@solana/web3.js';
4
+ import { createIntent } from "../intent.js";
5
+ import { secureStoreIntent, getSecureIntent, getAllSecureIntents } from "../storage/secureStorage.js";
6
+ import { processIntentsForSync } from "../intentManager.js";
7
+ import { TossError, NetworkError, StorageError, ERROR_CODES } from "../errors.js";
8
+ import { createNonceAccount, getNonce } from "../utils/nonceUtils.js";
9
+ import { useWallet } from "../contexts/WalletContext.js";
10
+ import { syncToChain, checkSyncStatus } from "../sync.js";
11
+ import { detectConflicts, getReconciliationState } from "../reconciliation.js";
12
+ const DEFAULT_RETRY_OPTIONS = {
13
+ maxRetries: 3,
14
+ retryDelay: 1000 // 1 second
15
+ };
16
+ export class TossClient {
17
+ static createClient(config) {
18
+ return new TossClient(config);
19
+ }
20
+ constructor(config) {
21
+ this.config = {
22
+ projectId: config.projectId,
23
+ mode: config.mode || 'devnet',
24
+ privateTransactions: config.privateTransactions || false,
25
+ provider: config.provider,
26
+ sync: config.sync || {
27
+ syncBackupDb: false
28
+ },
29
+ rpcUrl: config.rpcUrl || this.getDefaultRpcUrl(config.mode || 'devnet'),
30
+ maxRetries: config.maxRetries ?? DEFAULT_RETRY_OPTIONS.maxRetries,
31
+ retryDelay: config.retryDelay ?? DEFAULT_RETRY_OPTIONS.retryDelay,
32
+ feePayer: config.feePayer
33
+ };
34
+ this.connection = new Connection(this.config.rpcUrl, 'confirmed');
35
+ this.walletContext = useWallet();
36
+ if (!this.walletContext) {
37
+ throw new Error('TossClient must be used within a WalletProvider');
38
+ }
39
+ }
40
+ getDefaultRpcUrl(network) {
41
+ const urls = {
42
+ 'devnet': 'https://api.devnet.solana.com',
43
+ 'testnet': 'https://api.testnet.solana.com',
44
+ 'mainnet-beta': 'https://api.mainnet-beta.solana.com'
45
+ };
46
+ return urls[network] || urls.devnet;
47
+ }
48
+ async withRetry(fn, context) {
49
+ let lastError = null;
50
+ const {
51
+ maxRetries,
52
+ retryDelay
53
+ } = this.config;
54
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
55
+ try {
56
+ return await fn();
57
+ } catch (error) {
58
+ lastError = error;
59
+
60
+ // Don't retry on validation errors
61
+ if (error instanceof TossError) {
62
+ throw error;
63
+ }
64
+
65
+ // Exponential backoff
66
+ if (attempt < maxRetries) {
67
+ const delay = retryDelay * Math.pow(2, attempt - 1);
68
+ await new Promise(resolve => setTimeout(resolve, delay));
69
+ }
70
+ }
71
+ }
72
+ throw new NetworkError(`Failed after ${maxRetries} attempts: ${lastError?.message}`, {
73
+ context,
74
+ cause: lastError
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Initialize a nonce account for durable transactions
80
+ * @param amount SOL amount to fund the nonce account with (default: 1 SOL)
81
+ * @returns Object containing nonce account and authority public keys
82
+ */
83
+ async initializeNonceAccount(amount = 1) {
84
+ if (!this.config.feePayer) {
85
+ throw new Error('Fee payer keypair is required for nonce account creation');
86
+ }
87
+ const {
88
+ nonceAccount,
89
+ nonceAuth
90
+ } = await createNonceAccount(this.connection, this.config.feePayer, undefined, amount * 1e9 // Convert SOL to lamports
91
+ );
92
+ this.nonceAccount = nonceAccount;
93
+ this.nonceAuth = nonceAuth;
94
+ return {
95
+ nonceAccount: nonceAccount.publicKey.toBase58(),
96
+ nonceAuth: nonceAuth.toBase58()
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Get the current nonce value from the nonce account
102
+ * @returns The current nonce value as a base58 string
103
+ */
104
+ async getCurrentNonce() {
105
+ if (!this.nonceAccount) {
106
+ throw new Error('Nonce account not initialized. Call initializeNonceAccount() first.');
107
+ }
108
+ return getNonce(this.connection, this.nonceAccount.publicKey);
109
+ }
110
+ async createIntent(sender, recipient, amount, feePayer, options = {}) {
111
+ return this.withRetry(async () => {
112
+ try {
113
+ if (!this.connection) {
114
+ throw new TossError('Connection not initialized', ERROR_CODES.NETWORK_ERROR);
115
+ }
116
+
117
+ // Handle 'current' sender to use the wallet context
118
+ const senderKeypair = sender === 'current' ? this.walletContext.keypair : sender;
119
+ if (!senderKeypair) {
120
+ throw new TossError('No sender keypair provided and no wallet is connected', ERROR_CODES.SIGNATURE_VERIFICATION_FAILED);
121
+ }
122
+
123
+ // Convert string addresses to PublicKey if needed
124
+ const recipientPubkey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
125
+ const feePayerPubkey = feePayer ? typeof feePayer === 'string' ? new PublicKey(feePayer) : feePayer : senderKeypair.publicKey;
126
+
127
+ // Set up nonce account and auth if using durable nonce
128
+ if (options.useDurableNonce && this.nonceAccount && this.nonceAuth) {
129
+ // nonce account and auth are passed via options to createIntent
130
+ }
131
+
132
+ // Get the latest blockhash (no need to store it as it's handled internally)
133
+ await this.connection.getLatestBlockhash();
134
+ const intent = await createIntent(senderKeypair, recipientPubkey, amount, this.connection, {
135
+ ...options,
136
+ feePayer: feePayerPubkey,
137
+ nonceAccount: options.useDurableNonce ? this.nonceAccount : undefined,
138
+ nonceAuth: options.useDurableNonce ? this.nonceAuth : undefined
139
+ });
140
+ await secureStoreIntent(intent);
141
+ return intent;
142
+ } catch (error) {
143
+ if (error instanceof TossError) throw error;
144
+ throw new TossError('Failed to create intent', ERROR_CODES.TRANSACTION_FAILED, {
145
+ cause: error
146
+ });
147
+ }
148
+ }, 'createIntent');
149
+ }
150
+ async getIntents() {
151
+ return this.withRetry(async () => {
152
+ try {
153
+ return await getAllSecureIntents();
154
+ } catch (error) {
155
+ if (error instanceof TossError) throw error;
156
+ throw new StorageError('Failed to retrieve intents', {
157
+ cause: error
158
+ });
159
+ }
160
+ }, 'getIntents');
161
+ }
162
+ async updateIntentStatus(intentId, status, error) {
163
+ return this.withRetry(async () => {
164
+ try {
165
+ const intent = await getSecureIntent(intentId);
166
+ if (!intent) return null;
167
+
168
+ // Ensure updatedAt is a number (timestamp)
169
+ const updatedAt = Date.now();
170
+ const updatedIntent = {
171
+ ...intent,
172
+ status,
173
+ updatedAt,
174
+ ...(error ? {
175
+ error
176
+ } : {})
177
+ };
178
+ await secureStoreIntent(updatedIntent);
179
+ return updatedIntent;
180
+ } catch (error) {
181
+ if (error instanceof TossError) throw error;
182
+ throw new StorageError('Failed to update intent status', {
183
+ cause: error,
184
+ intentId,
185
+ status
186
+ });
187
+ }
188
+ }, 'updateIntentStatus');
189
+ }
190
+ async sync() {
191
+ return this.withRetry(async () => {
192
+ try {
193
+ const intents = await getAllSecureIntents();
194
+ if (!this.config.sync?.syncBackupDb || !this.config.sync.dbUrl) {
195
+ return intents;
196
+ }
197
+
198
+ // Process intents for sync and update their statuses
199
+ const processedIntents = await processIntentsForSync(intents, this.connection);
200
+
201
+ // Save updated intents
202
+ await Promise.all(processedIntents.map(intent => secureStoreIntent(intent)));
203
+ return processedIntents;
204
+ } catch (error) {
205
+ if (error instanceof TossError) throw error;
206
+ throw new NetworkError('Failed to sync intents', {
207
+ cause: error
208
+ });
209
+ }
210
+ }, 'sync');
211
+ }
212
+
213
+ /**
214
+ * Full synchronisation with Solana blockchain (TOSS Section 9)
215
+ *
216
+ * Performs complete reconciliation:
217
+ * - Detects conflicts with onchain state
218
+ * - Settles all pending intents
219
+ * - Updates local state deterministically
220
+ *
221
+ * @returns Complete sync results including settlements, conflicts, and final state
222
+ */
223
+ async fullSync() {
224
+ return this.withRetry(async () => {
225
+ try {
226
+ return await syncToChain(this.connection, this.config.feePayer?.publicKey);
227
+ } catch (error) {
228
+ if (error instanceof TossError) throw error;
229
+ throw new NetworkError('Full sync failed', {
230
+ cause: error
231
+ });
232
+ }
233
+ }, 'fullSync');
234
+ }
235
+
236
+ /**
237
+ * Check synchronisation status without settling
238
+ *
239
+ * Lightweight operation to query current reconciliation state
240
+ * without committing any settlements to the blockchain.
241
+ */
242
+ async checkSyncStatus() {
243
+ return this.withRetry(async () => {
244
+ return await checkSyncStatus(this.connection);
245
+ }, 'checkSyncStatus');
246
+ }
247
+
248
+ /**
249
+ * Detect conflicts between local intents and onchain state
250
+ *
251
+ * Useful for monitoring and alerting users to potential issues
252
+ * before attempting settlement.
253
+ */
254
+ async detectIntentConflicts() {
255
+ return this.withRetry(async () => {
256
+ return await detectConflicts(this.connection);
257
+ }, 'detectIntentConflicts');
258
+ }
259
+
260
+ /**
261
+ * Get current reconciliation state
262
+ *
263
+ * Returns summary of processed, failed, and conflicting intents
264
+ * for UI updates or logging.
265
+ */
266
+ async getReconciliationStatus() {
267
+ return this.withRetry(async () => {
268
+ return await getReconciliationState(this.connection);
269
+ }, 'getReconciliationStatus');
270
+ }
271
+
272
+ /**
273
+ * Create an intent from the current user's wallet
274
+ */
275
+ async createUserIntent(recipient, amount, options = {}) {
276
+ if (!this.walletContext.user) {
277
+ throw new TossError('No user is currently signed in', ERROR_CODES.SIGNATURE_VERIFICATION_FAILED);
278
+ }
279
+
280
+ // Ensure wallet is unlocked
281
+ if (!this.walletContext.isUnlocked) {
282
+ const unlocked = await this.walletContext.unlockWallet();
283
+ if (!unlocked) {
284
+ throw new TossError('Wallet is locked', ERROR_CODES.SIGNATURE_VERIFICATION_FAILED);
285
+ }
286
+ }
287
+ const recipientPubkey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
288
+ return this.createIntent('current',
289
+ // This will use the wallet context's keypair
290
+ recipientPubkey, amount, this.walletContext.user.wallet.publicKey, {
291
+ ...options,
292
+ memo: options.memo || `TOSS transfer to ${recipientPubkey.toBase58()}`
293
+ });
294
+ }
295
+
296
+ /**
297
+ * Get the current user's wallet address
298
+ */
299
+ getCurrentUserAddress() {
300
+ return this.walletContext.user?.wallet.publicKey.toString() || null;
301
+ }
302
+
303
+ /**
304
+ * Check if the wallet is currently unlocked
305
+ */
306
+ isWalletUnlocked() {
307
+ return this.walletContext.isUnlocked;
308
+ }
309
+
310
+ /**
311
+ * Lock the wallet
312
+ */
313
+ async lockWallet() {
314
+ await this.walletContext.lockWallet();
315
+ }
316
+
317
+ /**
318
+ * Sign out the current user
319
+ */
320
+ async signOut() {
321
+ await this.walletContext.signOut();
322
+ }
323
+ }
324
+ //# sourceMappingURL=TossClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Connection","PublicKey","createIntent","secureStoreIntent","getSecureIntent","getAllSecureIntents","processIntentsForSync","TossError","NetworkError","StorageError","ERROR_CODES","createNonceAccount","getNonce","useWallet","syncToChain","checkSyncStatus","detectConflicts","getReconciliationState","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","TossClient","createClient","config","constructor","projectId","mode","privateTransactions","provider","sync","syncBackupDb","rpcUrl","getDefaultRpcUrl","feePayer","connection","walletContext","Error","network","urls","devnet","withRetry","fn","context","lastError","attempt","error","delay","Math","pow","Promise","resolve","setTimeout","message","cause","initializeNonceAccount","amount","nonceAccount","nonceAuth","undefined","publicKey","toBase58","getCurrentNonce","sender","recipient","options","NETWORK_ERROR","senderKeypair","keypair","SIGNATURE_VERIFICATION_FAILED","recipientPubkey","feePayerPubkey","useDurableNonce","getLatestBlockhash","intent","TRANSACTION_FAILED","getIntents","updateIntentStatus","intentId","status","updatedAt","Date","now","updatedIntent","intents","dbUrl","processedIntents","all","map","fullSync","detectIntentConflicts","getReconciliationStatus","createUserIntent","user","isUnlocked","unlocked","unlockWallet","wallet","memo","getCurrentUserAddress","toString","isWalletUnlocked","lockWallet","signOut"],"sourceRoot":"../../../src","sources":["client/TossClient.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export * from "./TossClient.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["client/index.ts"],"mappings":";;AAAA,cAAc,iBAAc","ignoreList":[]}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ import { createContext, useContext, useState, useEffect } from 'react';
4
+ import { AuthService } from "../services/authService.js";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ const WalletContext = /*#__PURE__*/createContext(undefined);
7
+ export const WalletProvider = ({
8
+ children
9
+ }) => {
10
+ const [isInitialized, setIsInitialized] = useState(false);
11
+ const [isUnlocked, setIsUnlocked] = useState(false);
12
+ const [user, setUser] = useState(null);
13
+ const [keypair, setKeypair] = useState(null);
14
+ useEffect(() => {
15
+ const checkAuth = async () => {
16
+ try {
17
+ const session = await AuthService.getSession();
18
+ if (session) {
19
+ // In a real app, you'd fetch the user from your backend
20
+ const {
21
+ user
22
+ } = await AuthService.signInWithWallet(session.walletAddress);
23
+ setUser(user);
24
+ setIsUnlocked(await AuthService.isWalletUnlocked());
25
+ }
26
+ } catch (error) {
27
+ console.error('Auth check failed:', error);
28
+ } finally {
29
+ setIsInitialized(true);
30
+ }
31
+ };
32
+ checkAuth();
33
+ }, []);
34
+ const unlockWallet = async () => {
35
+ try {
36
+ // Biometric authentication REQUIRED - throws if not authorized
37
+ const unlockedKeypair = await AuthService.unlockWalletWithBiometrics();
38
+ if (unlockedKeypair) {
39
+ // Keypair held ONLY in React state memory (NOT persisted to disk)
40
+ setKeypair(unlockedKeypair);
41
+ setIsUnlocked(true);
42
+ return true;
43
+ }
44
+ return false;
45
+ } catch (error) {
46
+ console.error('Biometric authentication failed:', error);
47
+ setIsUnlocked(false);
48
+ setKeypair(null);
49
+ return false;
50
+ }
51
+ };
52
+ const lockWallet = async () => {
53
+ // Clear keypair from memory (from React state)
54
+ // Encrypted keypair remains stored securely (requires biometric to re-unlock)
55
+ setKeypair(null);
56
+ setIsUnlocked(false);
57
+ };
58
+ const signIn = async (walletAddress, isTemporary = false) => {
59
+ const {
60
+ user
61
+ } = await AuthService.signInWithWallet(walletAddress, isTemporary);
62
+ setUser(user);
63
+ setIsUnlocked(true);
64
+ };
65
+ const signOut = async () => {
66
+ // Clear session from storage
67
+ await AuthService.signOut();
68
+
69
+ // Clear all memory (state)
70
+ setUser(null);
71
+ setKeypair(null); // Remove from RAM
72
+ setIsUnlocked(false);
73
+
74
+ // NOTE: Encrypted keypair remains in SecureStore
75
+ // It can only be accessed again with biometric authentication
76
+ };
77
+ return /*#__PURE__*/_jsx(WalletContext.Provider, {
78
+ value: {
79
+ isInitialized,
80
+ isUnlocked,
81
+ user,
82
+ keypair,
83
+ unlockWallet,
84
+ lockWallet,
85
+ signIn,
86
+ signOut
87
+ },
88
+ children: children
89
+ });
90
+ };
91
+ export const useWallet = () => {
92
+ const context = useContext(WalletContext);
93
+ if (context === undefined) {
94
+ throw new Error('useWallet must be used within a WalletProvider');
95
+ }
96
+ return context;
97
+ };
98
+ export default WalletContext;
99
+ //# sourceMappingURL=WalletContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createContext","useContext","useState","useEffect","AuthService","jsx","_jsx","WalletContext","undefined","WalletProvider","children","isInitialized","setIsInitialized","isUnlocked","setIsUnlocked","user","setUser","keypair","setKeypair","checkAuth","session","getSession","signInWithWallet","walletAddress","isWalletUnlocked","error","console","unlockWallet","unlockedKeypair","unlockWalletWithBiometrics","lockWallet","signIn","isTemporary","signOut","Provider","value","useWallet","context","Error"],"sourceRoot":"../../../src","sources":["contexts/WalletContext.tsx"],"mappings":"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","ignoreList":[]}