Skip to content

Commit c9e8db9

Browse files
committed
intersect custom network config with wallet-provided config
1 parent 189ba2a commit c9e8db9

3 files changed

Lines changed: 82 additions & 61 deletions

File tree

packages/0xsequence/tests/browser/wallet-provider/dapp.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export const tests = async () => {
2121
//
2222
const providerConfig = { ...DefaultProviderConfig }
2323
providerConfig.walletAppURL = 'http://localhost:9999/mock-wallet/mock-wallet.test.html'
24+
providerConfig.networks = [{
25+
name: 'hardhat', rpcUrl: 'http://0.0.0.0:8545'
26+
}]
2427

2528
const wallet = new Wallet('hardhat', providerConfig)
2629

packages/network/src/utils.ts

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const maybeNetworkId = (chainId?: ChainId): number | undefined => {
2121
return getNetworkId(chainId)
2222
}
2323

24-
export const isValidNetworkConfig = (networkConfig: NetworkConfig | NetworkConfig[], raise: boolean = false): boolean => {
24+
export const isValidNetworkConfig = (networkConfig: NetworkConfig | NetworkConfig[], raise: boolean = false, skipRelayerCheck: boolean = false): boolean => {
2525
if (!networkConfig) throw new Error(`invalid network config: empty config`)
2626

2727
const configs: NetworkConfig[] = []
@@ -67,9 +67,11 @@ export const isValidNetworkConfig = (networkConfig: NetworkConfig | NetworkConfi
6767
if (raise) throw new Error(`invalid network config for chainId ${c.chainId}: rpcUrl or provider must be provided`)
6868
return false
6969
}
70-
if ((!c.relayerUrl || c.relayerUrl === '') && !c.relayer) {
71-
if (raise) throw new Error(`invalid network config for chainId ${c.chainId}: relayerUrl or relayer must be provided`)
72-
return false
70+
if (!skipRelayerCheck) {
71+
if ((!c.relayerUrl || c.relayerUrl === '') && !c.relayer) {
72+
if (raise) throw new Error(`invalid network config for chainId ${c.chainId}: relayerUrl or relayer must be provided`)
73+
return false
74+
}
7375
}
7476
if (c.isDefaultChain) {
7577
if (defaultChain) {
@@ -98,8 +100,8 @@ export const isValidNetworkConfig = (networkConfig: NetworkConfig | NetworkConfi
98100
return true
99101
}
100102

101-
export const ensureValidNetworks = (networks: NetworkConfig[]): NetworkConfig[] => {
102-
isValidNetworkConfig(networks, true)
103+
export const ensureValidNetworks = (networks: NetworkConfig[], skipRelayerCheck: boolean = false): NetworkConfig[] => {
104+
isValidNetworkConfig(networks, true, skipRelayerCheck)
103105
return networks
104106
}
105107

@@ -155,6 +157,42 @@ export const sortNetworks = (networks: Networks, defaultChainId?: string | numbe
155157
return config
156158
}
157159

160+
export const updateNetworkConfig = (src: Partial<NetworkConfig>, dest: NetworkConfig) => {
161+
if (!src || !dest) return
162+
163+
if (!src.chainId && !src.name) {
164+
throw new Error('failed to update network config: source config is missing chainId or name')
165+
}
166+
if (src.chainId !== dest.chainId && src.name !== dest.name) {
167+
throw new Error('failed to update network config: one of chainId or name must match')
168+
}
169+
170+
if (src.rpcUrl) {
171+
dest.rpcUrl = src.rpcUrl
172+
dest.provider = undefined
173+
}
174+
if (src.provider) {
175+
dest.provider = src.provider
176+
}
177+
if (src.relayerUrl) {
178+
dest.relayerUrl = src.relayerUrl
179+
dest.relayer = undefined
180+
}
181+
if (src.relayer) {
182+
dest.relayer = src.relayer
183+
}
184+
if (src.ensAddress) {
185+
dest.ensAddress = src.ensAddress
186+
}
187+
// NOTE: we do not set default or auth chain from here
188+
// if (src.isDefaultChain) {
189+
// dest.isDefaultChain = src.isDefaultChain
190+
// }
191+
// if (src.isAuthChain) {
192+
// dest.isAuthChain = src.isAuthChain
193+
// }
194+
}
195+
158196
export const createNetworkConfig = (networks: Networks | NetworksBuilder, defaultChainId?: number, vars?: {[key: string]: any}): Networks => {
159197
let config: NetworkConfig[] = []
160198
if (typeof(networks) === 'function') {

packages/provider/src/wallet.ts

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Networks, NetworkConfig, WalletContext, sequenceContext, ChainId, getNetworkId, JsonRpcSender,
22
JsonRpcRouter, JsonRpcMiddleware, allowProviderMiddleware, CachedProvider, PublicProvider, loggingProviderMiddleware,
33
SigningProvider, EagerProvider, exceptionProviderMiddleware, JsonRpcExternalProvider,
4-
JsonRpcHandlerFunc, JsonRpcRequest, JsonRpcResponse, JsonRpcResponseCallback, JsonRpcHandler, findNetworkConfig
4+
JsonRpcHandlerFunc, JsonRpcRequest, JsonRpcResponse, JsonRpcResponseCallback, JsonRpcHandler, findNetworkConfig, updateNetworkConfig, ensureValidNetworks
55
} from '@0xsequence/network'
66
import { WalletConfig } from '@0xsequence/config'
77
import { JsonRpcProvider, JsonRpcSigner, ExternalProvider } from '@ethersproject/providers'
@@ -227,6 +227,7 @@ export class Wallet implements WalletProvider {
227227
isLoggedIn(): boolean {
228228
return this.session !== undefined &&
229229
this.session.networks !== undefined && this.session.networks.length > 0 &&
230+
this.networks !== undefined && this.networks.length > 0 &&
230231
this.session.accountAddress.startsWith('0x')
231232
}
232233

@@ -246,27 +247,23 @@ export class Wallet implements WalletProvider {
246247
if (!this.isLoggedIn()) {
247248
throw new Error('login first')
248249
}
249-
250-
const session = this.getSession()
251-
if (!session.networks) {
250+
if (!this.networks) {
252251
throw new Error('network has not been set by session. login first.')
253252
}
254-
255253
if (chainId) {
256-
const network = findNetworkConfig(session.networks, chainId)
254+
const network = findNetworkConfig(this.networks, chainId)
257255
return network ? [network] : []
258256
}
259-
return session.networks
257+
return this.networks
260258
}
261259

262260
// getChainId returns the default chain id
263261
getChainId = async (): Promise<number> => {
264-
const session = this.getSession()
265-
if (!session.networks || session.networks.length < 1) {
262+
if (!this.networks || this.networks.length < 1) {
266263
throw new Error('networks have not been set by session. login first.')
267264
}
268265
// default chain id is first one in the list, by design
269-
return session.networks[0].chainId
266+
return this.networks[0].chainId
270267
}
271268

272269
openWallet = async (path?: string, state?: any): Promise<boolean> => {
@@ -304,13 +301,13 @@ export class Wallet implements WalletProvider {
304301
if (!chainId) {
305302
return this.transport.provider
306303
}
307-
if (this.session.networks.length === 0) {
304+
if (this.networks.length === 0) {
308305
throw new Error('networks list is empty. upon logging in, networks should be populated')
309306
}
310307

311-
let network = this.session.networks[0]
308+
let network = this.networks[0]
312309
if (chainId) {
313-
network = findNetworkConfig(this.session.networks, chainId)
310+
network = findNetworkConfig(this.networks, chainId)
314311
}
315312

316313
// return memoized network provider
@@ -420,11 +417,11 @@ export class Wallet implements WalletProvider {
420417
})
421418

422419
// set networks
423-
// TODO: build intersected list with this.config.networks
424420
if (session.networks) {
425421
this.useNetworks(session.networks)
426422
}
427423

424+
// save session
428425
this.saveSession(this.session)
429426

430427
// confirm the session address matches the one with the signer
@@ -435,20 +432,30 @@ export class Wallet implements WalletProvider {
435432
}
436433

437434
private useNetworks(networks: NetworkConfig[]) {
438-
this.networks = networks
439-
440-
// hmm.. here..?
435+
// set networks in the session
441436
if (!this.session) this.session = {}
442-
this.session.networks = networks // TODO ..
443-
444-
// // ..
445-
// if (this.config.networks) {
446-
// // intersect our this.config.networks if exists..
447-
// this.networks = networks
448-
// // TODO: add a method, which can combine network configs..
449-
// } else {
450-
// this.networks = networks
451-
// }
437+
this.session.networks = networks
438+
439+
if (!this.config.networks && !this.config.networkRpcUrl) {
440+
this.networks = networks
441+
return
442+
}
443+
444+
// combine custom network config with networks in the session
445+
if (this.config.networks) {
446+
this.networks = networks.map(n => ({ ...n })) // copy
447+
this.config.networks.forEach(n => {
448+
const network = findNetworkConfig(this.networks, n.chainId || n.name)
449+
if (!network) return
450+
updateNetworkConfig(n, network)
451+
})
452+
ensureValidNetworks(this.networks, true)
453+
}
454+
455+
// an extra override for convenience
456+
if (this.config.networkRpcUrl) {
457+
this.networks[0].rpcUrl = this.config.networkRpcUrl
458+
}
452459
}
453460
}
454461

@@ -474,7 +481,7 @@ export interface ProviderConfig {
474481
// networks is a configuration list of networks used by the wallet. This list
475482
// is combined with the network list supplied from the wallet upon login,
476483
// and settings here take precedence such as overriding a relayer setting, or rpcUrl.
477-
networks?: NetworkConfig[]
484+
networks?: Partial<NetworkConfig>[]
478485

479486
// networkRpcUrl will set the provider rpcUrl of the default network
480487
networkRpcUrl?: string
@@ -485,33 +492,6 @@ export interface ProviderConfig {
485492
defaultNetworkId?: string | number
486493
}
487494

488-
/*
489-
490-
const wallet = new Wallet({
491-
network: {
492-
chainId: 1,
493-
rpcUrl: 'https://.....',
494-
mode: 'mainnet'
495-
}
496-
})
497-
498-
//--
499-
500-
501-
const wallet = new Wallet('mainnet')
502-
503-
const wallet = new Wallet('mainnet', { etc ..})
504-
const wallet = new Wallet(1, { walletAppURL: 'xx', networkRpcUrl: 'xxx', networks: [{ chainId: 1, rpcUrl: 'xxx' }] })
505-
506-
507-
everything can be omitted and will default to mainnet.. as..
508-
509-
const wallet = new Wallet()
510-
511-
//--
512-
513-
514-
*/
515495

516496
// TODO: remove Web3Global ..?
517497
export type ProviderType = 'Web3Global' | 'Window' | 'Proxy' // TODO: combo..? ie, window+proxy ..

0 commit comments

Comments
 (0)