@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.
- package/CHANGELOG.md +49 -0
- package/dist/0xsequence-relayer.cjs.dev.js +153 -48
- package/dist/0xsequence-relayer.cjs.prod.js +153 -48
- package/dist/0xsequence-relayer.esm.js +155 -50
- package/dist/declarations/src/base-relayer.d.ts +9 -1
- package/dist/declarations/src/index.d.ts +2 -0
- package/dist/declarations/src/provider-relayer.d.ts +2 -1
- package/dist/declarations/src/rpc-relayer/index.d.ts +2 -1
- package/dist/declarations/src/rpc-relayer/relayer.gen.d.ts +32 -1
- package/package.json +7 -7
- package/src/base-relayer.ts +38 -19
- package/src/index.ts +3 -0
- package/src/local-relayer.ts +11 -3
- package/src/provider-relayer.ts +19 -15
- package/src/rpc-relayer/index.ts +46 -28
- package/src/rpc-relayer/relayer.gen.ts +54 -2
|
@@ -4,6 +4,7 @@ import { WalletContext } from '@0xsequence/network';
|
|
|
4
4
|
import { WalletConfig } from '@0xsequence/config';
|
|
5
5
|
import { proto } from './rpc-relayer';
|
|
6
6
|
export interface Relayer {
|
|
7
|
+
simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]>;
|
|
7
8
|
estimateGasLimits(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<Transaction[]>;
|
|
8
9
|
gasRefundOptions(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<FeeOption[]>;
|
|
9
10
|
getNonce(config: WalletConfig, context: WalletContext, space?: ethers.BigNumberish, blockTag?: providers.BlockTag): Promise<ethers.BigNumberish>;
|
|
@@ -15,5 +16,6 @@ export * from './base-relayer';
|
|
|
15
16
|
export * from './provider-relayer';
|
|
16
17
|
export * from './rpc-relayer';
|
|
17
18
|
export { proto as RpcRelayerProto } from './rpc-relayer';
|
|
19
|
+
export declare type SimulateResult = proto.SimulateResult;
|
|
18
20
|
export declare type FeeOption = proto.FeeOption;
|
|
19
21
|
export declare function isRelayer(cand: any): cand is Relayer;
|
|
@@ -4,7 +4,7 @@ import { SignedTransactions, Transaction } from '@0xsequence/transactions';
|
|
|
4
4
|
import { WalletContext } from '@0xsequence/network';
|
|
5
5
|
import { WalletConfig } from '@0xsequence/config';
|
|
6
6
|
import { BaseRelayer, BaseRelayerOptions } from './base-relayer';
|
|
7
|
-
import { FeeOption, Relayer } from '.';
|
|
7
|
+
import { FeeOption, Relayer, SimulateResult } from '.';
|
|
8
8
|
import { Optionals, Mask } from '@0xsequence/utils';
|
|
9
9
|
export interface ProviderRelayerOptions extends BaseRelayerOptions {
|
|
10
10
|
provider: Provider;
|
|
@@ -22,6 +22,7 @@ export declare abstract class ProviderRelayer extends BaseRelayer implements Rel
|
|
|
22
22
|
constructor(options: ProviderRelayerOptions);
|
|
23
23
|
abstract gasRefundOptions(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<FeeOption[]>;
|
|
24
24
|
abstract relay(signedTxs: SignedTransactions): Promise<TransactionResponse>;
|
|
25
|
+
simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]>;
|
|
25
26
|
estimateGasLimits(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<Transaction[]>;
|
|
26
27
|
getNonce(config: WalletConfig, context: WalletContext, space?: ethers.BigNumberish, blockTag?: BlockTag): Promise<ethers.BigNumberish>;
|
|
27
28
|
wait(metaTxnId: string | SignedTransactions, timeout: number): Promise<providers.TransactionResponse & {
|
|
@@ -2,7 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers';
|
|
|
2
2
|
import { ethers } from 'ethers';
|
|
3
3
|
import { Transaction, SignedTransactions } from '@0xsequence/transactions';
|
|
4
4
|
import { BaseRelayer, BaseRelayerOptions } from '../base-relayer';
|
|
5
|
-
import { FeeOption, Relayer } from '..';
|
|
5
|
+
import { FeeOption, Relayer, SimulateResult } from '..';
|
|
6
6
|
import { WalletContext } from '@0xsequence/network';
|
|
7
7
|
import { WalletConfig } from '@0xsequence/config';
|
|
8
8
|
import * as proto from './relayer.gen';
|
|
@@ -15,6 +15,7 @@ export declare class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
15
15
|
private readonly service;
|
|
16
16
|
constructor(options: RpcRelayerOptions);
|
|
17
17
|
waitReceipt(metaTxnHash: string | SignedTransactions, wait?: number): Promise<proto.GetMetaTxnReceiptReturn>;
|
|
18
|
+
simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]>;
|
|
18
19
|
estimateGasLimits(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<Transaction[]>;
|
|
19
20
|
gasRefundOptions(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<FeeOption[]>;
|
|
20
21
|
getNonce(config: WalletConfig, context: WalletContext, space?: ethers.BigNumberish): Promise<ethers.BigNumberish>;
|
|
@@ -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",
|
|
@@ -79,6 +79,10 @@ export interface MetaTxnLog {
|
|
|
79
79
|
metaTxnID?: string;
|
|
80
80
|
txnStatus: ETHTxnStatus;
|
|
81
81
|
txnRevertReason: string;
|
|
82
|
+
requeues: number;
|
|
83
|
+
queuedAt: string;
|
|
84
|
+
sentAt: string;
|
|
85
|
+
minedAt: string;
|
|
82
86
|
target: string;
|
|
83
87
|
input: string;
|
|
84
88
|
txnArgs: {
|
|
@@ -145,6 +149,14 @@ export interface SentTransactionsFilter {
|
|
|
145
149
|
pending?: boolean;
|
|
146
150
|
failed?: boolean;
|
|
147
151
|
}
|
|
152
|
+
export interface SimulateResult {
|
|
153
|
+
executed: boolean;
|
|
154
|
+
succeeded: boolean;
|
|
155
|
+
result?: string;
|
|
156
|
+
reason?: string;
|
|
157
|
+
gasUsed: number;
|
|
158
|
+
gasLimit: number;
|
|
159
|
+
}
|
|
148
160
|
export interface FeeOption {
|
|
149
161
|
token: FeeToken;
|
|
150
162
|
to: string;
|
|
@@ -184,8 +196,10 @@ export interface Relayer {
|
|
|
184
196
|
sendMetaTxn(args: SendMetaTxnArgs, headers?: object): Promise<SendMetaTxnReturn>;
|
|
185
197
|
getMetaTxnNonce(args: GetMetaTxnNonceArgs, headers?: object): Promise<GetMetaTxnNonceReturn>;
|
|
186
198
|
getMetaTxnReceipt(args: GetMetaTxnReceiptArgs, headers?: object): Promise<GetMetaTxnReceiptReturn>;
|
|
199
|
+
simulate(args: SimulateArgs, headers?: object): Promise<SimulateReturn>;
|
|
187
200
|
updateMetaTxnGasLimits(args: UpdateMetaTxnGasLimitsArgs, headers?: object): Promise<UpdateMetaTxnGasLimitsReturn>;
|
|
188
201
|
feeTokens(headers?: object): Promise<FeeTokensReturn>;
|
|
202
|
+
feeOptions(args: FeeOptionsArgs, headers?: object): Promise<FeeOptionsReturn>;
|
|
189
203
|
getMetaTxnNetworkFeeOptions(args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object): Promise<GetMetaTxnNetworkFeeOptionsReturn>;
|
|
190
204
|
sentTransactions(args: SentTransactionsArgs, headers?: object): Promise<SentTransactionsReturn>;
|
|
191
205
|
pendingTransactions(args: PendingTransactionsArgs, headers?: object): Promise<PendingTransactionsReturn>;
|
|
@@ -235,6 +249,13 @@ export interface GetMetaTxnReceiptArgs {
|
|
|
235
249
|
export interface GetMetaTxnReceiptReturn {
|
|
236
250
|
receipt: MetaTxnReceipt;
|
|
237
251
|
}
|
|
252
|
+
export interface SimulateArgs {
|
|
253
|
+
wallet: string;
|
|
254
|
+
transactions: string;
|
|
255
|
+
}
|
|
256
|
+
export interface SimulateReturn {
|
|
257
|
+
results: Array<SimulateResult>;
|
|
258
|
+
}
|
|
238
259
|
export interface UpdateMetaTxnGasLimitsArgs {
|
|
239
260
|
walletAddress: string;
|
|
240
261
|
walletConfig: WalletConfig;
|
|
@@ -249,6 +270,14 @@ export interface FeeTokensReturn {
|
|
|
249
270
|
isFeeRequired: boolean;
|
|
250
271
|
tokens: Array<FeeToken>;
|
|
251
272
|
}
|
|
273
|
+
export interface FeeOptionsArgs {
|
|
274
|
+
wallet: string;
|
|
275
|
+
to: string;
|
|
276
|
+
data: string;
|
|
277
|
+
}
|
|
278
|
+
export interface FeeOptionsReturn {
|
|
279
|
+
options: Array<FeeOption>;
|
|
280
|
+
}
|
|
252
281
|
export interface GetMetaTxnNetworkFeeOptionsArgs {
|
|
253
282
|
walletConfig: WalletConfig;
|
|
254
283
|
payload: string;
|
|
@@ -285,8 +314,10 @@ export declare class Relayer implements Relayer {
|
|
|
285
314
|
sendMetaTxn: (args: SendMetaTxnArgs, headers?: object | undefined) => Promise<SendMetaTxnReturn>;
|
|
286
315
|
getMetaTxnNonce: (args: GetMetaTxnNonceArgs, headers?: object | undefined) => Promise<GetMetaTxnNonceReturn>;
|
|
287
316
|
getMetaTxnReceipt: (args: GetMetaTxnReceiptArgs, headers?: object | undefined) => Promise<GetMetaTxnReceiptReturn>;
|
|
317
|
+
simulate: (args: SimulateArgs, headers?: object | undefined) => Promise<SimulateReturn>;
|
|
288
318
|
updateMetaTxnGasLimits: (args: UpdateMetaTxnGasLimitsArgs, headers?: object | undefined) => Promise<UpdateMetaTxnGasLimitsReturn>;
|
|
289
319
|
feeTokens: (headers?: object | undefined) => Promise<FeeTokensReturn>;
|
|
320
|
+
feeOptions: (args: FeeOptionsArgs, headers?: object | undefined) => Promise<FeeOptionsReturn>;
|
|
290
321
|
getMetaTxnNetworkFeeOptions: (args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object | undefined) => Promise<GetMetaTxnNetworkFeeOptionsReturn>;
|
|
291
322
|
sentTransactions: (args: SentTransactionsArgs, headers?: object | undefined) => Promise<SentTransactionsReturn>;
|
|
292
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,12 +17,12 @@
|
|
|
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.
|
|
24
|
-
"@ethersproject/providers": "^5.5.
|
|
25
|
-
"ethers": "^5.5.
|
|
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
|
+
"@ethersproject/providers": "^5.5.1",
|
|
25
|
+
"ethers": "^5.5.2",
|
|
26
26
|
"fetch-ponyfill": "^7.1.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {},
|
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/index.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { WalletConfig } from '@0xsequence/config'
|
|
|
5
5
|
import { proto } from './rpc-relayer'
|
|
6
6
|
|
|
7
7
|
export interface Relayer {
|
|
8
|
+
// simulate returns the execution results for a list of transactions.
|
|
9
|
+
simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]>
|
|
8
10
|
|
|
9
11
|
// estimateGasLimits will estimate the gas utilization from the transaction
|
|
10
12
|
// before submission.
|
|
@@ -39,6 +41,7 @@ export * from './base-relayer'
|
|
|
39
41
|
export * from './provider-relayer'
|
|
40
42
|
export * from './rpc-relayer'
|
|
41
43
|
export { proto as RpcRelayerProto } from './rpc-relayer'
|
|
44
|
+
export type SimulateResult = proto.SimulateResult
|
|
42
45
|
export type FeeOption = proto.FeeOption
|
|
43
46
|
|
|
44
47
|
export function isRelayer(cand: any): cand is Relayer {
|
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/provider-relayer.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { computeMetaTxnHash, encodeNonce, SignedTransactions, Transaction } from
|
|
|
5
5
|
import { WalletContext } from '@0xsequence/network'
|
|
6
6
|
import { WalletConfig, addressOf } from '@0xsequence/config'
|
|
7
7
|
import { BaseRelayer, BaseRelayerOptions } from './base-relayer'
|
|
8
|
-
import { FeeOption, Relayer } from '.'
|
|
8
|
+
import { FeeOption, Relayer, SimulateResult } from '.'
|
|
9
9
|
import { Optionals, Mask } from '@0xsequence/utils'
|
|
10
10
|
|
|
11
11
|
const DEFAULT_GAS_LIMIT = ethers.BigNumber.from(800000)
|
|
@@ -45,14 +45,8 @@ export abstract class ProviderRelayer extends BaseRelayer implements Relayer {
|
|
|
45
45
|
abstract gasRefundOptions(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<FeeOption[]>
|
|
46
46
|
abstract relay(signedTxs: SignedTransactions): Promise<TransactionResponse>
|
|
47
47
|
|
|
48
|
-
async
|
|
49
|
-
|
|
50
|
-
context: WalletContext,
|
|
51
|
-
...transactions: Transaction[]
|
|
52
|
-
): Promise<Transaction[]> {
|
|
53
|
-
const walletAddr = addressOf(config, context)
|
|
54
|
-
|
|
55
|
-
const gasCosts = await Promise.all(transactions.map(async tx => {
|
|
48
|
+
async simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]> {
|
|
49
|
+
return (await Promise.all(transactions.map(async tx => {
|
|
56
50
|
// Respect gasLimit request of the transaction (as long as its not 0)
|
|
57
51
|
if (tx.gasLimit && !ethers.BigNumber.from(tx.gasLimit || 0).eq(ethers.constants.Zero)) {
|
|
58
52
|
return tx.gasLimit
|
|
@@ -64,7 +58,7 @@ export abstract class ProviderRelayer extends BaseRelayer implements Relayer {
|
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
// Fee can't be estimated for self-called if wallet hasn't been deployed
|
|
67
|
-
if (tx.to ===
|
|
61
|
+
if (tx.to === wallet && !(await this.isWalletDeployed(wallet))) {
|
|
68
62
|
return DEFAULT_GAS_LIMIT
|
|
69
63
|
}
|
|
70
64
|
|
|
@@ -75,17 +69,27 @@ export abstract class ProviderRelayer extends BaseRelayer implements Relayer {
|
|
|
75
69
|
// TODO: If the wallet address has been deployed, gas limits can be
|
|
76
70
|
// estimated with more accurately by using self-calls with the batch transactions one by one
|
|
77
71
|
return this.provider.estimateGas({
|
|
78
|
-
from:
|
|
72
|
+
from: wallet,
|
|
79
73
|
to: tx.to,
|
|
80
74
|
data: tx.data,
|
|
81
75
|
value: tx.value
|
|
82
76
|
})
|
|
77
|
+
}))).map(gasLimit => ({
|
|
78
|
+
executed: true,
|
|
79
|
+
succeeded: true,
|
|
80
|
+
gasLimit: ethers.BigNumber.from(gasLimit).toNumber(),
|
|
81
|
+
gasUsed: ethers.BigNumber.from(gasLimit).toNumber()
|
|
83
82
|
}))
|
|
83
|
+
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
async estimateGasLimits(
|
|
86
|
+
config: WalletConfig,
|
|
87
|
+
context: WalletContext,
|
|
88
|
+
...transactions: Transaction[]
|
|
89
|
+
): Promise<Transaction[]> {
|
|
90
|
+
const walletAddr = addressOf(config, context)
|
|
91
|
+
const results = await this.simulate(walletAddr, ...transactions)
|
|
92
|
+
return transactions.map((t, i) => ({ ...t, gasLimit: results[i].gasLimit }))
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
async getNonce(
|
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,
|
|
@@ -12,9 +13,9 @@ import {
|
|
|
12
13
|
decodeNonce
|
|
13
14
|
} from '@0xsequence/transactions'
|
|
14
15
|
import { BaseRelayer, BaseRelayerOptions } from '../base-relayer'
|
|
15
|
-
import { FeeOption, Relayer } from '..'
|
|
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
|
|
|
@@ -66,6 +67,12 @@ export class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
66
67
|
return result
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
async simulate(wallet: string, ...transactions: Transaction[]): Promise<SimulateResult[]> {
|
|
71
|
+
const coder = ethers.utils.defaultAbiCoder
|
|
72
|
+
const encoded = coder.encode([MetaTransactionsType], [sequenceTxAbiEncode(transactions)])
|
|
73
|
+
return (await this.service.simulate({ wallet, transactions: encoded })).results
|
|
74
|
+
}
|
|
75
|
+
|
|
69
76
|
async estimateGasLimits(config: WalletConfig, context: WalletContext, ...transactions: Transaction[]): Promise<Transaction[]> {
|
|
70
77
|
logger.info(`[rpc-relayer/estimateGasLimits] estimate gas limits request ${JSON.stringify(transactions)}`)
|
|
71
78
|
|
|
@@ -116,23 +123,37 @@ export class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
116
123
|
const symbols = feeTokens.tokens.map(token => token.symbol).join(', ')
|
|
117
124
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are required, accepted tokens are ${symbols}`)
|
|
118
125
|
|
|
119
|
-
const
|
|
120
|
-
|
|
126
|
+
const wallet = addressOf(config, context)
|
|
127
|
+
|
|
128
|
+
let nonce = readSequenceNonce(...transactions)
|
|
129
|
+
if (nonce === undefined) {
|
|
130
|
+
nonce = await this.getNonce(config, context)
|
|
131
|
+
}
|
|
121
132
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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')
|
|
125
136
|
}
|
|
126
137
|
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
const { to, execute } = await this.prependWalletDeploy({
|
|
139
|
+
config,
|
|
140
|
+
context,
|
|
141
|
+
transactions,
|
|
142
|
+
nonce,
|
|
143
|
+
signature: buildStubSignature(this.provider, config)
|
|
132
144
|
})
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
136
157
|
} else {
|
|
137
158
|
logger.info(`[rpc-relayer/gasRefundOptions] relayer fees are not required`)
|
|
138
159
|
return []
|
|
@@ -158,20 +179,17 @@ export class RpcRelayer extends BaseRelayer implements Relayer {
|
|
|
158
179
|
throw new Error('provider is not set')
|
|
159
180
|
}
|
|
160
181
|
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
walletAddress: addr
|
|
173
|
-
}
|
|
174
|
-
})
|
|
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 } })
|
|
175
193
|
|
|
176
194
|
logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn)}`)
|
|
177
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
|
|
@@ -105,6 +105,10 @@ export interface MetaTxnLog {
|
|
|
105
105
|
metaTxnID?: string
|
|
106
106
|
txnStatus: ETHTxnStatus
|
|
107
107
|
txnRevertReason: string
|
|
108
|
+
requeues: number
|
|
109
|
+
queuedAt: string
|
|
110
|
+
sentAt: string
|
|
111
|
+
minedAt: string
|
|
108
112
|
target: string
|
|
109
113
|
input: string
|
|
110
114
|
txnArgs: { [key: string]: any }
|
|
@@ -173,6 +177,15 @@ export interface SentTransactionsFilter {
|
|
|
173
177
|
failed?: boolean
|
|
174
178
|
}
|
|
175
179
|
|
|
180
|
+
export interface SimulateResult {
|
|
181
|
+
executed: boolean
|
|
182
|
+
succeeded: boolean
|
|
183
|
+
result?: string
|
|
184
|
+
reason?: string
|
|
185
|
+
gasUsed: number
|
|
186
|
+
gasLimit: number
|
|
187
|
+
}
|
|
188
|
+
|
|
176
189
|
export interface FeeOption {
|
|
177
190
|
token: FeeToken
|
|
178
191
|
to: string
|
|
@@ -216,8 +229,10 @@ export interface Relayer {
|
|
|
216
229
|
sendMetaTxn(args: SendMetaTxnArgs, headers?: object): Promise<SendMetaTxnReturn>
|
|
217
230
|
getMetaTxnNonce(args: GetMetaTxnNonceArgs, headers?: object): Promise<GetMetaTxnNonceReturn>
|
|
218
231
|
getMetaTxnReceipt(args: GetMetaTxnReceiptArgs, headers?: object): Promise<GetMetaTxnReceiptReturn>
|
|
232
|
+
simulate(args: SimulateArgs, headers?: object): Promise<SimulateReturn>
|
|
219
233
|
updateMetaTxnGasLimits(args: UpdateMetaTxnGasLimitsArgs, headers?: object): Promise<UpdateMetaTxnGasLimitsReturn>
|
|
220
234
|
feeTokens(headers?: object): Promise<FeeTokensReturn>
|
|
235
|
+
feeOptions(args: FeeOptionsArgs, headers?: object): Promise<FeeOptionsReturn>
|
|
221
236
|
getMetaTxnNetworkFeeOptions(args: GetMetaTxnNetworkFeeOptionsArgs, headers?: object): Promise<GetMetaTxnNetworkFeeOptionsReturn>
|
|
222
237
|
sentTransactions(args: SentTransactionsArgs, headers?: object): Promise<SentTransactionsReturn>
|
|
223
238
|
pendingTransactions(args: PendingTransactionsArgs, headers?: object): Promise<PendingTransactionsReturn>
|
|
@@ -271,6 +286,14 @@ export interface GetMetaTxnReceiptArgs {
|
|
|
271
286
|
export interface GetMetaTxnReceiptReturn {
|
|
272
287
|
receipt: MetaTxnReceipt
|
|
273
288
|
}
|
|
289
|
+
export interface SimulateArgs {
|
|
290
|
+
wallet: string
|
|
291
|
+
transactions: string
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface SimulateReturn {
|
|
295
|
+
results: Array<SimulateResult>
|
|
296
|
+
}
|
|
274
297
|
export interface UpdateMetaTxnGasLimitsArgs {
|
|
275
298
|
walletAddress: string
|
|
276
299
|
walletConfig: WalletConfig
|
|
@@ -286,6 +309,15 @@ export interface FeeTokensReturn {
|
|
|
286
309
|
isFeeRequired: boolean
|
|
287
310
|
tokens: Array<FeeToken>
|
|
288
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
|
+
}
|
|
289
321
|
export interface GetMetaTxnNetworkFeeOptionsArgs {
|
|
290
322
|
walletConfig: WalletConfig
|
|
291
323
|
payload: string
|
|
@@ -410,6 +442,16 @@ export class Relayer implements Relayer {
|
|
|
410
442
|
})
|
|
411
443
|
}
|
|
412
444
|
|
|
445
|
+
simulate = (args: SimulateArgs, headers?: object): Promise<SimulateReturn> => {
|
|
446
|
+
return this.fetch(this.url('Simulate'), createHTTPRequest(args, headers)).then(res => {
|
|
447
|
+
return buildResponse(res).then(_data => {
|
|
448
|
+
return {
|
|
449
|
+
results: <Array<SimulateResult>>_data.results
|
|
450
|
+
}
|
|
451
|
+
})
|
|
452
|
+
})
|
|
453
|
+
}
|
|
454
|
+
|
|
413
455
|
updateMetaTxnGasLimits = (args: UpdateMetaTxnGasLimitsArgs, headers?: object): Promise<UpdateMetaTxnGasLimitsReturn> => {
|
|
414
456
|
return this.fetch(this.url('UpdateMetaTxnGasLimits'), createHTTPRequest(args, headers)).then(res => {
|
|
415
457
|
return buildResponse(res).then(_data => {
|
|
@@ -431,6 +473,16 @@ export class Relayer implements Relayer {
|
|
|
431
473
|
})
|
|
432
474
|
}
|
|
433
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
|
+
|
|
434
486
|
getMetaTxnNetworkFeeOptions = (
|
|
435
487
|
args: GetMetaTxnNetworkFeeOptionsArgs,
|
|
436
488
|
headers?: object
|