diff --git a/lib/explorer.dart b/lib/explorer.dart index e183fba..406dd10 100644 --- a/lib/explorer.dart +++ b/lib/explorer.dart @@ -5,7 +5,6 @@ export 'src/network/explorer/explorer_api.dart' show ExplorerException, Home, - Network, NetworkStats, NodePool, Status, @@ -25,4 +24,5 @@ export 'src/network/explorer/explorer_api.dart' TallyTxn, ValueTransferInfo, PrioritiesEstimate, - PriorityEstimate; + PriorityEstimate, + Mempool; diff --git a/lib/src/network/explorer/explorer_api.dart b/lib/src/network/explorer/explorer_api.dart index f5b5626..8b244c4 100644 --- a/lib/src/network/explorer/explorer_api.dart +++ b/lib/src/network/explorer/explorer_api.dart @@ -455,38 +455,33 @@ class Status { required this.databaseLastConfirmed, required this.databaseLastUnconfirmed, required this.databaseMessage, - required this.nodePool, required this.nodePoolMessage, + required this.expectedEpoch, }); - final List databaseLastConfirmed; - final List databaseLastUnconfirmed; + final Map databaseLastConfirmed; + final Map databaseLastUnconfirmed; final String databaseMessage; - final NodePool nodePool; - final String nodePoolMessage; + final Map nodePoolMessage; + final int expectedEpoch; factory Status.fromRawJson(String str) => Status.fromJson(json.decode(str)); String toRawJson() => json.encode(jsonMap()); factory Status.fromJson(Map json) => Status( - databaseLastConfirmed: - List.from(json["database_last_confirmed"].map((x) => x)), - databaseLastUnconfirmed: - List.from(json["database_last_unconfirmed"].map((x) => x)), - databaseMessage: json["database_message"], - nodePool: NodePool.fromJson(json["node_pool"]), - nodePoolMessage: json["node_pool_message"], - ); + databaseLastConfirmed: json["database_confirmed"], + databaseLastUnconfirmed: json["database_unconfirmed"], + databaseMessage: json["database_message"], + nodePoolMessage: json["node_pool_message"], + expectedEpoch: json["expected_epoch"]); Map jsonMap() => { - "database_last_confirmed": - List.from(databaseLastConfirmed.map((x) => x)), - "database_last_unconfirmed": - List.from(databaseLastUnconfirmed.map((x) => x)), + "database_last_confirmed": databaseLastConfirmed, + "database_last_unconfirmed": databaseLastUnconfirmed, "database_message": databaseMessage, - "node_pool": nodePool.jsonMap(), "node_pool_message": nodePoolMessage, + "expected_epoch": expectedEpoch, }; void printDebug() { @@ -494,57 +489,11 @@ class Status { print('databaseLastConfirmed: $databaseLastConfirmed'); print('databaseLastUnconfirmed: $databaseLastUnconfirmed'); print('databaseMessage: $databaseMessage'); - print('nodePool: ${nodePool.toRawJson()}'); print('nodePoolMessage: $nodePoolMessage'); + print('expectedEpoch: $expectedEpoch'); } } -class Network { - Network({ - required this.lastUpdated, - required this.rollbacks, - required this.top100DrSolvers, - required this.top100Miners, - required this.uniqueDrSolvers, - required this.uniqueMiners, - }); - - final int lastUpdated; - final List rollbacks; - final List top100DrSolvers; - final List top100Miners; - final int uniqueDrSolvers; - final int uniqueMiners; - - factory Network.fromRawJson(String str) => Network.fromJson(json.decode(str)); - - String toRawJson() => json.encode(jsonMap()); - - factory Network.fromJson(Map json) => Network( - lastUpdated: json["last_updated"], - rollbacks: List.from( - json["rollbacks"].map((rollback) => RollBack.fromList(rollback))), - top100DrSolvers: List.from(json["top_100_dr_solvers"] - .map((drSolver) => DrSolver.fromList(drSolver))), - top100Miners: List.from( - json["top_100_miners"].map((miner) => Miner.fromList(miner))), - uniqueDrSolvers: json["unique_dr_solvers"], - uniqueMiners: json["unique_miners"], - ); - - Map jsonMap() => { - "last_updated": lastUpdated, - "rollbacks": - List.from(rollbacks.map((rollback) => rollback.toList())), - "top_100_dr_solvers": List.from( - top100DrSolvers.map((drSolver) => drSolver.toList())), - "top_100_miners": - List.from(top100Miners.map((miner) => miner.toList())), - "unique_dr_solvers": uniqueDrSolvers, - "unique_miners": uniqueMiners, - }; -} - class DrSolver { PublicKeyHash pkh; int count; @@ -648,6 +597,127 @@ class NetworkStats { }; } +class NetworkBalances { + NetworkBalances({ + required this.balances, + required this.totalItems, + required this.totalBalancesSum, + required this.lastUpdated, + }); + + final List balances; + final int totalItems; + final int totalBalancesSum; + final int lastUpdated; + + factory NetworkBalances.fromRawJson(String str) => + NetworkBalances.fromJson(json.decode(str)); + + String toRawJson() => json.encode(jsonMap()); + + factory NetworkBalances.fromJson(Map json) => + NetworkBalances( + balances: json["balances"].map((e) => Balance.fromJson(e)), + totalItems: json["totalItems"], + totalBalancesSum: json["totalBalancesSum"], + lastUpdated: json["lastUpdated"], + ); + + Map jsonMap() => { + "balances": balances.map((e) => e.jsonMap()), + "total_items": totalItems, + "total_balances_sum": totalBalancesSum, + "lastUpdated": lastUpdated, + }; +} + +class Balance { + Balance({ + required this.address, + required this.balance, + required this.level, + }); + + final String address; + final int balance; + final String level; + + factory Balance.fromRawJson(String str) => Balance.fromJson(json.decode(str)); + + String toRawJson() => json.encode(jsonMap()); + + factory Balance.fromJson(Map json) => Balance( + address: json["address"], + balance: json["balance"], + level: json["level"], + ); + + Map jsonMap() => { + "address": address, + "balance": balance, + "level": level, + }; +} + +class NetworkReputation { + NetworkReputation({ + required this.reputations, + required this.totalReputation, + required this.lastUpdated, + }); + + final List reputations; + final int totalReputation; + final int lastUpdated; + + factory NetworkReputation.fromRawJson(String str) => + NetworkReputation.fromJson(json.decode(str)); + + String toRawJson() => json.encode(jsonMap()); + + factory NetworkReputation.fromJson(Map json) => + NetworkReputation( + reputations: json["reputation"].map((e) => Reputation.fromJson(e)), + totalReputation: json["total_reputation"], + lastUpdated: json["last_updated"], + ); + + Map jsonMap() => { + "reputations": reputations.map((e) => e.jsonMap()), + "total_reputation": totalReputation, + "last_updated": lastUpdated, + }; +} + +class Reputation { + Reputation({ + required this.address, + required this.reputation, + required this.eligibility, + }); + + final String address; + final int reputation; + final int eligibility; + + factory Reputation.fromRawJson(String str) => + Reputation.fromJson(json.decode(str)); + + String toRawJson() => json.encode(jsonMap()); + + factory Reputation.fromJson(Map json) => Reputation( + address: json["address"], + reputation: json["reputation"], + eligibility: json["eligility"], + ); + + Map jsonMap() => { + "address": address, + "reputation": reputation, + "eligibility": eligibility, + }; +} + class SupplyInfo { SupplyInfo({ required this.blocksMinted, @@ -767,45 +837,24 @@ class AddressBlocks { AddressBlocks({ required this.address, required this.blocks, - required this.numBlocksMinted, - required this.type, }); String address; List blocks; - int numBlocksMinted; - String type; - factory AddressBlocks.fromJson(Map data) { + factory AddressBlocks.fromJson(List> data) { return AddressBlocks( - address: data['address'], - blocks: List.from( - data['blocks'].map((blockInfo) => BlockInfo.fromList(blockInfo))), - numBlocksMinted: data['num_blocks_minted'] ?? 0, - type: data['type'] ?? ''); + address: data[0]['address'], + blocks: List.from( + data.map((blockInfo) => BlockInfo.fromJson(blockInfo))), + ); } Map jsonMap() { List blocksMined = blocks; return { 'address': address, - 'blocks': blocksMined - .map((e) => [ - e.blockID, - e.timestamp, - e.epoch, - e.reward, - e.fees, - e.valueTransferCount, - e.dataRequestCount, - e.commitCount, - e.revealCount, - e.tallyCount, - e.reverted - ].toList()) - .toList(), - 'numBlocksMinted': numBlocksMinted, - 'type': type, + 'blocks': blocksMined.map((e) => e.jsonMap()).toList(), }; } } @@ -855,14 +904,10 @@ class AddressDataRequestsSolved { AddressDataRequestsSolved({ required this.address, required this.dataRequestsSolved, - required this.numDataRequestsSolved, - required this.type, }); final String address; final List dataRequestsSolved; - final int numDataRequestsSolved; - final String type; factory AddressDataRequestsSolved.fromRawJson(String str) => AddressDataRequestsSolved.fromJson(json.decode(str)); @@ -874,43 +919,25 @@ class AddressDataRequestsSolved { address: json["address"], dataRequestsSolved: List.from( json["data_requests_solved"] - .map((dr) => DataRequestSolvedInfo.fromList(dr))), - numDataRequestsSolved: json["num_data_requests_solved"] ?? 0, - type: json["type"] ?? '', + .map((dr) => DataRequestSolvedInfo.fromJson(dr))), ); } Map toJson() => { "address": address, - "data_requests_solved": dataRequestsSolved - .map((e) => [ - e.success, - e.transactionID, - e.timestamp, - e.collateral, - e.epoch, - e.result, - e.error, - e.liar, - ].toList()) - .toList(), - "num_data_requests_solved": numDataRequestsSolved, - "type": type, + "data_requests_solved": + dataRequestsSolved.map((e) => e.jsonMap()).toList().toList(), }; } class AddressValueTransfers { AddressValueTransfers({ required this.address, - required this.numValueTransfers, - required this.type, - required this.transactionHashes, + required this.addressValueTransfers, }); final String address; - final int numValueTransfers; - final String type; - final List transactionHashes; + final List addressValueTransfers; factory AddressValueTransfers.fromRawJson(String str) => AddressValueTransfers.fromJson(json.decode(str)); @@ -920,17 +947,79 @@ class AddressValueTransfers { factory AddressValueTransfers.fromJson(Map json) => AddressValueTransfers( address: json["address"], - numValueTransfers: json["num_value_transfers"], - type: json["type"], - transactionHashes: - List.from(json["value_transfers"].map((x) => x[1])), + addressValueTransfers: List.from(json["value_transfers"] + .map((x) => AddressValueTransferInfo.fromJson(x))), ); Map jsonMap() => { "address": address, - "num_value_transfers": numValueTransfers, - "type": type, - "transaction_hashes": transactionHashes, + "address_value_transfers": addressValueTransfers, + }; +} + +class AddressValueTransferInfo { + AddressValueTransferInfo({ + required this.epoch, + required this.timestamp, + required this.hash, + required this.direction, + required this.inputAddresses, + required this.outputAddresses, + required this.value, + required this.fee, + required this.weight, + required this.priority, + required this.locked, + required this.confirmed, + }); + + final int epoch; + final int timestamp; + final String hash; + final String direction; + final List inputAddresses; + final List outputAddresses; + final int value; + final int fee; + final int weight; + final int priority; + final bool locked; + final bool confirmed; + + factory AddressValueTransferInfo.fromRawJson(String str) => + AddressValueTransferInfo.fromJson(json.decode(str)); + + String toRawJson() => json.encode(jsonMap()); + + factory AddressValueTransferInfo.fromJson(Map json) => + AddressValueTransferInfo( + epoch: json["epoch"], + timestamp: json["timestamp"], + hash: json["hash"], + direction: json["direction"], // in, out, sel, + inputAddresses: json["inputAddresses"], + outputAddresses: json["outputAddresses"], + value: json["value"], + fee: json["fee"], + weight: json["weight"], + priority: json["priority"], + locked: json["locked"], + confirmed: json["confirmed"], + ); + + Map jsonMap() => { + "epoch": epoch, + "timestamp": timestamp, + "hash": hash, + "direction": direction, // in, out, sel, + "input_addresses": inputAddresses, + "output_addresses": outputAddresses, + "value": value, + "fee": fee, + "weight": weight, + "priority": priority, + "locked": locked, + "confirmed": confirmed, }; } @@ -988,18 +1077,18 @@ class AddressInfo { class MintInfo { MintInfo({ + required this.miner, required this.blockHash, required this.outputs, - required this.status, required this.txnEpoch, required this.txnHash, required this.txnTime, required this.type, }); + final String miner; final String blockHash; final List outputs; - final String status; final int txnEpoch; final String txnHash; final int txnTime; @@ -1010,25 +1099,37 @@ class MintInfo { String rawJson() => json.encode(jsonMap()); - factory MintInfo.fromJson(Map json) => MintInfo( - blockHash: json["block_hash"], - outputs: List.from(json["mint_outputs"].map((x) => - ValueTransferOutput( - pkh: Address.fromAddress(x[0]).publicKeyHash!, - timeLock: 0, - value: x[1]))), - status: json["status"], - txnEpoch: json["txn_epoch"], - txnHash: json["txn_hash"], - txnTime: json["txn_time"], - type: json["type"], + factory MintInfo.fromJson(Map json) { + var outputAddresses = json["output_addresses"]; + var outputValues = json["output_values"]; + + List outputs = []; + for (int i = 0; i < outputAddresses.length; i++) { + ValueTransferOutput vto = ValueTransferOutput( + value: outputValues[i], + pkh: Address.fromAddress(outputAddresses[i]).publicKeyHash!, + // fixme: the explorer should return some value + timeLock: 0, ); + outputs.add(vto); + } + + return MintInfo( + miner: json["miner"], + blockHash: json["block_hash"], + outputs: outputs, + txnEpoch: json["txn_epoch"], + txnHash: json["txn_hash"], + txnTime: json["txn_time"], + type: json["type"], + ); + } Map jsonMap() => { + "miner": miner, "block_hash": blockHash, "mint_outputs": List>.from(outputs.map((x) => x.jsonMap())), - "status": status, "txn_epoch": txnEpoch, "txn_hash": txnHash, "txn_time": txnTime, @@ -1037,9 +1138,9 @@ class MintInfo { void printDebug() { print('Mint Info'); + print('miner: $miner'); print('block_hash: $blockHash'); print('mint_outputs: $outputs'); - print('status: $status'); print('txn_epoch: $txnEpoch'); print('txn_hash: $txnHash'); print('txn_time: $txnTime'); @@ -1078,118 +1179,58 @@ class InputUtxo { class ValueTransferInfo extends HashInfo { ValueTransferInfo({ - required this.blockHash, + required this.epoch, + required this.timestamp, + required this.hash, + required this.inputAddresses, + required this.outputAddresses, + required this.value, required this.fee, - required this.inputs, - required this.outputs, - required this.priority, - required this.status, - required this.txnEpoch, - required this.txnHash, - required this.txnTime, - required this.type, required this.weight, + required this.priority, }) : super( - txnHash: txnHash, - status: status, - type: type, - txnTime: txnTime, - blockHash: blockHash); + txnHash: hash, + // TODO: fix + status: "status", + // TODO: fix + type: "type", + txnTime: epoch, + blockHash: null); - final String? blockHash; + final int epoch; + final int timestamp; + final String hash; + final List inputAddresses; + final List outputAddresses; + final int value; final int fee; - final List inputs; - final List outputs; - final int priority; - String status; - final int? txnEpoch; - final String txnHash; - final int txnTime; - final String type; final int weight; + final int priority; factory ValueTransferInfo.fromJson(Map data) { - List inputs = []; - List outputs = []; - List inputAddresses = data['input_addresses'] ?? []; - List outputAddresses = data['output_addresses'] ?? []; - Map? inputUxtos = data['input_utxos']; - inputAddresses.forEach((element) { - if (inputUxtos != null && inputUxtos.containsKey(element[0])) { - var _sub = inputUxtos[element[0]]!.first; - - String outputPointer = '${_sub[1]}:${_sub[2]}'; - - inputs.add( - InputUtxo( - address: element[0] as String, - input: - Input(outputPointer: OutputPointer.fromString(outputPointer)), - value: element[1] as int, - ), - ); - } - }); - - outputAddresses.forEach((element) { - Address address = Address.fromAddress(element[0]); - - outputs.add(ValueTransferOutput( - pkh: address.publicKeyHash!, - timeLock: element[2], - value: element[1])); - }); return ValueTransferInfo( - blockHash: data["block_hash"], - fee: data["fee"] ?? 0, - priority: data["priority"] ?? 0, - status: data["status"], - txnEpoch: data["txn_epoch"], - txnHash: data["txn_hash"] ?? '', - txnTime: data["txn_time"] ?? 0, - type: data["type"], - weight: data["weight"] ?? 0, - inputs: inputs, - outputs: outputs, - ); + epoch: data["epoch"], + timestamp: data["timestamp"], + hash: data["hash"], + inputAddresses: data["input_addresses"], + outputAddresses: data["output_addresses"], + value: data["value"], + fee: data["fee"], + weight: data["weight"], + priority: data["priority"]); } factory ValueTransferInfo.fromDbJson(Map data) { - List inputs = []; - List outputs = []; - List out = data['outputs']; - List inp = data['inputs']; - inp.forEach((element) { - inputs.add( - InputUtxo( - address: element['pkh'], - input: Input( - outputPointer: - OutputPointer.fromString(element['output_pointer'])), - value: element['value'], - ), - ); - }); - out.forEach((element) { - outputs.add(ValueTransferOutput( - pkh: PublicKeyHash.fromAddress(element['pkh']), - timeLock: element['time_lock'], - value: element['value'], - )); - }); - return ValueTransferInfo( - blockHash: data["block_hash"], + epoch: data["epoch"], + timestamp: data["timestamp"], + hash: data["hash"], + inputAddresses: data["input_addresses"], + outputAddresses: data["output_addresses"], + value: data["value"], fee: data["fee"], - priority: data["priority"], - status: data["status"], - txnEpoch: data["txn_epoch"], - txnHash: data["txn_hash"], - txnTime: data["txn_time"], - type: 'value_transfer', weight: data["weight"], - inputs: inputs, - outputs: outputs, + priority: data["priority"], ); } @@ -1197,49 +1238,46 @@ class ValueTransferInfo extends HashInfo { Map jsonMap() { return { - "block_hash": blockHash, - "fee": fee, - "priority": priority, - "status": status, - "txn_epoch": txnEpoch, - "txn_hash": txnHash, - "txn_time": txnTime, - "weight": weight, - "inputs": List>.from(inputs.map((e) => e.jsonMap())), - "outputs": - List>.from(outputs.map((e) => e.jsonMap())), + "epoch": epoch, + 'timestamp': timestamp, + 'hash': hash, + 'input_addresses': inputAddresses, + 'output_addresses': outputAddresses, + 'value': value, + 'fee': fee, + 'weight': weight, + 'priority': priority, }; } void printDebug() { print('ValueTransferInfo:'); - - print('blockHash: $blockHash'); - print('txnHash: $txnHash'); - print('txnEpoch: $txnEpoch'); - print('txnTime: ${DateTime.fromMillisecondsSinceEpoch(txnTime * 1000)}'); - print('status: $status'); - print('fee: $fee'); - print('priority: $priority'); - print('Inputs:'); - inputs.forEach((element) { + print("epoch: $epoch"); + print('timestamp: $timestamp'); + print('hash: $hash'); + print('inputAddresses:'); + inputAddresses.forEach((element) { print(element); }); - print('Outputs:'); - outputs.forEach((element) { - print(element.rawJson); + print('outputAddresses:'); + outputAddresses.forEach((element) { + print(element); }); + print('value: $value'); + print('fee: $fee'); + print('weight: $weight'); + print('priority: $priority'); } bool containsAddress(String address) { bool isInTrx = false; - inputs.forEach((input) { - if (input.address == address) { + inputAddresses.forEach((input) { + if (input == address) { isInTrx = true; } }); - outputs.forEach((output) { - if (output.pkh.address == address) { + outputAddresses.forEach((output) { + if (output == address) { isInTrx = true; } }); @@ -1249,7 +1287,7 @@ class ValueTransferInfo extends HashInfo { class BlockInfo { BlockInfo({ - required this.blockID, + required this.hash, required this.timestamp, required this.epoch, required this.reward, @@ -1259,10 +1297,11 @@ class BlockInfo { required this.commitCount, required this.revealCount, required this.tallyCount, - required this.reverted, + required this.confirmed, + required this.miner, }); - final String blockID; + final String hash; final int timestamp; final int epoch; final int reward; @@ -1272,37 +1311,40 @@ class BlockInfo { final int commitCount; final int revealCount; final int tallyCount; - final bool reverted; + final bool confirmed; + final String miner; - factory BlockInfo.fromList(List data) { + factory BlockInfo.fromJson(Map data) { return BlockInfo( - blockID: data[0], - timestamp: data[1], - epoch: data[2], - reward: data[3], - fees: data[4], - valueTransferCount: data[5], - dataRequestCount: data[6], - commitCount: data[7], - revealCount: data[8], - tallyCount: data[9], - reverted: data[10], + hash: data["hash"], + timestamp: data["timestamp"], + epoch: data["epoch"], + reward: data["block_reward"], + fees: data["block_fees"], + valueTransferCount: data["value_transfers"], + dataRequestCount: data["data_requests"], + commitCount: data["commits"], + revealCount: data["reveals"], + tallyCount: data["tallies"], + confirmed: data["confirmed"], + miner: data["miner"], ); } - List toList() { - return [ - blockID, - timestamp, - epoch, - reward, - fees, - valueTransferCount, - commitCount, - revealCount, - tallyCount - ]; - } + Map jsonMap() => { + 'hash': hash, + 'timestamp': timestamp, + 'epoch': epoch, + 'block_reward': reward, + 'block_fees': fees, + 'value_transfers': valueTransferCount, + 'data_requests': dataRequestCount, + 'commits': commitCount, + 'reveals': revealCount, + 'tallies': tallyCount, + 'confirmed': confirmed, + 'miner': miner, + }; } class BlockDetails { @@ -1314,23 +1356,23 @@ class BlockDetails { required this.vtWeight, required this.blockWeight, required this.confirmed, - required this.status, + required this.reverted, required this.mintInfo, }); - final String blockHash; final int epoch; final int timestamp; + final String blockHash; final int drWeight; final int vtWeight; final int blockWeight; final bool confirmed; - final String status; + final bool reverted; final MintInfo mintInfo; factory BlockDetails.fromJson(Map json) { - Map mint_txn = json["mint_txn"]; - String mintHash = mint_txn["txn_hash"]; + Map mint_txn = json["transactions"]["mint"]; + String mintHash = mint_txn["hash"]; List outputs = []; for (int i = 0; i < mint_txn['output_addresses'].length; i++) { @@ -1343,23 +1385,23 @@ class BlockDetails { } MintInfo mintInfo = MintInfo( - blockHash: json["details"]["block_hash"], + miner: json["details"]["miner"], + blockHash: json["details"]["hash"], outputs: outputs, - status: json["details"]["status"], txnEpoch: json["details"]["epoch"], txnHash: mintHash, txnTime: json["details"]["time"], type: "mint"); return BlockDetails( - blockHash: json["details"]["block_hash"], + blockHash: json["details"]["hash"], epoch: json["details"]["epoch"], timestamp: json["details"]["time"], - drWeight: json["details"]["dr_weight"], - vtWeight: json["details"]["vt_weight"], - blockWeight: json["details"]["block_weight"], + drWeight: json["details"]["data_request_weight"], + vtWeight: json["details"]["value_transfer_weight"], + blockWeight: json["details"]["weight"], confirmed: json["details"]["confirmed"], - status: json["details"]["status"], + reverted: json["details"]["reverted"], mintInfo: mintInfo, ); } @@ -1368,64 +1410,57 @@ class BlockDetails { class DataRequestSolvedInfo { DataRequestSolvedInfo( {required this.success, - required this.transactionID, + required this.hash, + required this.epoch, required this.timestamp, required this.collateral, - required this.epoch, - required this.result, + required this.witnessReward, + required this.reveal, required this.error, required this.liar}); final String success; - final String transactionID; + final String hash; + final int epoch; final int timestamp; final int collateral; - final int epoch; - final int result; + final int witnessReward; + final String reveal; final String error; final String liar; - factory DataRequestSolvedInfo.fromList(List data) { + factory DataRequestSolvedInfo.fromJson(Map data) { return DataRequestSolvedInfo( - success: data[0].toString(), - transactionID: data[1].toString(), - timestamp: data[2], - collateral: data[3], - epoch: data[4], - result: data[5], - error: data[6].toString(), - liar: data[7].toString()); - } - - List tolist() { - return [ - success, - transactionID, - timestamp, - collateral, - epoch, - result, - error, - liar - ]; + success: data['success'], + hash: data["hash"], + epoch: data['epoch'], + timestamp: data['timestamp'], + collateral: data['collateral'], + witnessReward: data['witness_reward'], + reveal: data['reveal'], + error: data['error'], + liar: data['liar']); } Map jsonMap() => { 'success': success, - 'transactionID': transactionID, + 'hash': hash, 'timestamp': timestamp, 'collateral': collateral, 'epoch': epoch, - 'result': result, + 'witnessReward': witnessReward, + 'reveal': reveal, 'error': error, 'liar': liar, }; void printDebug() { - print('transactionID: $transactionID'); + print('transactionID: $hash'); print('timestamp: $timestamp'); print('collateral: $collateral'); print('error: $error'); + print('witnessReward: $witnessReward'); + print('reveal: $reveal'); print('liar $liar'); print('success: $success'); } @@ -1473,13 +1508,14 @@ class Tapi { class TapiInfo { TapiInfo({ - required this.accept, + required this.activated, required this.active, required this.bit, required this.currentEpoch, required this.description, + required this.finished, required this.globalAcceptanceRate, - required this.previousEpoch, + required this.lastUpdated, required this.rates, required this.relativeAcceptanceRate, required this.startEpoch, @@ -1491,13 +1527,14 @@ class TapiInfo { required this.urls, }); - final List accept; + final List activated; final bool active; final int bit; final int currentEpoch; final String description; + final bool finished; final double globalAcceptanceRate; - final int previousEpoch; + final int lastUpdated; final List rates; final double relativeAcceptanceRate; final int startEpoch; @@ -1514,13 +1551,14 @@ class TapiInfo { String toRawJson() => json.encode(jsonMap()); factory TapiInfo.fromJson(Map json) => TapiInfo( - accept: List.from(json["accept"].map((x) => x)), + activated: json["activated"], active: json["active"], bit: json["bit"], currentEpoch: json["current_epoch"], description: json["description"], + finished: json["finished"], globalAcceptanceRate: json["global_acceptance_rate"].toDouble(), - previousEpoch: json["previous_epoch"], + lastUpdated: json["last_updated"], rates: List.from(json["rates"].map((x) => Rate.fromJson(x))), relativeAcceptanceRate: json["relative_acceptance_rate"].toDouble(), startEpoch: json["start_epoch"], @@ -1533,13 +1571,14 @@ class TapiInfo { ); Map jsonMap() => { - "accept": List.from(accept.map((x) => x)), + "activated": activated, "active": active, "bit": bit, "current_epoch": currentEpoch, "description": description, + "finished": finished, "global_acceptance_rate": globalAcceptanceRate, - "previous_epoch": previousEpoch, + "last_updated": lastUpdated, "rates": List.from(rates.map((x) => x.jsonMap())), "relative_acceptance_rate": relativeAcceptanceRate, "start_epoch": startEpoch, @@ -1581,20 +1620,27 @@ class Rate { } class Blockchain { - Blockchain({required this.blockchain}); + Blockchain( + {required this.blockchain, + required this.reverted, + required this.totalEpochs}); + final List reverted; + final int totalEpochs; final List blockchain; factory Blockchain.fromJson(Map data) { return Blockchain( blockchain: List.from( - data['blockchain'].map((e) => BlockchainInfo.fromList(e)))); + data['blockchain'].map((e) => BlockchainInfo.fromJson(e))), + reverted: data["reverted"], + totalEpochs: data["total_epochs"]); } } class BlockchainInfo { BlockchainInfo( - {required this.blockID, + {required this.hash, required this.epoch, required this.timestamp, required this.minerAddress, @@ -1606,7 +1652,7 @@ class BlockchainInfo { required this.tallyCount, required this.confirmed}); - final String blockID; + final String hash; final int epoch; final int timestamp; final String minerAddress; @@ -1618,19 +1664,19 @@ class BlockchainInfo { final int tallyCount; final bool confirmed; - factory BlockchainInfo.fromList(List data) { + factory BlockchainInfo.fromJson(Map data) { return BlockchainInfo( - blockID: data[0], - epoch: data[1], - timestamp: data[2], - minerAddress: data[3], - fee: data[4], - valueTransferCount: data[5], - dataRequestCount: data[6], - commitCount: data[7], - revealCount: data[8], - tallyCount: data[9], - confirmed: data[10]); + hash: data["hash"], + minerAddress: data["miner"], + valueTransferCount: data["value_transfers"], + dataRequestCount: data["data_requests"], + commitCount: data["commits"], + revealCount: data["reveals"], + tallyCount: data["tallies"], + fee: data["fees"], + epoch: data["epoch"], + timestamp: data["timestamp"], + confirmed: data["confirmed"]); } } @@ -1763,3 +1809,27 @@ class PriorityEstimate { "time_to_block": timeToBlock, }; } + +class Mempool { + Mempool({ + required this.timestamp, + required this.fee, + required this.amount, + }); + + final int timestamp; + final List fee; + final List amount; + + factory Mempool.fromJson(Map json) => Mempool( + timestamp: json["timestamp"], + fee: json["fee"], + amount: json["amount"], + ); + + Map jsonMap() => { + "timestamp": timestamp, + "fee": fee, + "amount": amount, + }; +} diff --git a/lib/src/network/explorer/explorer_client.dart b/lib/src/network/explorer/explorer_client.dart index 81a8e9b..948e3e6 100644 --- a/lib/src/network/explorer/explorer_client.dart +++ b/lib/src/network/explorer/explorer_client.dart @@ -11,14 +11,15 @@ import 'explorer_api.dart' show AddressBlocks, AddressDataRequestsSolved, - AddressDetails, AddressValueTransfers, BlockDetails, + Mempool, Blockchain, ExplorerException, + NetworkBalances, Home, MintInfo, - Network, + NetworkReputation, PrioritiesEstimate, Status, Tapi; @@ -46,7 +47,8 @@ class ExplorerClient { } } - Future> _processGet(Uri uri) async { + // This function can return Map or List> + Future _processGet(Uri uri) async { var response = await http.get(uri); if (response.statusCode == 200) { // response is okay @@ -73,14 +75,14 @@ class ExplorerClient { } Future> getUtxoInfo({required String address}) async { - Uri urlEndpoint = api('utxos', {'address': address}); + Uri urlEndpoint = api('address/utxos', {'addresses': address}); // Await the http get response, then decode the json-formatted response. try { var response = await http.get(urlEndpoint); if (response.statusCode == 200) { var jsonResponse = convert.jsonDecode(response.body); - List _utxos = jsonResponse[address]['utxos'] as List; + List _utxos = jsonResponse[0]['utxos'] as List; List utxos = []; _utxos.forEach((element) { utxos.add(Utxo.fromJson(element)); @@ -107,8 +109,8 @@ class ExplorerClient { int end = (i + addressLimit < addresses.length) ? i + addressLimit : addresses.length; - urlCalls - .add(api('utxos', {'address': addresses.sublist(i, end).join(',')})); + urlCalls.add(api( + 'address/utxos', {'addresses': addresses.sublist(i, end).join(',')})); } // Await the http get response, then decode the json-formatted response. try { @@ -130,6 +132,7 @@ class ExplorerClient { } } + // TBD Future sendVTTransaction(VTTransaction transaction, {bool testing = true}) async { return await send( @@ -139,21 +142,27 @@ class ExplorerClient { Future hash(String value, [bool simple = true]) async { try { - Uri uri = api('hash', {'value': value, 'simple': simple.toString()}); + Uri uri = + api('search/hash', {'value': value, 'simple': simple.toString()}); var data = await _processGet(uri); - if (data.containsKey('type')) { - switch (data['type'] as String) { - case 'value_transfer_txn': + if (data.containsKey('response_type')) { + switch (data['response_type'] as String) { + case 'value_transfer': return ValueTransferInfo.fromJson(data); - case 'data_request_txn': - case 'commit_txn': - case 'reveal_txn': - case 'tally_txn': - case 'mint_txn': - MintInfo mintInfo = MintInfo.fromJson(data); - return mintInfo; case 'block': return BlockDetails.fromJson(data); + // fixme: add support for pending + // case 'pending': + + // fixme: add support for data requests + case 'data_request': + case 'commit': + case 'reveal': + case 'tally': + case 'data_request_report': + case 'data_request_history': + case 'mint': + return MintInfo.fromJson(data); } } } catch (e) { @@ -170,87 +179,91 @@ class ExplorerClient { } } - Future network() async { + Future networkBalances({int? page, int? pageSize}) async { try { - return Network.fromJson(await _processGet(api('network'))); + return NetworkBalances.fromJson(await _processGet( + api('network/balances', {"page": page, "page_size": pageSize}))); } on ExplorerException catch (e) { throw ExplorerException( code: e.code, message: '{"network": "${e.message}"}'); } } - Future status() async { + Future reputation({int? page, int? pageSize}) async { try { - return Status.fromJson(await _processGet(api('status'))); + return NetworkReputation.fromJson(await _processGet( + api('network/reputation', {"page": page, "page_size": pageSize}))); } on ExplorerException catch (e) { throw ExplorerException( - code: e.code, message: '{"status": "${e.message}"}'); - } - } - - Future mempool({String key = 'live'}) async { - try { - if (['live', 'history'].contains(key)) { - return await _processGet(api('mempool', {'key': '$key'})); - } - } on ExplorerException catch (e) { - throw ExplorerException( - code: e.code, message: '{"mempool": "${e.message}"}'); + code: e.code, message: '{"network": "${e.message}"}'); } } - Future reputation() async { + Future status() async { try { - return await _processGet(api('reputation')); + return Status.fromJson(await _processGet(api('status'))); } on ExplorerException catch (e) { throw ExplorerException( - code: e.code, message: '{"reputation": "${e.message}"}'); + code: e.code, message: '{"status": "${e.message}"}'); } } - Future richList({int start = 0, int stop = 1000}) async { + Future mempool( + {required String transactionType, + int? startEpoch, + int? stopEpoch}) async { + // TODO: This was not working on mywitwallet. Should we add a class? try { - return await _processGet( - api('richlist', {'start': '$start', 'stop': '$stop'})); + return Mempool.fromJson(await _processGet(api('network/mempool', { + "transaction_type": transactionType, + "start_epoch": startEpoch, + "stop_epoch": stopEpoch + }))); } on ExplorerException catch (e) { throw ExplorerException( - code: e.code, message: '{"richList": "${e.message}"}'); + code: e.code, message: '{"mempool": "${e.message}"}'); } } Future address( {required String value, required String tab, - int? limit, - int? epoch}) async { + int? page, + int? pageSize}) async { try { - var data = - await _processGet(api('address', {'value': value, 'tab': tab})); switch (tab) { case 'blocks': + List> data = await _processGet(api( + 'address/blocks', + {'address': value, 'page': page, 'page_size': pageSize})); return AddressBlocks.fromJson(data); - case 'details': - return AddressDetails.fromJson(data); + // case 'details': + // var data = await _processGet(api('address', {'value': value})); + // return AddressDetails.fromJson(data); case 'data_requests_solved': - return AddressDataRequestsSolved.fromJson(data); - case 'data_requests_launched': + var data = await _processGet(api('address/data-requests-solved', + {'value': value, 'page': page, 'page_size': pageSize})); + return AddressDataRequestsSolved.fromJson( + {'address': value, 'data_requests_solved': data}); + case 'data_requests_created': // TODO: implement method // waiting on the explorer to return valid response break; case 'value_transfers': + var data = await _processGet(api('address/value-transfers', + {'value': value, 'page': page, 'page_size': pageSize})); return AddressValueTransfers.fromJson(data); } - return data; } on ExplorerException catch (e) { throw ExplorerException( code: e.code, message: '{"address": "${e.message}"}'); } } - Future blockchain({int block = -100}) async { + Future blockchain({int? page, int? pageSize}) async { try { - return Blockchain.fromJson( - await _processGet(api('blockchain', {'block': '$block'}))); + return Blockchain.fromJson(await _processGet( + api('network/blockchain', {'page': page, 'page_size': pageSize}))); } on ExplorerException catch (e) { throw ExplorerException( code: e.code, message: '{"blockchain": "${e.message}"}'); @@ -259,13 +272,14 @@ class ExplorerClient { Future tapi() async { try { - return Tapi.fromJson(await _processGet(api('tapi'))); + return Tapi.fromJson(await _processGet(api('network/tapi'))); } on ExplorerException catch (e) { throw ExplorerException( code: e.code, message: '{"tapi": "${e.message}"}'); } } + // TBD Future send( {required Map transaction, bool test = false}) async { try { @@ -282,7 +296,7 @@ class ExplorerClient { Future valueTransferPriority() async { try { return PrioritiesEstimate.fromJson( - await _processGet(api('priority', {"type": "vtt"}))); + await _processGet(api('transaction/priority', {"key": "vtt"}))); } on ExplorerException catch (e) { throw ExplorerException( code: e.code, message: '{"priority": "${e.message}"}');