Skip to content

Commit 6069287

Browse files
committed
Start of implementation
1 parent ec13054 commit 6069287

File tree

11 files changed

+326
-383
lines changed

11 files changed

+326
-383
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@
4949
"bnc-sdk": "1.1.0",
5050
"bowser": "^2.5.2",
5151
"ethereumjs-tx": "^2.1.2",
52+
"ethereumjs-util": "^6.2.0",
53+
"ethereumjs-wallet": "^0.6.3",
5254
"fortmatic": "^0.8.2",
55+
"hdkey": "^1.1.1",
5356
"regenerator-runtime": "^0.13.3",
5457
"squarelink": "^1.1.4",
5558
"trezor-connect": "7.0.1",

rollup.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export default {
5959
'regenerator-runtime/runtime',
6060
'trezor-connect',
6161
'ethereumjs-tx',
62+
'ethereumjs-util',
63+
// 'ethereumjs-wallet/hdkey',
64+
'hdkey',
6265
'@ledgerhq/hw-transport-u2f',
6366
'@ledgerhq/hw-app-eth',
6467
'util',

src/@types/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ declare module 'web3-provider-engine/subproviders/subscriptions'
88
declare module 'web3-provider-engine/subproviders/filters'
99
declare module 'trezor-connect'
1010
declare module 'ethereumjs-tx'
11+
declare module 'ethereumjs-util'
12+
declare module 'hdkey'
13+
// declare module 'ethereumjs-wallet/hdkey'
1114
declare module '@ledgerhq/hw-app-eth'
1215
declare module '@ledgerhq/hw-transport-u2f'
1316

src/modules/check/accounts.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import { WalletCheckModule, StateAndHelpers } from '../../interfaces'
1+
import {
2+
WalletCheckModule,
3+
StateAndHelpers,
4+
WalletCheckModal
5+
} from '../../interfaces'
26

37
type AccountsAndBalances = Array<{ balance: string; address: string }>
48

5-
function accountSelect(): WalletCheckModule | never {
9+
function accountSelect(): WalletCheckModule {
610
let completed: boolean = false
711
let loadingAccounts: boolean = false
812
let accountsAndBalances: AccountsAndBalances = []
913

10-
return async (stateAndHelpers: StateAndHelpers) => {
14+
return async (
15+
stateAndHelpers: StateAndHelpers
16+
): Promise<WalletCheckModal | undefined> => {
1117
const { wallet, BigNumber, address, balance } = stateAndHelpers
1218
const { provider, type } = wallet
1319

@@ -51,7 +57,7 @@ function accountSelect(): WalletCheckModule | never {
5157
<select id="account-select" onchange="window.accountSelect()" style="padding: 0.5rem;">
5258
${accountsAndBalances.map(
5359
(account: { balance: string; address: string }) =>
54-
`<option value="${account.address}">${account.address} --- ${
60+
`<option>${account.address} --- ${
5561
account.balance != null
5662
? new BigNumber(account.balance)
5763
.div('1000000000000000000')

src/modules/check/connect.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
1-
import { WalletCheckModal, StateAndHelpers } from '../../interfaces'
1+
import {
2+
WalletCheckModal,
3+
StateAndHelpers,
4+
WalletCheckModule
5+
} from '../../interfaces'
6+
7+
function connect(options: {
8+
heading: string
9+
description: string
10+
icon: string
11+
}): WalletCheckModule {
12+
const { heading, description, icon } = options
213

3-
function connect() {
414
return (stateAndHelpers: StateAndHelpers): WalletCheckModal | undefined => {
515
const { wallet, address } = stateAndHelpers
616
if (!address && wallet && wallet.name) {
717
return {
8-
heading: 'Login and Authorize Your Wallet',
9-
description: `This dapp requires access to your wallet, please login and authorize access to your ${wallet.name} accounts to continue.`,
18+
heading: heading || 'Login and Authorize Your Wallet',
19+
description:
20+
description ||
21+
`This dapp requires access to your wallet, please login and authorize access to your ${wallet.name} accounts to continue.`,
1022
eventCode: 'loginFail',
1123
action: wallet.connect,
12-
icon: `
24+
icon:
25+
icon ||
26+
`
1327
<svg height="14" viewBox="0 0 18 14" width="18" xmlns="http://www.w3.org/2000/svg"><g fill="currentColor"><path d="m10.29375 4.05351563c0-.04921875 0-.09140625 0-.13007813 0-1.0546875 0-2.109375 0-3.1640625 0-.43945312.3480469-.76992188.7804688-.7453125.2003906.01054688.3585937.10546875.4992187.24609375.5800781.58359375 1.1566406 1.16367188 1.7367187 1.74023438 1.4695313 1.46953125 2.9390625 2.93906249 4.4050782 4.40859375.1335937.13359375.2425781.27421875.2707031.46757812.0351562.20742188-.0246094.421875-.1652344.58007813-.0246094.028125-.0492187.05273437-.0738281.08085937-2.0601563 2.06367188-4.1203125 4.1238281-6.1804688 6.1875-.2109375.2109375-.4570312.3023438-.7453125.2179688-.2707031-.0808594-.4464843-.2707032-.5132812-.5484375-.0140625-.0738282-.0175781-.1441407-.0140625-.2179688 0-1.0335937 0-2.0707031 0-3.1042969 0-.0386719 0-.08085935 0-.13359372h-5.06953125c-.49570313 0-.80507813-.309375-.80507813-.80859375 0-1.42382813 0-2.84414063 0-4.26796875 0-.49570313.30585938-.8015625.8015625-.8015625h4.93593748z"/><path d="m5.69882812 13.978125h-4.01132812c-.928125 0-1.6875-.8753906-1.6875-1.9511719v-10.06171872c0-1.07578125.75585938-1.95117188 1.6875-1.95117188h4.01132812c.34101563 0 .61523438.31992188.61523438.71015625 0 .39023438-.27421875.71015625-.61523438.71015625h-4.01132812c-.253125 0-.45703125.23554688-.45703125.52734375v10.06171875c0 .2917969.20390625.5273437.45703125.5273437h4.01132812c.34101563 0 .61523438.3199219.61523438.7101563s-.27773438.7171875-.61523438.7171875z"/></g></svg>
1428
`
1529
}

src/modules/check/derivation-path.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { WalletCheckModal, StateAndHelpers } from '../../interfaces'
2+
3+
interface DerivationPaths {
4+
[key: string]: Array<{ path?: string; label: string }>
5+
}
6+
7+
const derivationPaths: DerivationPaths = {
8+
Ledger: [
9+
{ path: `m/44'/60'`, label: 'Ethereum' },
10+
{ path: `m/44'/60'/0'`, label: 'Ethereum Legacy' },
11+
{ label: 'Custom Path' }
12+
],
13+
Trezor: [
14+
{ path: `m/44'/60'/0'/0`, label: 'Ethereum' },
15+
{ label: 'Custom Path' }
16+
]
17+
}
18+
19+
const customInputHtmlString = `
20+
<input id="custom-derivation-input" type="text" placeholder="custom derivation path" onchange="window.handleCustomInput()" />
21+
`
22+
23+
function derivationSelectHtmlString(walletName: string) {
24+
return `
25+
<select id="derivation-select" onchange="window.handleDerivationSelect()">
26+
${derivationPaths[walletName].map(
27+
(derivation: { path?: string; label: string }) => {
28+
const { path, label } = derivation
29+
return path
30+
? `
31+
<option>${label} - ${path}</option>
32+
`
33+
: `<option>${label}</option>`
34+
}
35+
)}
36+
</select>
37+
`
38+
}
39+
40+
function derivationPath() {
41+
let completed = false
42+
let showCustomInput = false
43+
let path = ''
44+
45+
return (stateAndHelpers: StateAndHelpers): WalletCheckModal | undefined => {
46+
const { wallet, address } = stateAndHelpers
47+
48+
if (!address && wallet && wallet.type === 'hardware' && !completed) {
49+
const handleCustomInput = () => {
50+
const input = <HTMLInputElement>(
51+
document.getElementById('custom-derivation-input')
52+
)
53+
path = input && input.value
54+
}
55+
56+
const handleDerivationSelect = () => {
57+
const pathIndex = (document as any).getElementById('derivation-select')
58+
.selectedIndex
59+
60+
const path = derivationPaths[wallet.name][pathIndex].path
61+
62+
if (!path) {
63+
showCustomInput = true
64+
}
65+
}
66+
67+
const deleteWindowProperties = () => {
68+
delete (window as any).handleCustomInput
69+
}
70+
;(window as any).handleCustomInput = handleCustomInput
71+
72+
return {
73+
heading: 'Hardware Wallet Connect',
74+
description: `Please select a derivation path to connect your ${wallet.name} accounts, or select custom to input a custom path:`,
75+
eventCode: 'derivationPath',
76+
html: showCustomInput
77+
? customInputHtmlString
78+
: derivationSelectHtmlString(wallet.name),
79+
button: {
80+
text: 'Connect',
81+
onclick: () => {
82+
wallet.connect &&
83+
wallet.connect().then(() => {
84+
deleteWindowProperties()
85+
completed = true
86+
})
87+
}
88+
},
89+
90+
icon: `
91+
<svg height="14" viewBox="0 0 18 14" width="18" xmlns="http://www.w3.org/2000/svg"><g fill="currentColor"><path d="m10.29375 4.05351563c0-.04921875 0-.09140625 0-.13007813 0-1.0546875 0-2.109375 0-3.1640625 0-.43945312.3480469-.76992188.7804688-.7453125.2003906.01054688.3585937.10546875.4992187.24609375.5800781.58359375 1.1566406 1.16367188 1.7367187 1.74023438 1.4695313 1.46953125 2.9390625 2.93906249 4.4050782 4.40859375.1335937.13359375.2425781.27421875.2707031.46757812.0351562.20742188-.0246094.421875-.1652344.58007813-.0246094.028125-.0492187.05273437-.0738281.08085937-2.0601563 2.06367188-4.1203125 4.1238281-6.1804688 6.1875-.2109375.2109375-.4570312.3023438-.7453125.2179688-.2707031-.0808594-.4464843-.2707032-.5132812-.5484375-.0140625-.0738282-.0175781-.1441407-.0140625-.2179688 0-1.0335937 0-2.0707031 0-3.1042969 0-.0386719 0-.08085935 0-.13359372h-5.06953125c-.49570313 0-.80507813-.309375-.80507813-.80859375 0-1.42382813 0-2.84414063 0-4.26796875 0-.49570313.30585938-.8015625.8015625-.8015625h4.93593748z"/><path d="m5.69882812 13.978125h-4.01132812c-.928125 0-1.6875-.8753906-1.6875-1.9511719v-10.06171872c0-1.07578125.75585938-1.95117188 1.6875-1.95117188h4.01132812c.34101563 0 .61523438.31992188.61523438.71015625 0 .39023438-.27421875.71015625-.61523438.71015625h-4.01132812c-.253125 0-.45703125.23554688-.45703125.52734375v10.06171875c0 .2917969.20390625.5273437.45703125.5273437h4.01132812c.34101563 0 .61523438.3199219.61523438.7101563s-.27773438.7171875-.61523438.7171875z"/></g></svg>
92+
`
93+
}
94+
}
95+
}
96+
}
97+
98+
export default derivationPath

src/modules/check/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ function getModule(name: string): Promise<any> | never {
4444
return import('./balance')
4545
case 'accounts':
4646
return import('./accounts')
47+
case 'derivationPath':
48+
return import('./derivation-path')
4749
default:
4850
throw new Error(`invalid module name: ${name}`)
4951
}

src/modules/check/loading-accounts.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import HDKey from 'hdkey'
2+
import { publicToAddress, toChecksumAddress } from 'ethereumjs-util'
3+
import buffer from 'buffer'
4+
5+
export function generateAddresses(
6+
publicKey: string,
7+
chainCode: string,
8+
basePath: string,
9+
amount: number = 30
10+
) {
11+
const hdk = new HDKey()
12+
13+
hdk.publicKey = new buffer.Buffer(publicKey, 'hex')
14+
hdk.chainCode = new buffer.Buffer(chainCode, 'hex')
15+
16+
const addresses = []
17+
18+
for (let i = 0; i < amount; i++) {
19+
const dkey = hdk.deriveChild(i)
20+
const address = publicToAddress(dkey.publicKey, true).toString('hex')
21+
addresses.push({
22+
dPath: `${basePath}/${i}`,
23+
address: toChecksumAddress(address)
24+
})
25+
}
26+
27+
return addresses
28+
}
29+
30+
// import * as hdKey from 'ethereumjs-wallet/hdkey'
31+
32+
// export function generateAddresses(xpub: string, basePath: string, amount = 30) {
33+
// const node = new hdKey.fromExtendedKey(xpub)
34+
35+
// const children = []
36+
37+
// for (let i = 0; i < amount; i++) {
38+
// children.push({ childNode: node.deriveChild(i), dPath: `${basePath}/${i}` })
39+
// }
40+
41+
// console.log({ children })
42+
43+
// const addresses = children.map(({ childNode, dPath }) => ({
44+
// address: childNode.getWallet().getChecksumAddressString(),
45+
// dPath
46+
// }))
47+
48+
// console.log({ addresses })
49+
50+
// return addresses
51+
// }

0 commit comments

Comments
 (0)