Skip to content

Commit ef29e29

Browse files
committed
generate TRON privateKey and address
1 parent 8e54c2d commit ef29e29

File tree

8 files changed

+206
-75
lines changed

8 files changed

+206
-75
lines changed

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
"@ledgerhq/hw-transport": "6.30.3",
3333
"@ledgerhq/react-native-hw-transport-ble": "6.30.0",
3434
"bech32-converting": "^1.0.9",
35+
"bip32": "1.0.4",
3536
"bip39": "^3.1.0",
36-
"ethereumjs-wallet": "^1.0.2",
3737
"ethers": "^5.7.2",
3838
"events": "^3.3.0",
3939
"rxjs": "^7.8.0"

Diff for: src/providers/mnemonic/provider.ts

+11-35
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ import {accountInfo, derive, seedFromEntropy} from '@haqq/provider-web3-utils';
22
import {generateEntropy} from '@haqq/provider-web3-utils/src/native-modules';
33
import {Share, encryptShare} from '@haqq/shared-react-native';
44
import {entropyToMnemonic, mnemonicToEntropy, mnemonicToSeed} from 'bip39';
5-
import {hdkey} from 'ethereumjs-wallet';
65
import EncryptedStorage from 'react-native-encrypted-storage';
76

87
import {ProviderMnemonicBaseOptions} from './types';
98

109
import {ITEM_KEYS, WalletType} from '../../constants';
10+
import {Multichain} from '../../services/multichain';
1111
import {compressPublicKey} from '../../utils';
1212
import {getMnemonic} from '../../utils/mnemonic/get-mnemonic';
1313
import {ProviderBase} from '../base-provider';
14-
import {ProviderBaseOptions, ProviderInterface} from '../types';
14+
import {NETWORK_TYPE, ProviderBaseOptions, ProviderInterface} from '../types';
1515

