-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
storage.ts
211 lines (184 loc) · 6.34 KB
/
storage.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Note: If a piece of data wasn't found, returning null instead of default state of the
// property to avoid coupling with redux reducers
import * as SecureStore from "expo-secure-store";
import { AsyncStorage } from "react-native";
import { createFromPrivateKey } from "tasit-account/dist/testHelpers/helpers";
import { logWarn, logInfo } from ".";
// Storage keys
const EPHEMERAL_ACCOUNT_PRIV_KEY = "EPHEMERAL_ACCOUNT_PRIV_KEY";
const MY_ASSETS_LIST = "MY_ASSETS_LIST";
const EPHEMERAL_ACCOUNT_CREATION_STATUS = "EPHEMERAL_ACCOUNT_CREATION_STATUS";
const EPHEMERAL_ACCOUNT_CREATION_ACTIONS = "EPHEMERAL_ACCOUNT_CREATION_ACTIONS";
const IS_FIRST_APP_USE = "IS_FIRST_APP_USE";
const USER_ACTIONS = "USER_ACTIONS";
const _clearData = async (key): Promise<void> => {
try {
await AsyncStorage.removeItem(key);
} catch (error) {
logWarn(`Unable to delete data (key = ${key}) from storage.`);
}
try {
const returnValue = await SecureStore.deleteItemAsync(key);
} catch (error) {
logWarn(`Unable to delete data key = ${key} from secure storage.`);
}
};
export const clearAllStorage = async (): Promise<void> => {
await _clearData(IS_FIRST_APP_USE);
await _clearData(EPHEMERAL_ACCOUNT_PRIV_KEY);
await _clearData(USER_ACTIONS);
await _clearData(EPHEMERAL_ACCOUNT_CREATION_ACTIONS);
await _clearData(EPHEMERAL_ACCOUNT_CREATION_STATUS);
await _clearData(MY_ASSETS_LIST);
};
const _toString = (obj): string => {
if (obj === null) return null;
try {
return JSON.stringify(obj);
} catch {
throw Error(`Unable to parse object to a JSON string.`);
}
};
const _fromString = (string): object | string | boolean => {
try {
return JSON.parse(string);
} catch {
throw Error(`Unable to parse JSON string to an object.`);
}
};
const _objectFromString = (string): object => {
const result = _fromString(string);
// We expect that the type after JSON.parse'ing it will be an object
if (typeof result === "string") {
return {};
} else if (typeof result === "boolean") {
return {};
}
return result;
};
const _booleanFromString = (string): boolean => {
const result = _fromString(string);
// We expect that the type after JSON.parse'ing it will be a boolean
if (typeof result === "string") {
return true;
} else if (typeof result === "object") {
return true;
}
return result;
};
const _arrayOfObjectsFromString = (string): object[] => {
const result = _fromString(string);
if (typeof result === "string") {
return [];
} else if (typeof result === "boolean") {
return [];
} else if (typeof result === "object") {
if (Array.isArray(result)) {
// TODO: Check that if the array isn't empty, the members are objects
return result;
}
}
return [];
};
// Note: the value should be a string
const _storeData = async (key, value, securely): Promise<void> => {
try {
if (securely) {
// More about options:
// https://docs.expo.io/versions/latest/sdk/securestore/#securestoresetitemasynckey-value-options
const options = { keychainAccessible: SecureStore.WHEN_UNLOCKED };
await SecureStore.setItemAsync(key, value, options);
} else {
await AsyncStorage.setItem(key, value);
}
} catch (error) {
throw Error(`Unable to ${securely ? "securely" : ""} store data.`);
}
};
export const storeUserActions = async (userActions): Promise<void> => {
const strUserActions = _toString(userActions);
await _storeData(USER_ACTIONS, strUserActions, false);
};
const _retrieveData = async (key): Promise<string> => {
try {
let value = await AsyncStorage.getItem(key);
if (value === null) value = await SecureStore.getItemAsync(key);
return value;
} catch (error) {
throw Error(`Unable to retrieve data from storage.`);
}
};
export const retrieveUserActions = async (): Promise<object> => {
const strUserActions = await _retrieveData(USER_ACTIONS);
const userActions = _objectFromString(strUserActions);
return userActions;
};
export const storeIsFirstUse = async (isFirstUse): Promise<void> => {
const strIsFirstUse = _toString(isFirstUse);
await _storeData(IS_FIRST_APP_USE, strIsFirstUse, false);
};
export const retrieveIsFirstUse = async (): Promise<boolean> => {
const strIsFirstUse = await _retrieveData(IS_FIRST_APP_USE);
if (strIsFirstUse === null) return true;
const isFirstUse = _booleanFromString(strIsFirstUse);
logInfo(`isFirstUse ${isFirstUse}`);
return isFirstUse;
};
export const storeAccountCreationActions = async (
creationActions
): Promise<void> => {
const strCreationActions = _toString(creationActions);
await _storeData(
EPHEMERAL_ACCOUNT_CREATION_ACTIONS,
strCreationActions,
false
);
};
export const retrieveAccountCreationActions = async (): Promise<object[]> => {
const strCreationActions = await _retrieveData(
EPHEMERAL_ACCOUNT_CREATION_ACTIONS
);
const creationActions = _arrayOfObjectsFromString(strCreationActions);
return creationActions;
};
export const storeAccountCreationStatus = async (status): Promise<void> => {
await _storeData(EPHEMERAL_ACCOUNT_CREATION_STATUS, status, false);
};
export const retrieveAccountCreationStatus = async (): Promise<string> => {
const status = await _retrieveData(EPHEMERAL_ACCOUNT_CREATION_STATUS);
return status;
};
export const storeAccount = async (account): Promise<void> => {
const privateKey = account !== null ? account.privateKey : null;
await _storeData(EPHEMERAL_ACCOUNT_PRIV_KEY, privateKey, true);
};
export const retrieveAccount = async (): Promise<object> => {
let account = null;
const privateKey = await _retrieveData(EPHEMERAL_ACCOUNT_PRIV_KEY);
if (privateKey != null) account = createFromPrivateKey(privateKey);
return account;
};
export const storeMyAssets = async (myAssets): Promise<void> => {
const strMyAssets = _toString(myAssets);
await _storeData(MY_ASSETS_LIST, strMyAssets, false);
};
export const retrieveMyAssets = async (): Promise<object[]> => {
const strMyAssets = await _retrieveData(MY_ASSETS_LIST);
const myAssets = _arrayOfObjectsFromString(strMyAssets);
return myAssets;
};
export default {
storeAccount,
retrieveAccount,
storeMyAssets,
retrieveMyAssets,
storeAccountCreationStatus,
retrieveAccountCreationStatus,
storeAccountCreationActions,
retrieveAccountCreationActions,
storeIsFirstUse,
retrieveIsFirstUse,
retrieveUserActions,
storeUserActions,
clearAllStorage,
};