/
wallet.js
145 lines (129 loc) Β· 4.25 KB
/
wallet.js
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
import ethers from 'ethers';
import lang from 'i18n-js';
import { AlertIOS } from 'react-native';
import {
ACCESS_CONTROL,
ACCESSIBLE,
AUTHENTICATION_TYPE,
canImplyAuthentication,
} from 'react-native-keychain';
import Piwik from 'react-native-matomo';
import * as keychain from './keychain';
const seedPhraseKey = 'balanceWalletSeedPhrase';
const privateKeyKey = 'balanceWalletPrivateKey';
const addressKey = 'balanceWalletAddressKey';
export function generateSeedPhrase() {
return ethers.HDNode.entropyToMnemonic(ethers.utils.randomBytes(16));
}
export const walletInit = async (seedPhrase = null) => {
let walletAddress = null;
if (seedPhrase) {
walletAddress = await createWallet(seedPhrase);
}
if (!walletAddress) {
walletAddress = await loadAddress();
}
if (!walletAddress) {
walletAddress = await createWallet();
}
return walletAddress;
};
export const loadWallet = async () => {
const privateKey = await loadPrivateKey();
if (privateKey) {
const wallet = new ethers.Wallet(privateKey);
wallet.provider = ethers.providers.getDefaultProvider();
return wallet;
}
return null;
};
export const getChainId = async () => {
const wallet = await loadWallet();
const { chainId } = wallet.provider;
return chainId;
};
export const createTransaction = async (to, data, value, gasLimit, gasPrice, nonce = null) => ({
data,
gasLimit,
gasPrice,
nonce,
to,
value: ethers.utils.parseEther(value),
});
export const sendTransaction = async ({ tracking, transaction }) => {
try {
const wallet = await loadWallet();
if (!wallet) {
return null;
}
try {
const result = await wallet.sendTransaction(transaction);
Piwik.trackEvent('Send', tracking.action, tracking.name, tracking.amount);
return result.hash;
} catch (error) {
AlertIOS.alert(lang.t('wallet.transaction.alert.failed_transaction'));
return null;
}
} catch (error) {
AlertIOS.alert(lang.t('wallet.transaction.alert.authentication'));
return null;
}
};
export const signMessage = async (message, authenticationPrompt = lang.t('wallet.authenticate.please')) => {
try {
const wallet = await loadWallet(authenticationPrompt);
try {
return await wallet.signMessage(message);
} catch (error) {
AlertIOS.alert(lang.t('wallet.message_signing.failed_signing'));
return null;
}
} catch (error) {
AlertIOS.alert(lang.t('wallet.transaction.alert.authentication'));
return null;
}
};
export const loadSeedPhrase = async (authenticationPrompt = lang.t('wallet.authenticate.please_seed_phrase')) => {
const seedPhrase = await keychain.loadString(seedPhraseKey, { authenticationPrompt });
return seedPhrase;
};
export const loadAddress = async () => {
try {
return await keychain.loadString(addressKey);
} catch (error) {
return null;
}
};
const createWallet = async (seedPhrase) => {
const walletSeedPhrase = seedPhrase || generateSeedPhrase();
const wallet = ethers.Wallet.fromMnemonic(walletSeedPhrase);
saveWalletDetails(walletSeedPhrase, wallet.privateKey, wallet.address);
return wallet.address;
};
const saveWalletDetails = async (seedPhrase, privateKey, address) => {
const canAuthenticate = await canImplyAuthentication({ authenticationType: AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS });
let accessControlOptions = {};
if (canAuthenticate) {
accessControlOptions = { accessControl: ACCESS_CONTROL.USER_PRESENCE, accessible: ACCESSIBLE.WHEN_UNLOCKED };
}
saveSeedPhrase(seedPhrase, accessControlOptions);
savePrivateKey(privateKey, accessControlOptions);
saveAddress(address);
};
const saveSeedPhrase = async (seedPhrase, accessControlOptions = {}) => {
await keychain.saveString(seedPhraseKey, seedPhrase, accessControlOptions);
};
const savePrivateKey = async (privateKey, accessControlOptions = {}) => {
await keychain.saveString(privateKeyKey, privateKey, accessControlOptions);
};
const loadPrivateKey = async (authenticationPrompt = lang.t('wallet.authenticate.please')) => {
try {
const privateKey = await keychain.loadString(privateKeyKey, { authenticationPrompt });
return privateKey;
} catch (error) {
return null;
}
};
const saveAddress = async (address) => {
await keychain.saveString(addressKey, address);
};