Skip to content

Commit 2483fc1

Browse files
committed
Change architecture for better dx
1 parent 5182a66 commit 2483fc1

File tree

10 files changed

+374
-277
lines changed

10 files changed

+374
-277
lines changed

README.md

Lines changed: 10 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -9,80 +9,28 @@ JavaScript library to easily onboard users to ethereum apps by enabling wallet s
99
## Quick Start
1010

1111
```javascript
12-
import Onboard, { modules } from 'bnc-onboard'
12+
import Onboard from 'bnc-onboard'
13+
import Web3 from 'web3'
14+
15+
// set a variable to store instantiated web3
16+
let web3
1317

1418
// head to blocknative.com to create a key
1519
const BLOCKNATIVE_KEY = 'blocknative-api-key'
1620

1721
// the network id that your dapp runs on
1822
const NETWORK_ID = 1
1923

20-
// SDK Wallet api keys
21-
const FORTMATIC_KEY = 'fortmatic-api-key'
22-
const PORTIS_KEY = 'portis-api-key'
23-
const INFURA_KEY = 'infura-api-key'
24-
const SQUARELINK_KEY = 'squarelink-api-key'
25-
26-
// the wallets you would like the user to be able to select
27-
// mobile wallets will only be displayed if the user is on a mobile device
28-
// wallets will be displayed in order
29-
const wallets = [
30-
{ name: 'coinbase' },
31-
{ name: 'trust' },
32-
{ name: 'metamask' },
33-
{ name: 'dapper' },
34-
{
35-
name: 'fortmatic',
36-
apiKey: FORTMATIC_KEY,
37-
networkId: NETWORK_ID
38-
},
39-
{
40-
name: 'portis',
41-
apiKey: PORTIS_KEY,
42-
networkId: NETWORK_ID
43-
},
44-
{
45-
name: 'squarelink',
46-
apiKey: SQUARELINK_KEY,
47-
networkId: NETWORK_ID
48-
},
49-
{ name: 'authereum', networkId: NETWORK_ID },
50-
{
51-
name: 'walletConnect',
52-
infuraKey: INFURA_KEY,
53-
networkId: NETWORK_ID
54-
}
55-
]
56-
57-
// the checks you would like the user's wallet to pass before being ready to transact
58-
const walletChecks = [
59-
{ name: 'connect' },
60-
{ name: 'network', networkId: NETWORK_ID },
61-
{ name: 'balance', minimumBalance: '1000000000' }
62-
]
63-
6424
// initialize onboard
6525
const onboard = Onboard({
6626
dappId: BLOCKNATIVE_KEY,
6727
networkId: NETWORK_ID,
6828
subscriptions: {
69-
address: address => console.log('user address has changed:', address),
70-
network: network => console.log('user network has changed:', network),
71-
balance: balance => console.log('user balance has changed:', balance),
72-
wallet: wallet =>
73-
console.log(
74-
'a new wallet has been selected by user',
75-
wallet.provider,
76-
wallet.name
77-
)
78-
},
79-
modules: {
80-
walletSelect: {
81-
heading: 'Select a Wallet',
82-
description: 'Please select a wallet to connect to this dapp:',
83-
wallets: modules.select(wallets)
84-
},
85-
walletCheck: modules.check(walletChecks)
29+
wallet: wallet => {
30+
// instantiate web3 when the user has selected a wallet
31+
web3 = new Web3(wallet.provider)
32+
console.log(`${wallet.name} connected!`)
33+
}
8634
}
8735
})
8836

src/interfaces.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export interface Initialization {
22
dappId: string
33
networkId: number
44
subscriptions: Subscriptions
5-
modules: Modules
5+
walletSelect: WalletSelectModule
6+
walletCheck: Array<WalletCheckModule | WalletCheckInit>
67
darkMode?: boolean
78
}
89

@@ -11,18 +12,12 @@ export interface Subscriptions {
1112
network: (networkId: number) => void
1213
balance: (balance: string) => void
1314
wallet: (wallet: Wallet) => void
14-
[Key: string]: (val: any) => void
15-
}
16-
17-
interface Modules {
18-
walletSelect: WalletSelectModule
19-
walletCheck: WalletCheckModule[] | Promise<WalletCheckModule[]>
2015
}
2116

2217
export interface WalletSelectModule {
2318
heading: string
2419
description: string
25-
wallets: WalletModule[] | Promise<WalletModule[]>
20+
wallets: Array<WalletModule | WalletInit>
2621
}
2722

2823
export interface WalletCheckModule {
@@ -58,6 +53,7 @@ export interface UserState {
5853
balance: string
5954
wallet: Wallet | null
6055
mobileDevice: boolean
56+
appNetworkId: number
6157
}
6258

6359
export interface StateAndHelpers extends UserState {
@@ -133,16 +129,15 @@ export interface WalletConnectOptions {
133129
}
134130

135131
export interface WalletInit {
136-
name: string
132+
walletName: string
137133
preferred?: boolean
138134
apiKey?: string
139135
infuraKey?: string
140136
networkId?: number
141137
}
142138

143139
export interface WalletCheckInit {
144-
name: string
145-
networkId?: number
140+
checkName: string
146141
minimumBalance?: string
147142
}
148143

src/modules/check/index.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
1-
import { validateWalletCheckInit } from '../../validation'
1+
import { isWalletCheckModule } from '../../validation'
22
import { WalletCheckModule, WalletCheckInit } from '../../interfaces'
33

4-
function walletChecks(
5-
walletCheckInit: WalletCheckInit[]
6-
): never | Promise<WalletCheckModule[]> {
7-
validateWalletCheckInit(walletCheckInit)
4+
const defaultChecks = ['connect', 'network']
85

9-
return Promise.all(
10-
walletCheckInit.map(init => {
11-
const { name, ...initParams } = init
6+
function check(
7+
walletChecks: Array<WalletCheckInit | WalletCheckModule> | undefined,
8+
networkId: number
9+
): Promise<WalletCheckModule[]> {
10+
if (walletChecks) {
11+
return Promise.all(
12+
walletChecks.map((checkOrModule: WalletCheckInit | WalletCheckModule) => {
13+
if (!isWalletCheckModule(checkOrModule)) {
14+
const { checkName, ...otherParams } = checkOrModule
15+
const module = getModule(checkName)
16+
return (
17+
module &&
18+
module.then((m: any) => m.default({ ...otherParams, networkId }))
19+
)
20+
}
21+
22+
return Promise.resolve(checkOrModule)
23+
})
24+
)
25+
}
1226

13-
return getModule(name).then((module: any) => module.default(initParams))
27+
return Promise.all(
28+
defaultChecks.map((checkName: string) => {
29+
const module = getModule(checkName)
30+
return module && module.then((m: any) => m.default({ networkId }))
1431
})
1532
)
1633
}
1734

18-
function getModule(name: string): Promise<any> {
35+
function getModule(name: string): Promise<any> | never {
1936
switch (name) {
2037
case 'connect':
2138
return import('./connect')
@@ -24,8 +41,8 @@ function getModule(name: string): Promise<any> {
2441
case 'balance':
2542
return import('./balance')
2643
default:
27-
return Promise.reject('invalid wallet check name')
44+
throw new Error(`invalid module name: ${name}`)
2845
}
2946
}
3047

31-
export default walletChecks
48+
export default check

src/modules/check/network.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import { networkName } from '../../utilities'
2-
import { validateType } from '../../validation'
32
import { WalletCheckModule, StateAndHelpers } from '../../interfaces'
43

5-
function network(options: { networkId: number }): WalletCheckModule | never {
6-
validateType({ name: 'network options', value: options, type: 'object' })
7-
8-
const { networkId } = options
9-
validateType({ name: 'networkId', value: networkId, type: 'number' })
10-
4+
function network(): WalletCheckModule | never {
115
return (stateAndHelpers: StateAndHelpers) => {
12-
const { network, walletSelect, exit } = stateAndHelpers
6+
const { network, appNetworkId, walletSelect, exit } = stateAndHelpers
137

14-
if (network != networkId) {
8+
if (network != appNetworkId) {
159
return {
1610
heading: 'You Must Change Networks',
1711
description: `We've detected that you need to switch your wallet's network from <b>${networkName(
1812
network
1913
)}</b> to <b>${networkName(
20-
networkId
14+
appNetworkId
2115
)} network</b> for this Dapp. <br><br> <i style="font-size: inherit; font-family: inherit;">*Some wallets may not support changing networks. If you can not change networks in your wallet you may consider switching to a different wallet.</i>`,
2216
eventCode: 'networkFail',
2317
button: {

src/modules/index.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
import select from './select'
22
import check from './check'
3+
import {
4+
WalletSelectModule,
5+
WalletCheckModule,
6+
WalletCheckInit
7+
} from '../interfaces'
38

4-
export default {
5-
select,
6-
check
9+
const defaultHeading = 'Select a Wallet'
10+
const defaultDescription = 'Please select a wallet to connect to this dapp:'
11+
12+
export default function initializeModules(
13+
networkId: number,
14+
walletSelect: WalletSelectModule | undefined,
15+
walletCheck: Array<WalletCheckModule | WalletCheckInit> | undefined
16+
) {
17+
return {
18+
walletSelect: {
19+
heading: (walletSelect && walletSelect.heading) || defaultHeading,
20+
description:
21+
(walletSelect && walletSelect.description) || defaultDescription,
22+
wallets: select(walletSelect && walletSelect.wallets, networkId)
23+
},
24+
walletCheck: check(walletCheck, networkId)
25+
}
726
}

src/modules/select/index.ts

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,49 @@
1-
import { WalletInit } from '../../interfaces'
2-
import { validateWalletInit } from '../../validation'
1+
import { WalletInit, WalletModule } from '../../interfaces'
2+
import { isWalletInit } from '../../validation'
33

4-
function wallets(walletInit: WalletInit[]) {
5-
validateWalletInit(walletInit)
4+
const defaultWalletNames = [
5+
'metamask',
6+
'dapper',
7+
'coinbase',
8+
'trust',
9+
'authereum',
10+
'opera',
11+
'operaTouch'
12+
]
613

7-
return Promise.all(
8-
walletInit.map((init: WalletInit) => {
9-
const { name, ...initParams } = init
14+
function select(
15+
wallets: Array<WalletInit | WalletModule> | undefined,
16+
networkId: number
17+
) {
18+
if (wallets) {
19+
return Promise.all(
20+
wallets.map(wallet => {
21+
if (isWalletInit(wallet)) {
22+
const { walletName, ...initParams } = wallet
23+
const module = getModule(walletName)
24+
25+
return (
26+
module &&
27+
module.then((m: any) => m.default({ ...initParams, networkId }))
28+
)
29+
}
1030

11-
return getModule(name).then((module: any) => module.default(initParams))
31+
return Promise.resolve(wallet)
32+
})
33+
)
34+
}
35+
36+
return Promise.all(
37+
defaultWalletNames.map(walletName => {
38+
const module = getModule(walletName)
39+
if (module) {
40+
return module.then((m: any) => m.default({ networkId }))
41+
}
1242
})
1343
)
1444
}
1545

16-
function getModule(name: string): Promise<any> {
46+
function getModule(name: string): Promise<any> | undefined {
1747
switch (name) {
1848
case 'metamask':
1949
return import('./wallets/metamask')
@@ -38,8 +68,8 @@ function getModule(name: string): Promise<any> {
3868
case 'operaTouch':
3969
return import('./wallets/opera-touch')
4070
default:
41-
return Promise.reject('invalid wallet name')
71+
return
4272
}
4373
}
4474

45-
export default wallets
75+
export default select

src/onboard.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
Wallet
3030
} from './interfaces'
3131

32-
export { default as modules } from './modules'
32+
import initializeModules from './modules'
3333

3434
let onboard: any
3535

@@ -41,7 +41,7 @@ function init(initialization: Initialization): API {
4141

4242
validateInit(initialization)
4343

44-
const { subscriptions, dappId, networkId, modules, darkMode } = initialization
44+
const { subscriptions, dappId, networkId, darkMode } = initialization
4545

4646
initializeBlocknative(dappId, networkId)
4747

@@ -54,11 +54,17 @@ function init(initialization: Initialization): API {
5454
darkMode
5555
}))
5656

57+
const initializedModules = initializeModules(
58+
networkId,
59+
initialization.walletSelect,
60+
initialization.walletCheck
61+
)
62+
5763
onboard = new Onboard({
5864
target: document.body,
5965
props: {
60-
walletSelectModule: modules.walletSelect,
61-
walletCheckModules: modules.walletCheck,
66+
walletSelectModule: initializedModules.walletSelect,
67+
walletCheckModules: initializedModules.walletCheck,
6268
walletSelect
6369
}
6470
})

src/stores.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ export const state = derived(
5757
network: $network,
5858
balance: $balance,
5959
wallet: $wallet,
60-
mobileDevice: $app.mobileDevice
60+
mobileDevice: $app.mobileDevice,
61+
appNetworkId: $app.networkId
6162
}
6263
}
6364
)

0 commit comments

Comments
 (0)