Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Tx Information Type Tweaked to Allow for Get Tx From Hash to Return P… #234

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/core/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class Web3Client {
Future<TransactionInformation> getTransactionByHash(String transactionHash) {
return _makeRPCCall<Map<String, dynamic>>(
'eth_getTransactionByHash', [transactionHash])
.then((s) => TransactionInformation.fromMap(s));
.then((s) => TransactionInformation.returnFromTxHash(s));
}

/// Returns an receipt of a transaction based on its hash.
Expand Down
194 changes: 126 additions & 68 deletions lib/src/core/transaction_information.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,83 @@
part of 'package:web3dart/web3dart.dart';

class TransactionInformation {
TransactionInformation.fromMap(Map<String, dynamic> map)
: blockHash = map['blockHash'] as String,
blockNumber = map['blockNumber'] != null
? BlockNum.exact(int.parse(map['blockNumber'] as String))
: const BlockNum.pending(),
from = EthereumAddress.fromHex(map['from'] as String),
gas = int.parse(map['gas'] as String),
gasPrice = EtherAmount.inWei(BigInt.parse(map['gasPrice'] as String)),
hash = map['hash'] as String,
input = hexToBytes(map['input'] as String),
nonce = int.parse(map['nonce'] as String),
to = map['to'] != null

TransactionInformation({
this.blockHash,
required this.blockNumber,
required this.from,
required this.gas,
required this.gasPrice,
required this.hash,
required this.input,
required this.nonce,
this.to,
this.transactionIndex,
required this.value,
required this.r,
required this.s,
required this.v
});

TransactionInformation.noSignature({
required this.blockHash,
required this.blockNumber,
required this.from,
required this.gas,
required this.gasPrice,
required this.hash,
required this.input,
required this.nonce,
required this.to,
required this.transactionIndex,
required this.value
});

factory TransactionInformation.returnFromTxHash(Map<String, dynamic> map) {
return TransactionInformation.noSignature(
blockHash: map['blockHash'] as String,
blockNumber: map['blockNumber'] != null ? BlockNum.exact(
int.parse(map['blockNumber'] as String)) : const BlockNum.pending(),
from: EthereumAddress.fromHex(map['from'] as String),
gas: int.parse(map['gas'] as String),
gasPrice: EtherAmount.inWei(BigInt.parse(map['gasPrice'] as String)),
hash: map['hash'] as String,
input: hexToBytes(map['input'] as String),
nonce: int.parse(map['nonce'] as String),
to: map['to'] != null
? EthereumAddress.fromHex(map['to'] as String)
: null,
transactionIndex: map['transactionIndex'] != null ? int.parse(
map['transactionIndex'] as String) : null,
value: EtherAmount.inWei(BigInt.parse(map['value'] as String)),
// v: int.parse(map['v'] as String),
// r: hexToInt(map['r'] as String),
// s: hexToInt(map['s'] as String)
);
}

factory TransactionInformation.fromMap(Map<String, dynamic> map) {
return TransactionInformation(
blockHash: map['blockHash'] as String,
blockNumber: map['blockNumber'] != null ? BlockNum.exact(
int.parse(map['blockNumber'] as String)) : const BlockNum.pending(),
from: EthereumAddress.fromHex(map['from'] as String),
gas: int.parse(map['gas'] as String),
gasPrice: EtherAmount.inWei(BigInt.parse(map['gasPrice'] as String)),
hash: map['hash'] as String,
input: hexToBytes(map['input'] as String),
nonce: int.parse(map['nonce'] as String),
to: map['to'] != null
? EthereumAddress.fromHex(map['to'] as String)
: null,
transactionIndex = map['transactionIndex'] != null
? int.parse(map['transactionIndex'] as String)
: null,
value = EtherAmount.inWei(BigInt.parse(map['value'] as String)),
v = int.parse(map['v'] as String),
r = hexToInt(map['r'] as String),
s = hexToInt(map['s'] as String);

transactionIndex: map['transactionIndex'] != null ? int.parse(
map['transactionIndex'] as String) : null,
value: EtherAmount.inWei(BigInt.parse(map['value'] as String)),
v: int.parse(map['v'] as String),
r: hexToInt(map['r'] as String),
s: hexToInt(map['s'] as String)
);
}
/// The hash of the block containing this transaction. If this transaction has
/// not been mined yet and is thus in no block, it will be `null`
final String? blockHash;
Expand Down Expand Up @@ -63,13 +118,13 @@ class TransactionInformation {

/// A cryptographic recovery id which can be used to verify the authenticity
/// of this transaction together with the signature [r] and [s]
final int v;
late final int v;

/// ECDSA signature r
final BigInt r;
late final BigInt r;

/// ECDSA signature s
final BigInt s;
late final BigInt s;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should make these late to indicate that they can be absent.

Instead, we could add a superclass (say RawTransactionInformation) that doesn't contain the signature. getTransactionByHash would then return a future of that class.


/// The ECDSA full signature used to sign this transaction.
MsgSignature get signature => MsgSignature(r, s, v);
Expand All @@ -78,50 +133,53 @@ class TransactionInformation {
class TransactionReceipt {
TransactionReceipt(
{required this.transactionHash,
required this.transactionIndex,
required this.blockHash,
required this.cumulativeGasUsed,
this.blockNumber = const BlockNum.pending(),
this.contractAddress,
this.status,
this.from,
this.to,
this.gasUsed,
this.effectiveGasPrice,
this.logs = const []});

TransactionReceipt.fromMap(Map<String, dynamic> map)
: transactionHash = hexToBytes(map['transactionHash'] as String),
transactionIndex = hexToDartInt(map['transactionIndex'] as String),
blockHash = hexToBytes(map['blockHash'] as String),
blockNumber = map['blockNumber'] != null
required this.transactionIndex,
required this.blockHash,
required this.cumulativeGasUsed,
this.blockNumber = const BlockNum.pending(),
this.contractAddress,
this.status,
this.from,
this.to,
this.gasUsed,
this.effectiveGasPrice,
this.logs = const []});

factory TransactionReceipt.fromMap(Map<String, dynamic> map) {
return TransactionReceipt(
transactionHash: hexToBytes(map['transactionHash'] as String),
transactionIndex: hexToDartInt(map['transactionIndex'] as String),
blockHash: hexToBytes(map['blockHash'] as String),
blockNumber: map['blockNumber'] != null
? BlockNum.exact(int.parse(map['blockNumber'] as String))
: const BlockNum.pending(),
from = map['from'] != null
from: map['from'] != null
? EthereumAddress.fromHex(map['from'] as String)
: null,
to = map['to'] != null
to: map['to'] != null
? EthereumAddress.fromHex(map['to'] as String)
: null,
cumulativeGasUsed = hexToInt(map['cumulativeGasUsed'] as String),
gasUsed =
map['gasUsed'] != null ? hexToInt(map['gasUsed'] as String) : null,
effectiveGasPrice = map['effectiveGasPrice'] != null
cumulativeGasUsed: hexToInt(map['cumulativeGasUsed'] as String),
gasUsed:
map['gasUsed'] != null ? hexToInt(map['gasUsed'] as String) : null,
effectiveGasPrice: map['effectiveGasPrice'] != null
? EtherAmount.inWei(
BigInt.parse(map['effectiveGasPrice'] as String))
BigInt.parse(map['effectiveGasPrice'] as String))
: null,
contractAddress = map['contractAddress'] != null
contractAddress: map['contractAddress'] != null
? EthereumAddress.fromHex(map['contractAddress'] as String)
: null,
status = map['status'] != null
status: map['status'] != null
? (hexToDartInt(map['status'] as String) == 1)
: null,
logs = map['logs'] != null
logs: map['logs'] != null
? (map['logs'] as List<dynamic>)
.map((log) => FilterEvent.fromMap(log as Map<String, dynamic>))
.toList()
: [];

.map((log) => FilterEvent.fromMap(log as Map<String, dynamic>))
.toList()
: [
]
);
}
/// Hash of the transaction (32 bytes).
final Uint8List transactionHash;

Expand Down Expand Up @@ -173,20 +231,20 @@ class TransactionReceipt {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TransactionReceipt &&
runtimeType == other.runtimeType &&
const ListEquality().equals(transactionHash, other.transactionHash) &&
transactionIndex == other.transactionIndex &&
const ListEquality().equals(blockHash, other.blockHash) &&
blockNumber == other.blockNumber &&
from == other.from &&
to == other.to &&
cumulativeGasUsed == other.cumulativeGasUsed &&
gasUsed == other.gasUsed &&
contractAddress == other.contractAddress &&
status == other.status &&
effectiveGasPrice == other.effectiveGasPrice &&
const ListEquality().equals(logs, other.logs);
other is TransactionReceipt &&
runtimeType == other.runtimeType &&
const ListEquality().equals(transactionHash, other.transactionHash) &&
transactionIndex == other.transactionIndex &&
const ListEquality().equals(blockHash, other.blockHash) &&
blockNumber == other.blockNumber &&
from == other.from &&
to == other.to &&
cumulativeGasUsed == other.cumulativeGasUsed &&
gasUsed == other.gasUsed &&
contractAddress == other.contractAddress &&
status == other.status &&
effectiveGasPrice == other.effectiveGasPrice &&
const ListEquality().equals(logs, other.logs);

@override
int get hashCode =>
Expand Down