1616
export class ProviderMnemonicBase
1717
extends ProviderBase<ProviderMnemonicBaseOptions>
@@ -22,19 +22,14 @@ export class ProviderMnemonicBase
2222
getPassword: () => Promise<string>,
2323
options: Omit<ProviderBaseOptions, 'getPassword'>,
2424
): Promise<ProviderMnemonicBase> {
25-
console.log('mnemonic', mnemonic);
26-
2725
const password = await getPassword();
28-
console.log('password', password);
2926

3027
const entropy =
3128
mnemonic === null
3229
? (await generateEntropy(16)).toString('hex')
3330
: mnemonicToEntropy(mnemonic);
34-
console.log('entropy', entropy);
3531

3632
const seed = await mnemonicToSeed(entropyToMnemonic(entropy));
37-
console.log('seed', seed);
3833

3934
const privateData = await encryptShare(
4035
{
@@ -44,34 +39,21 @@ export class ProviderMnemonicBase
4439
},
4540
password,
4641
);
47-
console.log('privateData', privateData);
4842

4943
const rootPrivateKey = await derive(seed.toString('hex'), 'm');
50-
console.log('rootPrivateKey', rootPrivateKey);
5144
const {address} = await accountInfo(rootPrivateKey);
52-
console.log('address', address);
5345

5446
await EncryptedStorage.setItem(
5547
`${ITEM_KEYS[WalletType.mnemonic]}_${address.toLowerCase()}`,
5648
JSON.stringify(privateData),
5749
);
5850

59-
console.log(
60-
`${ITEM_KEYS[WalletType.mnemonic]}_${address.toLowerCase()}`,
61-
JSON.stringify(privateData),
62-
);
63-
6451
const accounts = await ProviderMnemonicBase.getAccounts();
65-
console.log('accounts', accounts);
6652

6753
await EncryptedStorage.setItem(
6854
`${ITEM_KEYS[WalletType.mnemonic]}_accounts`,
6955
JSON.stringify(accounts.concat(address.toLowerCase())),
7056
);
71-
console.log(
72-
`${ITEM_KEYS[WalletType.mnemonic]}_accounts`,
73-
JSON.stringify(accounts.concat(address.toLowerCase())),
74-
);
7557

7658
return new ProviderMnemonicBase({
7759
...options,
@@ -137,7 +119,7 @@ export class ProviderMnemonicBase
137119
}
138120

139121
async getAccountInfo(hdPath: string) {
140-
let resp = {publicKey: '', address: ''};
122+
let resp = {publicKey: '', address: '', tronAddress: ''};
141123
try {
142124
const share = await getMnemonic(
143125
this._options.account,
@@ -150,28 +132,22 @@ export class ProviderMnemonicBase
150132

151133
const seed = await ProviderMnemonicBase.shareToSeed(share);
152134

153-
const entropyLength = parseInt(share.shareIndex, 10);
154-
const entropy = share.share
155-
.slice(-1 * entropyLength)
156-
.padStart(entropyLength, '0');
157-
158-
const hdwallet = hdkey.fromMasterSeed(Buffer.from(entropy, 'hex'));
159-
const derivationPath = "m/44'/195'/0'/0/0";
160-
const wallet = hdwallet.derivePath(derivationPath);
161-
const tronPrivateKey = wallet.getWallet().getPrivateKeyString();
162-
console.log('tronPrivateKey', tronPrivateKey);
163-
164-
const privateKey = await derive(seed, hdPath);
135+
const ethPrivateKey = await derive(seed, hdPath);
165136

166-
if (!privateKey) {
137+
if (!ethPrivateKey) {
167138
throw new Error('private_key_not_found');
168139
}
169140

170-
const account = await accountInfo(privateKey);
141+
const account = await accountInfo(ethPrivateKey);
171142

172143
resp = {
173144
publicKey: compressPublicKey(account.publicKey),
174145
address: account.address,
146+
tronAddress: await Multichain.generateAddress(
147+
NETWORK_TYPE.TRON,
148+
hdPath,
149+
await this.getMnemonicPhrase(),
150+
),
175151
};
176152
this.emit('getPublicKeyForHDPath', true);
177153
} catch (e) {

Diff for: src/providers/sss/provider.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ import EncryptedStorage from 'react-native-encrypted-storage';
1414
import {ProviderSSSBaseOptions, StorageInterface} from './types';
1515

1616
import {ITEM_KEYS, WalletType} from '../../constants';
17+
import {Multichain} from '../../services/multichain';
1718
import {
1819
Polynomial,
1920
compressPublicKey,
2021
getSeed,
2122
lagrangeInterpolation,
2223
} from '../../utils';
2324
import {ProviderBase} from '../base-provider';
24-
import {ProviderBaseOptions, ProviderInterface} from '../types';
25+
import {NETWORK_TYPE, ProviderBaseOptions, ProviderInterface} from '../types';
2526

2627
export class ProviderSSSBase
2728
extends ProviderBase<ProviderSSSBaseOptions>
@@ -244,7 +245,7 @@ export class ProviderSSSBase
244245
}
245246

246247
async getAccountInfo(hdPath: string) {
247-
let resp = {publicKey: '', address: ''};
248+
let resp = {publicKey: '', address: '', tronAddress: ''};
248249
try {
249250
const {seed} = await getSeed(
250251
this._options.account,
@@ -267,6 +268,11 @@ export class ProviderSSSBase
267268
resp = {
268269
publicKey: compressPublicKey(account.publicKey),
269270
address: account.address,
271+
tronAddress: await Multichain.generateAddress(
272+
NETWORK_TYPE.TRON,
273+
hdPath,
274+
await this.getMnemonicPhrase(),
275+
),
270276
};
271277
this.emit('getPublicKeyForHDPath', true);
272278
} catch (e) {

Diff for: src/providers/types.ts

+6
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,9 @@ export type ProviderBaseError = {
111111
error: Error;
112112
source: string;
113113
};
114+
115+
export enum NETWORK_TYPE {
116+
HAQQ,
117+
ETH,
118+
TRON,
119+
}

Diff for: src/services/multichain.ts

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import * as bip32 from 'bip32';
2+
import {mnemonicToSeed} from 'bip39';
3+
import * as CryptoJS from 'crypto-js';
4+
import {ec} from 'elliptic';
5+
6+
import {NETWORK_TYPE} from '../providers/types';
7+
import {encodeBase58} from '../utils';
8+
9+
export class Multichain {
10+
static async generatePrivateKey(
11+
type: NETWORK_TYPE,
12+
hdPath: string,
13+
mnemonic: string,
14+
): Promise<string> {
15+
switch (type) {
16+
case NETWORK_TYPE.TRON:
17+
return Multichain.generateTronPrivateKey(hdPath, mnemonic);
18+
default:
19+
return '';
20+
}
21+
}
22+
23+
private static async generateTronPrivateKey(
24+
hdPath: string,
25+
mnemonic: string,
26+
): Promise<string> {
27+
const tronSeed = await mnemonicToSeed(mnemonic);
28+
const root = bip32.fromSeed(tronSeed);
29+
const child = root.derivePath(hdPath);
30+
return child.privateKey.toString('hex');
31+
}
32+
33+
static async generateAddress(
34+
type: NETWORK_TYPE,
35+
hdPath: string,
36+
mnemonic: string,
37+
): Promise<string> {
38+
switch (type) {
39+
case NETWORK_TYPE.TRON:
40+
return Multichain.generateTronAddress(
41+
await this.generateTronPrivateKey(hdPath, mnemonic),
42+
);
43+
default:
44+
return '';
45+
}
46+
}
47+
48+
private static async generateTronAddress(
49+
privateKey: string,
50+
): Promise<string> {
51+
const EC = new ec('secp256k1');
52+
53+
// Create key pair from private key
54+
const keyPair = EC.keyFromPrivate(privateKey);
55+
56+
// Get public key and remove prefix 0x
57+
const publicKey = keyPair.getPublic('hex').slice(2);
58+
59+
// Hashing public key with Keccak256
60+
const publicKeyHash = CryptoJS.SHA3(publicKey, {
61+
outputLength: 256,
62+
}).toString();
63+
64+
// Get last 20 bites (40 hex symbols) from public key's hash
65+
// Also add TRON prefix 41
66+
const tronAddressHex = '41' + publicKeyHash.slice(-40);
67+
68+
// Convert hex-address to base58 which is TRON address format
69+
const addressBuffer = Buffer.from(tronAddressHex, 'hex');
70+
const addressHash = CryptoJS.SHA256(
71+
CryptoJS.SHA256(addressBuffer).toString(CryptoJS.enc.Hex),
72+
).toString(CryptoJS.enc.Hex);
73+
const checksum = addressHash.slice(0, 8);
74+
75+
return encodeBase58(
76+
Buffer.concat([addressBuffer, Buffer.from(checksum, 'hex')]),
77+
);
78+
}
79+
}

Diff for: src/utils/utils.ts

+25
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,28 @@ export function hexBuffer(str: string | Buffer): Buffer {
3030
export function normalize0x(strWith0x: string): string {
3131
return strWith0x.replace(/^(0x)*/, '0x');
3232
}
33+
34+
export function encodeBase58(buffer: Buffer): string {
35+
const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
36+
const base = BigInt(58);
37+
38+
let result = '';
39+
let num = BigInt('0x' + buffer.toString('hex'));
40+
41+
while (num > 0) {
42+
const remainder = num % base;
43+
num = num / base;
44+
result = alphabet[Number(remainder)] + result;
45+
}
46+
47+
// Добавляем ведущие нули
48+
for (const byte of buffer) {
49+
if (byte === 0x00) {
50+
result = alphabet[0] + result;
51+
} else {
52+
break;
53+
}
54+
}
55+
56+
return result;
57+
}

Diff for: tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"target": "es5",
3+
"target": "es2015",
44
"module": "commonjs",
55
"esModuleInterop": true,
66
"skipLibCheck": true,

0 commit comments

Comments
 (0)