@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/signer.ts
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { ethers } from "ethers"
|
|
2
|
+
|
|
3
|
+
import { SequenceProvider, SingleNetworkSequenceProvider } from "./provider"
|
|
4
|
+
import { SequenceClient } from "./client"
|
|
5
|
+
import { commons } from "@0xsequence/core"
|
|
6
|
+
import { ChainIdLike, NetworkConfig } from "@0xsequence/network"
|
|
7
|
+
import { resolveArrayProperties } from "./utils"
|
|
8
|
+
import { WalletUtils } from "./utils/index"
|
|
9
|
+
import { OptionalChainIdLike, OptionalEIP6492 } from "./types"
|
|
10
|
+
|
|
11
|
+
export interface ISequenceSigner extends ethers.Signer {
|
|
12
|
+
getProvider(): SequenceProvider
|
|
13
|
+
getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
|
|
14
|
+
getProvider(chainId?: ChainIdLike): SequenceProvider | SingleNetworkSequenceProvider
|
|
15
|
+
|
|
16
|
+
getSigner(): SequenceSigner
|
|
17
|
+
getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
|
|
18
|
+
getSigner(chainId?: ChainIdLike): SequenceSigner | SingleNetworkSequenceSigner
|
|
19
|
+
|
|
20
|
+
getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config>
|
|
21
|
+
getNetworks(): Promise<NetworkConfig[]>
|
|
22
|
+
|
|
23
|
+
signMessage(
|
|
24
|
+
message: ethers.BytesLike,
|
|
25
|
+
options?: OptionalChainIdLike & OptionalEIP6492
|
|
26
|
+
): Promise<string>
|
|
27
|
+
|
|
28
|
+
signTypedData(
|
|
29
|
+
domain: ethers.TypedDataDomain,
|
|
30
|
+
types: Record<string, Array<ethers.TypedDataField>>,
|
|
31
|
+
message: Record<string, any>,
|
|
32
|
+
options?: OptionalChainIdLike & OptionalEIP6492
|
|
33
|
+
): Promise<string>
|
|
34
|
+
|
|
35
|
+
// sendTransaction takes an unsigned transaction, or list of unsigned transactions, and then has it signed by
|
|
36
|
+
// the signer, and finally sends it to the relayer for submission to an Ethereum network.
|
|
37
|
+
// It supports any kind of transaction, including regular ethers transactions, and Sequence transactions.
|
|
38
|
+
sendTransaction(
|
|
39
|
+
transaction: (
|
|
40
|
+
ethers.utils.Deferrable<ethers.providers.TransactionRequest>[] |
|
|
41
|
+
ethers.utils.Deferrable<ethers.providers.TransactionRequest>
|
|
42
|
+
),
|
|
43
|
+
options?: OptionalChainIdLike
|
|
44
|
+
): Promise<commons.transaction.TransactionResponse>
|
|
45
|
+
|
|
46
|
+
utils: WalletUtils
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class SequenceSigner implements ISequenceSigner {
|
|
50
|
+
private readonly singleNetworkSigners: { [chainId: number]: SingleNetworkSequenceSigner } = {}
|
|
51
|
+
|
|
52
|
+
readonly _isSigner: boolean = true
|
|
53
|
+
readonly _isSequenceSigner: boolean = true
|
|
54
|
+
|
|
55
|
+
get utils(): WalletUtils {
|
|
56
|
+
return this.provider.utils
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
constructor (
|
|
60
|
+
public client: SequenceClient,
|
|
61
|
+
public provider: SequenceProvider
|
|
62
|
+
) { }
|
|
63
|
+
|
|
64
|
+
async getAddress(): Promise<string> {
|
|
65
|
+
return this.client.getAddress()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// This method shouldn't be used directly
|
|
69
|
+
// it exists to maintain compatibility with ethers.Signer
|
|
70
|
+
connect(provider: ethers.providers.Provider): SequenceSigner {
|
|
71
|
+
if (!SequenceProvider.is(provider)) {
|
|
72
|
+
throw new Error("SequenceSigner can only be connected to a SequenceProvider")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return new SequenceSigner(this.client, provider)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getSigner(): SequenceSigner
|
|
79
|
+
getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
|
|
80
|
+
getSigner(chainId?: ChainIdLike): SingleNetworkSequenceSigner | SequenceSigner
|
|
81
|
+
|
|
82
|
+
getSigner(chainId?: ChainIdLike): SingleNetworkSequenceSigner | SequenceSigner {
|
|
83
|
+
// The signer for the default network is this signer
|
|
84
|
+
if (!chainId) {
|
|
85
|
+
return this
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const useChainId = this.provider.toChainId(chainId)
|
|
89
|
+
|
|
90
|
+
if (!this.singleNetworkSigners[useChainId]) {
|
|
91
|
+
this.singleNetworkSigners[useChainId] = new SingleNetworkSequenceSigner(this.client, this.provider, useChainId)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return this.singleNetworkSigners[useChainId]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resolves the chainId to use for the given request. If no chainId is provided,
|
|
99
|
+
* it uses the chainId defined by the client (default chainId). This can be
|
|
100
|
+
* overriden to build a single-network SequenceProvider.
|
|
101
|
+
*/
|
|
102
|
+
protected useChainId(chainId?: ChainIdLike): number {
|
|
103
|
+
return this.provider.toChainId(chainId) || this.client.getChainId()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async signMessage(
|
|
107
|
+
message: ethers.BytesLike,
|
|
108
|
+
options?: OptionalChainIdLike & OptionalEIP6492
|
|
109
|
+
): Promise<string> {
|
|
110
|
+
const { eip6492 = true } = options || {}
|
|
111
|
+
const chainId = this.useChainId(options?.chainId)
|
|
112
|
+
return this.client.signMessage(message, { eip6492, chainId })
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async signTypedData(
|
|
116
|
+
domain: ethers.TypedDataDomain,
|
|
117
|
+
types: Record<string, Array<ethers.TypedDataField>>,
|
|
118
|
+
message: Record<string, any>,
|
|
119
|
+
options?: OptionalChainIdLike & OptionalEIP6492
|
|
120
|
+
): Promise<string> {
|
|
121
|
+
const { eip6492 = true } = options || {}
|
|
122
|
+
const chainId = this.useChainId(options?.chainId)
|
|
123
|
+
return this.client.signTypedData({ domain, types, message }, { eip6492, chainId })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
getProvider(): SequenceProvider
|
|
127
|
+
getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
|
|
128
|
+
getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider | SequenceProvider
|
|
129
|
+
|
|
130
|
+
getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider | SequenceProvider {
|
|
131
|
+
return this.provider.getProvider(chainId)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async sendTransaction(
|
|
135
|
+
transaction: (
|
|
136
|
+
ethers.utils.Deferrable<ethers.providers.TransactionRequest>[] |
|
|
137
|
+
ethers.utils.Deferrable<ethers.providers.TransactionRequest>
|
|
138
|
+
),
|
|
139
|
+
options?: OptionalChainIdLike
|
|
140
|
+
) {
|
|
141
|
+
const chainId = this.useChainId(options?.chainId)
|
|
142
|
+
const resolved = await resolveArrayProperties(transaction)
|
|
143
|
+
const txHash = await this.client.sendTransaction(resolved, { chainId })
|
|
144
|
+
const provider = this.getProvider(chainId)
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
return await ethers.utils.poll(async () => {
|
|
148
|
+
const tx = await provider.getTransaction(txHash)
|
|
149
|
+
return tx ? provider._wrapTransaction(tx, txHash) : undefined
|
|
150
|
+
}, { onceBlock: provider }) as ethers.providers.TransactionResponse
|
|
151
|
+
} catch (err) {
|
|
152
|
+
err.transactionHash = txHash
|
|
153
|
+
throw err
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async getWalletConfig(chainId?: ChainIdLike | undefined): Promise<commons.config.Config> {
|
|
158
|
+
const useChainId = this.useChainId(chainId)
|
|
159
|
+
return this.client.getOnchainWalletConfig({ chainId: useChainId })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getNetworks(): Promise<NetworkConfig[]> {
|
|
163
|
+
return this.client.getNetworks()
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async getBalance(
|
|
167
|
+
blockTag?: ethers.providers.BlockTag | undefined,
|
|
168
|
+
optionals?: OptionalChainIdLike
|
|
169
|
+
): Promise<ethers.BigNumber> {
|
|
170
|
+
const provider = this.getProvider(optionals?.chainId)
|
|
171
|
+
return provider.getBalance(this.getAddress(), blockTag)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async estimateGas(
|
|
175
|
+
transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
|
|
176
|
+
optionals?: OptionalChainIdLike
|
|
177
|
+
): Promise<ethers.BigNumber> {
|
|
178
|
+
return this.getProvider(optionals?.chainId).estimateGas(transaction)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async call(
|
|
182
|
+
transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
|
|
183
|
+
blockTag?: ethers.providers.BlockTag | undefined,
|
|
184
|
+
optionals?: OptionalChainIdLike
|
|
185
|
+
): Promise<string> {
|
|
186
|
+
return this.getProvider(optionals?.chainId).call(transaction, blockTag)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
getChainId(): Promise<number> {
|
|
190
|
+
return Promise.resolve(this.client.getChainId())
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async getGasPrice(optionals?: OptionalChainIdLike): Promise<ethers.BigNumber> {
|
|
194
|
+
return this.getProvider(optionals?.chainId).getGasPrice()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async getFeeData(optionals?: OptionalChainIdLike): Promise<ethers.providers.FeeData> {
|
|
198
|
+
return this.getProvider(optionals?.chainId).getFeeData()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async resolveName(name: string): Promise<string> {
|
|
202
|
+
const res = await this.provider.resolveName(name)
|
|
203
|
+
|
|
204
|
+
// For some reason ethers.Signer expects this to return `string`
|
|
205
|
+
// but ethers.providers.Provider expects this to return `string | null`.
|
|
206
|
+
// The signer doesn't have any other source of information, so we'll
|
|
207
|
+
// fail if the provider doesn't return a result.
|
|
208
|
+
if (res === null) {
|
|
209
|
+
throw new Error(`ENS name not found: ${name}`)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return res
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
_checkProvider(_operation?: string | undefined): void {
|
|
216
|
+
// We always have a provider, so this is a noop
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
populateTransaction(
|
|
220
|
+
_transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>
|
|
221
|
+
): Promise<ethers.providers.TransactionRequest> {
|
|
222
|
+
throw new Error("SequenceSigner does not support populateTransaction")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
checkTransaction(
|
|
226
|
+
_transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>
|
|
227
|
+
): ethers.utils.Deferrable<ethers.providers.TransactionRequest> {
|
|
228
|
+
throw new Error("SequenceSigner does not support checkTransaction")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
getTransactionCount(_blockTag?: ethers.providers.BlockTag | undefined): Promise<number> {
|
|
232
|
+
// We could try returning the sequence nonce here
|
|
233
|
+
// but we aren't sure how ethers will use this nonce
|
|
234
|
+
throw new Error("SequenceSigner does not support getTransactionCount")
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
signTransaction(_transaction: ethers.utils.Deferrable<commons.transaction.Transactionish>): Promise<string> {
|
|
238
|
+
// We could implement signTransaction/sendTransaction here
|
|
239
|
+
// but first we need a way of serializing these signed transactions
|
|
240
|
+
// and it could lead to more trouble, because the dapp could try to send this transaction
|
|
241
|
+
// using a different provider, which would fail.
|
|
242
|
+
throw new Error("SequenceWallet does not support signTransaction, use sendTransaction instead.")
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
static is(cand: any): cand is SequenceSigner {
|
|
246
|
+
return (
|
|
247
|
+
cand &&
|
|
248
|
+
typeof cand === "object" &&
|
|
249
|
+
cand._isSequenceSigner === true
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* This is the same provider, but it only allows a single network at a time.
|
|
256
|
+
* the network defined by the constructor is the only one that can be used.
|
|
257
|
+
*
|
|
258
|
+
* Attempting to call any method with a different network will throw an error.
|
|
259
|
+
* Attempting to change the network of this provider will throw an error.
|
|
260
|
+
*
|
|
261
|
+
* NOTICE: These networks won't support ENS unless they are the mainnet.
|
|
262
|
+
*/
|
|
263
|
+
export class SingleNetworkSequenceSigner extends SequenceSigner {
|
|
264
|
+
readonly _isSingleNetworkSequenceSigner = true
|
|
265
|
+
|
|
266
|
+
constructor (
|
|
267
|
+
client: SequenceClient,
|
|
268
|
+
provider: SequenceProvider,
|
|
269
|
+
public readonly chainId: ChainIdLike
|
|
270
|
+
) {
|
|
271
|
+
super(client, provider.getProvider(chainId))
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private _useChainId(chainId?: ChainIdLike): number {
|
|
275
|
+
const provided = this.provider.toChainId(chainId)
|
|
276
|
+
|
|
277
|
+
if (provided && provided !== this.chainId) {
|
|
278
|
+
throw new Error(`This signer only supports the network ${this.chainId}, but ${provided} was requested.`)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return provided || this.provider.toChainId(this.chainId)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
protected useChainId(chainId?: ChainIdLike): number {
|
|
285
|
+
return this._useChainId(chainId)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
getChainId(): Promise<number> {
|
|
289
|
+
return Promise.resolve(this.provider.toChainId(this.chainId))
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Override getProvider and getSigner so they always use `useChainId`
|
|
294
|
+
* this way they can't return providers and signers that can switch networks,
|
|
295
|
+
* or that don't match the chainId of this signer.
|
|
296
|
+
*/
|
|
297
|
+
getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider {
|
|
298
|
+
return super.getProvider(this._useChainId(chainId))
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
getSigner(chainId?: ChainIdLike | undefined): SingleNetworkSequenceSigner {
|
|
302
|
+
if (this._useChainId(chainId) !== this.chainId) {
|
|
303
|
+
throw new Error(`Unreachable code`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return this
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static is(cand: any): cand is SingleNetworkSequenceSigner {
|
|
310
|
+
return (
|
|
311
|
+
cand &&
|
|
312
|
+
typeof cand === "object" &&
|
|
313
|
+
cand._isSingleNetworkSequenceSigner === true
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -19,7 +19,7 @@ import { logger, sanitizeAlphanumeric, sanitizeHost, sanitizeNumberString } from
|
|
|
19
19
|
import { AuthorizationOptions } from '@0xsequence/auth'
|
|
20
20
|
|
|
21
21
|
import { PROVIDER_OPEN_TIMEOUT } from './base-provider-transport'
|
|
22
|
-
import { isBrowserExtension,
|
|
22
|
+
import { isBrowserExtension, useBestStore } from '../utils'
|
|
23
23
|
import { commons } from '@0xsequence/core'
|
|
24
24
|
|
|
25
25
|
const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession'
|
|
@@ -375,11 +375,6 @@ export abstract class BaseWalletTransport implements WalletTransport {
|
|
|
375
375
|
// Set connect options on the walletRequestHandler as our primary
|
|
376
376
|
// wallet controller, and fall back to networkId if necessary
|
|
377
377
|
this.walletRequestHandler.setConnectOptions(connectOptions)
|
|
378
|
-
if (connectOptions.networkId) {
|
|
379
|
-
networkId = connectOptions.networkId
|
|
380
|
-
} else if (networkId) {
|
|
381
|
-
connectOptions.networkId = networkId
|
|
382
|
-
}
|
|
383
378
|
} else {
|
|
384
379
|
this.walletRequestHandler.setConnectOptions(undefined)
|
|
385
380
|
}
|
|
@@ -452,11 +447,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
|
|
|
452
447
|
}
|
|
453
448
|
|
|
454
449
|
private saveTransportSession = (session: TransportSession) => {
|
|
455
|
-
|
|
450
|
+
useBestStore().setItem(TRANSPORT_SESSION_LS_KEY, JSON.stringify(session))
|
|
456
451
|
}
|
|
457
452
|
|
|
458
453
|
protected getCachedTransportSession = async (): Promise<TransportSession | null> => {
|
|
459
|
-
const session =
|
|
454
|
+
const session = useBestStore().getItem(TRANSPORT_SESSION_LS_KEY)
|
|
460
455
|
|
|
461
456
|
try {
|
|
462
457
|
return session ? (JSON.parse(session) as TransportSession) : null
|
|
@@ -1,12 +1,62 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ProviderMessage,
|
|
2
|
+
ProviderMessage, ProviderTransport,
|
|
3
3
|
ProviderEventTypes, ProviderMessageRequest, ProviderMessageResponse, WalletSession, OpenWalletIntent, ConnectDetails
|
|
4
4
|
} from '../../types'
|
|
5
5
|
|
|
6
6
|
import { JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network'
|
|
7
|
+
import { ProxyMessageChannelPort, ProxyMessageProvider } from '../proxy-transport'
|
|
8
|
+
import { Runtime } from 'webextension-polyfill'
|
|
9
|
+
import { UnrealMessageProvider } from '../unreal-transport'
|
|
10
|
+
import { ExtensionMessageProvider } from '../extension-transport'
|
|
11
|
+
import { WindowMessageProvider } from '../window-transport'
|
|
7
12
|
|
|
8
|
-
export
|
|
13
|
+
export type MuxTransportTemplate = {
|
|
14
|
+
walletAppURL?: string
|
|
15
|
+
|
|
16
|
+
// WindowMessage transport (optional)
|
|
17
|
+
windowTransport?: {
|
|
18
|
+
enabled: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ProxyMessage transport (optional)
|
|
22
|
+
proxyTransport?: {
|
|
23
|
+
enabled: boolean
|
|
24
|
+
appPort?: ProxyMessageChannelPort
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Extension transport (optional)
|
|
28
|
+
extensionTransport?: {
|
|
29
|
+
enabled: boolean
|
|
30
|
+
runtime: Runtime.Static
|
|
31
|
+
}
|
|
9
32
|
|
|
33
|
+
// Unreal Engine transport (optional)
|
|
34
|
+
unrealTransport?: {
|
|
35
|
+
enabled: boolean
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isMuxTransportTemplate(obj: any): obj is MuxTransportTemplate {
|
|
40
|
+
return (
|
|
41
|
+
obj &&
|
|
42
|
+
typeof obj === 'object' &&
|
|
43
|
+
(
|
|
44
|
+
(obj.windowTransport && typeof obj.windowTransport === 'object') ||
|
|
45
|
+
(obj.proxyTransport && typeof obj.proxyTransport === 'object') ||
|
|
46
|
+
(obj.extensionTransport && typeof obj.extensionTransport === 'object') ||
|
|
47
|
+
(obj.unrealTransport && typeof obj.unrealTransport === 'object')
|
|
48
|
+
) &&
|
|
49
|
+
(
|
|
50
|
+
// One of the transports must be enabled
|
|
51
|
+
(obj.windowTransport && obj.windowTransport.enabled) ||
|
|
52
|
+
(obj.proxyTransport && obj.proxyTransport.enabled) ||
|
|
53
|
+
(obj.extensionTransport && obj.extensionTransport.enabled) ||
|
|
54
|
+
(obj.unrealTransport && obj.unrealTransport.enabled)
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class MuxMessageProvider implements ProviderTransport {
|
|
10
60
|
private messageProviders: ProviderTransport[]
|
|
11
61
|
private provider: ProviderTransport | undefined
|
|
12
62
|
|
|
@@ -15,6 +65,40 @@ export class MuxMessageProvider implements ProviderTransport {
|
|
|
15
65
|
this.provider = undefined
|
|
16
66
|
}
|
|
17
67
|
|
|
68
|
+
static new(template: MuxTransportTemplate): MuxMessageProvider {
|
|
69
|
+
const muxMessageProvider = new MuxMessageProvider()
|
|
70
|
+
|
|
71
|
+
if (template.windowTransport?.enabled && typeof window === 'object' && template.walletAppURL) {
|
|
72
|
+
const windowMessageProvider = new WindowMessageProvider(template.walletAppURL)
|
|
73
|
+
muxMessageProvider.add(windowMessageProvider)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (template.proxyTransport?.enabled) {
|
|
77
|
+
const proxyMessageProvider = new ProxyMessageProvider(template.proxyTransport.appPort!)
|
|
78
|
+
muxMessageProvider.add(proxyMessageProvider)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (template.extensionTransport?.enabled) {
|
|
82
|
+
const extensionMessageProvider = new ExtensionMessageProvider(template.extensionTransport.runtime)
|
|
83
|
+
muxMessageProvider.add(extensionMessageProvider)
|
|
84
|
+
|
|
85
|
+
// NOTE/REVIEW: see note in mux-message-provider
|
|
86
|
+
//
|
|
87
|
+
// We don't add the extensionMessageProvider here because we don't send requests to it anyways, we seem to
|
|
88
|
+
// send all requests to the WindowMessageProvider anyways. By allowing it, if browser restarts, it will break
|
|
89
|
+
// the entire extension because messageProvider.provider will be undefined. So this is a hack to fix it.
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (template.unrealTransport?.enabled && template.windowTransport && template.walletAppURL) {
|
|
93
|
+
const unrealMessageProvider = new UnrealMessageProvider(template.walletAppURL)
|
|
94
|
+
muxMessageProvider.add(unrealMessageProvider)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
muxMessageProvider.register()
|
|
98
|
+
|
|
99
|
+
return muxMessageProvider
|
|
100
|
+
}
|
|
101
|
+
|
|
18
102
|
add(...messageProviders: ProviderTransport[]) {
|
|
19
103
|
this.messageProviders.push(...messageProviders)
|
|
20
104
|
}
|
|
@@ -13,7 +13,7 @@ export class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
13
13
|
constructor(port: ProxyMessageChannelPort) {
|
|
14
14
|
super()
|
|
15
15
|
this.state = OpenState.CLOSED
|
|
16
|
-
this.port = port
|
|
16
|
+
this.port = port
|
|
17
17
|
if (!port) {
|
|
18
18
|
throw new Error('port argument cannot be empty')
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
ProviderEventTypes,
|
|
23
23
|
TypedEventEmitter
|
|
24
24
|
} from '../types'
|
|
25
|
-
import {
|
|
25
|
+
import { prefixEIP191Message } from '../utils'
|
|
26
26
|
|
|
27
27
|
type ExternalProvider = providers.ExternalProvider
|
|
28
28
|
|
|
@@ -64,19 +64,6 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
64
64
|
return this.prompter?.getDefaultChainId() ?? this.networks[0].chainId
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
private findNetworkID(network: string | number) {
|
|
68
|
-
const lnet = typeof network === 'string' ? network.toLowerCase() : network
|
|
69
|
-
const networkId = this.networks.find(n => {
|
|
70
|
-
return n.name.toLowerCase() === lnet || n.chainId.toString() === lnet || n.chainId === lnet
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
if (!networkId) {
|
|
74
|
-
throw new Error(`Network ${network} not found`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return networkId.chainId
|
|
78
|
-
}
|
|
79
|
-
|
|
80
67
|
async signIn(account: Account | null, options: WalletSignInOptions = {}) {
|
|
81
68
|
this.setAccount(account)
|
|
82
69
|
|
|
@@ -150,25 +137,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
150
137
|
}
|
|
151
138
|
}
|
|
152
139
|
|
|
153
|
-
|
|
154
|
-
switch (typeof options?.networkId) {
|
|
155
|
-
case 'string':
|
|
156
|
-
// First see if it matches the name of a network
|
|
157
|
-
try {
|
|
158
|
-
chainId = this.findNetworkID(options.networkId)
|
|
159
|
-
} catch (err) {
|
|
160
|
-
// If not, try to parse it as a big number
|
|
161
|
-
chainId = getChainId(options.networkId)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
break
|
|
165
|
-
case 'number':
|
|
166
|
-
chainId = options.networkId
|
|
167
|
-
break
|
|
168
|
-
default:
|
|
169
|
-
chainId = this.prompter?.getDefaultChainId() ?? 1
|
|
170
|
-
break
|
|
171
|
-
}
|
|
140
|
+
const chainId: number | string = this.prompter?.getDefaultChainId() ?? 1
|
|
172
141
|
|
|
173
142
|
const connectDetails: ConnectDetails = {
|
|
174
143
|
connected: true,
|
|
@@ -740,6 +709,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
740
709
|
}
|
|
741
710
|
|
|
742
711
|
notifyConnect(connectDetails: ConnectDetails, origin?: string) {
|
|
712
|
+
console.log('emit connect', connectDetails)
|
|
743
713
|
this.events.emit('connect', connectDetails)
|
|
744
714
|
if (connectDetails.session?.accountAddress) {
|
|
745
715
|
this.events.emit('accountsChanged', [connectDetails.session?.accountAddress], origin)
|
|
@@ -88,11 +88,13 @@ export class WindowMessageProvider extends BaseProviderTransport {
|
|
|
88
88
|
// when connecting to the wallet, however, this will be verified and enforced
|
|
89
89
|
// on the wallet-side, so if a dapp provides the wrong origin, it will be dropped.
|
|
90
90
|
if (intent.type === 'connect') {
|
|
91
|
-
if (!intent.options) intent.options = {
|
|
91
|
+
if (!intent.options) intent.options = {
|
|
92
|
+
app: window.location.origin
|
|
93
|
+
}
|
|
92
94
|
|
|
93
95
|
// skip setting origin host if we're in an browser extension execution context
|
|
94
96
|
// allow origin that is passed in
|
|
95
|
-
if (!isBrowserExtension() && !isUnityPlugin()) {
|
|
97
|
+
if (!isBrowserExtension() && !isUnityPlugin() && intent.options) {
|
|
96
98
|
intent.options.origin = window.location.origin
|
|
97
99
|
}
|
|
98
100
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ETHAuthProof as AuthETHAuthProof } from '@0xsequence/auth'
|
|
2
2
|
import { commons } from '@0xsequence/core'
|
|
3
|
-
import { JsonRpcHandler, JsonRpcRequest, JsonRpcResponse, NetworkConfig, ProviderRpcError as NetworkProviderRpcError } from '@0xsequence/network'
|
|
3
|
+
import { ChainIdLike, JsonRpcHandler, JsonRpcRequest, JsonRpcResponse, NetworkConfig, ProviderRpcError as NetworkProviderRpcError } from '@0xsequence/network'
|
|
4
4
|
import { TypedData } from '@0xsequence/utils'
|
|
5
5
|
|
|
6
6
|
export interface ProviderTransport extends JsonRpcHandler, ProviderMessageTransport, ProviderMessageRequestHandler {
|
|
@@ -21,6 +21,20 @@ export interface ProviderTransport extends JsonRpcHandler, ProviderMessageTransp
|
|
|
21
21
|
waitUntilConnected(): Promise<ConnectDetails>
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export function isProviderTransport(transport: any): transport is ProviderTransport {
|
|
25
|
+
return (
|
|
26
|
+
transport &&
|
|
27
|
+
typeof transport === 'object' &&
|
|
28
|
+
typeof transport.register === 'function' &&
|
|
29
|
+
typeof transport.unregister === 'function' &&
|
|
30
|
+
typeof transport.openWallet === 'function' &&
|
|
31
|
+
typeof transport.closeWallet === 'function' &&
|
|
32
|
+
typeof transport.isOpened === 'function' &&
|
|
33
|
+
typeof transport.isConnected === 'function' &&
|
|
34
|
+
typeof transport.on === 'function'
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
24
38
|
export interface WalletTransport extends JsonRpcHandler, ProviderMessageTransport, ProviderMessageRequestHandler {
|
|
25
39
|
register(): void
|
|
26
40
|
unregister(): void
|
|
@@ -134,12 +148,8 @@ export enum InitState {
|
|
|
134
148
|
}
|
|
135
149
|
|
|
136
150
|
export interface ConnectOptions {
|
|
137
|
-
/** Specifies the default network a dapp would like to connect to. This field
|
|
138
|
-
* is optional as it can be provided a number of different ways. */
|
|
139
|
-
networkId?: string | number
|
|
140
|
-
|
|
141
151
|
/** app name of the dapp which will be announced to user on connect screen */
|
|
142
|
-
app
|
|
152
|
+
app: string
|
|
143
153
|
|
|
144
154
|
/** custom protocol for auth redirect (unity/unreal) */
|
|
145
155
|
appProtocol?: string
|
|
@@ -171,6 +181,13 @@ export interface ConnectOptions {
|
|
|
171
181
|
settings?: Settings
|
|
172
182
|
}
|
|
173
183
|
|
|
184
|
+
export interface NetworkedConnectOptions extends ConnectOptions {
|
|
185
|
+
/** chainId is the chainId to connect to. If not specified, the default chainId
|
|
186
|
+
* will be used. This does not define a default chain id, it is only used for the connect
|
|
187
|
+
* authorization signature. */
|
|
188
|
+
networkId?: string | number;
|
|
189
|
+
}
|
|
190
|
+
|
|
174
191
|
/** Options to further customize the wallet experience. */
|
|
175
192
|
export interface Settings {
|
|
176
193
|
/** Specify a wallet theme. `light` and `dark` are the main themes, to use other available
|
|
@@ -256,7 +273,7 @@ export interface ConnectDetails {
|
|
|
256
273
|
export type PromptConnectDetails = Pick<ConnectDetails, 'chainId' | 'error' | 'connected' | 'proof' | 'email'>
|
|
257
274
|
|
|
258
275
|
export type OpenWalletIntent =
|
|
259
|
-
| { type: 'connect'; options?:
|
|
276
|
+
| { type: 'connect'; options?: NetworkedConnectOptions }
|
|
260
277
|
| { type: 'openWithOptions'; options?: ConnectOptions }
|
|
261
278
|
| { type: 'jsonRpcRequest'; method: string }
|
|
262
279
|
|
|
@@ -280,9 +297,6 @@ export interface WalletSession {
|
|
|
280
297
|
// Networks in use for the session. The default/dapp network will show
|
|
281
298
|
// up as the first one in the list as the "main chain"
|
|
282
299
|
networks?: NetworkConfig[]
|
|
283
|
-
|
|
284
|
-
// Caching provider responses for things such as account and chainId
|
|
285
|
-
providerCache?: { [key: string]: any }
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
export class ProviderError extends Error {
|
|
@@ -314,3 +328,20 @@ export interface TypedEventEmitter<Events> {
|
|
|
314
328
|
}
|
|
315
329
|
|
|
316
330
|
type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] ? [] : [T]
|
|
331
|
+
|
|
332
|
+
export type OptionalChainIdLike = {
|
|
333
|
+
chainId?: ChainIdLike
|
|
334
|
+
} | undefined
|
|
335
|
+
|
|
336
|
+
export type OptionalChainId = {
|
|
337
|
+
chainId?: number
|
|
338
|
+
} | undefined
|
|
339
|
+
|
|
340
|
+
export type OptionalEIP6492 = {
|
|
341
|
+
eip6492?: boolean
|
|
342
|
+
} | undefined
|
|
343
|
+
|
|
344
|
+
// This is required by viem, it expects a provider to have an EIP-1193 compliant `request` attribute.
|
|
345
|
+
export interface EIP1193Provider {
|
|
346
|
+
request: (request: { method: string, params?: Array<any> }) => Promise<any>
|
|
347
|
+
}
|