Skip to content
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 .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
EXPLORER_ADDRESS = 'witnet.network'
EXPLORER_DEV_ADDRESS = '0.0.0.0'

EXPLORER_MOCK_ADDRESS = '0.0.0.0:8080'
# [ Integration Test Settings ]

# how long to delay on the first screen
Expand Down
90 changes: 90 additions & 0 deletions bin/mock_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
"headers": {
"content-length": "body.length",
"content-type": "text/plain; charset=utf-8",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-powered-by": "Dart with package:shelf",
"x-xss-protection": "1; mode=block",
"x-version": "1.0.0"
},
"status": {
"database_confirmed": {
"epoch": 1,
"hash": "69fae23c1a316313189559fa6ecb10213e90770cdd0288b8873d3462051f362f"
},
"database_message": "database processes seem healthy",
"database_unconfirmed": {
"epoch": 1,
"hash": "41250277bd1601f11659077df12cb5cc39efff19d1ef1ec37992d8060223ac86"
},
"expected_epoch": 1,
"message": "all backend services are up and running",
"node_pool_message": {
"epoch": 1,
"message": "fetched node pool status correctly",
"status": "Synced"
}
},
"utxos": {
"wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u": {
"address": "wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u",
"utxos": [
{"output_pointer":"0000000000000000000000000000000000000000000000000000000000000001:0","timelock":0,"utxo_mature":false,"value":805030938},
{"output_pointer":"0000000000000000000000000000000000000000000000000000000000000001:1","timelock":0,"utxo_mature":false,"value":799999912469}
]
}
},
"value-transfers": {
"wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u": [
{
"confirmed":true,
"direction":"self",
"epoch":2563701,
"fee":0,
"hash":"0000000000000000000000000000000000000000000000000000000000000001",
"input_addresses":["wit100000000000000000000000000000000r0v4g2"],
"locked":false,
"output_addresses":["wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u"],
"priority":1,
"timestamp":1718032590,
"value":0,
"weight":493}
]
},
"priority": {
"vtt_stinky": {"priority": 0.1, "time_to_block": 21600},
"vtt_low": {"priority": 0.2, "time_to_block": 3600},
"vtt_medium": {"priority": 0.3, "time_to_block": 900},
"vtt_high": {"priority": 0.4, "time_to_block": 300},
"vtt_opulent": {"priority": 0.5, "time_to_block": 60}
},
"hashes": {
"0000000000000000000000000000000000000000000000000000000000000001": {
"response_type":"value_transfer",
"value_transfer": {
"block":"0000000000000000000000000000000000000000000000000000000000000000",
"change_output_addresses":["wit100000000000000000000000000000000r0v4g2"],
"change_value":0,
"confirmed":true,
"epoch":2052870,
"fee":0,
"hash":"0000000000000000000000000000000000000000000000000000000000000001",
"input_addresses":["wit100000000000000000000000000000000r0v4g2"],
"input_utxos":[
{"address":"wit100000000000000000000000000000000r0v4g2", "input_utxo":"000000000000000000000000000000000000000000000000000000000000000A:1", "value":800804943407}],
"inputs_merged":[{"address":"wit100000000000000000000000000000000r0v4g2", "value":800804943407}],
"output_addresses":["wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u","wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u"],
"output_values":[805030938,799999912469],
"priority":1,
"reverted":false,
"timelocks":[0,0],
"timestamp":1695045195,
"true_output_addresses":[],
"true_value":0,
"utxos":[
{"address":"wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u","locked":false,"timelock":0,"value":805030938},
{"address":"wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u","locked":false,"timelock":0,"value":799999912469}],
"utxos_merged":[{"address":"wit1vzm7xrguwf5uzjx72l65stgj3npfn292tya50u","locked":false,"timelock":0,"value":800804943407}],"value":800804943407,"weight":853}}
}
}
142 changes: 142 additions & 0 deletions bin/mock_explorer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';

void main(List<String> args) async {
await _loadMockData();
final InternetAddress ip = InternetAddress.anyIPv4;
final FutureOr<Response> Function(Request) handler =
Pipeline().addMiddleware(logRequests()).addHandler(_router);
final int port = int.parse(Platform.environment['PORT'] ?? '8080');
final HttpServer server = await serve(handler, ip, port);
print('Server listening on ${ip.address}:${server.port}');
}

// Configure routes.
final _router = Router()
..get('/', _rootHandler)
..get('/echo/<message>', _echoHandler)
..get('/api/status', statusHandler)
..get('/api/address/<path>', addressHandler)
..get('/api/transaction/<path>', transactionHandler)
..get('/api/search/<path>', searchHandler);

Future<Map<String, dynamic>> readJsonFile(String filePath) async {
var input = await File(filePath).readAsString();
var map = jsonDecode(input);
return map;
}

Response searchHandler(Request request) {
final Map<String, dynamic> queryParams = request.url.queryParameters;
return Response.ok(
json.encode(_hashData[queryParams['value']]),
headers: _headerData,
);
}

Response statusHandler(Request request) {
return Response.ok(json.encode(_statusData), headers: _headerData);
}

