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

BlockInformation Type Port from Web3.js #232

Open
wants to merge 2 commits 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 analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ linter:
#- lines_longer_than_80_chars ignored because it's annoying for long literals in tests
- non_constant_identifier_names
- null_closures
- omit_local_variable_types
# - omit_local_variable_types
- one_member_abstracts
- only_throw_errors
- overridden_fields
Expand Down
115 changes: 109 additions & 6 deletions lib/src/core/block_information.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,120 @@
import 'package:web3dart/credentials.dart';
import 'package:web3dart/src/crypto/formatting.dart';
import 'package:web3dart/web3dart.dart';

class BlockInformation {
EtherAmount? baseFeePerGas;
final EthereumAddress? from; // Author
final String? boundary;
final String? difficulty;
final String? extraData;
final String? gasLimit;
final String? gasUsed;
final String? hash;
final String? logsBloom;
final EthereumAddress? miner;
final String? mixHash;
final String? nonce;
final EtherAmount? baseFeePerGas;
final String? number;
final String? parentHash;
final String? receiptsRoot;
final String? seedHash;
final String? sha3Uncles;
final String? size;
final String? stateRoot;
final String? timestamp;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should not rush to add all the info that eth_getBlockByNumber returns without carefully choosing an appropriate data type for each field. If we make them strings and then decide to change to int, it would be a breaking change.

If we do not have resources to choose carefully, we should add only the fields we are conscious about, like this timestamp which is definitely int and not null.

final String? totalDifficulty;
final List<TransactionInformation>? transactions;
final String? transactionsRoot;
final List<dynamic>? uncles;

BlockInformation({this.baseFeePerGas});
BlockInformation({
this.from,
this.boundary,
this.difficulty,
this.extraData,
this.gasLimit,
this.gasUsed,
this.hash,
this.logsBloom,
this.miner,
this.mixHash,
this.nonce,
this.baseFeePerGas,
this.number,
this.parentHash,
this.receiptsRoot,
this.seedHash,
this.sha3Uncles,
this.size,
this.stateRoot,
this.timestamp,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can timestamp be int safely?

Copy link
Owner

Choose a reason for hiding this comment

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

Yeah it should probably be a DateTime

this.totalDifficulty,
this.transactions,
this.transactionsRoot,
this.uncles,
});

factory BlockInformation.fromJson(Map<String, dynamic> json) {
final List<Map<String, dynamic>>? _list = List.castFrom(json['transactions'] as List<dynamic>);
List<TransactionInformation>? _transactions;
if (_list != null) {
_transactions = _list.map((Map<String, dynamic> e) => TransactionInformation.fromMap(e)).toList();
} else {
_transactions = null;
}

final EthereumAddress? _from = json.containsKey('author') ? EthereumAddress.fromHex(json['author'] as String) : null;
final String? _boundary = json.containsKey('boundary') ? json['boundary'] as String : null;
final String? _difficulty = json.containsKey('difficulty') ? json['difficulty'] as String : null;
final String? _extraData = json.containsKey('extraData') ? json['extraData'] as String : null;
final String? _gasLimit = json.containsKey('gasLimit') ? json['gasLimit'] as String : null;
final String? _gasUsed = json.containsKey('gasUsed') ? json['gasUsed'] as String : null;
final String? _hash = json.containsKey('hash') ? json['hash'] as String : null;
final String? _logsBloom = json.containsKey('logsBloom') ? json['logsBloom'] as String : null;
final EthereumAddress? _miner = json.containsKey('miner') ? EthereumAddress.fromHex(json['miner'] as String) : null;
final String? _mixHash = json.containsKey('mixHash') ? json['mixHash'] as String : null;
final String? _nonce = json.containsKey('nonce') ? json['nonce'] as String : null;
final EtherAmount? _baseFeePerGas = json.containsKey('baseFeePerGas') ? EtherAmount.fromUnitAndValue(EtherUnit.wei, hexToInt(json['baseFeePerGas'] as String)) : null;
final String? _number = json.containsKey('number') ? json['number'] as String : null;
final String? _parentHash = json.containsKey('parentHash') ? json['parentHash'] as String : null;
final String? _receiptsRoot = json.containsKey('receiptsRoot') ? json['receiptsRoot'] as String : null;
final String? _seedHash = json.containsKey('seedHash') ? json['seedHash'] as String : null;
final String? _sha3Uncles = json.containsKey('sha3Uncles') ? json['sha3Uncles'] as String : null;
final String? _size = json.containsKey('size') ? json['size'] as String : null;
final String? _stateRoot = json.containsKey('stateRoot') ? json['size'] as String : null;
final String? _timestamp = json.containsKey('timestamp') ? json['timestamp'] as String : null;
final String? _totalDifficulty = json.containsKey('totalDifficulty') ? json['totalDifficulty'] as String : null;
final String? _transactionsRoot = json.containsKey('transactionsRoot') ? json['transactionsRoot'] as String : null;
final List<dynamic>? _uncles = json.containsKey('uncles') ? json['uncles'] as List<dynamic> : null;


return BlockInformation(
baseFeePerGas: json.containsKey('baseFeePerGas')
? EtherAmount.fromUnitAndValue(
EtherUnit.wei, hexToInt(json['baseFeePerGas'] as String))
: null);
from: _from,
boundary: _boundary,
difficulty: _difficulty,
extraData: _extraData,
gasLimit: _gasLimit,
gasUsed: _gasUsed,
hash: _hash,
logsBloom: _logsBloom,
miner: _miner,
mixHash: _mixHash,
nonce: _nonce,
baseFeePerGas: _baseFeePerGas,
number: _number,
parentHash: _parentHash,
receiptsRoot: _receiptsRoot,
seedHash: _seedHash,
sha3Uncles: _sha3Uncles,
size: _size,
stateRoot: _stateRoot,
timestamp: _timestamp,
totalDifficulty: _totalDifficulty,
transactions: _transactions,
transactionsRoot: _transactionsRoot,
uncles: _uncles,
);
}

