@@ -3,11 +3,11 @@ import { BytesLike } from '@ethersproject/bytes'
3
3
import { Web3Provider as EthersWeb3Provider , ExternalProvider , JsonRpcProvider , Networkish } from "@ethersproject/providers"
4
4
import { TypedDataDomain , TypedDataField , TypedDataSigner } from '@ethersproject/abstract-signer'
5
5
import { NetworkConfig , Networks , WalletContext , ChainId , JsonRpcHandler , JsonRpcHandlerFunc , JsonRpcFetchFunc , JsonRpcRequest , JsonRpcResponseCallback , JsonRpcResponse , maybeNetworkId , JsonRpcVersion , JsonRpcSender , isJsonRpcProvider } from '@0xsequence/network'
6
- import { Signer } from '@0xsequence/wallet'
6
+ import { resolveArrayProperties , Signer } from '@0xsequence/wallet'
7
7
import { WalletConfig , WalletState } from '@0xsequence/config'
8
8
import { Relayer } from '@0xsequence/relayer'
9
9
import { Deferrable , shallowCopy , resolveProperties } from '@0xsequence/utils'
10
- import { TransactionRequest , TransactionResponse , Transactionish , SignedTransactions } from '@0xsequence/transactions'
10
+ import { Transaction , TransactionRequest , TransactionResponse , Transactionish , SignedTransactions } from '@0xsequence/transactions'
11
11
import { WalletRequestHandler } from './transports/wallet-request-handler'
12
12
13
13
// naming..?
@@ -235,6 +235,29 @@ export class Web3Signer extends Signer implements TypedDataSigner {
235
235
} )
236
236
}
237
237
238
+ // sendTransactionBatch is a convience method to call sendTransaction in a batch format, allowing you to
239
+ // send multiple transaction as a single payload and just one on-chain transaction.
240
+ async sendTransactionBatch (
241
+ transactions : Deferrable < TransactionRequest [ ] | Transaction [ ] > ,
242
+ chainId ?: ChainId ,
243
+ allSigners ?: boolean
244
+ ) : Promise < TransactionResponse > {
245
+ const batch = await resolveArrayProperties < TransactionRequest [ ] | Transaction [ ] > ( transactions )
246
+ if ( ! batch || batch . length === 0 ) {
247
+ throw new Error ( 'cannot send empty batch' )
248
+ }
249
+
250
+ const tx : TransactionRequest = {
251
+ ...batch [ 0 ] ,
252
+ auxiliary : [ ]
253
+ }
254
+ if ( batch . length > 1 ) {
255
+ tx . auxiliary = batch . splice ( 1 )
256
+ }
257
+
258
+ return this . sendTransaction ( tx , chainId , allSigners )
259
+ }
260
+
238
261
signTransactions ( transaction : Deferrable < TransactionRequest > , chainId ?: ChainId , allSigners ?: boolean ) : Promise < SignedTransactions > {
239
262
transaction = shallowCopy ( transaction )
240
263
// TODO: transaction argument..? make sure to resolve any properties and serialize property before sending over
@@ -320,7 +343,7 @@ export class Web3Signer extends Signer implements TypedDataSigner {
320
343
tx . from = sender ;
321
344
}
322
345
323
- const hexTx = ( < any > this . provider . constructor ) . hexlifyTransaction ( tx , { from : true } )
346
+ const hexTx = hexlifyTransaction ( tx )
324
347
325
348
return provider . send ( 'eth_sendTransaction' , [ hexTx ] ) . then ( ( hash ) => {
326
349
return hash
@@ -340,3 +363,48 @@ export class Web3Signer extends Signer implements TypedDataSigner {
340
363
return this . provider . send ( "personal_unlockAccount" , [ address . toLowerCase ( ) , password , null ] )
341
364
}
342
365
}
366
+
367
+
368
+ // NOTE: method has been copied + modified from ethers.js JsonRpcProvider
369
+ // Convert an ethers.js transaction into a JSON-RPC transaction
370
+
371
+ const allowedTransactionKeys : { [ key : string ] : boolean } = {
372
+ chainId : true , data : true , gasLimit : true , gasPrice :true , nonce : true , to : true , value : true ,
373
+ from : true , auxiliary : true , expiration : true , afterNonce : true
374
+ }
375
+
376
+ const hexlifyTransaction = ( transaction : TransactionRequest , allowExtra ?: { [ key : string ] : boolean } ) : { [ key : string ] : string } => {
377
+ // Check only allowed properties are given
378
+ const allowed = shallowCopy ( allowedTransactionKeys )
379
+ if ( allowExtra ) {
380
+ for ( const key in allowExtra ) {
381
+ if ( allowExtra [ key ] ) { allowed [ key ] = true ; }
382
+ }
383
+ }
384
+ ethers . utils . checkProperties ( transaction , allowed )
385
+
386
+ const result : { [ key : string ] : any } = { } ;
387
+
388
+ // Some nodes (INFURA ropsten; INFURA mainnet is fine) do not like leading zeros.
389
+ [ 'gasLimit' , 'gasPrice' , 'nonce' , 'value' ] . forEach ( key => {
390
+ if ( ! ( < any > transaction ) [ key ] ) { return }
391
+ const value = ethers . utils . hexValue ( ( < any > transaction ) [ key ] )
392
+ if ( key === 'gasLimit' ) { key = 'gas' }
393
+ result [ key ] = value
394
+ } ) ;
395
+
396
+ [ 'from' , 'to' , 'data' ] . forEach ( key => {
397
+ if ( ! ( < any > transaction ) [ key ] ) { return }
398
+ result [ key ] = ethers . utils . hexlify ( ( < any > transaction ) [ key ] )
399
+ } )
400
+
401
+ const auxiliary = < any > transaction [ 'auxiliary' ]
402
+ if ( auxiliary && auxiliary . length > 0 ) {
403
+ result [ 'auxiliary' ] = [ ]
404
+ auxiliary . forEach ( a => {
405
+ result [ 'auxiliary' ] . push ( hexlifyTransaction ( a ) )
406
+ } )
407
+ }
408
+
409
+ return result
410
+ }
0 commit comments