@0xsequence/provider 0.0.0-2021823181734
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/CHANGELOG.md +909 -0
- package/README.md +4 -0
- package/dist/0xsequence-provider.cjs.d.ts +1 -0
- package/dist/0xsequence-provider.cjs.dev.js +3540 -0
- package/dist/0xsequence-provider.cjs.js +7 -0
- package/dist/0xsequence-provider.cjs.prod.js +3540 -0
- package/dist/0xsequence-provider.esm.js +3508 -0
- package/dist/declarations/src/commands/index.d.ts +20 -0
- package/dist/declarations/src/index.d.ts +5 -0
- package/dist/declarations/src/provider.d.ts +59 -0
- package/dist/declarations/src/transports/base-provider-transport.d.ts +40 -0
- package/dist/declarations/src/transports/base-wallet-transport.d.ts +38 -0
- package/dist/declarations/src/transports/extension-transport/base-injected-transport.d.ts +18 -0
- package/dist/declarations/src/transports/extension-transport/extension-message-handler.d.ts +12 -0
- package/dist/declarations/src/transports/extension-transport/extension-message-provider.d.ts +11 -0
- package/dist/declarations/src/transports/extension-transport/index.d.ts +3 -0
- package/dist/declarations/src/transports/index.d.ts +7 -0
- package/dist/declarations/src/transports/mux-transport/index.d.ts +1 -0
- package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +22 -0
- package/dist/declarations/src/transports/proxy-transport/index.d.ts +3 -0
- package/dist/declarations/src/transports/proxy-transport/proxy-message-channel.d.ts +15 -0
- package/dist/declarations/src/transports/proxy-transport/proxy-message-handler.d.ts +12 -0
- package/dist/declarations/src/transports/proxy-transport/proxy-message-provider.d.ts +12 -0
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +51 -0
- package/dist/declarations/src/transports/window-transport/index.d.ts +2 -0
- package/dist/declarations/src/transports/window-transport/window-message-handler.d.ts +15 -0
- package/dist/declarations/src/transports/window-transport/window-message-provider.d.ts +13 -0
- package/dist/declarations/src/types.d.ts +170 -0
- package/dist/declarations/src/utils.d.ts +14 -0
- package/dist/declarations/src/wallet.d.ts +99 -0
- package/package.json +37 -0
- package/src/commands/index.ts +146 -0
- package/src/index.ts +5 -0
- package/src/provider.ts +494 -0
- package/src/transports/base-provider-transport.ts +411 -0
- package/src/transports/base-wallet-transport.ts +441 -0
- package/src/transports/extension-transport/base-injected-transport.ts +100 -0
- package/src/transports/extension-transport/extension-message-handler.ts +25 -0
- package/src/transports/extension-transport/extension-message-provider.ts +41 -0
- package/src/transports/extension-transport/index.ts +3 -0
- package/src/transports/index.ts +7 -0
- package/src/transports/mux-transport/index.ts +1 -0
- package/src/transports/mux-transport/mux-message-provider.ts +160 -0
- package/src/transports/proxy-transport/index.ts +3 -0
- package/src/transports/proxy-transport/proxy-message-channel.ts +58 -0
- package/src/transports/proxy-transport/proxy-message-handler.ts +46 -0
- package/src/transports/proxy-transport/proxy-message-provider.ts +81 -0
- package/src/transports/wallet-request-handler.ts +702 -0
- package/src/transports/window-transport/index.ts +2 -0
- package/src/transports/window-transport/window-message-handler.ts +166 -0
- package/src/transports/window-transport/window-message-provider.ts +183 -0
- package/src/types.ts +252 -0
- package/src/utils.ts +76 -0
- package/src/wallet.ts +692 -0
package/src/provider.ts
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
import { ethers } from 'ethers'
|
|
2
|
+
import { BytesLike } from '@ethersproject/bytes'
|
|
3
|
+
import { Web3Provider as EthersWeb3Provider, ExternalProvider, JsonRpcProvider, Networkish } from '@ethersproject/providers'
|
|
4
|
+
import { TypedDataDomain, TypedDataField, TypedDataSigner } from '@ethersproject/abstract-signer'
|
|
5
|
+
import {
|
|
6
|
+
NetworkConfig,
|
|
7
|
+
Networks,
|
|
8
|
+
WalletContext,
|
|
9
|
+
ChainIdLike,
|
|
10
|
+
JsonRpcHandler,
|
|
11
|
+
JsonRpcHandlerFunc,
|
|
12
|
+
JsonRpcFetchFunc,
|
|
13
|
+
JsonRpcRequest,
|
|
14
|
+
JsonRpcResponseCallback,
|
|
15
|
+
JsonRpcResponse,
|
|
16
|
+
maybeChainId,
|
|
17
|
+
JsonRpcVersion,
|
|
18
|
+
JsonRpcSender,
|
|
19
|
+
isJsonRpcProvider
|
|
20
|
+
} from '@0xsequence/network'
|
|
21
|
+
import { resolveArrayProperties, Signer } from '@0xsequence/wallet'
|
|
22
|
+
import { WalletConfig, WalletState } from '@0xsequence/config'
|
|
23
|
+
import { Relayer } from '@0xsequence/relayer'
|
|
24
|
+
import { Deferrable, shallowCopy, resolveProperties, Forbid } from '@0xsequence/utils'
|
|
25
|
+
import {
|
|
26
|
+
Transaction,
|
|
27
|
+
TransactionRequest,
|
|
28
|
+
TransactionResponse,
|
|
29
|
+
Transactionish,
|
|
30
|
+
SignedTransactions
|
|
31
|
+
} from '@0xsequence/transactions'
|
|
32
|
+
import { WalletRequestHandler } from './transports/wallet-request-handler'
|
|
33
|
+
|
|
34
|
+
export class Web3Provider extends EthersWeb3Provider implements JsonRpcHandler {
|
|
35
|
+
static isSequenceProvider(cand: any): cand is Web3Provider {
|
|
36
|
+
return isSequenceProvider(cand)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
readonly _sender: JsonRpcSender
|
|
40
|
+
|
|
41
|
+
readonly _isSequenceProvider: boolean
|
|
42
|
+
|
|
43
|
+
// defaultChainId is the default chainId to use with requests, but may be
|
|
44
|
+
// overridden by passing chainId argument to a specific request
|
|
45
|
+
readonly _defaultChainId?: number
|
|
46
|
+
|
|
47
|
+
constructor(provider: JsonRpcProvider | JsonRpcHandler | JsonRpcFetchFunc, defaultChainId?: ChainIdLike) {
|
|
48
|
+
const sender = new JsonRpcSender(provider, maybeChainId(defaultChainId))
|
|
49
|
+
provider = sender
|
|
50
|
+
|
|
51
|
+
super(provider, 'any')
|
|
52
|
+
|
|
53
|
+
this._sender = sender
|
|
54
|
+
this._isSequenceProvider = true
|
|
55
|
+
this._defaultChainId = maybeChainId(defaultChainId)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
sendAsync(
|
|
59
|
+
request: JsonRpcRequest,
|
|
60
|
+
callback: JsonRpcResponseCallback | ((error: any, response: any) => void),
|
|
61
|
+
chainId?: number
|
|
62
|
+
) {
|
|
63
|
+
this._sender.sendAsync(request, callback, chainId)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
send(method: string, params: Array<any>, chainId?: number): Promise<any> {
|
|
67
|
+
return this._sender.send(method, params, chainId)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getSigner(): Web3Signer {
|
|
71
|
+
return new Web3Signer(this, this._defaultChainId)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async getChainId(): Promise<number> {
|
|
75
|
+
const result = await this.send('eth_chainId', [])
|
|
76
|
+
const chainId = ethers.BigNumber.from(result).toNumber()
|
|
77
|
+
|
|
78
|
+
if (this._defaultChainId && this._defaultChainId !== chainId) {
|
|
79
|
+
throw new Error(`provider chainId (${chainId}) does not match provider-bound chainId ${this._defaultChainId}`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return chainId
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isSequenceProvider(provider: any): provider is Web3Provider {
|
|
87
|
+
const cand = provider as Web3Provider
|
|
88
|
+
return cand && cand.send !== undefined && cand._isSequenceProvider === true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export class LocalWeb3Provider extends Web3Provider {
|
|
92
|
+
constructor(signer: Signer, networks?: Networks) {
|
|
93
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || [])
|
|
94
|
+
super(walletRequestHandler)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export class Web3Signer extends Signer implements TypedDataSigner {
|
|
99
|
+
readonly provider: Web3Provider
|
|
100
|
+
readonly defaultChainId?: number
|
|
101
|
+
|
|
102
|
+
constructor(provider: Web3Provider, defaultChainId?: number) {
|
|
103
|
+
super()
|
|
104
|
+
this.provider = provider
|
|
105
|
+
this.defaultChainId = defaultChainId
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// memoized
|
|
109
|
+
_address: string
|
|
110
|
+
_index: number
|
|
111
|
+
_context: WalletContext
|
|
112
|
+
_networks: NetworkConfig[]
|
|
113
|
+
private _providers: { [key: number]: Web3Provider } = {}
|
|
114
|
+
|
|
115
|
+
//
|
|
116
|
+
// ethers AbstractSigner methods
|
|
117
|
+
//
|
|
118
|
+
|
|
119
|
+
async getAddress(): Promise<string> {
|
|
120
|
+
if (this._address) return this._address
|
|
121
|
+
const accounts = await this.provider.send('eth_accounts', [])
|
|
122
|
+
this._address = accounts[0]
|
|
123
|
+
this._index = 0
|
|
124
|
+
return ethers.utils.getAddress(this._address)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
signTransaction(transaction: Deferrable<TransactionRequest>): Promise<string> {
|
|
128
|
+
// TODO .. since ethers isn't using this method, perhaps we will?
|
|
129
|
+
throw new Error('signTransaction is unsupported, use signTransactions instead')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
connect(provider: ethers.providers.Provider): ethers.providers.JsonRpcSigner {
|
|
133
|
+
throw new Error('unsupported: cannot alter JSON-RPC Signer connection')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
//
|
|
137
|
+
// Sequence Signer methods
|
|
138
|
+
//
|
|
139
|
+
|
|
140
|
+
// getProvider returns a Web3Provider instance for the current chain. Note that this method
|
|
141
|
+
// and signer is bound to a particular chain to prevent misuse. If you'd like a provider
|
|
142
|
+
// for a specific chain, try getSender(chainId), or wallet.getProvider(chainId).
|
|
143
|
+
async getProvider(chainId?: number): Promise<Web3Provider | undefined> {
|
|
144
|
+
if (chainId) {
|
|
145
|
+
const currentChainId = await this.getChainId()
|
|
146
|
+
if (currentChainId !== chainId) {
|
|
147
|
+
throw new Error(`signer is attempting to access chain ${chainId}, but is already bound to chain ${currentChainId}`)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return this.provider
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// getSender returns a Web3Provider instance via the signer transport. Note: for our case
|
|
154
|
+
// the of sequence wallet, this will bring up the wallet window whenever using it, as the json-rpc
|
|
155
|
+
// requests are sent to the window transport. Therefore, for anything non-signing related
|
|
156
|
+
// you can write a higher-order JsonRpcRouter sender to route to the public provider endpoints
|
|
157
|
+
// as we do in the WalletProvider.
|
|
158
|
+
//
|
|
159
|
+
// This method is primarily utilized internally when routing requests to a particular chainId.
|
|
160
|
+
async getSender(chainId?: number): Promise<Web3Provider | undefined> {
|
|
161
|
+
if (!chainId || (chainId && chainId === this.defaultChainId)) {
|
|
162
|
+
return this.provider
|
|
163
|
+
}
|
|
164
|
+
if (!this._providers[chainId]) {
|
|
165
|
+
this._providers[chainId] = new Web3Provider(new JsonRpcSender(this.provider, chainId), chainId)
|
|
166
|
+
}
|
|
167
|
+
return this._providers[chainId]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getRelayer(chainId?: number): Promise<Relayer | undefined> {
|
|
171
|
+
// TODO: JsonRpcRelayer ......? or, Web3Relayer.. or SequenceRelayer?
|
|
172
|
+
// sequence_estimateGasLimits
|
|
173
|
+
// sequence_gasRefundOptions
|
|
174
|
+
// sequence_getNonce
|
|
175
|
+
// sequence_relay
|
|
176
|
+
throw new Error('TODO')
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async getWalletContext(): Promise<WalletContext> {
|
|
180
|
+
if (!this._context) {
|
|
181
|
+
this._context = await this.provider.send('sequence_getWalletContext', [])
|
|
182
|
+
}
|
|
183
|
+
return this._context
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async getWalletConfig(chainId?: ChainIdLike): Promise<WalletConfig[]> {
|
|
187
|
+
return await this.provider.send(
|
|
188
|
+
'sequence_getWalletConfig',
|
|
189
|
+
[maybeChainId(chainId)],
|
|
190
|
+
maybeChainId(chainId) || this.defaultChainId
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async getWalletState(chainId?: ChainIdLike): Promise<WalletState[]> {
|
|
195
|
+
return await this.provider.send(
|
|
196
|
+
'sequence_getWalletState',
|
|
197
|
+
[maybeChainId(chainId)],
|
|
198
|
+
maybeChainId(chainId) || this.defaultChainId
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async getNetworks(): Promise<NetworkConfig[]> {
|
|
203
|
+
if (!this._networks) {
|
|
204
|
+
this._networks = await this.provider.send('sequence_getNetworks', [])
|
|
205
|
+
}
|
|
206
|
+
return this._networks
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async getSigners(): Promise<string[]> {
|
|
210
|
+
const networks = await this.getNetworks()
|
|
211
|
+
|
|
212
|
+
const authChainId = networks.find(n => n.isAuthChain)
|
|
213
|
+
if (!authChainId) {
|
|
214
|
+
throw new Error('authChainId could not be determined from network list')
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const walletConfig = await this.getWalletConfig(authChainId)
|
|
218
|
+
if (!walletConfig || walletConfig.length === 0) {
|
|
219
|
+
throw new Error(`walletConfig returned zero results for authChainId {authChainId}`)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return walletConfig[0].signers.map(s => s.address)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// signMessage matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
226
|
+
// multi-chain support.
|
|
227
|
+
async signMessage(message: BytesLike, chainId?: ChainIdLike, allSigners?: boolean): Promise<string> {
|
|
228
|
+
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
|
|
229
|
+
|
|
230
|
+
const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message
|
|
231
|
+
const address = await this.getAddress()
|
|
232
|
+
|
|
233
|
+
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
|
|
234
|
+
return await provider!.send('eth_sign', [address, ethers.utils.hexlify(data)])
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// signTypedData matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
238
|
+
// multi-chain support.
|
|
239
|
+
async signTypedData(
|
|
240
|
+
domain: TypedDataDomain,
|
|
241
|
+
types: Record<string, Array<TypedDataField>>,
|
|
242
|
+
message: Record<string, any>,
|
|
243
|
+
chainId?: ChainIdLike,
|
|
244
|
+
allSigners?: boolean
|
|
245
|
+
): Promise<string> {
|
|
246
|
+
// Populate any ENS names (in-place)
|
|
247
|
+
// const populated = await ethers.utils._TypedDataEncoder.resolveNames(domain, types, message, (name: string) => {
|
|
248
|
+
// return this.provider.resolveName(name)
|
|
249
|
+
// })
|
|
250
|
+
|
|
251
|
+
return await this.provider.send(
|
|
252
|
+
'eth_signTypedData_v4',
|
|
253
|
+
[await this.getAddress(), ethers.utils._TypedDataEncoder.getPayload(domain, types, message)],
|
|
254
|
+
maybeChainId(chainId) || this.defaultChainId
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// sendTransaction matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
259
|
+
// multi-chain support.
|
|
260
|
+
async sendTransaction(
|
|
261
|
+
transaction: Deferrable<TransactionRequest>,
|
|
262
|
+
chainId?: ChainIdLike,
|
|
263
|
+
allSigners?: boolean
|
|
264
|
+
): Promise<TransactionResponse> {
|
|
265
|
+
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
|
|
266
|
+
|
|
267
|
+
const tx = this.sendUncheckedTransaction(transaction, chainId).then(hash => {
|
|
268
|
+
return ethers.utils
|
|
269
|
+
.poll(
|
|
270
|
+
() => {
|
|
271
|
+
return provider!.getTransaction(hash).then((tx: TransactionResponse) => {
|
|
272
|
+
if (tx === null) {
|
|
273
|
+
return undefined
|
|
274
|
+
}
|
|
275
|
+
return provider!._wrapTransaction(tx, hash)
|
|
276
|
+
})
|
|
277
|
+
},
|
|
278
|
+
{ onceBlock: this.provider! }
|
|
279
|
+
)
|
|
280
|
+
.catch((error: Error) => {
|
|
281
|
+
;(<any>error).transactionHash = hash
|
|
282
|
+
throw error
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
// @ts-ignore
|
|
287
|
+
return tx
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// sendTransactionBatch is a convenience method to call sendTransaction in a batch format, allowing you to
|
|
291
|
+
// send multiple transaction as a single payload and just one on-chain transaction.
|
|
292
|
+
async sendTransactionBatch(
|
|
293
|
+
transactions: Deferrable<Forbid<TransactionRequest, "wait">[]>,
|
|
294
|
+
chainId?: ChainIdLike,
|
|
295
|
+
allSigners?: boolean
|
|
296
|
+
): Promise<TransactionResponse> {
|
|
297
|
+
const batch = await resolveArrayProperties<Forbid<TransactionRequest, "wait">[]>(transactions)
|
|
298
|
+
if (!batch || batch.length === 0) {
|
|
299
|
+
throw new Error('cannot send empty batch')
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// sendTransactionBatch only accepts TransactionRequest, not TransactionResponses
|
|
303
|
+
if (batch.find((v) => v.wait !== undefined && v.wait !== null)) {
|
|
304
|
+
throw new Error('transaction request expected for sendTransactionBatch, transaction response found')
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const tx: TransactionRequest = { ...batch[0] }
|
|
308
|
+
if (batch.length > 1) {
|
|
309
|
+
tx.auxiliary = batch.splice(1)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return this.sendTransaction(tx, chainId, allSigners)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
signTransactions(
|
|
316
|
+
transaction: Deferrable<TransactionRequest>,
|
|
317
|
+
chainId?: ChainIdLike,
|
|
318
|
+
allSigners?: boolean
|
|
319
|
+
): Promise<SignedTransactions> {
|
|
320
|
+
transaction = shallowCopy(transaction)
|
|
321
|
+
// TODO: transaction argument..? make sure to resolve any properties and serialize property before sending over
|
|
322
|
+
// the wire.. see sendUncheckedTransaction and resolveProperties
|
|
323
|
+
return this.provider.send('eth_signTransaction', [transaction], maybeChainId(chainId) || this.defaultChainId)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
sendSignedTransactions(signedTxs: SignedTransactions, chainId?: ChainIdLike): Promise<TransactionResponse> {
|
|
327
|
+
// sequence_relay
|
|
328
|
+
throw new Error('TODO')
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// updateConfig..
|
|
332
|
+
// NOTE: this is not supported by the remote wallet by default.
|
|
333
|
+
async updateConfig(newConfig?: WalletConfig): Promise<[WalletConfig, TransactionResponse | undefined]> {
|
|
334
|
+
// sequence_updateConfig
|
|
335
|
+
const [config, tx] = await this.provider.send('sequence_updateConfig', [newConfig], this.defaultChainId)
|
|
336
|
+
if (tx === null) {
|
|
337
|
+
return [config, undefined]
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const provider = await this.getSender(this.defaultChainId)
|
|
341
|
+
return [config, provider!._wrapTransaction(tx, tx.hash)]
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// publishConfig..
|
|
345
|
+
// NOTE: this is not supported by the remote wallet by default.
|
|
346
|
+
async publishConfig(): Promise<TransactionResponse | undefined> {
|
|
347
|
+
const provider = await this.getSender(this.defaultChainId)
|
|
348
|
+
|
|
349
|
+
const tx = await provider!.send('sequence_publishConfig', [])
|
|
350
|
+
if (tx === null) {
|
|
351
|
+
return undefined
|
|
352
|
+
}
|
|
353
|
+
return provider!._wrapTransaction(tx, tx.hash)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async isDeployed(chainId?: ChainIdLike): Promise<boolean> {
|
|
357
|
+
const provider = await this.getSender(maybeChainId(chainId))
|
|
358
|
+
const walletCode = await provider!.getCode(await this.getAddress())
|
|
359
|
+
return !!walletCode && walletCode !== '0x'
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
//
|
|
363
|
+
// ethers JsonRpcSigner methods
|
|
364
|
+
//
|
|
365
|
+
|
|
366
|
+
async _signTypedData(
|
|
367
|
+
domain: TypedDataDomain,
|
|
368
|
+
types: Record<string, Array<TypedDataField>>,
|
|
369
|
+
message: Record<string, any>,
|
|
370
|
+
chainId?: ChainIdLike,
|
|
371
|
+
allSigners?: boolean
|
|
372
|
+
): Promise<string> {
|
|
373
|
+
return this.signTypedData(domain, types, message, chainId, allSigners)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async sendUncheckedTransaction(transaction: Deferrable<TransactionRequest>, chainId?: ChainIdLike): Promise<string> {
|
|
377
|
+
transaction = shallowCopy(transaction)
|
|
378
|
+
|
|
379
|
+
const fromAddress = this.getAddress()
|
|
380
|
+
|
|
381
|
+
// NOTE: we do not use provider estimation, and instead rely on our relayer to determine the gasLimit and gasPrice
|
|
382
|
+
//
|
|
383
|
+
// TODO: alternatively/one day, we could write a provider middleware to eth_estimateGas
|
|
384
|
+
// and send it to our relayer url instead for estimation..
|
|
385
|
+
//
|
|
386
|
+
// if (!transaction.gasLimit) {
|
|
387
|
+
// const estimate = shallowCopy(transaction)
|
|
388
|
+
// estimate.from = fromAddress
|
|
389
|
+
// transaction.gasLimit = this.provider.estimateGas(estimate)
|
|
390
|
+
// }
|
|
391
|
+
|
|
392
|
+
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
|
|
393
|
+
|
|
394
|
+
return resolveProperties({
|
|
395
|
+
tx: resolveProperties(transaction),
|
|
396
|
+
sender: await fromAddress
|
|
397
|
+
}).then(({ tx, sender }) => {
|
|
398
|
+
if (tx.from != null) {
|
|
399
|
+
if (ethers.utils.getAddress(tx.from) !== sender) {
|
|
400
|
+
// logger.throwArgumentError("from address mismatch", "transaction", transaction)
|
|
401
|
+
throw new Error(`from address mismatch for transaction ${transaction}`)
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
tx.from = sender
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const hexTx = hexlifyTransaction(tx)
|
|
408
|
+
|
|
409
|
+
return provider!.send('eth_sendTransaction', [hexTx]).then(
|
|
410
|
+
hash => {
|
|
411
|
+
return hash
|
|
412
|
+
},
|
|
413
|
+
error => {
|
|
414
|
+
// return checkError("sendTransaction", error, hexTx)
|
|
415
|
+
throw new Error(`sendTransaction ${error}`)
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
connectUnchecked(): ethers.providers.JsonRpcSigner {
|
|
422
|
+
throw new Error('connectUnchecked is unsupported')
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async unlock(password: string): Promise<boolean> {
|
|
426
|
+
const address = await this.getAddress()
|
|
427
|
+
return this.provider.send('personal_unlockAccount', [address, password, null])
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// NOTE: method has been copied + modified from ethers.js JsonRpcProvider
|
|
432
|
+
// Convert an ethers.js transaction into a JSON-RPC transaction
|
|
433
|
+
|
|
434
|
+
const allowedTransactionKeys: { [key: string]: boolean } = {
|
|
435
|
+
chainId: true,
|
|
436
|
+
data: true,
|
|
437
|
+
gasLimit: true,
|
|
438
|
+
gasPrice: true,
|
|
439
|
+
nonce: true,
|
|
440
|
+
to: true,
|
|
441
|
+
value: true,
|
|
442
|
+
from: true,
|
|
443
|
+
auxiliary: true,
|
|
444
|
+
expiration: true,
|
|
445
|
+
afterNonce: true,
|
|
446
|
+
delegateCall: true,
|
|
447
|
+
revertOnError: true
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const hexlifyTransaction = (
|
|
451
|
+
transaction: TransactionRequest,
|
|
452
|
+
allowExtra?: { [key: string]: boolean }
|
|
453
|
+
): { [key: string]: string } => {
|
|
454
|
+
// Check only allowed properties are given
|
|
455
|
+
const allowed = shallowCopy(allowedTransactionKeys)
|
|
456
|
+
if (allowExtra) {
|
|
457
|
+
for (const key in allowExtra) {
|
|
458
|
+
if (allowExtra[key]) {
|
|
459
|
+
allowed[key] = true
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
ethers.utils.checkProperties(transaction, allowed)
|
|
464
|
+
|
|
465
|
+
const result: { [key: string]: any } = {}
|
|
466
|
+
|
|
467
|
+
// Some nodes (INFURA ropsten; INFURA mainnet is fine) do not like leading zeros.
|
|
468
|
+
;['gasLimit', 'gasPrice', 'nonce', 'value'].forEach(key => {
|
|
469
|
+
if (!(<any>transaction)[key]) {
|
|
470
|
+
return
|
|
471
|
+
}
|
|
472
|
+
const value = ethers.utils.hexValue((<any>transaction)[key])
|
|
473
|
+
if (key === 'gasLimit') {
|
|
474
|
+
key = 'gas'
|
|
475
|
+
}
|
|
476
|
+
result[key] = value
|
|
477
|
+
})
|
|
478
|
+
;['from', 'to', 'data'].forEach(key => {
|
|
479
|
+
if (!(<any>transaction)[key]) {
|
|
480
|
+
return
|
|
481
|
+
}
|
|
482
|
+
result[key] = ethers.utils.hexlify((<any>transaction)[key])
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
const auxiliary = <any>transaction['auxiliary']
|
|
486
|
+
if (auxiliary && auxiliary.length > 0) {
|
|
487
|
+
result['auxiliary'] = []
|
|
488
|
+
auxiliary.forEach((a: any) => {
|
|
489
|
+
result['auxiliary'].push(hexlifyTransaction(a))
|
|
490
|
+
})
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return result
|
|
494
|
+
}
|