Skip to content

Commit

Permalink
Merge branch 'meta' into meta_hidden_chrome_pool
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmeta committed Dec 10, 2024
2 parents a603465 + faf4850 commit 4a96e8a
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 21 deletions.
30 changes: 19 additions & 11 deletions magic/lib/cubits/pane/wallet/cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,25 +125,27 @@ class WalletCubit extends UpdatableCubit<WalletState> {
var storedData = jsonDecode(storedDataString ?? '{}');
String? privateKey = storedData['satori_magic_pool'];
final holdings = setCorrespondingFlag(_sort(_newRateThese(
symbol: 'EVR',
rate: await rates.getRateOf('EVR'),
symbolRate: {
'EVR': await rates.getRateOf('EVR'),
'SATORI': await rates.getRateOf('SATORI'),
},
holdings: await HoldingBalancesCall(
blockchain: Blockchain.evrmoreMain,
derivationWallets: cubits.keys.master.derivationWallets,
keypairWallets: cubits.keys.master.keypairWallets,
).call()) +
_newRateThese(
symbol: 'RVN',
rate: await rates.getRateOf('RVN'),
symbolRate: {
'RVN': await rates.getRateOf('RVN'),
},
holdings: await HoldingBalancesCall(
blockchain: Blockchain.ravencoinMain,
derivationWallets: cubits.keys.master.derivationWallets,
keypairWallets: cubits.keys.master.keypairWallets,
).call())));
logWTF('holdings: $holdings');
final poolHolding = _newRateThese(
symbol: 'EVR',
rate: await rates.getRateOf('EVR'),
symbolRate: {'SATORI': await rates.getRateOf('SATORI')},
holdings: await HoldingBalancesCall(
blockchain: Blockchain.evrmoreMain,
derivationWallets: [],
Expand Down Expand Up @@ -235,19 +237,25 @@ class WalletCubit extends UpdatableCubit<WalletState> {
void newRate({required Rate rate}) {
if (state.holdings.isEmpty) return;
final holdings = _newRateThese(
symbol: rate.base.symbol, rate: rate.rate, holdings: state.holdings);
symbolRate: {rate.base.symbol: rate.rate},
holdings: state.holdings,
);
update(holdings: holdings);
cacheRate(rate, holdings);
}

/// update all the holding with the new rate
List<Holding> _newRateThese(
{required String symbol, double? rate, required List<Holding> holdings}) {
if (holdings.isEmpty || rate == null || rate <= 0) {
List<Holding> _newRateThese({
required Map<String, double?> symbolRate,
required List<Holding> holdings,
}) {
if (holdings.isEmpty) {
return holdings;
}
return holdings
.map((e) => e.symbol == symbol ? e.copyWith(rate: rate) : e)
.map((e) => symbolRate[e.symbol] != null
? e.copyWith(rate: symbolRate[e.symbol])
: e)
.toList();
}

Expand Down
79 changes: 79 additions & 0 deletions magic/lib/services/prices.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// services/prices.dart

import 'dart:convert';
import 'package:http/http.dart' as http;

class ExchangeFiatValueService {
static final List<String> validTickers = ['EVR', 'RVN', 'SATORI'];

static Future<String> getFiatValue(String ticker, double amount) async {
if (!validTickers.contains(ticker.toUpperCase())) {
return '0';
}

try {
final price = await ExchangeFiatValueRepo.getFiatValue(ticker);
final fiatValue = price * amount;
return fiatValue.toStringAsFixed(2);
} catch (error) {
print('Error getting fiat value: $error');
return '0';
}
}
}

class ExchangeFiatValueRepo {
static const String XEGGEX_BASE_URL =
'https://api.xeggex.com/api/v2/market/getbysymbol/';
static const String BINANCE_BASE_URL =
'https://api.binance.us/api/v3/ticker/price';
static const String SAFETRADE_BASE_URL =
'https://safe.trade/api/v2/trade/public/tickers/satoriusdt';

static Future<double> getFiatValue(String ticker) async {
try {
double lastPrice;

if (ticker.toLowerCase() == 'evr') {
lastPrice = await getXeggexPrice(ticker);
} else if (ticker.toLowerCase() == 'rvn') {
lastPrice = await getBinancePrice(ticker);
} else if (ticker.toLowerCase() == 'satori') {
lastPrice = await getSafeTradePrice(ticker);
} else {
throw Exception('Unsupported ticker: $ticker');
}

print('ExchangeFiatValueRepo $ticker lastPrice: $lastPrice');
return lastPrice;
} catch (error) {
print('Error fetching fiat value: $error');
return 0;
}
}

static Future<double> getXeggexPrice(String ticker) async {
final response = await http
.get(Uri.parse('$XEGGEX_BASE_URL${ticker.toUpperCase()}/USDT'));
final data = jsonDecode(response.body);
return parsePrice(data['lastPrice']);
}

static Future<double> getBinancePrice(String ticker) async {
final response = await http
.get(Uri.parse('$BINANCE_BASE_URL?symbol=${ticker.toUpperCase()}USDT'));
final data = jsonDecode(response.body);
return parsePrice(data['price']);
}

static Future<double> getSafeTradePrice(String ticker) async {
final response = await http.get(Uri.parse(SAFETRADE_BASE_URL));
final data = jsonDecode(response.body);
return parsePrice(data['last']);
}

static double parsePrice(String price) {
final parsedPrice = double.tryParse(price);
return parsedPrice ?? 0;
}
}
16 changes: 15 additions & 1 deletion magic/lib/services/rate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import 'package:http/http.dart' as http;
import 'package:magic/utils/logger.dart';
import 'package:tuple/tuple.dart';
import 'package:moontree_utils/moontree_utils.dart';
import 'package:magic/services/prices.dart';

abstract class Grabber {
late final String symbol;
Future<double?> get();
}

class RateGrabber implements Grabber {
final String symbol;
@override
late final String symbol;
final String fiat;
Map<String, dynamic> pull = {};

Expand Down Expand Up @@ -103,3 +106,14 @@ class RateGrabber implements Grabber {
return price;
}
}

class ExchangeRateGrabber implements Grabber {
@override
late final String symbol;

ExchangeRateGrabber({required this.symbol});

@override
Future<double?> get() async =>
await ExchangeFiatValueRepo.getFiatValue('SATORI');
}
3 changes: 2 additions & 1 deletion magic/lib/services/services.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ void init({
//server = ServerCall();
rates = RateWaiter(
evrGrabber: RateGrabber(symbol: 'EVR'),
rvnGrabber: RateGrabber(symbol: 'RVN'))
rvnGrabber: RateGrabber(symbol: 'RVN'),
satoriGrabber: ExchangeRateGrabber(symbol: 'SATORI'))
..init();
websocket = WebSocketConnection();
initialized = true;
Expand Down
40 changes: 32 additions & 8 deletions magic/lib/services/triggers/rate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,25 @@ import 'package:magic/utils/logger.dart';
import 'package:moontree_utils/moontree_utils.dart' show Trigger;

class RateWaiter extends Trigger {
final RateGrabber evrGrabber;
final RateGrabber rvnGrabber;
final Grabber evrGrabber;
final Grabber rvnGrabber;
final Grabber satoriGrabber;
// eventually (once swaps matter) we should push this to the device rather than pull every 10 minutes
static const Duration _rateWait = Duration(minutes: 10);
Rate? rvnUsdRate;
Rate? evrUsdRate;
Rate? satoriUsdRate;

RateWaiter({required this.evrGrabber, required this.rvnGrabber});
RateWaiter(
{required this.evrGrabber,
required this.rvnGrabber,
required this.satoriGrabber});

void init() {
void saveRates() {
_saveRate(evrGrabber);
_saveRate(rvnGrabber);
_saveRate(satoriGrabber);
}

saveRates();
Expand All @@ -33,10 +39,10 @@ class RateWaiter extends Trigger {
);
}

Future<void> _saveRate(RateGrabber rateGrabber) async =>
Future<void> _saveRate(Grabber rateGrabber) async =>
_save(rateGrabber: rateGrabber, rate: await _rate(rateGrabber));

Future<double?> _getExistingRate(RateGrabber rateGrabber) async {
Future<double?> _getExistingRate(Grabber rateGrabber) async {
Future<double?> fromCache() async => double.tryParse(await storage.read(
key: StorageKey.rate
.key(_toRate(rateGrabber: rateGrabber, rate: 0)!.id)) ??
Expand All @@ -47,12 +53,14 @@ class RateWaiter extends Trigger {
return evrUsdRate?.rate ?? (await fromCache());
case 'RVN':
return rvnUsdRate?.rate ?? (await fromCache());
case 'SATORI':
return satoriUsdRate?.rate ?? (await fromCache());
default:
return null;
}
}

Future<double> _rate(RateGrabber rateGrabber) async {
Future<double> _rate(Grabber rateGrabber) async {
try {
return (await rateGrabber.get()) ??
await _getExistingRate(rateGrabber) ??
Expand All @@ -70,10 +78,13 @@ class RateWaiter extends Trigger {
if (symbol == 'RVN') {
return await _rate(rvnGrabber);
}
if (symbol == 'SATORI') {
return await _rate(satoriGrabber);
}
return null;
}

Rate? _toRate({required RateGrabber rateGrabber, required double rate}) {
Rate? _toRate({required Grabber rateGrabber, required double rate}) {
switch (rateGrabber.symbol) {
case 'EVR':
return Rate(
Expand All @@ -93,12 +104,21 @@ class RateWaiter extends Trigger {
blockchain: Blockchain.ravencoinMain,
),
);
case 'SATORI':
return Rate(
rate: rate,
quote: currency.Currency.usd,
base: Security(
symbol: rateGrabber.symbol,
blockchain: Blockchain.evrmoreMain,
),
);
default:
return null;
}
}

void _save({required RateGrabber rateGrabber, required double rate}) {
void _save({required Grabber rateGrabber, required double rate}) {
logD('saving ${rateGrabber.symbol}, rate: $rate');
switch (rateGrabber.symbol) {
case 'EVR':
Expand All @@ -109,6 +129,10 @@ class RateWaiter extends Trigger {
rvnUsdRate = _toRate(rateGrabber: rateGrabber, rate: rate);
cubits.wallet.newRate(rate: rvnUsdRate!);
return;
case 'SATORI':
satoriUsdRate = _toRate(rateGrabber: rateGrabber, rate: rate);
cubits.wallet.newRate(rate: satoriUsdRate!);
return;
default:
return;
}
Expand Down

0 comments on commit 4a96e8a

Please sign in to comment.