@@ -23,18 +23,23 @@ Future<_SigningInput> _fillMissingData({
23
23
24
24
final sender = transaction.from ?? await credentials.extractAddress ();
25
25
var gasPrice = transaction.gasPrice;
26
- var nonce = transaction.nonce;
27
- if (gasPrice == null || nonce == null ) {
28
- if (client == null ) {
29
- throw ArgumentError ("Can't find suitable gas price and nonce from client "
30
- 'because no client is set. Please specify a gas price on the '
31
- 'transaction.' );
32
- }
33
- gasPrice ?? = await client.getGasPrice ();
34
- nonce ?? = await client.getTransactionCount (sender,
35
- atBlock: const BlockNum .pending ());
26
+
27
+ if (client == null &&
28
+ (transaction.nonce == null ||
29
+ transaction.maxGas == null ||
30
+ loadChainIdFromNetwork) ||
31
+ (! transaction.isEIP1559 && gasPrice == null )) {
32
+ throw ArgumentError ('Client is required to perform network actions' );
33
+ }
34
+
35
+ if (! transaction.isEIP1559 && gasPrice == null ) {
36
+ gasPrice = await client! .getGasPrice ();
36
37
}
37
38
39
+ final nonce = transaction.nonce ??
40
+ await client!
41
+ .getTransactionCount (sender, atBlock: const BlockNum .pending ());
42
+
38
43
final maxGas = transaction.maxGas ??
39
44
await client!
40
45
.estimateGas (
@@ -43,6 +48,8 @@ Future<_SigningInput> _fillMissingData({
43
48
data: transaction.data,
44
49
value: transaction.value,
45
50
gasPrice: gasPrice,
51
+ maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,
52
+ maxFeePerGas: transaction.maxFeePerGas,
46
53
)
47
54
.then ((bigInt) => bigInt.toInt ());
48
55
@@ -60,12 +67,7 @@ Future<_SigningInput> _fillMissingData({
60
67
if (! loadChainIdFromNetwork) {
61
68
resolvedChainId = chainId! ;
62
69
} else {
63
- if (client == null ) {
64
- throw ArgumentError (
65
- "Can't load chain id from network when no client is set" );
66
- }
67
-
68
- resolvedChainId = await client.getNetworkId ();
70
+ resolvedChainId = await client! .getNetworkId ();
69
71
}
70
72
71
73
return _SigningInput (
@@ -75,8 +77,27 @@ Future<_SigningInput> _fillMissingData({
75
77
);
76
78
}
77
79
80
+ Uint8List prependTransactionType (int type, Uint8List transaction) {
81
+ return Uint8List (transaction.length + 1 )
82
+ ..[0 ] = type
83
+ ..setAll (1 , transaction);
84
+ }
85
+
78
86
Future <Uint8List > _signTransaction (
79
87
Transaction transaction, Credentials c, int ? chainId) async {
88
+ if (transaction.isEIP1559 && chainId != null ) {
89
+ final encodedTx = LengthTrackingByteSink ();
90
+ encodedTx.addByte (0x02 );
91
+ encodedTx.add (rlp
92
+ .encode (_encodeEIP1559ToRlp (transaction, null , BigInt .from (chainId))));
93
+
94
+ encodedTx.close ();
95
+ final signature = await c.signToSignature (encodedTx.asBytes (),
96
+ chainId: chainId, isEIP1559: transaction.isEIP1559);
97
+
98
+ return uint8ListFromList (rlp.encode (
99
+ _encodeEIP1559ToRlp (transaction, signature, BigInt .from (chainId))));
100
+ }
80
101
final innerSignature =
81
102
chainId == null ? null : MsgSignature (BigInt .zero, BigInt .zero, chainId);
82
103
@@ -87,6 +108,38 @@ Future<Uint8List> _signTransaction(
87
108
return uint8ListFromList (rlp.encode (_encodeToRlp (transaction, signature)));
88
109
}
89
110
111
+ List <dynamic > _encodeEIP1559ToRlp (
112
+ Transaction transaction, MsgSignature ? signature, BigInt chainId) {
113
+ final list = [
114
+ chainId,
115
+ transaction.nonce,
116
+ transaction.maxPriorityFeePerGas! .getInWei,
117
+ transaction.maxFeePerGas! .getInWei,
118
+ transaction.maxGas,
119
+ ];
120
+
121
+ if (transaction.to != null ) {
122
+ list.add (transaction.to! .addressBytes);
123
+ } else {
124
+ list.add ('' );
125
+ }
126
+
127
+ list
128
+ ..add (transaction.value? .getInWei)
129
+ ..add (transaction.data);
130
+
131
+ list.add ([]); // access list
132
+
133
+ if (signature != null ) {
134
+ list
135
+ ..add (signature.v)
136
+ ..add (signature.r)
137
+ ..add (signature.s);
138
+ }
139
+
140
+ return list;
141
+ }
142
+
90
143
List <dynamic > _encodeToRlp (Transaction transaction, MsgSignature ? signature) {
91
144
final list = [
92
145
transaction.nonce,
0 commit comments