bool get isSupportEIP1559 => baseFeePerGas != null;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/core/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class Web3Client {
{String blockNumber = 'latest', bool isContainFullObj = true}) {
return _makeRPCCall<Map<String, dynamic>>(
'eth_getBlockByNumber', [blockNumber, isContainFullObj])
.then((json) => BlockInformation.fromJson(json));
.then((Map<String, dynamic> json) => BlockInformation.fromJson(json));
}

/// Gets the balance of the account with the specified address.
Expand Down
126 changes: 74 additions & 52 deletions lib/src/core/transaction_information.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
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
});

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 @@ -90,38 +109,41 @@ class TransactionReceipt {
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
? BlockNum.exact(int.parse(map['blockNumber'] as String))
: const BlockNum.pending(),
from = map['from'] != null
? EthereumAddress.fromHex(map['from'] as String)
: 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
? EtherAmount.inWei(
BigInt.parse(map['effectiveGasPrice'] as String))
: null,
contractAddress = map['contractAddress'] != null
? EthereumAddress.fromHex(map['contractAddress'] as String)
: null,
status = map['status'] != null
? (hexToDartInt(map['status'] as String) == 1)
: null,
logs = map['logs'] != null
? (map['logs'] as List<dynamic>)
.map((log) => FilterEvent.fromMap(log as Map<String, dynamic>))
.toList()
: [];

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
? EthereumAddress.fromHex(map['from'] as String)
: 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
? EtherAmount.inWei(
BigInt.parse(map['effectiveGasPrice'] as String))
: null,
contractAddress: map['contractAddress'] != null
? EthereumAddress.fromHex(map['contractAddress'] as String)
: null,
status: map['status'] != null
? (hexToDartInt(map['status'] as String) == 1)
: null,
logs: map['logs'] != null
? (map['logs'] as List<dynamic>)
.map((log) => FilterEvent.fromMap(log as Map<String, dynamic>))
.toList()
: [
]
);
}
/// Hash of the transaction (32 bytes).
final Uint8List transactionHash;

Expand Down