Skip to content

Commit 35d5882

Browse files
authored
message provider multiplexer (#85)
1 parent c9e8db9 commit 35d5882

22 files changed

Lines changed: 618 additions & 322 deletions

File tree

packages/0xsequence/tests/browser/mock-wallet/mock-wallet.test.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,13 @@ const main = async () => {
7777
context: deployedWalletContext
7878
}, owner)
7979

80-
81-
// const txn = await relayer.deployWallet(wallet.config, sequenceContext)
82-
// console.log('...', txn)
83-
84-
8580
// the json-rpc signer via the wallet
86-
// const mockUserPrompter = new MockWalletUserPrompter(true)
8781
const walletRequestHandler = new WalletRequestHandler(account, null, networks)
8882

89-
9083
// setup and register window message transport
9184
const windowHandler = new WindowMessageHandler(walletRequestHandler)
9285
windowHandler.register()
9386

94-
// TODO: register the ProxyMessageHandler() + register()
95-
9687
}
9788

9889
main()
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import {
2+
ProxyMessageProvider, ProviderMessageTransport, ProviderMessage, WalletRequestHandler,
3+
ProxyMessageChannel, ProxyMessageHandler, Wallet, DefaultProviderConfig, Web3Provider,
4+
WindowMessageHandler
5+
} from '@0xsequence/provider'
6+
import { ethers, Wallet as EOAWallet } from 'ethers'
7+
import { JsonRpcProvider } from '@ethersproject/providers'
8+
import { test, assert } from '../../utils/assert'
9+
import { Networks, WalletContext } from '@0xsequence/network'
10+
import { Wallet as SequenceWallet, Account as SequenceAccount, isValidSignature, packMessageData, recoverConfig } from '@0xsequence/wallet'
11+
import { addressOf } from '@0xsequence/config'
12+
import { LocalRelayer } from '@0xsequence/relayer'
13+
import { testAccounts, getEOAWallet, testWalletContext } from '../testutils'
14+
15+
16+
// Tests simulates a multi-message provider environment by having a wallet available via the
17+
// proxy channel and wallet window.
18+
export const tests = async () => {
19+
20+
//
21+
// Providers
22+
//
23+
const provider1 = new JsonRpcProvider('http://localhost:8545')
24+
const provider2 = new JsonRpcProvider('http://localhost:9545')
25+
26+
27+
//
28+
// Deploy Sequence WalletContext (deterministic). We skip deployment
29+
// as we rely on mock-wallet to deploy it.
30+
//
31+
const deployedWalletContext = testWalletContext
32+
console.log('walletContext:', deployedWalletContext)
33+
34+
35+
//
36+
// Proxy Channel (normally would be out-of-band)
37+
//
38+
const ch = new ProxyMessageChannel()
39+
40+
41+
//
42+
// Wallet Handler (local mock wallet, same a mock-wallet tests)
43+
//
44+
45+
// owner account address: 0x4e37E14f5d5AAC4DF1151C6E8DF78B7541680853
46+
const owner = getEOAWallet(testAccounts[0].privateKey)
47+
48+
49+
// relayers, account address: 0x3631d4d374c3710c3456d6b1de1ee8745fbff8ba
50+
// const relayerAccount = getEOAWallet(testAccounts[5].privateKey)
51+
const relayer1 = new LocalRelayer(getEOAWallet(testAccounts[5].privateKey))
52+
const relayer2 = new LocalRelayer(getEOAWallet(testAccounts[5].privateKey, provider2))
53+
54+
55+
// wallet account address: 0x24E78922FE5eCD765101276A422B8431d7151259 based on the chainId
56+
const swallet = (await SequenceWallet.singleOwner(owner, deployedWalletContext)).connect(provider1, relayer1)
57+
58+
// Network available list
59+
const networks: Networks = [
60+
{
61+
name: 'hardhat',
62+
chainId: 31337,
63+
rpcUrl: provider1.connection.url,
64+
provider: provider1,
65+
relayer: relayer1,
66+
isDefaultChain: true,
67+
// isAuthChain: true
68+
},
69+
{
70+
name: 'hardhat2',
71+
chainId: 31338,
72+
rpcUrl: provider2.connection.url,
73+
provider: provider2,
74+
relayer: relayer2,
75+
isAuthChain: true
76+
}
77+
]
78+
79+
// Account for managing multi-network wallets
80+
const saccount = new SequenceAccount({
81+
initialConfig: swallet.config,
82+
networks,
83+
context: deployedWalletContext
84+
}, owner)
85+
86+
// the rpc signer via the wallet
87+
const walletRequestHandler = new WalletRequestHandler(saccount, null, networks)
88+
89+
// register wallet message handler, in this case using the ProxyMessage transport.
90+
const proxyHandler = new ProxyMessageHandler(walletRequestHandler, ch.wallet)
91+
proxyHandler.register()
92+
93+
// register window message transport
94+
const windowHandler = new WindowMessageHandler(walletRequestHandler)
95+
windowHandler.register()
96+
97+
98+
//
99+
// Dapp, wallet provider and dapp tests
100+
//
101+
102+
// wallet provider with multiple message provider transports enabled
103+
const wallet = new Wallet('hardhat', {
104+
walletAppURL: 'http://localhost:9999/mock-wallet/mock-wallet.test.html',
105+
transports: {
106+
windowTransport: { enabled: true },
107+
proxyTransport: { enabled: true, appPort: ch.app }
108+
}
109+
})
110+
111+
// provider + signer, by default if a chainId is not specified it will direct
112+
// requests to the defaultChain
113+
// const provider = wallet.getProvider()
114+
// const signer = wallet.getSigner()
115+
116+
// clear it in case we're testing in browser session
117+
wallet.logout()
118+
119+
await test('is logged out', async () => {
120+
assert.false(wallet.isLoggedIn(), 'is logged out')
121+
})
122+
123+
await test('is disconnected', async () => {
124+
assert.false(wallet.isConnected(), 'is disconnnected')
125+
})
126+
127+
await test('login', async () => {
128+
const loggedIn = await wallet.login()
129+
assert.true(loggedIn, 'is logged in')
130+
})
131+
132+
await test('isConnected', async () => {
133+
assert.true(wallet.isConnected(), 'is connected')
134+
})
135+
136+
let walletContext: WalletContext
137+
await test('getWalletContext', async () => {
138+
walletContext = await wallet.getWalletContext()
139+
assert.equal(walletContext.factory, deployedWalletContext.factory, 'wallet context factory')
140+
assert.equal(walletContext.guestModule, deployedWalletContext.guestModule, 'wallet context guestModule')
141+
})
142+
143+
await test('getChainId', async () => {
144+
const chainId = await wallet.getChainId()
145+
assert.equal(chainId, 31337, 'chainId is correct')
146+
})
147+
148+
await test('getChainId for other chain', async () => {
149+
const p = wallet.getProvider(31338)
150+
assert.equal(await p.getChainId(), 31338, 'chainId of other chain is 31338')
151+
})
152+
153+
}
154+

