on 616e621 help sign in
bridge/src/lib/wallet.js
109 lines 2.6 kB history raw
1import * as bip32 from 'bip32'
2import * as bip39 from 'bip39'
3import keccak from 'keccak'
4import * as lodash from 'lodash'
5import Maybe from 'folktale/maybe'
6import * as secp256k1 from 'secp256k1'
8const DEFAULT_HD_PATH = "m/44'/60'/0'/0/0"
10const ETH_ZERO_ADDR = '0x0000000000000000000000000000000000000000'
11const CURVE_ZERO_ADDR = "0x0000000000000000000000000000000000000000000000000000000000000000"
13const WALLET_NAMES = {
14 MNEMONIC: Symbol('MNEMONIC'),
15 TICKET: Symbol('TICKET'),
16 SHARDS: Symbol('SHARDS'),
17 LEDGER: Symbol('LEDGER'),
18 TREZOR: Symbol('TREZOR')
21const renderWalletType = (wallet) =>
22 wallet === WALLET_NAMES.MNEMONIC
23 ? 'Mnemonic'
24 : wallet === WALLET_NAMES.TICKET
25 ? 'Ticket'
26 : wallet === WALLET_NAMES.SHARDS
27 ? 'Ticket Shards'
28 : wallet === WALLET_NAMES.LEDGER
29 ? 'Ledger'
30 : wallet === WALLET_NAMES.TREZOR
31 ? 'Trezor'
32 : 'Wallet'
34const addressFromSecp256k1Public = pub => {
35 const compressed = false
36 const uncompressed = secp256k1.publicKeyConvert(
37 Buffer.from(pub, 'hex'),
38 compressed
39 )
40 const chopped = uncompressed.slice(1) // chop parity byte
41 const hashed = keccak256(chopped)
42 const addr = addHexPrefix(hashed.slice(-20).toString('hex'))
43 return toChecksumAddress(addr)
46const addHexPrefix = hex =>
47 hex.slice(0, 2) === '0x'
48 ? hex
49 : '0x' + hex
51const stripHexPrefix = hex =>
52 hex.slice(0, 2) === '0x'
53 ? hex.slice(2)
54 : hex
56const keccak256 = str =>
57 keccak('keccak256').update(str).digest()
59const isValidAddress = (address) =>
60 /^0x[0-9a-fA-F]{40}$/.test(address)
62const toChecksumAddress = (address) => {
63 const addr = stripHexPrefix(address).toLowerCase()
64 const hash = keccak256(addr).toString('hex')
66 return lodash.reduce(addr, (acc, char, idx) =>
67 parseInt(hash[idx], 16) >= 8
68 ? acc + char.toUpperCase()
69 : acc + char,
70 '0x')
73const eqAddr = (addr0, addr1) =>
74 toChecksumAddress(addr0) === toChecksumAddress(addr1)
76const walletFromMnemonic = (mnemonic, hdpath) => {
77 const seed =
78 bip39.validateMnemonic(mnemonic)
79 ? Maybe.Just(bip39.mnemonicToSeed(mnemonic))
80 : Maybe.Nothing()
82 const toWallet = (sd, path) => {
83 let wal
84 try {
85 const hd = bip32.fromSeed(sd)
86 wal = Maybe.Just(hd.derivePath(path))
87 } catch (_) {
88 wal = Maybe.Nothing()
89 }
90 return wal
91 }
93 const wallet = seed.chain(sd => toWallet(sd, hdpath))
94 return wallet
97export {
98 DEFAULT_HD_PATH,
99 WALLET_NAMES,
100 ETH_ZERO_ADDR,
101 CURVE_ZERO_ADDR,
102 renderWalletType,
103 isValidAddress,
104 toChecksumAddress,
105 addressFromSecp256k1Public,
106 eqAddr,
107 walletFromMnemonic,
108 addHexPrefix