Future<Response> _utxos(Request request) async {
final Map<String, dynamic> queryParams = request.url.queryParameters;
var addresses = queryParams['addresses'];
List<Object> addressList = [];
if (addresses.runtimeType == String) {
if (_utxoData.containsKey(addresses)) {
addressList.add(json.encode(_utxoData[addresses]!));
} else {
addressList.add(json.encode({"address": addresses, "utxos": []}));
}
} else {
addresses.forEach((address) {
if (_utxoData.containsKey(address)) {
addressList.add(json.encode(_utxoData[address]!));
} else {
addressList.add(json.encode({"address": address, "utxos": []}));
}
});
}
return Response.ok(addressList.toString());
}

Response _valueTransfers(Request request) {
Map<String, dynamic> queryParams = request.requestedUri.queryParameters;
String response = json.encode(_vttData[queryParams['address']]!);
return Response.ok(response, headers: _headerData);
}

Response _dataRequestsSolved(Request request) {
return Response.ok('[]', headers: _headerData);
}

Response _blocks(Request request) {
return Response.ok('[]', headers: _headerData);
}

Future<Response> addressHandler(Request request) async {
String method =
request.requestedUri.toString().split('/').last.split('?').first;

switch (method) {
case "utxos":
return _utxos(request);
case 'value-transfers':
return _valueTransfers(request);
case 'data-requests-solved':
return _dataRequestsSolved(request);
case 'blocks':
return _blocks(request);
default:
return Response.notFound("");
}
}

Response transactionHandler(Request request) {
String method =
request.requestedUri.toString().split('/').last.split('?').first;
switch (method) {
case 'priority':
return Response.ok(json.encode(_priorityData));
}
return Response.ok('');
}

Response _rootHandler(Request req) {
return Response.ok('Hello, World!\n');
}

Response _echoHandler(Request request) {
final message = request.params['message'];
return Response.ok('$message\n');
}

Map<String, Object> _headerData = {};
Map<String, dynamic> _statusData = {};
Map<String, dynamic> _utxoData = {};
Map<String, dynamic> _vttData = {};
Map<String, dynamic> _hashData = {};
Map<String, dynamic> _priorityData = {};

Future<void> _loadMockData() async {
var input = await File('bin/mock_data.json').readAsString();
var map = jsonDecode(input);
_headerData = Map<String, Object>.from(map['headers']);
_headerData['x-pagination'] = json.encode({
"total": 1,
"total_pages": 1,
"first_page": 1,
"last_page": 1,
"page": 1
});
_statusData = map['status'];
_utxoData = map['utxos'];
_vttData = map['value-transfers'];
_priorityData = map['priority'];
_hashData = map['hashes'];
}
14 changes: 10 additions & 4 deletions lib/bloc/explorer/api_explorer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ class ApiExplorer {
late ExplorerClient client;
late Status status;
ApiExplorer() {
client = (USE_EXPLORER_DEV)
? ExplorerClient(
url: EXPLORER_DEV_ADDRESS, mode: ExplorerMode.development)
: ExplorerClient(url: EXPLORER_ADDRESS, mode: ExplorerMode.production);

if(USE_EXPLORER_MOCK) {
client = ExplorerClient(
url: EXPLORER_MOCK_ADDRESS, mode: ExplorerMode.development);
} else {
client = (USE_EXPLORER_DEV)
? ExplorerClient(
url: EXPLORER_DEV_ADDRESS, mode: ExplorerMode.development)
: ExplorerClient(url: EXPLORER_ADDRESS, mode: ExplorerMode.production);
}
}

Future<dynamic> hash(String value, [bool simple = true]) async {
Expand Down
3 changes: 3 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ Map<ConfigSteps, String> localizedConfigSteps = {

/// Explorer Settings
const bool USE_EXPLORER_DEV = false;
const bool USE_EXPLORER_MOCK = false;
const bool USE_MOCK_WALLETS_FILE = false;
// ignore: non_constant_identifier_names
String EXPLORER_ADDRESS = dotenv.get('EXPLORER_ADDRESS');
// ignore: non_constant_identifier_names
String EXPLORER_DEV_ADDRESS = dotenv.get('EXPLORER_DEV_ADDRESS');
String EXPLORER_MOCK_ADDRESS = dotenv.get('EXPLORER_MOCK_ADDRESS');
const int EXPLORER_DELAY_MS = 100;
const int SYNC_TIMER_IN_SECONDS = 30;

Expand Down
4 changes: 4 additions & 0 deletions lib/util/storage/path_provider_interface.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:io' as io;
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/globals.dart' as globals;
import 'package:path_provider/path_provider.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
Expand Down Expand Up @@ -71,6 +72,9 @@ class PathProviderInterface {
}

String getDbWalletsPath() {
if (USE_MOCK_WALLETS_FILE){
return getFilePath('mock-wallets', 'wit');
}
return getFilePath(
globals.testingActive ? 'test-wallets' : 'wallets', 'wit');
}
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies:
updat: ^1.2.0+1
logger: ^2.0.2+1
pub_semver: ^2.1.4
shelf_router: ^1.1.0

flutter_icons:
android: true
Expand Down