packages/0xsequence/tests/browser/proxy-transport/channel.test.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { ProxyMessageProvider, ProviderMessageTransport, ProviderMessage, WalletRequestHandler, ProxyMessageChannel, ProxyMessageHandler } from '@0xsequence/provider'
1+
import { Web3Provider, ProxyMessageProvider, ProviderMessageTransport, ProviderMessage, WalletRequestHandler, ProxyMessageChannel, ProxyMessageHandler } from '@0xsequence/provider'
22
import { ethers, Wallet as EOAWallet } from 'ethers'
3-
import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers'
3+
import { JsonRpcProvider } from '@ethersproject/providers'
44
import { test, assert } from '../../utils/assert'
55
import { sequenceContext, testnetNetworks } from '@0xsequence/network'
66
import { Wallet, isValidSignature, packMessageData, recoverConfig } from '@0xsequence/wallet'
@@ -17,13 +17,15 @@ export const tests = async () => {
1717
// `ch.app` (port) will be injected into the app, and `ch.wallet` (port) will be injected into the wallet.
1818
//
1919
// Sending messages to the app port will go through channel and get received by the wallet.
20-
// Sending message to the wallet port will go through channel and get received by the app.
20+
// Sending messages to the wallet port will go through channel and get received by the app.
2121
const ch = new ProxyMessageChannel()
2222

23-
//
24-
// App Provider
25-
//
26-
const walletProvider = new ProxyMessageProvider(ch.app)
23+
ch.app.on('connect', () => {
24+
console.log('wallet connected.')
25+
})
26+
ch.app.on('disconnect', () => {
27+
console.log('wallet disconnected.')
28+
})
2729

2830
//
2931
// Wallet Handler
@@ -39,24 +41,30 @@ export const tests = async () => {
3941
const rpcProvider = new JsonRpcProvider('http://localhost:8545')
4042
const wallet = (await Wallet.singleOwner(owner)).connect(rpcProvider, relayer)
4143

42-
43-
4444
// the rpc signer via the wallet
4545
const walletRequestHandler = new WalletRequestHandler(wallet, null, [])
4646

47+
// register wallet message handler, in this case using the ProxyMessage transport.
4748
const proxyHandler = new ProxyMessageHandler(walletRequestHandler, ch.wallet)
4849
proxyHandler.register()
4950

50-
//--
5151

52-
// TODO: switch to Sequence Web3Provider ........
52+
//
53+
// App Provider
54+
//
55+
const walletProvider = new ProxyMessageProvider(ch.app)
56+
walletProvider.register()
57+
58+
walletProvider.openWallet()
59+
await walletProvider.waitUntilConnected()
60+
61+
// setup web3 provider
5362
const provider = new Web3Provider(walletProvider)
5463
const signer = provider.getSigner()
55-
5664
const address = await signer.getAddress()
5765

5866
await test('verifying getAddress result', async () => {
59-
assert.equal(address, '0x24E78922FE5eCD765101276A422B8431d7151259', 'wallet address')
67+
assert.equal(address.toLowerCase(), '0x24E78922FE5eCD765101276A422B8431d7151259'.toLowerCase(), 'wallet address')
6068
})
6169

6270
await test('sending a json-rpc request', async () => {
@@ -81,9 +89,6 @@ export const tests = async () => {
8189
await test('sign a message and validate/recover', async () => {
8290
const message = ethers.utils.toUtf8Bytes('hihi')
8391

84-
// TODO: signer should be a Sequence signer, and should be able to specify the chainId
85-
// however, for a single wallet, it can check the chainId and throw if doesnt match, for multi-wallet it will select
86-
8792
//
8893
// Sign the message
8994
//
@@ -121,7 +126,6 @@ export const tests = async () => {
121126
assert.true(singleSignerAddress.toLowerCase() === walletConfig.signers[0].address.toLowerCase(), 'owner address check')
122127
})
123128

124-
// TODO: we need to test wallet notifications from wallet to app..
125-
// TODO: perhaps we can trigger a network change there..? and notifyNetwork..?
129+
walletProvider.closeWallet()
126130

127131
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ export const tests = async () => {
114114
assert.equal(allWalletStates.length, 2, '2 wallet states (one for each chain)')
115115

116116
// we expect network order to be [defaultChain, authChain, ..], so chain 31337 will be at index 0
117-
// hmm.. TODO: WalletProvider defaultNetwork should specify the "defaultNetwork", which will
118-
// become our *defaultChain* ..
119117
const state1 = allWalletStates[0]
120118
assert.true(state1.chainId === 31337, 'state1, chainId is 31337')
121119
assert.true(state1.config.threshold === 1, 'state1, threshold')
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { runBrowserTests } from './utils/browser-test-runner'
2+
3+
runBrowserTests('mux-transport', 'mux-transport/mux.test.html')

packages/config/src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface WalletState {
2525

2626
deployed: boolean
2727
imageHash: string
28-
currentImageHash?: string // TODO: rename to deployedImageHash
28+
currentImageHash?: string
2929

3030
published?: boolean
3131
}

packages/provider/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * from './transports'
22
export * from './types'
33
export * from './wallet'
4-
export * from './wallet-request-handler'
54
export * from './provider'

packages/provider/src/provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { WalletConfig, WalletState } from '@0xsequence/config'
88
import { Relayer } from '@0xsequence/relayer'
99
import { Deferrable, shallowCopy, resolveProperties } from '@0xsequence/utils'
1010
import { TransactionRequest, TransactionResponse, Transactionish, SignedTransactions } from '@0xsequence/transactions'
11-
import { WalletRequestHandler } from './wallet-request-handler'
11+
import { WalletRequestHandler } from './transports/wallet-request-handler'
1212

1313
// naming..?
1414
// Web3Provider, Web3Signer, Web3Relayer, Web3Indexer

0 commit comments

Comments
 (0)