@0xsequence/relayer 0.34.0 → 0.35.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/CHANGELOG.md +22 -0
- package/dist/0xsequence-relayer.cjs.dev.js +117 -39
- package/dist/0xsequence-relayer.cjs.prod.js +117 -39
- package/dist/0xsequence-relayer.esm.js +118 -40
- package/dist/declarations/src/base-relayer.d.ts +9 -1
- package/dist/declarations/src/rpc-relayer/relayer.gen.d.ts +14 -1
- package/package.json +5 -5
- package/src/base-relayer.ts +38 -19
- package/src/local-relayer.ts +11 -3
- package/src/rpc-relayer/index.ts +39 -27
- package/src/rpc-relayer/relayer.gen.ts +25 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @0xsequence/relayer
|
|
2
2
|
|
|
3
|
+
## 0.35.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- - config: add buildStubSignature
|
|
8
|
+
- provider: add checks to signing cases for wallet deployment and config statuses
|
|
9
|
+
- provider: add prompt for wallet deployment
|
|
10
|
+
- relayer: add BaseRelayer.prependWalletDeploy
|
|
11
|
+
- relayer: add Relayer.feeOptions
|
|
12
|
+
- relayer: account for wallet deployment in fee estimation
|
|
13
|
+
- transactions: add fromTransactionish
|
|
14
|
+
- wallet: add Account.prependConfigUpdate
|
|
15
|
+
- wallet: add Account.getFeeOptions
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @0xsequence/abi@0.35.0
|
|
21
|
+
- @0xsequence/config@0.35.0
|
|
22
|
+
- @0xsequence/transactions@0.35.0
|
|
23
|
+
- @0xsequence/utils@0.35.0
|
|
24
|
+
|
|
3
25
|
## 0.34.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var ethers = require('ethers');
|
|
6
|
-
var providers = require('@ethersproject/providers');
|
|
7
6
|
var abi = require('@0xsequence/abi');
|
|
8
7
|
var transactions = require('@0xsequence/transactions');
|
|
8
|
+
var providers = require('@ethersproject/providers');
|
|
9
9
|
var config = require('@0xsequence/config');
|
|
10
10
|
var utils$1 = require('ethers/lib/utils');
|
|
11
11
|
var utils = require('@0xsequence/utils');
|
|
@@ -66,8 +66,14 @@ class BaseRelayer {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
async
|
|
70
|
-
|
|
69
|
+
async prependWalletDeploy(signedTransactions) {
|
|
70
|
+
const {
|
|
71
|
+
config: config$1,
|
|
72
|
+
context,
|
|
73
|
+
transactions: transactions$1,
|
|
74
|
+
nonce,
|
|
75
|
+
signature
|
|
76
|
+
} = signedTransactions;
|
|
71
77
|
const walletAddress = config.addressOf(config$1, context);
|
|
72
78
|
const walletInterface = new utils$1.Interface(abi.walletContracts.mainModule.abi);
|
|
73
79
|
|
|
@@ -80,28 +86,61 @@ class BaseRelayer {
|
|
|
80
86
|
if (this.bundleCreation && !(await this.isWalletDeployed(walletAddress))) {
|
|
81
87
|
return {
|
|
82
88
|
to: context.guestModule,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
execute: {
|
|
90
|
+
transactions: [_extends({}, this.prepareWalletDeploy(config$1, context), {
|
|
91
|
+
delegateCall: false,
|
|
92
|
+
revertOnError: false,
|
|
93
|
+
gasLimit: this.creationGasLimit,
|
|
94
|
+
value: ethers.ethers.constants.Zero
|
|
95
|
+
}), {
|
|
96
|
+
delegateCall: false,
|
|
97
|
+
revertOnError: true,
|
|
98
|
+
gasLimit: ethers.ethers.constants.Zero,
|
|
99
|
+
to: walletAddress,
|
|
100
|
+
value: ethers.ethers.constants.Zero,
|
|
101
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(transactions$1), nonce, await encodedSignature])
|
|
102
|
+
}],
|
|
103
|
+
nonce: ethers.ethers.constants.Zero,
|
|
104
|
+
signature: '0x'
|
|
105
|
+
}
|
|
96
106
|
};
|
|
97
107
|
} else {
|
|
98
108
|
return {
|
|
99
109
|
to: walletAddress,
|
|
100
|
-
|
|
110
|
+
execute: {
|
|
111
|
+
transactions: transactions$1,
|
|
112
|
+
nonce: ethers.ethers.BigNumber.from(nonce),
|
|
113
|
+
signature: await encodedSignature
|
|
114
|
+
}
|
|
101
115
|
};
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
|
|
119
|
+
async prepareTransactions(config, context, signature, ...transactions$1) {
|
|
120
|
+
//, gasLimit?: ethers.BigNumberish }> {
|
|
121
|
+
const nonce = transactions.readSequenceNonce(...transactions$1);
|
|
122
|
+
|
|
123
|
+
if (!nonce) {
|
|
124
|
+
throw new Error('Unable to prepare transactions without a defined nonce');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const {
|
|
128
|
+
to,
|
|
129
|
+
execute
|
|
130
|
+
} = await this.prependWalletDeploy({
|
|
131
|
+
config,
|
|
132
|
+
context,
|
|
133
|
+
transactions: transactions$1,
|
|
134
|
+
nonce,
|
|
135
|
+
signature
|
|
136
|
+
});
|
|
137
|
+
const walletInterface = new utils$1.Interface(abi.walletContracts.mainModule.abi);
|
|
138
|
+
return {
|
|
139
|
+
to,
|
|
140
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature])
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
105
144
|
}
|
|
106
145
|
|
|
107
146
|
const DEFAULT_GAS_LIMIT = ethers.ethers.BigNumber.from(800000);
|
|
@@ -281,18 +320,26 @@ class LocalRelayer extends ProviderRelayer {
|
|
|
281
320
|
throw new Error('LocalRelayer requires the context.guestModule address');
|
|
282
321
|
}
|
|
283
322
|
|
|
284
|
-
const
|
|
323
|
+
const {
|
|
324
|
+
to,
|
|
325
|
+
execute
|
|
326
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
327
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
328
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]); // TODO: think about computing gas limit individually, summing together and passing across
|
|
285
329
|
// NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
|
|
286
330
|
// const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
|
|
287
331
|
// txRequest.gasLimit = gasLimit
|
|
288
332
|
|
|
289
|
-
return this.signer.sendTransaction(
|
|
333
|
+
return this.signer.sendTransaction({
|
|
334
|
+
to,
|
|
335
|
+
data
|
|
336
|
+
});
|
|
290
337
|
}
|
|
291
338
|
|
|
292
339
|
}
|
|
293
340
|
|
|
294
341
|
/* eslint-disable */
|
|
295
|
-
// sequence-relayer v0.4.0
|
|
342
|
+
// sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
|
|
296
343
|
// --
|
|
297
344
|
// This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
|
|
298
345
|
// Do not edit by hand. Update your webrpc schema and re-generate.
|
|
@@ -301,7 +348,7 @@ const WebRPCVersion = 'v1'; // Schema version of your RIDL schema
|
|
|
301
348
|
|
|
302
349
|
const WebRPCSchemaVersion = 'v0.4.0'; // Schema hash generated from your RIDL schema
|
|
303
350
|
|
|
304
|
-
const WebRPCSchemaHash = '
|
|
351
|
+
const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'; //
|
|
305
352
|
// Types
|
|
306
353
|
//
|
|
307
354
|
|
|
@@ -464,6 +511,16 @@ class Relayer {
|
|
|
464
511
|
});
|
|
465
512
|
};
|
|
466
513
|
|
|
514
|
+
this.feeOptions = (args, headers) => {
|
|
515
|
+
return this.fetch(this.url('FeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
516
|
+
return buildResponse(res).then(_data => {
|
|
517
|
+
return {
|
|
518
|
+
options: _data.options
|
|
519
|
+
};
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
};
|
|
523
|
+
|
|
467
524
|
this.getMetaTxnNetworkFeeOptions = (args, headers) => {
|
|
468
525
|
return this.fetch(this.url('GetMetaTxnNetworkFeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
469
526
|
return buildResponse(res).then(_data => {
|
|
@@ -636,23 +693,39 @@ class RpcRelayer extends BaseRelayer {
|
|
|
636
693
|
if (feeTokens.isFeeRequired) {
|
|
637
694
|
const symbols = feeTokens.tokens.map(token => token.symbol).join(', ');
|
|
638
695
|
utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`);
|
|
639
|
-
const
|
|
640
|
-
|
|
696
|
+
const wallet = config.addressOf(config$1, context);
|
|
697
|
+
let nonce = transactions.readSequenceNonce(...transactions$1);
|
|
641
698
|
|
|
642
|
-
if (
|
|
643
|
-
|
|
699
|
+
if (nonce === undefined) {
|
|
700
|
+
nonce = await this.getNonce(config$1, context);
|
|
644
701
|
}
|
|
645
702
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
703
|
+
if (!this.provider) {
|
|
704
|
+
utils.logger.warn(`[rpc-relayer/gasRefundOptions] provider not set, needed for stub signature`);
|
|
705
|
+
throw new Error('provider is not set');
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const {
|
|
709
|
+
to,
|
|
710
|
+
execute
|
|
711
|
+
} = await this.prependWalletDeploy({
|
|
712
|
+
config: config$1,
|
|
713
|
+
context,
|
|
714
|
+
transactions: transactions$1,
|
|
715
|
+
nonce,
|
|
716
|
+
signature: config.buildStubSignature(this.provider, config$1)
|
|
717
|
+
});
|
|
718
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
719
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
720
|
+
const {
|
|
721
|
+
options
|
|
722
|
+
} = await this.service.feeOptions({
|
|
723
|
+
wallet,
|
|
724
|
+
to,
|
|
725
|
+
data
|
|
653
726
|
});
|
|
654
|
-
utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(
|
|
655
|
-
return
|
|
727
|
+
utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`);
|
|
728
|
+
return options;
|
|
656
729
|
} else {
|
|
657
730
|
utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`);
|
|
658
731
|
return [];
|
|
@@ -681,13 +754,18 @@ class RpcRelayer extends BaseRelayer {
|
|
|
681
754
|
throw new Error('provider is not set');
|
|
682
755
|
}
|
|
683
756
|
|
|
684
|
-
const
|
|
685
|
-
|
|
757
|
+
const {
|
|
758
|
+
to: contract,
|
|
759
|
+
execute
|
|
760
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
761
|
+
const walletAddress = config.addressOf(signedTxs.config, signedTxs.context);
|
|
762
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
763
|
+
const input = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
686
764
|
const metaTxn = await this.service.sendMetaTxn({
|
|
687
765
|
call: {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
766
|
+
walletAddress,
|
|
767
|
+
contract,
|
|
768
|
+
input
|
|
691
769
|
}
|
|
692
770
|
});
|
|
693
771
|
utils.logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn)}`);
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var ethers = require('ethers');
|
|
6
|
-
var providers = require('@ethersproject/providers');
|
|
7
6
|
var abi = require('@0xsequence/abi');
|
|
8
7
|
var transactions = require('@0xsequence/transactions');
|
|
8
|
+
var providers = require('@ethersproject/providers');
|
|
9
9
|
var config = require('@0xsequence/config');
|
|
10
10
|
var utils$1 = require('ethers/lib/utils');
|
|
11
11
|
var utils = require('@0xsequence/utils');
|
|
@@ -66,8 +66,14 @@ class BaseRelayer {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
async
|
|
70
|
-
|
|
69
|
+
async prependWalletDeploy(signedTransactions) {
|
|
70
|
+
const {
|
|
71
|
+
config: config$1,
|
|
72
|
+
context,
|
|
73
|
+
transactions: transactions$1,
|
|
74
|
+
nonce,
|
|
75
|
+
signature
|
|
76
|
+
} = signedTransactions;
|
|
71
77
|
const walletAddress = config.addressOf(config$1, context);
|
|
72
78
|
const walletInterface = new utils$1.Interface(abi.walletContracts.mainModule.abi);
|
|
73
79
|
|
|
@@ -80,28 +86,61 @@ class BaseRelayer {
|
|
|
80
86
|
if (this.bundleCreation && !(await this.isWalletDeployed(walletAddress))) {
|
|
81
87
|
return {
|
|
82
88
|
to: context.guestModule,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
execute: {
|
|
90
|
+
transactions: [_extends({}, this.prepareWalletDeploy(config$1, context), {
|
|
91
|
+
delegateCall: false,
|
|
92
|
+
revertOnError: false,
|
|
93
|
+
gasLimit: this.creationGasLimit,
|
|
94
|
+
value: ethers.ethers.constants.Zero
|
|
95
|
+
}), {
|
|
96
|
+
delegateCall: false,
|
|
97
|
+
revertOnError: true,
|
|
98
|
+
gasLimit: ethers.ethers.constants.Zero,
|
|
99
|
+
to: walletAddress,
|
|
100
|
+
value: ethers.ethers.constants.Zero,
|
|
101
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(transactions$1), nonce, await encodedSignature])
|
|
102
|
+
}],
|
|
103
|
+
nonce: ethers.ethers.constants.Zero,
|
|
104
|
+
signature: '0x'
|
|
105
|
+
}
|
|
96
106
|
};
|
|
97
107
|
} else {
|
|
98
108
|
return {
|
|
99
109
|
to: walletAddress,
|
|
100
|
-
|
|
110
|
+
execute: {
|
|
111
|
+
transactions: transactions$1,
|
|
112
|
+
nonce: ethers.ethers.BigNumber.from(nonce),
|
|
113
|
+
signature: await encodedSignature
|
|
114
|
+
}
|
|
101
115
|
};
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
|
|
119
|
+
async prepareTransactions(config, context, signature, ...transactions$1) {
|
|
120
|
+
//, gasLimit?: ethers.BigNumberish }> {
|
|
121
|
+
const nonce = transactions.readSequenceNonce(...transactions$1);
|
|
122
|
+
|
|
123
|
+
if (!nonce) {
|
|
124
|
+
throw new Error('Unable to prepare transactions without a defined nonce');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const {
|
|
128
|
+
to,
|
|
129
|
+
execute
|
|
130
|
+
} = await this.prependWalletDeploy({
|
|
131
|
+
config,
|
|
132
|
+
context,
|
|
133
|
+
transactions: transactions$1,
|
|
134
|
+
nonce,
|
|
135
|
+
signature
|
|
136
|
+
});
|
|
137
|
+
const walletInterface = new utils$1.Interface(abi.walletContracts.mainModule.abi);
|
|
138
|
+
return {
|
|
139
|
+
to,
|
|
140
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature])
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
105
144
|
}
|
|
106
145
|
|
|
107
146
|
const DEFAULT_GAS_LIMIT = ethers.ethers.BigNumber.from(800000);
|
|
@@ -281,18 +320,26 @@ class LocalRelayer extends ProviderRelayer {
|
|
|
281
320
|
throw new Error('LocalRelayer requires the context.guestModule address');
|
|
282
321
|
}
|
|
283
322
|
|
|
284
|
-
const
|
|
323
|
+
const {
|
|
324
|
+
to,
|
|
325
|
+
execute
|
|
326
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
327
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
328
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]); // TODO: think about computing gas limit individually, summing together and passing across
|
|
285
329
|
// NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
|
|
286
330
|
// const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
|
|
287
331
|
// txRequest.gasLimit = gasLimit
|
|
288
332
|
|
|
289
|
-
return this.signer.sendTransaction(
|
|
333
|
+
return this.signer.sendTransaction({
|
|
334
|
+
to,
|
|
335
|
+
data
|
|
336
|
+
});
|
|
290
337
|
}
|
|
291
338
|
|
|
292
339
|
}
|
|
293
340
|
|
|
294
341
|
/* eslint-disable */
|
|
295
|
-
// sequence-relayer v0.4.0
|
|
342
|
+
// sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
|
|
296
343
|
// --
|
|
297
344
|
// This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
|
|
298
345
|
// Do not edit by hand. Update your webrpc schema and re-generate.
|
|
@@ -301,7 +348,7 @@ const WebRPCVersion = 'v1'; // Schema version of your RIDL schema
|
|
|
301
348
|
|
|
302
349
|
const WebRPCSchemaVersion = 'v0.4.0'; // Schema hash generated from your RIDL schema
|
|
303
350
|
|
|
304
|
-
const WebRPCSchemaHash = '
|
|
351
|
+
const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'; //
|
|
305
352
|
// Types
|
|
306
353
|
//
|
|
307
354
|
|
|
@@ -464,6 +511,16 @@ class Relayer {
|
|
|
464
511
|
});
|
|
465
512
|
};
|
|
466
513
|
|
|
514
|
+
this.feeOptions = (args, headers) => {
|
|
515
|
+
return this.fetch(this.url('FeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
516
|
+
return buildResponse(res).then(_data => {
|
|
517
|
+
return {
|
|
518
|
+
options: _data.options
|
|
519
|
+
};
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
};
|
|
523
|
+
|
|
467
524
|
this.getMetaTxnNetworkFeeOptions = (args, headers) => {
|
|
468
525
|
return this.fetch(this.url('GetMetaTxnNetworkFeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
469
526
|
return buildResponse(res).then(_data => {
|
|
@@ -636,23 +693,39 @@ class RpcRelayer extends BaseRelayer {
|
|
|
636
693
|
if (feeTokens.isFeeRequired) {
|
|
637
694
|
const symbols = feeTokens.tokens.map(token => token.symbol).join(', ');
|
|
638
695
|
utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`);
|
|
639
|
-
const
|
|
640
|
-
|
|
696
|
+
const wallet = config.addressOf(config$1, context);
|
|
697
|
+
let nonce = transactions.readSequenceNonce(...transactions$1);
|
|
641
698
|
|
|
642
|
-
if (
|
|
643
|
-
|
|
699
|
+
if (nonce === undefined) {
|
|
700
|
+
nonce = await this.getNonce(config$1, context);
|
|
644
701
|
}
|
|
645
702
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
703
|
+
if (!this.provider) {
|
|
704
|
+
utils.logger.warn(`[rpc-relayer/gasRefundOptions] provider not set, needed for stub signature`);
|
|
705
|
+
throw new Error('provider is not set');
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const {
|
|
709
|
+
to,
|
|
710
|
+
execute
|
|
711
|
+
} = await this.prependWalletDeploy({
|
|
712
|
+
config: config$1,
|
|
713
|
+
context,
|
|
714
|
+
transactions: transactions$1,
|
|
715
|
+
nonce,
|
|
716
|
+
signature: config.buildStubSignature(this.provider, config$1)
|
|
717
|
+
});
|
|
718
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
719
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
720
|
+
const {
|
|
721
|
+
options
|
|
722
|
+
} = await this.service.feeOptions({
|
|
723
|
+
wallet,
|
|
724
|
+
to,
|
|
725
|
+
data
|
|
653
726
|
});
|
|
654
|
-
utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(
|
|
655
|
-
return
|
|
727
|
+
utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`);
|
|
728
|
+
return options;
|
|
656
729
|
} else {
|
|
657
730
|
utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`);
|
|
658
731
|
return [];
|
|
@@ -681,13 +754,18 @@ class RpcRelayer extends BaseRelayer {
|
|
|
681
754
|
throw new Error('provider is not set');
|
|
682
755
|
}
|
|
683
756
|
|
|
684
|
-
const
|
|
685
|
-
|
|
757
|
+
const {
|
|
758
|
+
to: contract,
|
|
759
|
+
execute
|
|
760
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
761
|
+
const walletAddress = config.addressOf(signedTxs.config, signedTxs.context);
|
|
762
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
763
|
+
const input = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
686
764
|
const metaTxn = await this.service.sendMetaTxn({
|
|
687
765
|
call: {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
766
|
+
walletAddress,
|
|
767
|
+
contract,
|
|
768
|
+
input
|
|
691
769
|
}
|
|
692
770
|
});
|
|
693
771
|
utils.logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn)}`);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ethers, providers, Signer } from 'ethers';
|
|
2
|
-
import { Provider } from '@ethersproject/providers';
|
|
3
2
|
import { walletContracts } from '@0xsequence/abi';
|
|
4
3
|
import { sequenceTxAbiEncode, readSequenceNonce, encodeNonce, computeMetaTxnHash, MetaTransactionsType, appendNonce, decodeNonce } from '@0xsequence/transactions';
|
|
5
|
-
import {
|
|
4
|
+
import { Provider } from '@ethersproject/providers';
|
|
5
|
+
import { imageHash, addressOf, encodeSignature, buildStubSignature } from '@0xsequence/config';
|
|
6
6
|
import { Interface } from 'ethers/lib/utils';
|
|
7
7
|
import { isBigNumberish, logger } from '@0xsequence/utils';
|
|
8
8
|
import fetchPonyfill from 'fetch-ponyfill';
|
|
@@ -58,8 +58,14 @@ class BaseRelayer {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
async
|
|
62
|
-
|
|
61
|
+
async prependWalletDeploy(signedTransactions) {
|
|
62
|
+
const {
|
|
63
|
+
config,
|
|
64
|
+
context,
|
|
65
|
+
transactions,
|
|
66
|
+
nonce,
|
|
67
|
+
signature
|
|
68
|
+
} = signedTransactions;
|
|
63
69
|
const walletAddress = addressOf(config, context);
|
|
64
70
|
const walletInterface = new Interface(walletContracts.mainModule.abi);
|
|
65
71
|
|
|
@@ -72,28 +78,61 @@ class BaseRelayer {
|
|
|
72
78
|
if (this.bundleCreation && !(await this.isWalletDeployed(walletAddress))) {
|
|
73
79
|
return {
|
|
74
80
|
to: context.guestModule,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
execute: {
|
|
82
|
+
transactions: [_extends({}, this.prepareWalletDeploy(config, context), {
|
|
83
|
+
delegateCall: false,
|
|
84
|
+
revertOnError: false,
|
|
85
|
+
gasLimit: this.creationGasLimit,
|
|
86
|
+
value: ethers.constants.Zero
|
|
87
|
+
}), {
|
|
88
|
+
delegateCall: false,
|
|
89
|
+
revertOnError: true,
|
|
90
|
+
gasLimit: ethers.constants.Zero,
|
|
91
|
+
to: walletAddress,
|
|
92
|
+
value: ethers.constants.Zero,
|
|
93
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(transactions), nonce, await encodedSignature])
|
|
94
|
+
}],
|
|
95
|
+
nonce: ethers.constants.Zero,
|
|
96
|
+
signature: '0x'
|
|
97
|
+
}
|
|
88
98
|
};
|
|
89
99
|
} else {
|
|
90
100
|
return {
|
|
91
101
|
to: walletAddress,
|
|
92
|
-
|
|
102
|
+
execute: {
|
|
103
|
+
transactions,
|
|
104
|
+
nonce: ethers.BigNumber.from(nonce),
|
|
105
|
+
signature: await encodedSignature
|
|
106
|
+
}
|
|
93
107
|
};
|
|
94
108
|
}
|
|
95
109
|
}
|
|
96
110
|
|
|
111
|
+
async prepareTransactions(config, context, signature, ...transactions) {
|
|
112
|
+
//, gasLimit?: ethers.BigNumberish }> {
|
|
113
|
+
const nonce = readSequenceNonce(...transactions);
|
|
114
|
+
|
|
115
|
+
if (!nonce) {
|
|
116
|
+
throw new Error('Unable to prepare transactions without a defined nonce');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const {
|
|
120
|
+
to,
|
|
121
|
+
execute
|
|
122
|
+
} = await this.prependWalletDeploy({
|
|
123
|
+
config,
|
|
124
|
+
context,
|
|
125
|
+
transactions,
|
|
126
|
+
nonce,
|
|
127
|
+
signature
|
|
128
|
+
});
|
|
129
|
+
const walletInterface = new Interface(walletContracts.mainModule.abi);
|
|
130
|
+
return {
|
|
131
|
+
to,
|
|
132
|
+
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature])
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
97
136
|
}
|
|
98
137
|
|
|
99
138
|
const DEFAULT_GAS_LIMIT = ethers.BigNumber.from(800000);
|
|
@@ -273,18 +312,26 @@ class LocalRelayer extends ProviderRelayer {
|
|
|
273
312
|
throw new Error('LocalRelayer requires the context.guestModule address');
|
|
274
313
|
}
|
|
275
314
|
|
|
276
|
-
const
|
|
315
|
+
const {
|
|
316
|
+
to,
|
|
317
|
+
execute
|
|
318
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
319
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi);
|
|
320
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]); // TODO: think about computing gas limit individually, summing together and passing across
|
|
277
321
|
// NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
|
|
278
322
|
// const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
|
|
279
323
|
// txRequest.gasLimit = gasLimit
|
|
280
324
|
|
|
281
|
-
return this.signer.sendTransaction(
|
|
325
|
+
return this.signer.sendTransaction({
|
|
326
|
+
to,
|
|
327
|
+
data
|
|
328
|
+
});
|
|
282
329
|
}
|
|
283
330
|
|
|
284
331
|
}
|
|
285
332
|
|
|
286
333
|
/* eslint-disable */
|
|
287
|
-
// sequence-relayer v0.4.0
|
|
334
|
+
// sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
|
|
288
335
|
// --
|
|
289
336
|
// This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
|
|
290
337
|
// Do not edit by hand. Update your webrpc schema and re-generate.
|
|
@@ -293,7 +340,7 @@ const WebRPCVersion = 'v1'; // Schema version of your RIDL schema
|
|
|
293
340
|
|
|
294
341
|
const WebRPCSchemaVersion = 'v0.4.0'; // Schema hash generated from your RIDL schema
|
|
295
342
|
|
|
296
|
-
const WebRPCSchemaHash = '
|
|
343
|
+
const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'; //
|
|
297
344
|
// Types
|
|
298
345
|
//
|
|
299
346
|
|
|
@@ -456,6 +503,16 @@ class Relayer {
|
|
|
456
503
|
});
|
|
457
504
|
};
|
|
458
505
|
|
|
506
|
+
this.feeOptions = (args, headers) => {
|
|
507
|
+
return this.fetch(this.url('FeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
508
|
+
return buildResponse(res).then(_data => {
|
|
509
|
+
return {
|
|
510
|
+
options: _data.options
|
|
511
|
+
};
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
};
|
|
515
|
+
|
|
459
516
|
this.getMetaTxnNetworkFeeOptions = (args, headers) => {
|
|
460
517
|
return this.fetch(this.url('GetMetaTxnNetworkFeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
461
518
|
return buildResponse(res).then(_data => {
|
|
@@ -628,23 +685,39 @@ class RpcRelayer extends BaseRelayer {
|
|
|
628
685
|
if (feeTokens.isFeeRequired) {
|
|
629
686
|
const symbols = feeTokens.tokens.map(token => token.symbol).join(', ');
|
|
630
687
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`);
|
|
631
|
-
const
|
|
632
|
-
|
|
688
|
+
const wallet = addressOf(config, context);
|
|
689
|
+
let nonce = readSequenceNonce(...transactions);
|
|
633
690
|
|
|
634
|
-
if (
|
|
635
|
-
|
|
691
|
+
if (nonce === undefined) {
|
|
692
|
+
nonce = await this.getNonce(config, context);
|
|
636
693
|
}
|
|
637
694
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
695
|
+
if (!this.provider) {
|
|
696
|
+
logger.warn(`[rpc-relayer/gasRefundOptions] provider not set, needed for stub signature`);
|
|
697
|
+
throw new Error('provider is not set');
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
const {
|
|
701
|
+
to,
|
|
702
|
+
execute
|
|
703
|
+
} = await this.prependWalletDeploy({
|
|
704
|
+
config,
|
|
705
|
+
context,
|
|
706
|
+
transactions,
|
|
707
|
+
nonce,
|
|
708
|
+
signature: buildStubSignature(this.provider, config)
|
|
645
709
|
});
|
|
646
|
-
|
|
647
|
-
|
|
710
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi);
|
|
711
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
712
|
+
const {
|
|
713
|
+
options
|
|
714
|
+
} = await this.service.feeOptions({
|
|
715
|
+
wallet,
|
|
716
|
+
to,
|
|
717
|
+
data
|
|
718
|
+
});
|
|
719
|
+
logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`);
|
|
720
|
+
return options;
|
|
648
721
|
} else {
|
|
649
722
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`);
|
|
650
723
|
return [];
|
|
@@ -673,13 +746,18 @@ class RpcRelayer extends BaseRelayer {
|
|
|
673
746
|
throw new Error('provider is not set');
|
|
674
747
|
}
|
|
675
748
|
|
|
676
|
-
const
|
|
677
|
-
|
|
749
|
+
const {
|
|
750
|
+
to: contract,
|
|
751
|
+
execute
|
|
752
|
+
} = await this.prependWalletDeploy(signedTxs);
|
|
753
|
+
const walletAddress = addressOf(signedTxs.config, signedTxs.context);
|
|
754
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi);
|
|
755
|
+
const input = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(execute.transactions), execute.nonce, execute.signature]);
|
|
678
756
|
const metaTxn = await this.service.sendMetaTxn({
|
|
679
757
|
call: {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
758
|
+
walletAddress,
|
|
759
|
+
contract,
|
|
760
|
+
input
|
|
683
761
|
}
|
|
684
762
|
});
|
|
685
763
|
logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn)}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ethers, providers } from "ethers";
|
|
2
2
|
import { WalletContext } from '@0xsequence/network';
|
|
3
3
|
import { WalletConfig, DecodedSignature } from '@0xsequence/config';
|
|
4
|
-
import { Transaction } from '@0xsequence/transactions';
|
|
4
|
+
import { SignedTransactions, Transaction } from '@0xsequence/transactions';
|
|
5
5
|
import { Optionals } from '@0xsequence/utils';
|
|
6
6
|
import { Provider } from "@ethersproject/providers";
|
|
7
7
|
export interface BaseRelayerOptions {
|
|
@@ -21,6 +21,14 @@ export declare class BaseRelayer {
|
|
|
21
21
|
to: string;
|
|
22
22
|
data: string;
|
|
23
23
|
};
|
|
24
|
+
prependWalletDeploy(signedTransactions: Pick<SignedTransactions, 'config' | 'context' | 'transactions' | 'nonce' | 'signature'>): Promise<{
|
|
25
|
+
to: string;
|
|
26
|
+
execute: {
|
|
27
|
+
transactions: Transaction[];
|
|
28
|
+
nonce: ethers.BigNumber;
|
|
29
|
+
signature: string;
|
|
30
|
+
};
|
|
31
|
+
}>;
|
|
24
32
|
prepareTransactions(config: WalletConfig, context: WalletContext, signature: string | Promise<string> | DecodedSignature | Promise<DecodedSignature>, ...transactions: Transaction[]): Promise<{
|
|
25
33
|
to: string;
|
|
26
34
|
data: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const WebRPCVersion = "v1";
|
|
2
2
|
export declare const WebRPCSchemaVersion = "v0.4.0";
|
|
3
|
-
export declare const WebRPCSchemaHash = "
|
|
3
|
+
export declare const WebRPCSchemaHash = "7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd";
|
|
4
4
|
export declare enum ETHTxnStatus {
|
|
5
5
|
UNKNOWN = "UNKNOWN",
|
|
6
6
|
DROPPED = "DROPPED",
|
|
@@ -80,6 +80,9 @@ export interface MetaTxnLog {
|
|
|
80
80
|
txnStatus: ETHTxnStatus;
|
|
81
81
|
txnRevertReason: string;
|
|
82
82
|
requeues: number;
|
|
83
|
+
queuedAt: string;
|
|
84
|
+
sentAt: string;
|
|
85
|
+
minedAt: string;
|
|
83
86
|
target: string;
|
|
84
87
|
input: string;
|
|
85
88
|
txnArgs: {
|
|
@@ -196,6 +199,7 @@ export interface Relayer {
|
|
|
196
199
|
simulate(args: SimulateArgs, headers?: object): Promise<SimulateReturn>;
|
|
197
200
|
updateMetaTxnGasLimits(args: UpdateMetaTxnGasLimitsArgs, headers?: object): Promise<UpdateMetaTxnGasLimitsReturn>;
|
|
198
201
|
feeTokens(headers?: object): Promise<FeeTokensReturn>;
|
|
202
|
+
feeOptions(args: FeeOptionsArgs, headers?: object): Promise<FeeOptionsReturn>;
|
|
199
203
|
getMetaTxnNetworkFeeOptions(args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object): Promise<GetMetaTxnNetworkFeeOptionsReturn>;
|
|
200
204
|
sentTransactions(args: SentTransactionsArgs, headers?: object): Promise<SentTransactionsReturn>;
|
|
201
205
|
pendingTransactions(args: PendingTransactionsArgs, headers?: object): Promise<PendingTransactionsReturn>;
|
|
@@ -266,6 +270,14 @@ export interface FeeTokensReturn {
|
|
|
266
270
|
isFeeRequired: boolean;
|
|
267
271
|
tokens: Array<FeeToken>;
|
|
268
272
|
}
|
|
273
|
+
export interface FeeOptionsArgs {
|
|
274
|
+
wallet: string;
|
|
275
|
+
to: string;
|
|
276
|
+
data: string;
|
|
277
|
+
}
|
|
278
|
+
export interface FeeOptionsReturn {
|
|
279
|
+
options: Array<FeeOption>;
|
|
280
|
+
}
|
|
269
281
|
export interface GetMetaTxnNetworkFeeOptionsArgs {
|
|
270
282
|
walletConfig: WalletConfig;
|
|
271
283
|
payload: string;
|
|
@@ -305,6 +317,7 @@ export declare class Relayer implements Relayer {
|
|
|
305
317
|
simulate: (args: SimulateArgs, headers?: object | undefined) => Promise<SimulateReturn>;
|
|
306
318
|
updateMetaTxnGasLimits: (args: UpdateMetaTxnGasLimitsArgs, headers?: object | undefined) => Promise<UpdateMetaTxnGasLimitsReturn>;
|
|
307
319
|
feeTokens: (headers?: object | undefined) => Promise<FeeTokensReturn>;
|
|
320
|
+
feeOptions: (args: FeeOptionsArgs, headers?: object | undefined) => Promise<FeeOptionsReturn>;
|
|
308
321
|
getMetaTxnNetworkFeeOptions: (args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object | undefined) => Promise<GetMetaTxnNetworkFeeOptionsReturn>;
|
|
309
322
|
sentTransactions: (args: SentTransactionsArgs, headers?: object | undefined) => Promise<SentTransactionsReturn>;
|
|
310
323
|
pendingTransactions: (args: PendingTransactionsArgs, headers?: object | undefined) => Promise<PendingTransactionsReturn>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/relayer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "relayer sub-package for Sequence",
|
|
5
5
|
"repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/relayer",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"typecheck": "tsc --noEmit"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@0xsequence/abi": "^0.
|
|
21
|
-
"@0xsequence/config": "^0.
|
|
22
|
-
"@0xsequence/transactions": "^0.
|
|
23
|
-
"@0xsequence/utils": "^0.
|
|
20
|
+
"@0xsequence/abi": "^0.35.0",
|
|
21
|
+
"@0xsequence/config": "^0.35.0",
|
|
22
|
+
"@0xsequence/transactions": "^0.35.0",
|
|
23
|
+
"@0xsequence/utils": "^0.35.0",
|
|
24
24
|
"@ethersproject/providers": "^5.5.1",
|
|
25
25
|
"ethers": "^5.5.2",
|
|
26
26
|
"fetch-ponyfill": "^7.1.0"
|
package/src/base-relayer.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Interface } from "ethers/lib/utils"
|
|
|
3
3
|
import { walletContracts } from '@0xsequence/abi'
|
|
4
4
|
import { WalletContext } from '@0xsequence/network'
|
|
5
5
|
import { WalletConfig, addressOf, imageHash, DecodedSignature, encodeSignature } from '@0xsequence/config'
|
|
6
|
-
import { Transaction, sequenceTxAbiEncode, readSequenceNonce } from '@0xsequence/transactions'
|
|
6
|
+
import { SignedTransactions, Transaction, sequenceTxAbiEncode, readSequenceNonce } from '@0xsequence/transactions'
|
|
7
7
|
import { isBigNumberish, Optionals } from '@0xsequence/utils'
|
|
8
8
|
import { Provider } from "@ethersproject/providers"
|
|
9
9
|
|
|
@@ -58,12 +58,10 @@ export class BaseRelayer {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
async
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
...transactions: Transaction[]
|
|
66
|
-
): Promise<{ to: string, data: string }> { //, gasLimit?: ethers.BigNumberish }> {
|
|
61
|
+
async prependWalletDeploy(
|
|
62
|
+
signedTransactions: Pick<SignedTransactions, 'config' | 'context' | 'transactions' | 'nonce' | 'signature'>
|
|
63
|
+
): Promise<{ to: string, execute: { transactions: Transaction[], nonce: ethers.BigNumber, signature: string } }> {
|
|
64
|
+
const { config, context, transactions, nonce, signature } = signedTransactions
|
|
67
65
|
const walletAddress = addressOf(config, context)
|
|
68
66
|
const walletInterface = new Interface(walletContracts.mainModule.abi)
|
|
69
67
|
|
|
@@ -77,8 +75,8 @@ export class BaseRelayer {
|
|
|
77
75
|
if (this.bundleCreation && !(await this.isWalletDeployed(walletAddress))) {
|
|
78
76
|
return {
|
|
79
77
|
to: context.guestModule!,
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
execute: {
|
|
79
|
+
transactions: [
|
|
82
80
|
{
|
|
83
81
|
...this.prepareWalletDeploy(config, context),
|
|
84
82
|
delegateCall: false,
|
|
@@ -95,25 +93,46 @@ export class BaseRelayer {
|
|
|
95
93
|
data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'),
|
|
96
94
|
[
|
|
97
95
|
sequenceTxAbiEncode(transactions),
|
|
98
|
-
|
|
96
|
+
nonce,
|
|
99
97
|
await encodedSignature
|
|
100
98
|
]
|
|
101
99
|
)
|
|
102
100
|
}
|
|
103
|
-
]
|
|
104
|
-
|
|
101
|
+
],
|
|
102
|
+
nonce: ethers.constants.Zero,
|
|
103
|
+
signature: '0x'
|
|
104
|
+
}
|
|
105
105
|
}
|
|
106
106
|
} else {
|
|
107
107
|
return {
|
|
108
108
|
to: walletAddress,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
]
|
|
115
|
-
)
|
|
109
|
+
execute: {
|
|
110
|
+
transactions,
|
|
111
|
+
nonce: ethers.BigNumber.from(nonce),
|
|
112
|
+
signature: await encodedSignature
|
|
113
|
+
}
|
|
116
114
|
}
|
|
117
115
|
}
|
|
118
116
|
}
|
|
117
|
+
|
|
118
|
+
async prepareTransactions(
|
|
119
|
+
config: WalletConfig,
|
|
120
|
+
context: WalletContext,
|
|
121
|
+
signature: string | Promise<string> | DecodedSignature | Promise<DecodedSignature>,
|
|
122
|
+
...transactions: Transaction[]
|
|
123
|
+
): Promise<{ to: string, data: string }> { //, gasLimit?: ethers.BigNumberish }> {
|
|
124
|
+
const nonce = readSequenceNonce(...transactions)
|
|
125
|
+
if (!nonce) {
|
|
126
|
+
throw new Error('Unable to prepare transactions without a defined nonce')
|
|
127
|
+
}
|
|
128
|
+
const { to, execute } = await this.prependWalletDeploy({ config, context, transactions, nonce, signature })
|
|
129
|
+
const walletInterface = new Interface(walletContracts.mainModule.abi)
|
|
130
|
+
return {
|
|
131
|
+
to, data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [
|
|
132
|
+
sequenceTxAbiEncode(execute.transactions),
|
|
133
|
+
execute.nonce,
|
|
134
|
+
execute.signature
|
|
135
|
+
])
|
|
136
|
+
}
|
|
137
|
+
}
|
|
119
138
|
}
|
package/src/local-relayer.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TransactionResponse } from '@ethersproject/providers'
|
|
2
2
|
import { Signer as AbstractSigner, ethers } from 'ethers'
|
|
3
|
-
import {
|
|
3
|
+
import { walletContracts } from '@0xsequence/abi'
|
|
4
|
+
import { SignedTransactions, Transaction, sequenceTxAbiEncode } from '@0xsequence/transactions'
|
|
4
5
|
import { WalletContext } from '@0xsequence/network'
|
|
5
6
|
import { WalletConfig } from '@0xsequence/config'
|
|
6
7
|
import { FeeOption, Relayer } from '.'
|
|
@@ -46,13 +47,20 @@ export class LocalRelayer extends ProviderRelayer implements Relayer {
|
|
|
46
47
|
throw new Error('LocalRelayer requires the context.guestModule address')
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
const
|
|
50
|
+
const { to, execute } = await this.prependWalletDeploy(signedTxs)
|
|
51
|
+
|
|
52
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi)
|
|
53
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [
|
|
54
|
+
sequenceTxAbiEncode(execute.transactions),
|
|
55
|
+
execute.nonce,
|
|
56
|
+
execute.signature
|
|
57
|
+
])
|
|
50
58
|
|
|
51
59
|
// TODO: think about computing gas limit individually, summing together and passing across
|
|
52
60
|
// NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
|
|
53
61
|
// const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
|
|
54
62
|
// txRequest.gasLimit = gasLimit
|
|
55
63
|
|
|
56
|
-
return this.signer.sendTransaction(
|
|
64
|
+
return this.signer.sendTransaction({ to, data })
|
|
57
65
|
}
|
|
58
66
|
}
|
package/src/rpc-relayer/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TransactionResponse } from '@ethersproject/providers'
|
|
2
2
|
import { ethers } from 'ethers'
|
|
3
3
|
import fetchPonyfill from 'fetch-ponyfill'
|
|
4
|
+
import { walletContracts } from '@0xsequence/abi'
|
|
4
5
|
import {
|
|
5
6
|
Transaction,
|
|
6
7
|
readSequenceNonce,
|
|
@@ -14,7 +15,7 @@ import {
|
|
|
14
15
|
import { BaseRelayer, BaseRelayerOptions } from '../base-relayer'
|
|
15
16
|
import { FeeOption, Relayer, SimulateResult } from '..'
|
|
16
17
|
import { WalletContext } from '@0xsequence/network'
|
|
17
|
-
import { WalletConfig, addressOf } from '@0xsequence/config'
|
|
18
|
+
import { WalletConfig, addressOf, buildStubSignature } from '@0xsequence/config'
|
|
18
19
|
import { logger } from '@0xsequence/utils'
|
|
19
20
|
import * as proto from './relayer.gen'
|
|
20
21
|
|
|
@@ -122,23 +123,37 @@ export class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
122
123
|
const symbols = feeTokens.tokens.map(token => token.symbol).join(', ')
|
|
123
124
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`)
|
|
124
125
|
|
|
125
|
-
const
|
|
126
|
-
const prevNonce = readSequenceNonce(...transactions)
|
|
126
|
+
const wallet = addressOf(config, context)
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
if (
|
|
130
|
-
|
|
128
|
+
let nonce = readSequenceNonce(...transactions)
|
|
129
|
+
if (nonce === undefined) {
|
|
130
|
+
nonce = await this.getNonce(config, context)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
if (!this.provider) {
|
|
134
|
+
logger.warn(`[rpc-relayer/gasRefundOptions] provider not set, needed for stub signature`)
|
|
135
|
+
throw new Error('provider is not set')
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const { to, execute } = await this.prependWalletDeploy({
|
|
139
|
+
config,
|
|
140
|
+
context,
|
|
141
|
+
transactions,
|
|
142
|
+
nonce,
|
|
143
|
+
signature: buildStubSignature(this.provider, config)
|
|
138
144
|
})
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi)
|
|
147
|
+
const data = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [
|
|
148
|
+
sequenceTxAbiEncode(execute.transactions),
|
|
149
|
+
execute.nonce,
|
|
150
|
+
execute.signature
|
|
151
|
+
])
|
|
152
|
+
|
|
153
|
+
const { options } = await this.service.feeOptions({ wallet, to, data })
|
|
154
|
+
|
|
155
|
+
logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`)
|
|
156
|
+
return options
|
|
142
157
|
} else {
|
|
143
158
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`)
|
|
144
159
|
return []
|
|
@@ -164,20 +179,17 @@ export class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
164
179
|
throw new Error('provider is not set')
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
walletAddress: addr
|
|
179
|
-
}
|
|
180
|
-
})
|
|
182
|
+
const { to: contract, execute } = await this.prependWalletDeploy(signedTxs)
|
|
183
|
+
|
|
184
|
+
const walletAddress = addressOf(signedTxs.config, signedTxs.context)
|
|
185
|
+
const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi)
|
|
186
|
+
const input = walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [
|
|
187
|
+
sequenceTxAbiEncode(execute.transactions),
|
|
188
|
+
execute.nonce,
|
|
189
|
+
execute.signature
|
|
190
|
+
])
|
|
191
|
+
|
|
192
|
+
const metaTxn = await this.service.sendMetaTxn({ call: { walletAddress, contract, input } })
|
|
181
193
|
|
|
182
194
|
logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn)}`)
|
|
183
195
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// sequence-relayer v0.4.0
|
|
2
|
+
// sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
|
|
3
3
|
// --
|
|
4
4
|
// This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
|
|
5
5
|
// Do not edit by hand. Update your webrpc schema and re-generate.
|
|
@@ -11,7 +11,7 @@ export const WebRPCVersion = 'v1'
|
|
|
11
11
|
export const WebRPCSchemaVersion = 'v0.4.0'
|
|
12
12
|
|
|
13
13
|
// Schema hash generated from your RIDL schema
|
|
14
|
-
export const WebRPCSchemaHash = '
|
|
14
|
+
export const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'
|
|
15
15
|
|
|
16
16
|
//
|
|
17
17
|
// Types
|
|
@@ -106,6 +106,9 @@ export interface MetaTxnLog {
|
|
|
106
106
|
txnStatus: ETHTxnStatus
|
|
107
107
|
txnRevertReason: string
|
|
108
108
|
requeues: number
|
|
109
|
+
queuedAt: string
|
|
110
|
+
sentAt: string
|
|
111
|
+
minedAt: string
|
|
109
112
|
target: string
|
|
110
113
|
input: string
|
|
111
114
|
txnArgs: { [key: string]: any }
|
|
@@ -229,6 +232,7 @@ export interface Relayer {
|
|
|
229
232
|
simulate(args: SimulateArgs, headers?: object): Promise<SimulateReturn>
|
|
230
233
|
updateMetaTxnGasLimits(args: UpdateMetaTxnGasLimitsArgs, headers?: object): Promise<UpdateMetaTxnGasLimitsReturn>
|
|
231
234
|
feeTokens(headers?: object): Promise<FeeTokensReturn>
|
|
235
|
+
feeOptions(args: FeeOptionsArgs, headers?: object): Promise<FeeOptionsReturn>
|
|
232
236
|
getMetaTxnNetworkFeeOptions(args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object): Promise<GetMetaTxnNetworkFeeOptionsReturn>
|
|
233
237
|
sentTransactions(args: SentTransactionsArgs, headers?: object): Promise<SentTransactionsReturn>
|
|
234
238
|
pendingTransactions(args: PendingTransactionsArgs, headers?: object): Promise<PendingTransactionsReturn>
|
|
@@ -305,6 +309,15 @@ export interface FeeTokensReturn {
|
|
|
305
309
|
isFeeRequired: boolean
|
|
306
310
|
tokens: Array<FeeToken>
|
|
307
311
|
}
|
|
312
|
+
export interface FeeOptionsArgs {
|
|
313
|
+
wallet: string
|
|
314
|
+
to: string
|
|
315
|
+
data: string
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export interface FeeOptionsReturn {
|
|
319
|
+
options: Array<FeeOption>
|
|
320
|
+
}
|
|
308
321
|
export interface GetMetaTxnNetworkFeeOptionsArgs {
|
|
309
322
|
walletConfig: WalletConfig
|
|
310
323
|
payload: string
|
|
@@ -460,6 +473,16 @@ export class Relayer implements Relayer {
|
|
|
460
473
|
})
|
|
461
474
|
}
|
|
462
475
|
|
|
476
|
+
feeOptions = (args: FeeOptionsArgs, headers?: object): Promise<FeeOptionsReturn> => {
|
|
477
|
+
return this.fetch(this.url('FeeOptions'), createHTTPRequest(args, headers)).then(res => {
|
|
478
|
+
return buildResponse(res).then(_data => {
|
|
479
|
+
return {
|
|
480
|
+
options: <Array<FeeOption>>_data.options
|
|
481
|
+
}
|
|
482
|
+
})
|
|
483
|
+
})
|
|
484
|
+
}
|
|
485
|
+
|
|
463
486
|
getMetaTxnNetworkFeeOptions = (
|
|
464
487
|
args: GetMetaTxnNetworkFeeOptionsArgs,
|
|
465
488
|
headers?: object
|