@0xsequence/provider 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/0xsequence-provider.cjs.d.ts +1 -0
- package/dist/0xsequence-provider.cjs.d.ts.map +1 -0
- package/dist/0xsequence-provider.cjs.dev.js +1742 -1678
- package/dist/0xsequence-provider.cjs.prod.js +1742 -1678
- package/dist/0xsequence-provider.esm.js +1735 -1676
- package/dist/declarations/src/client.d.ts +74 -0
- package/dist/declarations/src/index.d.ts +7 -5
- package/dist/declarations/src/init.d.ts +25 -0
- package/dist/declarations/src/provider.d.ts +127 -63
- package/dist/declarations/src/signer.d.ts +87 -0
- package/dist/declarations/src/transports/base-provider-transport.d.ts +1 -1
- package/dist/declarations/src/transports/base-wallet-transport.d.ts +2 -2
- package/dist/declarations/src/transports/extension-transport/base-injected-transport.d.ts +1 -1
- package/dist/declarations/src/transports/extension-transport/extension-message-handler.d.ts +3 -3
- package/dist/declarations/src/transports/extension-transport/extension-message-provider.d.ts +2 -2
- package/dist/declarations/src/transports/extension-transport/index.d.ts +3 -3
- package/dist/declarations/src/transports/index.d.ts +8 -8
- package/dist/declarations/src/transports/mux-transport/index.d.ts +1 -1
- package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +22 -1
- package/dist/declarations/src/transports/proxy-transport/index.d.ts +3 -3
- package/dist/declarations/src/transports/proxy-transport/proxy-message-channel.d.ts +1 -1
- package/dist/declarations/src/transports/proxy-transport/proxy-message-handler.d.ts +4 -4
- package/dist/declarations/src/transports/proxy-transport/proxy-message-provider.d.ts +3 -3
- package/dist/declarations/src/transports/unreal-transport/index.d.ts +2 -2
- package/dist/declarations/src/transports/unreal-transport/unreal-message-handler.d.ts +3 -3
- package/dist/declarations/src/transports/unreal-transport/unreal-message-provider.d.ts +2 -2
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +1 -2
- package/dist/declarations/src/transports/window-transport/index.d.ts +2 -2
- package/dist/declarations/src/transports/window-transport/window-message-handler.d.ts +3 -3
- package/dist/declarations/src/transports/window-transport/window-message-provider.d.ts +2 -2
- package/dist/declarations/src/types.d.ts +25 -9
- package/dist/declarations/src/utils/index.d.ts +10 -7
- package/dist/declarations/src/utils.d.ts +21 -15
- package/package.json +19 -12
- package/src/client.ts +423 -0
- package/src/extended.ts +4 -0
- package/src/index.ts +3 -1
- package/src/init.ts +134 -0
- package/src/provider.ts +447 -424
- package/src/signer.ts +316 -0
- package/src/transports/base-wallet-transport.ts +3 -8
- package/src/transports/mux-transport/mux-message-provider.ts +86 -2
- package/src/transports/proxy-transport/proxy-message-provider.ts +1 -1
- package/src/transports/wallet-request-handler.ts +3 -33
- package/src/transports/window-transport/window-message-provider.ts +4 -2
- package/src/types.ts +41 -10
- package/src/utils/index.ts +16 -76
- package/src/utils.ts +81 -51
- package/dist/declarations/src/eip191exceptions.d.ts +0 -3
- package/dist/declarations/src/extended.d.ts +0 -6
- package/dist/declarations/src/transports/unreal-transport/overridelogs.d.ts +0 -4
- package/dist/declarations/src/wallet.d.ts +0 -105
- package/src/wallet.ts +0 -770
package/src/provider.ts
CHANGED
|
@@ -1,531 +1,554 @@
|
|
|
1
|
-
import { ethers, BytesLike, Bytes, providers, TypedDataDomain, TypedDataField } from 'ethers'
|
|
2
1
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
JsonRpcSender,
|
|
11
|
-
maybeChainId
|
|
12
|
-
} from '@0xsequence/network'
|
|
2
|
+
import { ethers } from "ethers"
|
|
3
|
+
import { SequenceClient } from "./client"
|
|
4
|
+
import { ChainIdLike, NetworkConfig, allNetworks, findNetworkConfig } from "@0xsequence/network"
|
|
5
|
+
import { ConnectDetails, ConnectOptions, EIP1193Provider, OpenWalletIntent, OptionalChainIdLike, WalletSession } from "./types"
|
|
6
|
+
import { commons } from "@0xsequence/core"
|
|
7
|
+
import { WalletUtils } from "./utils/index"
|
|
8
|
+
import { SequenceSigner, SingleNetworkSequenceSigner } from "./signer"
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { Deferrable, shallowCopy, resolveProperties, Forbid } from '@0xsequence/utils'
|
|
17
|
-
import { WalletRequestHandler } from './transports/wallet-request-handler'
|
|
18
|
-
import { commons, universal } from '@0xsequence/core'
|
|
19
|
-
import { Account, AccountStatus } from '@0xsequence/account'
|
|
20
|
-
import { ExtendedTransactionRequest, toExtended } from './extended'
|
|
10
|
+
export interface ISequenceProvider {
|
|
11
|
+
readonly _isSequenceProvider: true
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return isSequenceProvider(cand)
|
|
25
|
-
}
|
|
13
|
+
connect(options?: ConnectOptions): Promise<ConnectDetails>
|
|
14
|
+
disconnect(): void
|
|
26
15
|
|
|
27
|
-
|
|
16
|
+
isConnected(): boolean
|
|
17
|
+
getSession(): WalletSession | undefined
|
|
28
18
|
|
|
29
|
-
|
|
19
|
+
listAccounts(): string[]
|
|
30
20
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
readonly _defaultChainId?: number
|
|
21
|
+
// @deprecated use getSigner().getAddress() instead
|
|
22
|
+
getAddress(): string
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
provider = sender
|
|
24
|
+
getNetworks(): Promise<NetworkConfig[]>
|
|
25
|
+
getChainId(): number
|
|
38
26
|
|
|
39
|
-
|
|
27
|
+
setDefaultChainId(chainId: ChainIdLike): void
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
isOpened(): boolean
|
|
30
|
+
openWallet(path?: string, intent?: OpenWalletIntent): Promise<boolean>
|
|
31
|
+
closeWallet(): void
|
|
32
|
+
|
|
33
|
+
getProvider(): SequenceProvider
|
|
34
|
+
getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
|
|
35
|
+
getProvider(chainId?: ChainIdLike): SequenceProvider | SingleNetworkSequenceProvider
|
|
36
|
+
|
|
37
|
+
getSigner(): SequenceSigner
|
|
38
|
+
getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
|
|
39
|
+
getSigner(chainId?: ChainIdLike): SequenceSigner | SingleNetworkSequenceSigner
|
|
40
|
+
|
|
41
|
+
// @deprecated use getSigner().getWalletContext() instead
|
|
42
|
+
getWalletContext(): Promise<commons.context.VersionedContext>
|
|
43
|
+
|
|
44
|
+
// @deprecated use getSigner().getWalletConfig() instead
|
|
45
|
+
getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config>
|
|
46
|
+
|
|
47
|
+
utils: WalletUtils
|
|
48
|
+
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
export class SequenceProvider extends ethers.providers.BaseProvider implements ISequenceProvider, EIP1193Provider {
|
|
51
|
+
private readonly singleNetworkProviders: { [chainId: number]: SingleNetworkSequenceProvider } = {}
|
|
52
|
+
|
|
53
|
+
readonly _isSequenceProvider = true
|
|
54
|
+
readonly utils: WalletUtils
|
|
55
|
+
|
|
56
|
+
readonly signer: SequenceSigner
|
|
57
|
+
|
|
58
|
+
constructor (
|
|
59
|
+
public readonly client: SequenceClient,
|
|
60
|
+
private readonly providerFor: (networkId: number) => ethers.providers.JsonRpcProvider,
|
|
61
|
+
public readonly networks: NetworkConfig[] = allNetworks
|
|
50
62
|
) {
|
|
51
|
-
|
|
63
|
+
// We support a lot of networks
|
|
64
|
+
// but we start with the default one
|
|
65
|
+
super(client.getChainId())
|
|
66
|
+
|
|
67
|
+
// Emit events as defined by EIP-1193
|
|
68
|
+
client.onConnect((details) => {
|
|
69
|
+
this.emit('connect', details)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
client.onDisconnect((error) => {
|
|
73
|
+
this.emit('disconnect', error)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
client.onDefaultChainIdChanged((chainId) => {
|
|
77
|
+
this.emit('chainChanged', chainId)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
client.onAccountsChanged((accounts) => {
|
|
81
|
+
this.emit('accountsChanged', accounts)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// NOTICE: We don't emit 'open' and 'close' events
|
|
85
|
+
// because these are handled by the library, and they
|
|
86
|
+
// are not part of EIP-1193
|
|
87
|
+
|
|
88
|
+
// devs can still access them using
|
|
89
|
+
// client.onOpen()
|
|
90
|
+
// client.onClose()
|
|
91
|
+
|
|
92
|
+
// Create a Sequence signer too
|
|
93
|
+
this.signer = new SequenceSigner(this.client, this)
|
|
94
|
+
|
|
95
|
+
// Create a utils instance
|
|
96
|
+
this.utils = new WalletUtils(this.signer)
|
|
52
97
|
}
|
|
53
98
|
|
|
54
|
-
|
|
55
|
-
|
|
99
|
+
getSigner(): SequenceSigner
|
|
100
|
+
getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
|
|
101
|
+
getSigner(chainId?: ChainIdLike): SequenceSigner | SingleNetworkSequenceSigner
|
|
102
|
+
|
|
103
|
+
getSigner(chainId?: ChainIdLike) {
|
|
104
|
+
return this.signer.getSigner(chainId)
|
|
56
105
|
}
|
|
57
106
|
|
|
58
|
-
|
|
59
|
-
return this.
|
|
107
|
+
connect(options: ConnectOptions) {
|
|
108
|
+
return this.client.connect(options)
|
|
60
109
|
}
|
|
61
110
|
|
|
62
|
-
|
|
63
|
-
return
|
|
111
|
+
disconnect() {
|
|
112
|
+
return this.client.disconnect()
|
|
64
113
|
}
|
|
65
114
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (defaultChainId) return defaultChainId
|
|
115
|
+
isConnected() {
|
|
116
|
+
return this.client.isConnected()
|
|
117
|
+
}
|
|
70
118
|
|
|
71
|
-
|
|
72
|
-
return this.
|
|
119
|
+
getSession() {
|
|
120
|
+
return this.client.getSession()
|
|
73
121
|
}
|
|
74
122
|
|
|
75
|
-
|
|
76
|
-
return this.
|
|
123
|
+
listAccounts(): string[] {
|
|
124
|
+
return [this.client.getAddress()]
|
|
77
125
|
}
|
|
78
|
-
}
|
|
79
126
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
127
|
+
// @deprecated use getSigner() instead
|
|
128
|
+
getAddress() {
|
|
129
|
+
return this.client.getAddress()
|
|
130
|
+
}
|
|
84
131
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const walletRequestHandler = new WalletRequestHandler(account, null, networks || [])
|
|
88
|
-
super(walletRequestHandler)
|
|
132
|
+
getNetworks(): Promise<NetworkConfig[]> {
|
|
133
|
+
return this.client.getNetworks()
|
|
89
134
|
}
|
|
90
|
-
}
|
|
91
135
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
domain: TypedDataDomain,
|
|
96
|
-
types: Record<string, Array<TypedDataField>>,
|
|
97
|
-
value: Record<string, any>
|
|
98
|
-
): Promise<string>
|
|
99
|
-
}
|
|
136
|
+
getChainId(): number {
|
|
137
|
+
return this.client.getChainId()
|
|
138
|
+
}
|
|
100
139
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
140
|
+
setDefaultChainId(chainId: ChainIdLike) {
|
|
141
|
+
return this.client.setDefaultChainId(this.toChainId(chainId))
|
|
142
|
+
}
|
|
104
143
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.provider = provider
|
|
108
|
-
this.defaultChainId = defaultChainId
|
|
144
|
+
isOpened(): boolean {
|
|
145
|
+
return this.client.isOpened()
|
|
109
146
|
}
|
|
110
147
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
_context: commons.context.VersionedContext
|
|
115
|
-
_networks: NetworkConfig[]
|
|
116
|
-
private _providers: { [key: number]: Web3Provider } = {}
|
|
148
|
+
closeWallet(): void {
|
|
149
|
+
return this.client.closeWallet()
|
|
150
|
+
}
|
|
117
151
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
getWalletContext(): Promise<commons.context.VersionedContext> {
|
|
153
|
+
return this.client.getWalletContext()
|
|
154
|
+
}
|
|
121
155
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
this.
|
|
126
|
-
this._index = 0
|
|
127
|
-
return ethers.utils.getAddress(this._address)
|
|
156
|
+
// @deprecated use getSigner() instead
|
|
157
|
+
async getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config> {
|
|
158
|
+
const useChainId = await this.useChainId(chainId)
|
|
159
|
+
return this.client.getOnchainWalletConfig({ chainId: useChainId })
|
|
128
160
|
}
|
|
129
161
|
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
|
|
162
|
+
authorize(options: ConnectOptions) {
|
|
163
|
+
// Just an alias for connect with authorize: true
|
|
164
|
+
return this.client.connect({ ...options, authorize: true })
|
|
133
165
|
}
|
|
134
166
|
|
|
135
|
-
|
|
136
|
-
|
|
167
|
+
async openWallet(
|
|
168
|
+
path?: string,
|
|
169
|
+
intent?: OpenWalletIntent
|
|
170
|
+
) {
|
|
171
|
+
await this.client.openWallet(path, intent)
|
|
172
|
+
return true
|
|
137
173
|
}
|
|
138
174
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
//
|
|
175
|
+
toChainId(chainId: ChainIdLike): number
|
|
176
|
+
toChainId(chainId?: ChainIdLike): number | undefined
|
|
142
177
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
async getProvider(chainId?: number): Promise<Web3Provider | undefined> {
|
|
147
|
-
if (chainId) {
|
|
148
|
-
const currentChainId = await this.getChainId()
|
|
149
|
-
if (currentChainId !== chainId) {
|
|
150
|
-
throw new Error(`signer is attempting to access chain ${chainId}, but is already bound to chain ${currentChainId}`)
|
|
151
|
-
}
|
|
178
|
+
toChainId(chainId?: ChainIdLike) {
|
|
179
|
+
if (chainId === undefined) {
|
|
180
|
+
return undefined
|
|
152
181
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// requests are sent to the window transport. Therefore, for anything non-signing related
|
|
159
|
-
// you can write a higher-order JsonRpcRouter sender to route to the public provider endpoints
|
|
160
|
-
// as we do in the WalletProvider.
|
|
161
|
-
//
|
|
162
|
-
// This method is primarily utilized internally when routing requests to a particular chainId.
|
|
163
|
-
async getSender(chainId?: number): Promise<Web3Provider | undefined> {
|
|
164
|
-
if (!chainId || (chainId && chainId === this.defaultChainId)) {
|
|
165
|
-
return this.provider
|
|
182
|
+
|
|
183
|
+
const resolved = findNetworkConfig(this.networks, chainId as ChainIdLike)
|
|
184
|
+
|
|
185
|
+
if (!resolved) {
|
|
186
|
+
throw new Error(`Unsupported network ${chainId}`)
|
|
166
187
|
}
|
|
167
|
-
|
|
168
|
-
|
|
188
|
+
|
|
189
|
+
return resolved.chainId
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Resolves the chainId to use for the given request. If no chainId is provided,
|
|
194
|
+
* it uses the chainId defined by the client (default chainId). This can be
|
|
195
|
+
* overriden to build a single-network SequenceProvider.
|
|
196
|
+
*/
|
|
197
|
+
protected async useChainId(chainId?: ChainIdLike): Promise<number> {
|
|
198
|
+
return this.toChainId(chainId) || this.client.getChainId()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* This generates a provider that ONLY works for the given chainId.
|
|
203
|
+
* the generated provider can't switch networks, and can't handle requests
|
|
204
|
+
* for other networks.
|
|
205
|
+
*/
|
|
206
|
+
getProvider(): SequenceProvider
|
|
207
|
+
getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
|
|
208
|
+
getProvider(chainId?: ChainIdLike): SequenceProvider | SingleNetworkSequenceProvider
|
|
209
|
+
|
|
210
|
+
getProvider(chainId?: ChainIdLike) {
|
|
211
|
+
// The provider without a chainId is... this one
|
|
212
|
+
if (!chainId) {
|
|
213
|
+
return this
|
|
169
214
|
}
|
|
170
|
-
return this._providers[chainId]
|
|
171
|
-
}
|
|
172
215
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
216
|
+
const useChainId = this.toChainId(chainId)
|
|
217
|
+
|
|
218
|
+
if (!this.singleNetworkProviders[useChainId]) {
|
|
219
|
+
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(
|
|
220
|
+
this.client,
|
|
221
|
+
this.providerFor,
|
|
222
|
+
useChainId
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return this.singleNetworkProviders[useChainId]
|
|
179
227
|
}
|
|
180
228
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
229
|
+
/**
|
|
230
|
+
* This returns a subprovider, this is a regular non-sequence provider that
|
|
231
|
+
* can be used to fulfill read only requests on a given network.
|
|
232
|
+
*/
|
|
233
|
+
async _getSubprovider(chainId?: ChainIdLike): Promise<ethers.providers.JsonRpcProvider> {
|
|
234
|
+
const useChainId = await this.useChainId(chainId)
|
|
235
|
+
|
|
236
|
+
// Whoever implements providerFrom should memoize the generated provider
|
|
237
|
+
// otherwise every instance of SequenceProvider will create a new subprovider
|
|
238
|
+
const provider = this.providerFor(useChainId)
|
|
239
|
+
|
|
240
|
+
if (!provider) {
|
|
241
|
+
throw new Error(`Unsupported network ${useChainId}`)
|
|
184
242
|
}
|
|
185
|
-
|
|
243
|
+
|
|
244
|
+
return provider
|
|
186
245
|
}
|
|
187
246
|
|
|
188
|
-
async
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
247
|
+
async perform(method: string, params: any): Promise<any> {
|
|
248
|
+
// First we check if the method should be handled by the client
|
|
249
|
+
if (method === 'eth_chainId') {
|
|
250
|
+
return this.useChainId()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (method === 'eth_accounts') {
|
|
254
|
+
return [this.client.getAddress()]
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (method === 'wallet_switchEthereumChain') {
|
|
258
|
+
const args = params[0] as { chainId: string } | number | string
|
|
259
|
+
const chainId = normalizeChainId(args)
|
|
260
|
+
return this.setDefaultChainId(chainId)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Usually these methods aren't used by calling the provider
|
|
264
|
+
// but to maximize compatibility we support them too.
|
|
265
|
+
// The correct way of accessing these methods is by using .getSigner()
|
|
266
|
+
if (
|
|
267
|
+
method === 'eth_sendTransaction' ||
|
|
268
|
+
method === 'eth_sign' ||
|
|
269
|
+
method === 'eth_signTypedData' ||
|
|
270
|
+
method === 'eth_signTypedData_v4' ||
|
|
271
|
+
method === 'personal_sign' ||
|
|
272
|
+
// These methods will use EIP-6492
|
|
273
|
+
// but this is handled directly by the wallet
|
|
274
|
+
method === 'sequence_sign' ||
|
|
275
|
+
method === 'sequence_signTypedData_v4'
|
|
276
|
+
) {
|
|
277
|
+
// We pass the chainId to the client, if we don't pass one
|
|
278
|
+
// the client will use its own default chainId
|
|
279
|
+
return this.client.send({ method, params }, this.getChainId())
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Forward call to the corresponding provider
|
|
283
|
+
// we use the provided chainId, or the default one provided by the client
|
|
284
|
+
const provider = await this._getSubprovider()
|
|
285
|
+
const prepared = provider.prepareRequest(method, params) ?? [method, params]
|
|
286
|
+
return provider.send(prepared[0], prepared[1])
|
|
196
287
|
}
|
|
197
288
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (!reqChainId) throw new Error('chainId is required')
|
|
201
|
-
return (await this.provider.send(
|
|
202
|
-
'sequence_getWalletState',
|
|
203
|
-
[reqChainId],
|
|
204
|
-
reqChainId
|
|
205
|
-
))[0].status
|
|
289
|
+
send (method: string, params: any): Promise<any> {
|
|
290
|
+
return this.perform(method, params)
|
|
206
291
|
}
|
|
207
292
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return this._networks
|
|
293
|
+
request (request: { method: string; params?: any[] | undefined }) {
|
|
294
|
+
return this.perform(request.method, request.params)
|
|
211
295
|
}
|
|
212
296
|
|
|
213
|
-
async
|
|
214
|
-
const
|
|
297
|
+
async detectNetwork(): Promise<ethers.providers.Network> {
|
|
298
|
+
const chainId = this.client.getChainId()
|
|
299
|
+
const network = findNetworkConfig(this.networks, chainId)
|
|
215
300
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (!config) {
|
|
219
|
-
throw new Error(`walletConfig returned zero results for authChainId {authChainId}`)
|
|
301
|
+
if (!network) {
|
|
302
|
+
throw new Error(`Unknown network ${chainId}`)
|
|
220
303
|
}
|
|
221
304
|
|
|
222
|
-
return
|
|
305
|
+
return network
|
|
223
306
|
}
|
|
224
307
|
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
308
|
+
// Override most of the methods, so we add support for an optional chainId
|
|
309
|
+
// argument, which is used to select the provider to use.
|
|
310
|
+
//
|
|
311
|
+
// NOTICE: We could use generics to avoid repeating the same code
|
|
312
|
+
// but this would make the code harder to read, and it's not worth it
|
|
313
|
+
// since we only have a few methods to override.
|
|
314
|
+
|
|
315
|
+
async waitForTransaction(
|
|
316
|
+
transactionHash: string,
|
|
317
|
+
confirmations?: number,
|
|
318
|
+
timeout?: number,
|
|
319
|
+
optionals?: OptionalChainIdLike
|
|
320
|
+
) {
|
|
321
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
322
|
+
return provider.waitForTransaction(transactionHash, confirmations, timeout)
|
|
323
|
+
}
|
|
229
324
|
|
|
230
|
-
|
|
231
|
-
const
|
|
325
|
+
async getBlockNumber(optionals?: OptionalChainIdLike) {
|
|
326
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
327
|
+
return provider.getBlockNumber()
|
|
328
|
+
}
|
|
232
329
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return provider!.send(
|
|
237
|
-
sequenceVerified ? 'sequence_sign' : 'personal_sign',
|
|
238
|
-
[ethers.utils.hexlify(data), address]
|
|
239
|
-
)
|
|
330
|
+
async getGasPrice(optionals?: OptionalChainIdLike) {
|
|
331
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
332
|
+
return provider.getGasPrice()
|
|
240
333
|
}
|
|
241
334
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
sequenceVerified: boolean = true
|
|
250
|
-
): Promise<string> {
|
|
251
|
-
// Populate any ENS names (in-place)
|
|
252
|
-
// const populated = await ethers.utils._TypedDataEncoder.resolveNames(domain, types, message, (name: string) => {
|
|
253
|
-
// return this.provider.resolveName(name)
|
|
254
|
-
// })
|
|
255
|
-
|
|
256
|
-
return this.provider.send(
|
|
257
|
-
sequenceVerified ? 'sequence_signTypedData_v4' : 'eth_signTypedData_v4',
|
|
258
|
-
[await this.getAddress(), ethers.utils._TypedDataEncoder.getPayload(domain, types, message)],
|
|
259
|
-
maybeChainId(chainId) || this.defaultChainId
|
|
260
|
-
)
|
|
335
|
+
async getBalance(
|
|
336
|
+
addressOrName: string | Promise<string>,
|
|
337
|
+
blockTag?: ethers.providers.BlockTag | Promise<ethers.providers.BlockTag>,
|
|
338
|
+
optionals?: OptionalChainIdLike
|
|
339
|
+
) {
|
|
340
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
341
|
+
return provider.getBalance(addressOrName, blockTag)
|
|
261
342
|
}
|
|
262
343
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const tx = this.sendUncheckedTransaction(transaction, chainId).then(hash => {
|
|
272
|
-
return ethers.utils
|
|
273
|
-
.poll(
|
|
274
|
-
() => {
|
|
275
|
-
return provider!.getTransaction(hash).then((tx: ethers.providers.TransactionResponse) => {
|
|
276
|
-
if (tx === null) {
|
|
277
|
-
return undefined
|
|
278
|
-
}
|
|
279
|
-
return provider!._wrapTransaction(tx, hash)
|
|
280
|
-
})
|
|
281
|
-
},
|
|
282
|
-
{ onceBlock: this.provider! }
|
|
283
|
-
)
|
|
284
|
-
.catch((error: Error) => {
|
|
285
|
-
;(<any>error).transactionHash = hash
|
|
286
|
-
throw error
|
|
287
|
-
})
|
|
288
|
-
})
|
|
344
|
+
async getTransactionCount(
|
|
345
|
+
addressOrName: string | Promise<string>,
|
|
346
|
+
blockTag?: ethers.providers.BlockTag | Promise<ethers.providers.BlockTag>,
|
|
347
|
+
optionals?: OptionalChainIdLike
|
|
348
|
+
) {
|
|
349
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
350
|
+
return provider.getTransactionCount(addressOrName, blockTag)
|
|
351
|
+
}
|
|
289
352
|
|
|
290
|
-
|
|
291
|
-
|
|
353
|
+
async getCode(
|
|
354
|
+
addressOrName: string | Promise<string>,
|
|
355
|
+
blockTag?: ethers.providers.BlockTag | Promise<ethers.providers.BlockTag>,
|
|
356
|
+
optionals?: OptionalChainIdLike
|
|
357
|
+
) {
|
|
358
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
359
|
+
return provider.getCode(addressOrName, blockTag)
|
|
292
360
|
}
|
|
293
361
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
)
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
362
|
+
async getStorageAt(
|
|
363
|
+
addressOrName: string | Promise<string>,
|
|
364
|
+
position: ethers.BigNumberish | Promise<ethers.BigNumberish>,
|
|
365
|
+
blockTag?: ethers.providers.BlockTag | Promise<ethers.providers.BlockTag>,
|
|
366
|
+
optionals?: OptionalChainIdLike
|
|
367
|
+
) {
|
|
368
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
369
|
+
return provider.getStorageAt(addressOrName, position, blockTag)
|
|
370
|
+
}
|
|
304
371
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
372
|
+
async call(
|
|
373
|
+
transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
|
|
374
|
+
blockTag?: ethers.providers.BlockTag | Promise<ethers.providers.BlockTag>,
|
|
375
|
+
optionals?: OptionalChainIdLike
|
|
376
|
+
) {
|
|
377
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
378
|
+
return provider.call(transaction, blockTag)
|
|
379
|
+
}
|
|
309
380
|
|
|
310
|
-
|
|
311
|
-
|
|
381
|
+
async estimateGas(
|
|
382
|
+
transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
|
|
383
|
+
optionals?: OptionalChainIdLike
|
|
384
|
+
) {
|
|
385
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
386
|
+
return provider.estimateGas(transaction)
|
|
312
387
|
}
|
|
313
388
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
// the wire.. see sendUncheckedTransaction and resolveProperties
|
|
321
|
-
return this.provider.send('eth_signTransaction', [transaction], maybeChainId(chainId) || this.defaultChainId)
|
|
389
|
+
async getBlock(
|
|
390
|
+
blockHashOrBlockTag: ethers.providers.BlockTag | string | Promise<ethers.providers.BlockTag | string>,
|
|
391
|
+
optionals?: OptionalChainIdLike
|
|
392
|
+
) {
|
|
393
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
394
|
+
return provider.getBlock(blockHashOrBlockTag)
|
|
322
395
|
}
|
|
323
396
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
|
|
397
|
+
async getTransaction(
|
|
398
|
+
transactionHash: string | Promise<string>,
|
|
399
|
+
optionals?: OptionalChainIdLike
|
|
400
|
+
) {
|
|
401
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
402
|
+
return provider.getTransaction(transactionHash)
|
|
330
403
|
}
|
|
331
404
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
405
|
+
async getLogs(
|
|
406
|
+
filter: ethers.providers.Filter | Promise<ethers.providers.Filter>,
|
|
407
|
+
optionals?: OptionalChainIdLike
|
|
408
|
+
) {
|
|
409
|
+
const provider = await this._getSubprovider(optionals?.chainId)
|
|
410
|
+
return provider.getLogs(filter)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ENS methods
|
|
414
|
+
|
|
415
|
+
async supportsENS(): Promise<boolean> {
|
|
416
|
+
const networks = await this.getNetworks()
|
|
417
|
+
return networks.some(n => n.chainId === 1)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async getResolver(name: string) {
|
|
421
|
+
if (!await this.supportsENS()) {
|
|
422
|
+
return null
|
|
339
423
|
}
|
|
340
424
|
|
|
341
|
-
|
|
342
|
-
|
|
425
|
+
// Resolver is always on the chainId 1
|
|
426
|
+
const provider = await this._getSubprovider(1)
|
|
427
|
+
return provider.getResolver(name)
|
|
343
428
|
}
|
|
344
429
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
430
|
+
async resolveName(name: string | Promise<string>) {
|
|
431
|
+
if (ethers.utils.isAddress(await name)) {
|
|
432
|
+
return name
|
|
433
|
+
}
|
|
349
434
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return undefined
|
|
435
|
+
if (!await this.supportsENS()) {
|
|
436
|
+
return null
|
|
353
437
|
}
|
|
354
|
-
return provider!._wrapTransaction(tx, tx.hash)
|
|
355
|
-
}
|
|
356
438
|
|
|
357
|
-
|
|
358
|
-
const provider = await this.
|
|
359
|
-
|
|
360
|
-
return !!walletCode && walletCode !== '0x'
|
|
439
|
+
// Resolver is always on the chainId 1
|
|
440
|
+
const provider = await this._getSubprovider(1)
|
|
441
|
+
return provider.resolveName(name)
|
|
361
442
|
}
|
|
362
443
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
444
|
+
async lookupAddress(address: string | Promise<string>) {
|
|
445
|
+
if (!await this.supportsENS()) {
|
|
446
|
+
return null
|
|
447
|
+
}
|
|
366
448
|
|
|
367
|
-
|
|
368
|
-
const provider = await this.
|
|
369
|
-
|
|
370
|
-
const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message
|
|
371
|
-
const address = await this.getAddress()
|
|
372
|
-
|
|
373
|
-
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
|
|
374
|
-
// NOTE: ethers since 5.5 has switched to using personal_sign, we should review, etc.
|
|
375
|
-
return await provider!.send('eth_sign', [address, ethers.utils.hexlify(data)])
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
async _signTypedData(
|
|
379
|
-
domain: TypedDataDomain,
|
|
380
|
-
types: Record<string, Array<TypedDataField>>,
|
|
381
|
-
message: Record<string, any>,
|
|
382
|
-
chainId?: ChainIdLike
|
|
383
|
-
): Promise<string> {
|
|
384
|
-
return this.signTypedData(domain, types, message, chainId)
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
async sendUncheckedTransaction(transaction: Deferrable<ExtendedTransactionRequest>, chainId?: ChainIdLike): Promise<string> {
|
|
388
|
-
transaction = shallowCopy(transaction)
|
|
389
|
-
|
|
390
|
-
const fromAddress = this.getAddress()
|
|
391
|
-
|
|
392
|
-
// NOTE: we do not use provider estimation, and instead rely on our relayer to determine the gasLimit and gasPrice
|
|
393
|
-
//
|
|
394
|
-
// TODO: alternatively/one day, we could write a provider middleware to eth_estimateGas
|
|
395
|
-
// and send it to our relayer url instead for estimation..
|
|
396
|
-
//
|
|
397
|
-
// if (!transaction.gasLimit) {
|
|
398
|
-
// const estimate = shallowCopy(transaction)
|
|
399
|
-
// estimate.from = fromAddress
|
|
400
|
-
// transaction.gasLimit = this.provider.estimateGas(estimate)
|
|
401
|
-
// }
|
|
402
|
-
|
|
403
|
-
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
|
|
404
|
-
|
|
405
|
-
return resolveProperties({
|
|
406
|
-
tx: resolveProperties(transaction),
|
|
407
|
-
sender: await fromAddress
|
|
408
|
-
}).then(({ tx, sender }) => {
|
|
409
|
-
if (tx.from != null) {
|
|
410
|
-
if (ethers.utils.getAddress(tx.from) !== sender) {
|
|
411
|
-
// logger.throwArgumentError("from address mismatch", "transaction", transaction)
|
|
412
|
-
throw new Error(`from address mismatch for transaction ${transaction}`)
|
|
413
|
-
}
|
|
414
|
-
} else {
|
|
415
|
-
tx.from = sender
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const hexTx = hexlifyTransaction(tx)
|
|
419
|
-
|
|
420
|
-
return provider!.send('eth_sendTransaction', [hexTx]).then(
|
|
421
|
-
hash => {
|
|
422
|
-
return hash
|
|
423
|
-
},
|
|
424
|
-
error => {
|
|
425
|
-
// return checkError("sendTransaction", error, hexTx)
|
|
426
|
-
throw error
|
|
427
|
-
}
|
|
428
|
-
)
|
|
429
|
-
})
|
|
449
|
+
// Resolver is always on the chainId 1
|
|
450
|
+
const provider = await this._getSubprovider(1)
|
|
451
|
+
return provider.lookupAddress(address)
|
|
430
452
|
}
|
|
431
453
|
|
|
432
|
-
|
|
433
|
-
|
|
454
|
+
async getAvatar(nameOrAddress: string) {
|
|
455
|
+
if (!await this.supportsENS()) {
|
|
456
|
+
return null
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const provider = await this._getSubprovider(1)
|
|
460
|
+
return provider.getAvatar(nameOrAddress)
|
|
434
461
|
}
|
|
435
462
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
463
|
+
static is = (provider: any): provider is SequenceProvider => {
|
|
464
|
+
return (
|
|
465
|
+
provider &&
|
|
466
|
+
typeof provider === 'object' &&
|
|
467
|
+
provider._isSequenceProvider === true
|
|
468
|
+
)
|
|
439
469
|
}
|
|
440
470
|
}
|
|
441
471
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const allowedTransactionKeys: { [key: string]: boolean } = {
|
|
446
|
-
chainId: true,
|
|
447
|
-
data: true,
|
|
448
|
-
gasLimit: true,
|
|
449
|
-
gasPrice: true,
|
|
450
|
-
nonce: true,
|
|
451
|
-
to: true,
|
|
452
|
-
value: true,
|
|
453
|
-
from: true,
|
|
454
|
-
auxiliary: true,
|
|
455
|
-
expiration: true,
|
|
456
|
-
afterNonce: true,
|
|
457
|
-
delegateCall: true,
|
|
458
|
-
revertOnError: true
|
|
472
|
+
function normalizeChainId(chainId: string | number | bigint | { chainId: string }): number {
|
|
473
|
+
if (typeof chainId === 'object') return normalizeChainId(chainId.chainId)
|
|
474
|
+
return ethers.BigNumber.from(chainId).toNumber()
|
|
459
475
|
}
|
|
460
476
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
/**
|
|
478
|
+
* This is the same provider, but it only allows a single network at a time.
|
|
479
|
+
* the network defined by the constructor is the only one that can be used.
|
|
480
|
+
*
|
|
481
|
+
* Attempting to call any method with a different network will throw an error.
|
|
482
|
+
* Attempting to change the network of this provider will throw an error.
|
|
483
|
+
*
|
|
484
|
+
* NOTICE: These networks won't support ENS unless they are the mainnet.
|
|
485
|
+
*/
|
|
486
|
+
export class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
487
|
+
readonly _isSingleNetworkSequenceProvider = true
|
|
488
|
+
|
|
489
|
+
constructor(
|
|
490
|
+
client: SequenceClient,
|
|
491
|
+
providerFor: (networkId: number) => ethers.providers.JsonRpcProvider,
|
|
492
|
+
public readonly chainId: ChainIdLike
|
|
493
|
+
) {
|
|
494
|
+
super(client, providerFor)
|
|
473
495
|
}
|
|
474
|
-
ethers.utils.checkProperties(transaction, allowed)
|
|
475
496
|
|
|
476
|
-
|
|
497
|
+
private _useChainId(chainId?: ChainIdLike): number {
|
|
498
|
+
const provided = this.toChainId(chainId)
|
|
477
499
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const value = (transaction as any)[key]
|
|
481
|
-
if (value === null || value === undefined) {
|
|
482
|
-
return
|
|
483
|
-
}
|
|
484
|
-
const hexValue = ethers.utils.hexValue(value)
|
|
485
|
-
if (key === 'gasLimit') {
|
|
486
|
-
key = 'gas'
|
|
500
|
+
if (provided && provided !== this.chainId) {
|
|
501
|
+
throw new Error(`This provider only supports the network ${this.chainId}, but ${provided} was requested.`)
|
|
487
502
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
503
|
+
|
|
504
|
+
return provided || super.toChainId(this.chainId)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
protected useChainId(chainId?: ChainIdLike): Promise<number> {
|
|
508
|
+
return Promise.resolve(this._useChainId(chainId))
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
getChainId(): number {
|
|
512
|
+
return super.toChainId(this.chainId)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
async getNetwork(): Promise<NetworkConfig> {
|
|
516
|
+
const networks = await this.client.getNetworks()
|
|
517
|
+
const res = findNetworkConfig(networks, this.chainId)
|
|
518
|
+
|
|
519
|
+
if (!res) {
|
|
520
|
+
throw new Error(`Unsupported network ${this.chainId}`)
|
|
500
521
|
}
|
|
501
|
-
})
|
|
502
522
|
|
|
503
|
-
|
|
504
|
-
if (auxiliary && auxiliary.length > 0) {
|
|
505
|
-
result['auxiliary'] = []
|
|
506
|
-
auxiliary.forEach((a: any) => {
|
|
507
|
-
result['auxiliary'].push(hexlifyTransaction(a))
|
|
508
|
-
})
|
|
523
|
+
return res
|
|
509
524
|
}
|
|
510
525
|
|
|
511
|
-
|
|
512
|
-
|
|
526
|
+
/**
|
|
527
|
+
* Override getProvider and getSigner so they always use `useChainId`
|
|
528
|
+
* this way they can't return providers and signers that can switch networks,
|
|
529
|
+
* or that don't match the chainId of this signer.
|
|
530
|
+
*/
|
|
531
|
+
getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider {
|
|
532
|
+
if (this._useChainId(chainId) !== this.chainId) {
|
|
533
|
+
throw new Error(`Unreachable code`)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return this
|
|
537
|
+
}
|
|
513
538
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
})
|
|
539
|
+
getSigner(chainId?: ChainIdLike): SingleNetworkSequenceSigner {
|
|
540
|
+
return super.getSigner(this._useChainId(chainId))
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
setDefaultChainId(_chainId: ChainIdLike): void {
|
|
544
|
+
throw new Error(`This provider only supports the network ${this.chainId}; use the parent provider to switch networks.`)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
static is(cand: any): cand is SingleNetworkSequenceProvider {
|
|
548
|
+
return (
|
|
549
|
+
cand &&
|
|
550
|
+
typeof cand === 'object' &&
|
|
551
|
+
cand._isSingleNetworkSequenceProvider === true
|
|
552
|
+
)
|
|
530
553
|
}
|
|
531
554
|
}
|