@spacesops/wdk-react-native-provider 1.0.0-beta.3
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/LICENSE +176 -0
- package/README.md +841 -0
- package/lib/module/contexts/constants.js +20 -0
- package/lib/module/contexts/constants.js.map +1 -0
- package/lib/module/contexts/reducer.js +87 -0
- package/lib/module/contexts/reducer.js.map +1 -0
- package/lib/module/contexts/types.js +4 -0
- package/lib/module/contexts/types.js.map +1 -0
- package/lib/module/contexts/wallet-context.js +409 -0
- package/lib/module/contexts/wallet-context.js.map +1 -0
- package/lib/module/index.js +15 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/polyfills.js +34 -0
- package/lib/module/polyfills.js.map +1 -0
- package/lib/module/services/wdk-service/bare-api.js +69 -0
- package/lib/module/services/wdk-service/bare-api.js.map +1 -0
- package/lib/module/services/wdk-service/index.js +506 -0
- package/lib/module/services/wdk-service/index.js.map +1 -0
- package/lib/module/services/wdk-service/types.js +48 -0
- package/lib/module/services/wdk-service/types.js.map +1 -0
- package/lib/module/services/wdk-service/wdk-encryption-salt.js +29 -0
- package/lib/module/services/wdk-service/wdk-encryption-salt.js.map +1 -0
- package/lib/module/services/wdk-service/wdk-secret-manager-storage.js +64 -0
- package/lib/module/services/wdk-service/wdk-secret-manager-storage.js.map +1 -0
- package/lib/module/services/wdk-service/wdk-secret-manager-worklet.bundle.js +1 -0
- package/lib/module/services/wdk-service/wdk-worklet.mobile.bundle.js +1 -0
- package/lib/module/spec/hrpc/hrpc.json +66 -0
- package/lib/module/spec/hrpc/index.js +121 -0
- package/lib/module/spec/hrpc/index.js.map +1 -0
- package/lib/module/spec/hrpc/messages.js +291 -0
- package/lib/module/spec/hrpc/messages.js.map +1 -0
- package/lib/module/spec/schema/index.js +291 -0
- package/lib/module/spec/schema/index.js.map +1 -0
- package/lib/module/spec/schema/schema.json +186 -0
- package/lib/module/utils/get-balances-from-balance-map.js +18 -0
- package/lib/module/utils/get-balances-from-balance-map.js.map +1 -0
- package/lib/module/utils/get-transactions-from-transaction-map.js +10 -0
- package/lib/module/utils/get-transactions-from-transaction-map.js.map +1 -0
- package/lib/module/worklet/wdk-secret-manager-worklet.js +106 -0
- package/lib/module/worklet/wdk-secret-manager-worklet.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/contexts/constants.d.ts +3 -0
- package/lib/typescript/src/contexts/constants.d.ts.map +1 -0
- package/lib/typescript/src/contexts/reducer.d.ts +38 -0
- package/lib/typescript/src/contexts/reducer.d.ts.map +1 -0
- package/lib/typescript/src/contexts/types.d.ts +40 -0
- package/lib/typescript/src/contexts/types.d.ts.map +1 -0
- package/lib/typescript/src/contexts/wallet-context.d.ts +10 -0
- package/lib/typescript/src/contexts/wallet-context.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +7 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/polyfills.d.ts +7 -0
- package/lib/typescript/src/polyfills.d.ts.map +1 -0
- package/lib/typescript/src/services/wdk-service/bare-api.d.ts +32 -0
- package/lib/typescript/src/services/wdk-service/bare-api.d.ts.map +1 -0
- package/lib/typescript/src/services/wdk-service/index.d.ts +68 -0
- package/lib/typescript/src/services/wdk-service/index.d.ts.map +1 -0
- package/lib/typescript/src/services/wdk-service/types.d.ts +125 -0
- package/lib/typescript/src/services/wdk-service/types.d.ts.map +1 -0
- package/lib/typescript/src/services/wdk-service/wdk-encryption-salt.d.ts +6 -0
- package/lib/typescript/src/services/wdk-service/wdk-encryption-salt.d.ts.map +1 -0
- package/lib/typescript/src/services/wdk-service/wdk-secret-manager-storage.d.ts +13 -0
- package/lib/typescript/src/services/wdk-service/wdk-secret-manager-storage.d.ts.map +1 -0
- package/lib/typescript/src/utils/get-balances-from-balance-map.d.ts +4 -0
- package/lib/typescript/src/utils/get-balances-from-balance-map.d.ts.map +1 -0
- package/lib/typescript/src/utils/get-transactions-from-transaction-map.d.ts +4 -0
- package/lib/typescript/src/utils/get-transactions-from-transaction-map.d.ts.map +1 -0
- package/metro-polyfills.js +89 -0
- package/package.json +152 -0
- package/src/contexts/constants.ts +19 -0
- package/src/contexts/reducer.ts +103 -0
- package/src/contexts/types.ts +51 -0
- package/src/contexts/wallet-context.tsx +411 -0
- package/src/index.tsx +28 -0
- package/src/polyfills.ts +31 -0
- package/src/services/wdk-service/bare-api.ts +88 -0
- package/src/services/wdk-service/index.ts +765 -0
- package/src/services/wdk-service/types.ts +137 -0
- package/src/services/wdk-service/wdk-encryption-salt.ts +30 -0
- package/src/services/wdk-service/wdk-secret-manager-storage.ts +102 -0
- package/src/spec/hrpc/hrpc.json +66 -0
- package/src/spec/hrpc/index.js +228 -0
- package/src/spec/hrpc/messages.js +328 -0
- package/src/spec/schema/index.js +328 -0
- package/src/spec/schema/schema.json +186 -0
- package/src/utils/get-balances-from-balance-map.ts +22 -0
- package/src/utils/get-transactions-from-transaction-map.ts +18 -0
- package/src/worklet/wdk-secret-manager-worklet.js +118 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { createContext, useContext, useEffect, useReducer } from 'react';
|
|
4
|
+
import { WDKService } from '../services/wdk-service';
|
|
5
|
+
import type {
|
|
6
|
+
AddressMap,
|
|
7
|
+
AssetTicker,
|
|
8
|
+
BalanceMap,
|
|
9
|
+
TransactionMap,
|
|
10
|
+
} from '../services/wdk-service/types';
|
|
11
|
+
import type {
|
|
12
|
+
WalletContextState,
|
|
13
|
+
WalletContextType,
|
|
14
|
+
WalletProviderConfig,
|
|
15
|
+
} from './types';
|
|
16
|
+
import walletReducer from './reducer';
|
|
17
|
+
import { getUniqueId } from 'react-native-device-info';
|
|
18
|
+
import { WALLET_CONTEXT_INITIAL_STATE } from './constants';
|
|
19
|
+
|
|
20
|
+
const STORAGE_KEY_WALLET = 'wdk_wallet_data';
|
|
21
|
+
const STORAGE_KEY_ADDRESSES = 'wdk_wallet_addresses';
|
|
22
|
+
const STORAGE_KEY_BALANCES = 'wdk_wallet_balances';
|
|
23
|
+
const STORAGE_KEY_TRANSACTIONS = 'wdk_wallet_transactions';
|
|
24
|
+
|
|
25
|
+
// Create context
|
|
26
|
+
const WalletContext = createContext<WalletContextType | undefined>(undefined);
|
|
27
|
+
|
|
28
|
+
// Provider component
|
|
29
|
+
export function WalletProvider({
|
|
30
|
+
children,
|
|
31
|
+
config,
|
|
32
|
+
}: {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
config: WalletProviderConfig;
|
|
35
|
+
}) {
|
|
36
|
+
const [state, dispatch] = useReducer(
|
|
37
|
+
walletReducer,
|
|
38
|
+
WALLET_CONTEXT_INITIAL_STATE
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Set WDK config on mount
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
WDKService.setConfig({
|
|
44
|
+
...config,
|
|
45
|
+
indexer: { ...config.indexer, version: config.indexer.version || 'v1' },
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
initializeWDK();
|
|
49
|
+
}, [config]);
|
|
50
|
+
|
|
51
|
+
// Load wallet from storage on mount
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
loadStoredWallet();
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
const enabledAssets = state.wallet?.enabledAssets;
|
|
58
|
+
const addressMap = state.addresses;
|
|
59
|
+
|
|
60
|
+
if (enabledAssets && addressMap) {
|
|
61
|
+
fetchBalances();
|
|
62
|
+
fetchTransactions();
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
|
+
}, [state.wallet?.enabledAssets, state.addresses]);
|
|
66
|
+
|
|
67
|
+
// Save wallet to storage whenever wallet changes
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (state.isInitialized && state.wallet) {
|
|
70
|
+
saveWalletToStorage();
|
|
71
|
+
}
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [state.wallet, state.isInitialized]);
|
|
74
|
+
|
|
75
|
+
const loadStoredWallet = async () => {
|
|
76
|
+
try {
|
|
77
|
+
const stored = await AsyncStorage.getItem(STORAGE_KEY_WALLET);
|
|
78
|
+
if (stored) {
|
|
79
|
+
const data = JSON.parse(stored);
|
|
80
|
+
let parsed: WalletContextState['wallet'] = data;
|
|
81
|
+
|
|
82
|
+
if (parsed) {
|
|
83
|
+
dispatch({ type: 'SET_WALLET', payload: parsed });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
dispatch({
|
|
88
|
+
type: 'SET_ERROR',
|
|
89
|
+
payload:
|
|
90
|
+
error instanceof Error
|
|
91
|
+
? error.message
|
|
92
|
+
: 'Failed to load stored wallet',
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
console.error('Failed to load stored wallet:', error);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const saveWalletToStorage = async () => {
|
|
100
|
+
try {
|
|
101
|
+
if (state.wallet) {
|
|
102
|
+
await AsyncStorage.setItem(
|
|
103
|
+
STORAGE_KEY_WALLET,
|
|
104
|
+
JSON.stringify(state.wallet)
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Failed to save wallet to storage:', error);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const getWalletAddresses = async (enabledAssets: AssetTicker[]) => {
|
|
113
|
+
try {
|
|
114
|
+
const stored = await AsyncStorage.getItem(STORAGE_KEY_ADDRESSES);
|
|
115
|
+
if (stored) {
|
|
116
|
+
return JSON.parse(stored);
|
|
117
|
+
} else {
|
|
118
|
+
const addresses =
|
|
119
|
+
await WDKService.resolveWalletAddresses(enabledAssets);
|
|
120
|
+
await AsyncStorage.setItem(
|
|
121
|
+
STORAGE_KEY_ADDRESSES,
|
|
122
|
+
JSON.stringify(addresses)
|
|
123
|
+
);
|
|
124
|
+
return addresses;
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Failed to get wallet addresses:', error);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const clearError = () => {
|
|
132
|
+
dispatch({ type: 'SET_ERROR', payload: null });
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const initializeWDK = async () => {
|
|
136
|
+
try {
|
|
137
|
+
dispatch({ type: 'SET_LOADING', payload: true });
|
|
138
|
+
await WDKService.initialize();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
const errorMessage =
|
|
141
|
+
error instanceof Error ? error.message : 'Failed to initialize WDK';
|
|
142
|
+
dispatch({ type: 'SET_ERROR', payload: errorMessage });
|
|
143
|
+
throw error;
|
|
144
|
+
} finally {
|
|
145
|
+
dispatch({ type: 'SET_LOADING', payload: false });
|
|
146
|
+
dispatch({ type: 'SET_INITIALIZED', payload: true });
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const createWallet = async (params: {
|
|
151
|
+
name: string;
|
|
152
|
+
mnemonic?: string;
|
|
153
|
+
}): Promise<WalletContextState['wallet']> => {
|
|
154
|
+
if (!state.isInitialized) {
|
|
155
|
+
throw new Error('WDK is not initialized');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
dispatch({ type: 'SET_LOADING', payload: true });
|
|
160
|
+
|
|
161
|
+
const prf = await getUniqueId();
|
|
162
|
+
|
|
163
|
+
if (params.mnemonic) {
|
|
164
|
+
await WDKService.importSeedPhrase({ prf, seedPhrase: params.mnemonic });
|
|
165
|
+
} else {
|
|
166
|
+
await WDKService.createSeed({ prf });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const wallet = await WDKService.createWallet({
|
|
170
|
+
walletName: params.name,
|
|
171
|
+
prf,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const addresses = await getWalletAddresses(wallet.enabledAssets);
|
|
175
|
+
|
|
176
|
+
dispatch({ type: 'SET_WALLET', payload: wallet });
|
|
177
|
+
dispatch({ type: 'SET_ADDRESSES', payload: addresses });
|
|
178
|
+
dispatch({ type: 'SET_UNLOCKED', payload: true });
|
|
179
|
+
|
|
180
|
+
return wallet;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
const errorMessage =
|
|
183
|
+
error instanceof Error ? error.message : 'Failed to create wallet';
|
|
184
|
+
dispatch({ type: 'SET_ERROR', payload: errorMessage });
|
|
185
|
+
throw error;
|
|
186
|
+
} finally {
|
|
187
|
+
dispatch({ type: 'SET_LOADING', payload: false });
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const unlockWallet = async () => {
|
|
192
|
+
if (!state.wallet) {
|
|
193
|
+
throw new Error('No wallet found');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
// Get device ID for seed retrieval
|
|
198
|
+
const prf = await getUniqueId();
|
|
199
|
+
|
|
200
|
+
// Create wallet using the stored seed
|
|
201
|
+
const wallet = await WDKService.createWallet({
|
|
202
|
+
walletName: state.wallet.name,
|
|
203
|
+
prf,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const addresses = await getWalletAddresses(wallet.enabledAssets);
|
|
207
|
+
|
|
208
|
+
dispatch({ type: 'SET_WALLET', payload: wallet });
|
|
209
|
+
dispatch({ type: 'SET_ADDRESSES', payload: addresses });
|
|
210
|
+
dispatch({ type: 'SET_UNLOCKED', payload: true });
|
|
211
|
+
|
|
212
|
+
return true;
|
|
213
|
+
} catch (error) {
|
|
214
|
+
const errorMessage =
|
|
215
|
+
error instanceof Error ? error.message : 'Failed to unlock wallet';
|
|
216
|
+
throw new Error(errorMessage);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const clearWallet = async () => {
|
|
221
|
+
dispatch({ type: 'CLEAR_WALLET' });
|
|
222
|
+
try {
|
|
223
|
+
await AsyncStorage.removeItem(STORAGE_KEY_WALLET);
|
|
224
|
+
await AsyncStorage.removeItem(STORAGE_KEY_ADDRESSES);
|
|
225
|
+
await AsyncStorage.removeItem(STORAGE_KEY_BALANCES);
|
|
226
|
+
await AsyncStorage.removeItem(STORAGE_KEY_TRANSACTIONS);
|
|
227
|
+
await WDKService.clearWallet();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('Failed to clear wallet from AsyncStorage:', error);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const getUpdatedBalances = async (params: {
|
|
234
|
+
enabledAssets: AssetTicker[];
|
|
235
|
+
addressMap: AddressMap;
|
|
236
|
+
}): Promise<BalanceMap> => {
|
|
237
|
+
const { enabledAssets, addressMap } = params;
|
|
238
|
+
const balanceMap = await WDKService.resolveWalletBalances(
|
|
239
|
+
enabledAssets,
|
|
240
|
+
addressMap
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
if (config.enableCaching) {
|
|
244
|
+
// save fresh data to AsyncStorage
|
|
245
|
+
await AsyncStorage.setItem(
|
|
246
|
+
STORAGE_KEY_BALANCES,
|
|
247
|
+
JSON.stringify(balanceMap)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return balanceMap;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const getUpdatedTransactions = async (params: {
|
|
255
|
+
enabledAssets: AssetTicker[];
|
|
256
|
+
addressMap: AddressMap;
|
|
257
|
+
}): Promise<TransactionMap> => {
|
|
258
|
+
const { enabledAssets, addressMap } = params;
|
|
259
|
+
const transactionMap = await WDKService.resolveWalletTransactions(
|
|
260
|
+
enabledAssets,
|
|
261
|
+
addressMap
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
if (config.enableCaching) {
|
|
265
|
+
// save fresh data to AsyncStorage
|
|
266
|
+
await AsyncStorage.setItem(
|
|
267
|
+
STORAGE_KEY_TRANSACTIONS,
|
|
268
|
+
JSON.stringify(transactionMap)
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return transactionMap;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const fetchBalances = async (params?: { forceUpdate?: boolean }) => {
|
|
276
|
+
const { forceUpdate = false } = params || {};
|
|
277
|
+
|
|
278
|
+
if (!state.wallet) {
|
|
279
|
+
throw new Error('Wallet not found');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (!state.addresses) {
|
|
283
|
+
throw new Error('Addresses not found');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const enabledAssets = state.wallet.enabledAssets || [];
|
|
287
|
+
const addressMap = state.addresses || {};
|
|
288
|
+
|
|
289
|
+
// Check if we have cached balances in state
|
|
290
|
+
if (config.enableCaching && !forceUpdate) {
|
|
291
|
+
try {
|
|
292
|
+
const stored = await AsyncStorage.getItem(STORAGE_KEY_BALANCES);
|
|
293
|
+
if (stored) {
|
|
294
|
+
const balanceMap: BalanceMap = JSON.parse(stored);
|
|
295
|
+
dispatch({ type: 'SET_BALANCES', payload: balanceMap });
|
|
296
|
+
}
|
|
297
|
+
} catch (error) {
|
|
298
|
+
console.error('Failed to load cached balances:', error);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Set loading state
|
|
303
|
+
dispatch({ type: 'SET_LOADING_BALANCES', payload: true });
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
// Fetch fresh data
|
|
307
|
+
const balanceMap = await getUpdatedBalances({
|
|
308
|
+
enabledAssets,
|
|
309
|
+
addressMap,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Update state with fresh data
|
|
313
|
+
dispatch({ type: 'SET_BALANCES', payload: balanceMap });
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.error('Failed to fetch balances:', error);
|
|
316
|
+
} finally {
|
|
317
|
+
dispatch({ type: 'SET_LOADING_BALANCES', payload: false });
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const fetchTransactions = async (params?: { forceUpdate?: boolean }) => {
|
|
322
|
+
const { forceUpdate = false } = params || {};
|
|
323
|
+
|
|
324
|
+
if (!state.wallet) {
|
|
325
|
+
throw new Error('Wallet not found');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (!state.addresses) {
|
|
329
|
+
throw new Error('Addresses not found');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const enabledAssets = state.wallet.enabledAssets;
|
|
333
|
+
const addressMap = state.addresses;
|
|
334
|
+
|
|
335
|
+
// Check if we have cached transactions in state
|
|
336
|
+
if (config.enableCaching && !forceUpdate) {
|
|
337
|
+
try {
|
|
338
|
+
const stored = await AsyncStorage.getItem(STORAGE_KEY_TRANSACTIONS);
|
|
339
|
+
if (stored) {
|
|
340
|
+
const transactionMap: TransactionMap = JSON.parse(stored);
|
|
341
|
+
dispatch({ type: 'SET_TRANSACTIONS', payload: transactionMap });
|
|
342
|
+
}
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error('Failed to load cached balances:', error);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Set loading state
|
|
349
|
+
dispatch({ type: 'SET_LOADING_TRANSACTIONS', payload: true });
|
|
350
|
+
|
|
351
|
+
try {
|
|
352
|
+
// Fetch fresh data
|
|
353
|
+
const transactionMap = await getUpdatedTransactions({
|
|
354
|
+
enabledAssets,
|
|
355
|
+
addressMap,
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Update state with fresh data
|
|
359
|
+
dispatch({
|
|
360
|
+
type: 'SET_TRANSACTIONS',
|
|
361
|
+
payload: transactionMap,
|
|
362
|
+
});
|
|
363
|
+
} catch (error) {
|
|
364
|
+
console.error('Failed to fetch transactions:', error);
|
|
365
|
+
} finally {
|
|
366
|
+
dispatch({ type: 'SET_LOADING_TRANSACTIONS', payload: false });
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const refreshWalletBalance = async () => {
|
|
371
|
+
const balanceMap = await getUpdatedBalances({
|
|
372
|
+
enabledAssets: state.wallet?.enabledAssets || [],
|
|
373
|
+
addressMap: state.addresses || {},
|
|
374
|
+
});
|
|
375
|
+
dispatch({ type: 'SET_BALANCES', payload: balanceMap });
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const refreshTransactions = async () => {
|
|
379
|
+
const transactionMap = await getUpdatedTransactions({
|
|
380
|
+
enabledAssets: state.wallet?.enabledAssets || [],
|
|
381
|
+
addressMap: state.addresses || {},
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
dispatch({ type: 'SET_TRANSACTIONS', payload: transactionMap });
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const value: WalletContextType = {
|
|
388
|
+
...state,
|
|
389
|
+
createWallet,
|
|
390
|
+
clearWallet,
|
|
391
|
+
clearError,
|
|
392
|
+
refreshWalletBalance,
|
|
393
|
+
refreshTransactions,
|
|
394
|
+
unlockWallet,
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
return (
|
|
398
|
+
<WalletContext.Provider value={value}>{children}</WalletContext.Provider>
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Custom hook to use wallet context
|
|
403
|
+
export function useWallet() {
|
|
404
|
+
const context = useContext(WalletContext);
|
|
405
|
+
if (context === undefined) {
|
|
406
|
+
throw new Error('useWallet must be used within a WalletProvider');
|
|
407
|
+
}
|
|
408
|
+
return context;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export default WalletContext;
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Import polyfills first - these must be loaded before any other code
|
|
2
|
+
import './polyfills';
|
|
3
|
+
|
|
4
|
+
// Export the wallet context and provider
|
|
5
|
+
export {
|
|
6
|
+
useWallet,
|
|
7
|
+
default as WalletContext,
|
|
8
|
+
WalletProvider,
|
|
9
|
+
} from './contexts/wallet-context';
|
|
10
|
+
export type { WalletProviderConfig } from './contexts/types';
|
|
11
|
+
|
|
12
|
+
// Export WDK service
|
|
13
|
+
export {
|
|
14
|
+
WDKService,
|
|
15
|
+
wdkService,
|
|
16
|
+
SMART_CONTRACT_BALANCE_ADDRESSES,
|
|
17
|
+
} from './services/wdk-service';
|
|
18
|
+
|
|
19
|
+
// Export all types
|
|
20
|
+
export type { Amount, Transaction, Wallet } from './services/wdk-service/types';
|
|
21
|
+
|
|
22
|
+
// Export enums (can be used as both types and values)
|
|
23
|
+
export {
|
|
24
|
+
AssetAddressMap,
|
|
25
|
+
AssetBalanceMap,
|
|
26
|
+
AssetTicker,
|
|
27
|
+
NetworkType,
|
|
28
|
+
} from './services/wdk-service/types';
|
package/src/polyfills.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polyfills for React Native environment
|
|
3
|
+
* This file sets up necessary polyfills for cryptographic and stream operations
|
|
4
|
+
* that are required by the WDK library and related crypto packages.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Buffer } from '@craftzdog/react-native-buffer';
|
|
8
|
+
import 'react-native-get-random-values';
|
|
9
|
+
|
|
10
|
+
// Set up Buffer polyfill
|
|
11
|
+
if (typeof global.Buffer === 'undefined') {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
global.Buffer = Buffer;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Set up process polyfill for stream operations
|
|
17
|
+
if (typeof global.process === 'undefined') {
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
global.process = require('process');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Initialize crypto polyfill after Buffer and process are available
|
|
23
|
+
if (typeof global.crypto === 'undefined') {
|
|
24
|
+
try {
|
|
25
|
+
const crypto = require('react-native-crypto');
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
global.crypto = crypto;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.warn('Failed to load crypto polyfill:', e);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { HRPC as wdkManagerHRPC } from '@spacesops/pear-wrk-wdk';
|
|
2
|
+
import { Worklet } from 'react-native-bare-kit';
|
|
3
|
+
// @ts-expect-error - spec files don't have type definitions
|
|
4
|
+
import HRPC from '../../spec/hrpc';
|
|
5
|
+
// @ts-expect-error - spec files don't have type definitions
|
|
6
|
+
import { getEnum } from '../../spec/schema';
|
|
7
|
+
export enum InstanceEnum {
|
|
8
|
+
wdkSecretManager = 'wdkSecretManager',
|
|
9
|
+
wdkManager = 'wdkManager',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type BareInstanceTypes = Partial<{
|
|
13
|
+
[K in InstanceEnum]: Worklet;
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
export type HRPCInstanceTypes = Partial<{
|
|
17
|
+
[K in InstanceEnum]: HRPC | wdkManagerHRPC;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
export class BareWorkletApi {
|
|
21
|
+
static bareInstances: BareInstanceTypes = {
|
|
22
|
+
wdkSecretManager: undefined,
|
|
23
|
+
wdkManager: undefined,
|
|
24
|
+
};
|
|
25
|
+
static hrpcInstances: HRPCInstanceTypes = {
|
|
26
|
+
wdkSecretManager: null,
|
|
27
|
+
wdkManager: null,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Start bare worklet and assign HRPC instance.
|
|
32
|
+
* @param {InstanceEnum} instance
|
|
33
|
+
* @param {string} fileName
|
|
34
|
+
* @param {string} source
|
|
35
|
+
* @return Worklet
|
|
36
|
+
*/
|
|
37
|
+
static startWorklet(
|
|
38
|
+
instance: InstanceEnum,
|
|
39
|
+
fileName: string,
|
|
40
|
+
source: string
|
|
41
|
+
): Worklet | undefined {
|
|
42
|
+
try {
|
|
43
|
+
if (BareWorkletApi.bareInstances[instance])
|
|
44
|
+
return BareWorkletApi.bareInstances[instance];
|
|
45
|
+
BareWorkletApi.bareInstances[instance] = new Worklet();
|
|
46
|
+
BareWorkletApi.bareInstances[instance].start(fileName, source);
|
|
47
|
+
switch (instance) {
|
|
48
|
+
case InstanceEnum.wdkSecretManager:
|
|
49
|
+
BareWorkletApi.hrpcInstances[instance] = new HRPC(
|
|
50
|
+
BareWorkletApi.bareInstances[instance].IPC
|
|
51
|
+
);
|
|
52
|
+
BareWorkletApi.registerHRPCLog(
|
|
53
|
+
BareWorkletApi.hrpcInstances[instance]
|
|
54
|
+
);
|
|
55
|
+
break;
|
|
56
|
+
case InstanceEnum.wdkManager:
|
|
57
|
+
BareWorkletApi.hrpcInstances[instance] = new wdkManagerHRPC(
|
|
58
|
+
BareWorkletApi.bareInstances[instance].IPC
|
|
59
|
+
);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
return BareWorkletApi.bareInstances[instance];
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error(error);
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static registerHRPCLog(instance: any): void {
|
|
70
|
+
const logEnums = getEnum('@tetherto/wdk-secret-manager/log-type-enum');
|
|
71
|
+
instance.onCommandLog((data: any) => {
|
|
72
|
+
if (data.type === logEnums.info) console.info(data.data);
|
|
73
|
+
if (data.type === logEnums.error) console.error(data.data);
|
|
74
|
+
if (data.type === logEnums.debug) console.debug(data.data);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Terminate worklet
|
|
80
|
+
* @param {InstanceEnum} instance
|
|
81
|
+
*/
|
|
82
|
+
static terminateWorklet(instance: InstanceEnum): void {
|
|
83
|
+
if (BareWorkletApi.bareInstances[instance])
|
|
84
|
+
BareWorkletApi.bareInstances[instance].terminate();
|
|
85
|
+
if (BareWorkletApi.hrpcInstances[instance])
|
|
86
|
+
BareWorkletApi.hrpcInstances[instance] = null;
|
|
87
|
+
}
|
|
88
|
+
}
|