@0xsequence/relayer 0.31.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.
@@ -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 prepareTransactions(config$1, context, signature, ...transactions$1) {
70
- //, gasLimit?: ethers.BigNumberish }> {
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
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode([_extends({}, this.prepareWalletDeploy(config$1, context), {
84
- delegateCall: false,
85
- revertOnError: false,
86
- gasLimit: this.creationGasLimit,
87
- value: ethers.ethers.constants.Zero
88
- }), {
89
- delegateCall: false,
90
- revertOnError: true,
91
- gasLimit: ethers.ethers.constants.Zero,
92
- to: walletAddress,
93
- value: ethers.ethers.constants.Zero,
94
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(transactions$1), transactions.readSequenceNonce(...transactions$1), await encodedSignature])
95
- }]), 0, []])
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
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [transactions.sequenceTxAbiEncode(transactions$1), transactions.readSequenceNonce(...transactions$1), await encodedSignature])
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);
@@ -129,11 +168,10 @@ class ProviderRelayer extends BaseRelayer {
129
168
  this.fromBlockLog = opts.fromBlockLog;
130
169
  }
131
170
 
132
- async estimateGasLimits(config$1, context, ...transactions) {
171
+ async simulate(wallet, ...transactions) {
133
172
  var _this = this;
134
173
 
135
- const walletAddr = config.addressOf(config$1, context);
136
- const gasCosts = await Promise.all(transactions.map(async function (tx) {
174
+ return (await Promise.all(transactions.map(async function (tx) {
137
175
  // Respect gasLimit request of the transaction (as long as its not 0)
138
176
  if (tx.gasLimit && !ethers.ethers.BigNumber.from(tx.gasLimit || 0).eq(ethers.ethers.constants.Zero)) {
139
177
  return tx.gasLimit;
@@ -145,7 +183,7 @@ class ProviderRelayer extends BaseRelayer {
145
183
  } // Fee can't be estimated for self-called if wallet hasn't been deployed
146
184
 
147
185
 
148
- if (tx.to === walletAddr && !(await _this.isWalletDeployed(walletAddr))) {
186
+ if (tx.to === wallet && !(await _this.isWalletDeployed(wallet))) {
149
187
  return DEFAULT_GAS_LIMIT;
150
188
  }
151
189
 
@@ -156,16 +194,25 @@ class ProviderRelayer extends BaseRelayer {
156
194
 
157
195
 
158
196
  return _this.provider.estimateGas({
159
- from: walletAddr,
197
+ from: wallet,
160
198
  to: tx.to,
161
199
  data: tx.data,
162
200
  value: tx.value
163
201
  });
202
+ }))).map(gasLimit => ({
203
+ executed: true,
204
+ succeeded: true,
205
+ gasLimit: ethers.ethers.BigNumber.from(gasLimit).toNumber(),
206
+ gasUsed: ethers.ethers.BigNumber.from(gasLimit).toNumber()
207
+ }));
208
+ }
209
+
210
+ async estimateGasLimits(config$1, context, ...transactions) {
211
+ const walletAddr = config.addressOf(config$1, context);
212
+ const results = await this.simulate(walletAddr, ...transactions);
213
+ return transactions.map((t, i) => _extends({}, t, {
214
+ gasLimit: results[i].gasLimit
164
215
  }));
165
- return transactions.map((t, i) => {
166
- t.gasLimit = gasCosts[i];
167
- return t;
168
- });
169
216
  }
170
217
 
171
218
  async getNonce(config$1, context, space, blockTag) {
@@ -273,18 +320,26 @@ class LocalRelayer extends ProviderRelayer {
273
320
  throw new Error('LocalRelayer requires the context.guestModule address');
274
321
  }
275
322
 
276
- const txRequest = await this.prepareTransactions(signedTxs.config, signedTxs.context, signedTxs.signature, ...signedTxs.transactions); // TODO: think about computing gas limit individually, summing together and passing across
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
277
329
  // NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
278
330
  // const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
279
331
  // txRequest.gasLimit = gasLimit
280
332
 
281
- return this.signer.sendTransaction(txRequest);
333
+ return this.signer.sendTransaction({
334
+ to,
335
+ data
336
+ });
282
337
  }
283
338
 
284
339
  }
285
340
 
286
341
  /* eslint-disable */
287
- // sequence-relayer v0.4.0 fc9652e2bc0c3df8d1ce0b4a8e24ab8790e4dae2
342
+ // sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
288
343
  // --
289
344
  // This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
290
345
  // Do not edit by hand. Update your webrpc schema and re-generate.
@@ -293,7 +348,7 @@ const WebRPCVersion = 'v1'; // Schema version of your RIDL schema
293
348
 
294
349
  const WebRPCSchemaVersion = 'v0.4.0'; // Schema hash generated from your RIDL schema
295
350
 
296
- const WebRPCSchemaHash = 'fc9652e2bc0c3df8d1ce0b4a8e24ab8790e4dae2'; //
351
+ const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'; //
297
352
  // Types
298
353
  //
299
354
 
@@ -425,6 +480,16 @@ class Relayer {
425
480
  });
426
481
  };
427
482
 
483
+ this.simulate = (args, headers) => {
484
+ return this.fetch(this.url('Simulate'), createHTTPRequest(args, headers)).then(res => {
485
+ return buildResponse(res).then(_data => {
486
+ return {
487
+ results: _data.results
488
+ };
489
+ });
490
+ });
491
+ };
492
+
428
493
  this.updateMetaTxnGasLimits = (args, headers) => {
429
494
  return this.fetch(this.url('UpdateMetaTxnGasLimits'), createHTTPRequest(args, headers)).then(res => {
430
495
  return buildResponse(res).then(_data => {
@@ -446,6 +511,16 @@ class Relayer {
446
511
  });
447
512
  };
448
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
+
449
524
  this.getMetaTxnNetworkFeeOptions = (args, headers) => {
450
525
  return this.fetch(this.url('GetMetaTxnNetworkFeeOptions'), createHTTPRequest(args, headers)).then(res => {
451
526
  return buildResponse(res).then(_data => {
@@ -565,6 +640,15 @@ class RpcRelayer extends BaseRelayer {
565
640
  return result;
566
641
  }
567
642
 
643
+ async simulate(wallet, ...transactions$1) {
644
+ const coder = ethers.ethers.utils.defaultAbiCoder;
645
+ const encoded = coder.encode([transactions.MetaTransactionsType], [transactions.sequenceTxAbiEncode(transactions$1)]);
646
+ return (await this.service.simulate({
647
+ wallet,
648
+ transactions: encoded
649
+ })).results;
650
+ }
651
+
568
652
  async estimateGasLimits(config$1, context, ...transactions$1) {
569
653
  utils.logger.info(`[rpc-relayer/estimateGasLimits] estimate gas limits request ${JSON.stringify(transactions$1)}`);
570
654
 
@@ -609,23 +693,39 @@ class RpcRelayer extends BaseRelayer {
609
693
  if (feeTokens.isFeeRequired) {
610
694
  const symbols = feeTokens.tokens.map(token => token.symbol).join(', ');
611
695
  utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`);
612
- const addr = config.addressOf(config$1, context);
613
- const prevNonce = transactions.readSequenceNonce(...transactions$1); // Set temporal nonce to simulate meta-txn
696
+ const wallet = config.addressOf(config$1, context);
697
+ let nonce = transactions.readSequenceNonce(...transactions$1);
698
+
699
+ if (nonce === undefined) {
700
+ nonce = await this.getNonce(config$1, context);
701
+ }
614
702
 
615
- if (prevNonce === undefined) {
616
- transactions$1 = transactions.appendNonce(transactions$1, await this.getNonce(config$1, context));
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');
617
706
  }
618
707
 
619
- const coder = ethers.ethers.utils.defaultAbiCoder;
620
- const encoded = coder.encode([transactions.MetaTransactionsType], [transactions.sequenceTxAbiEncode(transactions$1)]);
621
- const res = await this.service.getMetaTxnNetworkFeeOptions({
622
- walletConfig: _extends({}, config$1, {
623
- address: addr
624
- }),
625
- payload: encoded
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
626
726
  });
627
- utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(res.options)}`);
628
- return res.options;
727
+ utils.logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`);
728
+ return options;
629
729
  } else {
630
730
  utils.logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`);
631
731
  return [];
@@ -654,13 +754,18 @@ class RpcRelayer extends BaseRelayer {
654
754
  throw new Error('provider is not set');
655
755
  }
656
756
 
657
- const addr = config.addressOf(signedTxs.config, signedTxs.context);
658
- const prep = await this.prepareTransactions(signedTxs.config, signedTxs.context, signedTxs.signature, ...signedTxs.transactions);
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]);
659
764
  const metaTxn = await this.service.sendMetaTxn({
660
765
  call: {
661
- contract: prep.to,
662
- input: prep.data,
663
- walletAddress: addr
766
+ walletAddress,
767
+ contract,
768
+ input
664
769
  }
665
770
  });
666
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
- import { sequenceTxAbiEncode, readSequenceNonce, encodeNonce, computeMetaTxnHash, appendNonce, MetaTransactionsType, decodeNonce } from '@0xsequence/transactions';
5
- import { imageHash, addressOf, encodeSignature } from '@0xsequence/config';
3
+ import { sequenceTxAbiEncode, readSequenceNonce, encodeNonce, computeMetaTxnHash, MetaTransactionsType, appendNonce, decodeNonce } from '@0xsequence/transactions';
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 prepareTransactions(config, context, signature, ...transactions) {
62
- //, gasLimit?: ethers.BigNumberish }> {
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
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode([_extends({}, this.prepareWalletDeploy(config, context), {
76
- delegateCall: false,
77
- revertOnError: false,
78
- gasLimit: this.creationGasLimit,
79
- value: ethers.constants.Zero
80
- }), {
81
- delegateCall: false,
82
- revertOnError: true,
83
- gasLimit: ethers.constants.Zero,
84
- to: walletAddress,
85
- value: ethers.constants.Zero,
86
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(transactions), readSequenceNonce(...transactions), await encodedSignature])
87
- }]), 0, []])
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
- data: walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [sequenceTxAbiEncode(transactions), readSequenceNonce(...transactions), await encodedSignature])
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);
@@ -121,11 +160,10 @@ class ProviderRelayer extends BaseRelayer {
121
160
  this.fromBlockLog = opts.fromBlockLog;
122
161
  }
123
162
 
124
- async estimateGasLimits(config, context, ...transactions) {
163
+ async simulate(wallet, ...transactions) {
125
164
  var _this = this;
126
165
 
127
- const walletAddr = addressOf(config, context);
128
- const gasCosts = await Promise.all(transactions.map(async function (tx) {
166
+ return (await Promise.all(transactions.map(async function (tx) {
129
167
  // Respect gasLimit request of the transaction (as long as its not 0)
130
168
  if (tx.gasLimit && !ethers.BigNumber.from(tx.gasLimit || 0).eq(ethers.constants.Zero)) {
131
169
  return tx.gasLimit;
@@ -137,7 +175,7 @@ class ProviderRelayer extends BaseRelayer {
137
175
  } // Fee can't be estimated for self-called if wallet hasn't been deployed
138
176
 
139
177
 
140
- if (tx.to === walletAddr && !(await _this.isWalletDeployed(walletAddr))) {
178
+ if (tx.to === wallet && !(await _this.isWalletDeployed(wallet))) {
141
179
  return DEFAULT_GAS_LIMIT;
142
180
  }
143
181
 
@@ -148,16 +186,25 @@ class ProviderRelayer extends BaseRelayer {
148
186
 
149
187
 
150
188
  return _this.provider.estimateGas({
151
- from: walletAddr,
189
+ from: wallet,
152
190
  to: tx.to,
153
191
  data: tx.data,
154
192
  value: tx.value
155
193
  });
194
+ }))).map(gasLimit => ({
195
+ executed: true,
196
+ succeeded: true,
197
+ gasLimit: ethers.BigNumber.from(gasLimit).toNumber(),
198
+ gasUsed: ethers.BigNumber.from(gasLimit).toNumber()
199
+ }));
200
+ }
201
+
202
+ async estimateGasLimits(config, context, ...transactions) {
203
+ const walletAddr = addressOf(config, context);
204
+ const results = await this.simulate(walletAddr, ...transactions);
205
+ return transactions.map((t, i) => _extends({}, t, {
206
+ gasLimit: results[i].gasLimit
156
207
  }));
157
- return transactions.map((t, i) => {
158
- t.gasLimit = gasCosts[i];
159
- return t;
160
- });
161
208
  }
162
209
 
163
210
  async getNonce(config, context, space, blockTag) {
@@ -265,18 +312,26 @@ class LocalRelayer extends ProviderRelayer {
265
312
  throw new Error('LocalRelayer requires the context.guestModule address');
266
313
  }
267
314
 
268
- const txRequest = await this.prepareTransactions(signedTxs.config, signedTxs.context, signedTxs.signature, ...signedTxs.transactions); // TODO: think about computing gas limit individually, summing together and passing across
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
269
321
  // NOTE: we expect that all txns have set their gasLimit ahead of time through proper estimation
270
322
  // const gasLimit = signedTxs.transactions.reduce((sum, tx) => sum.add(tx.gasLimit), ethers.BigNumber.from(0))
271
323
  // txRequest.gasLimit = gasLimit
272
324
 
273
- return this.signer.sendTransaction(txRequest);
325
+ return this.signer.sendTransaction({
326
+ to,
327
+ data
328
+ });
274
329
  }
275
330
 
276
331
  }
277
332
 
278
333
  /* eslint-disable */
279
- // sequence-relayer v0.4.0 fc9652e2bc0c3df8d1ce0b4a8e24ab8790e4dae2
334
+ // sequence-relayer v0.4.0 7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd
280
335
  // --
281
336
  // This file has been generated by https://github.com/webrpc/webrpc using gen/typescript
282
337
  // Do not edit by hand. Update your webrpc schema and re-generate.
@@ -285,7 +340,7 @@ const WebRPCVersion = 'v1'; // Schema version of your RIDL schema
285
340
 
286
341
  const WebRPCSchemaVersion = 'v0.4.0'; // Schema hash generated from your RIDL schema
287
342
 
288
- const WebRPCSchemaHash = 'fc9652e2bc0c3df8d1ce0b4a8e24ab8790e4dae2'; //
343
+ const WebRPCSchemaHash = '7dbfaf5c04cf28e9259ff1a9bf3274c8d73be5dd'; //
289
344
  // Types
290
345
  //
291
346
 
@@ -417,6 +472,16 @@ class Relayer {
417
472
  });
418
473
  };
419
474
 
475
+ this.simulate = (args, headers) => {
476
+ return this.fetch(this.url('Simulate'), createHTTPRequest(args, headers)).then(res => {
477
+ return buildResponse(res).then(_data => {
478
+ return {
479
+ results: _data.results
480
+ };
481
+ });
482
+ });
483
+ };
484
+
420
485
  this.updateMetaTxnGasLimits = (args, headers) => {
421
486
  return this.fetch(this.url('UpdateMetaTxnGasLimits'), createHTTPRequest(args, headers)).then(res => {
422
487
  return buildResponse(res).then(_data => {
@@ -438,6 +503,16 @@ class Relayer {
438
503
  });
439
504
  };
440
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
+
441
516
  this.getMetaTxnNetworkFeeOptions = (args, headers) => {
442
517
  return this.fetch(this.url('GetMetaTxnNetworkFeeOptions'), createHTTPRequest(args, headers)).then(res => {
443
518
  return buildResponse(res).then(_data => {
@@ -557,6 +632,15 @@ class RpcRelayer extends BaseRelayer {
557
632
  return result;
558
633
  }
559
634
 
635
+ async simulate(wallet, ...transactions) {
636
+ const coder = ethers.utils.defaultAbiCoder;
637
+ const encoded = coder.encode([MetaTransactionsType], [sequenceTxAbiEncode(transactions)]);
638
+ return (await this.service.simulate({
639
+ wallet,
640
+ transactions: encoded
641
+ })).results;
642
+ }
643
+
560
644
  async estimateGasLimits(config, context, ...transactions) {
561
645
  logger.info(`[rpc-relayer/estimateGasLimits] estimate gas limits request ${JSON.stringify(transactions)}`);
562
646
 
@@ -601,23 +685,39 @@ class RpcRelayer extends BaseRelayer {
601
685
  if (feeTokens.isFeeRequired) {
602
686
  const symbols = feeTokens.tokens.map(token => token.symbol).join(', ');
603
687
  logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`);
604
- const addr = addressOf(config, context);
605
- const prevNonce = readSequenceNonce(...transactions); // Set temporal nonce to simulate meta-txn
688
+ const wallet = addressOf(config, context);
689
+ let nonce = readSequenceNonce(...transactions);
690
+
691
+ if (nonce === undefined) {
692
+ nonce = await this.getNonce(config, context);
693
+ }
606
694
 
607
- if (prevNonce === undefined) {
608
- transactions = appendNonce(transactions, await this.getNonce(config, context));
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');
609
698
  }
610
699
 
611
- const coder = ethers.utils.defaultAbiCoder;
612
- const encoded = coder.encode([MetaTransactionsType], [sequenceTxAbiEncode(transactions)]);
613
- const res = await this.service.getMetaTxnNetworkFeeOptions({
614
- walletConfig: _extends({}, config, {
615
- address: addr
616
- }),
617
- payload: encoded
700
+ const {
701
+ to,
702
+ execute
703
+ } = await this.prependWalletDeploy({
704
+ config,
705
+ context,
706
+ transactions,
707
+ nonce,
708
+ signature: buildStubSignature(this.provider, config)
709
+ });
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
618
718
  });
619
- logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(res.options)}`);
620
- return res.options;
719
+ logger.info(`[rpc-relayer/gasRefundOptions] got refund options ${JSON.stringify(options)}`);
720
+ return options;
621
721
  } else {
622
722
  logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`);
623
723
  return [];
@@ -646,13 +746,18 @@ class RpcRelayer extends BaseRelayer {
646
746
  throw new Error('provider is not set');
647
747
  }
648
748
 
649
- const addr = addressOf(signedTxs.config, signedTxs.context);
650
- const prep = await this.prepareTransactions(signedTxs.config, signedTxs.context, signedTxs.signature, ...signedTxs.transactions);
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]);
651
756
  const metaTxn = await this.service.sendMetaTxn({
652
757
  call: {
653
- contract: prep.to,
654
- input: prep.data,
655
- walletAddress: addr
758
+ walletAddress,
759
+ contract,
760
+ input
656
761
  }
657
762
  });
658
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;