Skip to content

Commit 4a96e8a

Browse files
committed
Merge branch 'meta' into meta_hidden_chrome_pool
2 parents a603465 + faf4850 commit 4a96e8a

File tree

5 files changed

+147
-21
lines changed

5 files changed

+147
-21
lines changed

magic/lib/cubits/pane/wallet/cubit.dart

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,27 @@ class WalletCubit extends UpdatableCubit<WalletState> {
125125
var storedData = jsonDecode(storedDataString ?? '{}');
126126
String? privateKey = storedData['satori_magic_pool'];
127127
final holdings = setCorrespondingFlag(_sort(_newRateThese(
128-
symbol: 'EVR',
129-
rate: await rates.getRateOf('EVR'),
128+
symbolRate: {
129+
'EVR': await rates.getRateOf('EVR'),
130+
'SATORI': await rates.getRateOf('SATORI'),
131+
},
130132
holdings: await HoldingBalancesCall(
131133
blockchain: Blockchain.evrmoreMain,
132134
derivationWallets: cubits.keys.master.derivationWallets,
133135
keypairWallets: cubits.keys.master.keypairWallets,
134136
).call()) +
135137
_newRateThese(
136-
symbol: 'RVN',
137-
rate: await rates.getRateOf('RVN'),
138+
symbolRate: {
139+
'RVN': await rates.getRateOf('RVN'),
140+
},
138141
holdings: await HoldingBalancesCall(
139142
blockchain: Blockchain.ravencoinMain,
140143
derivationWallets: cubits.keys.master.derivationWallets,
141144
keypairWallets: cubits.keys.master.keypairWallets,
142145
).call())));
143146
logWTF('holdings: $holdings');
144147
final poolHolding = _newRateThese(
145-
symbol: 'EVR',
146-
rate: await rates.getRateOf('EVR'),
148+
symbolRate: {'SATORI': await rates.getRateOf('SATORI')},
147149
holdings: await HoldingBalancesCall(
148150
blockchain: Blockchain.evrmoreMain,
149151
derivationWallets: [],
@@ -235,19 +237,25 @@ class WalletCubit extends UpdatableCubit<WalletState> {
235237
void newRate({required Rate rate}) {
236238
if (state.holdings.isEmpty) return;
237239
final holdings = _newRateThese(
238-
symbol: rate.base.symbol, rate: rate.rate, holdings: state.holdings);
240+
symbolRate: {rate.base.symbol: rate.rate},
241+
holdings: state.holdings,
242+
);
239243
update(holdings: holdings);
240244
cacheRate(rate, holdings);
241245
}
242246

243247
/// update all the holding with the new rate
244-
List<Holding> _newRateThese(
245-
{required String symbol, double? rate, required List<Holding> holdings}) {
246-
if (holdings.isEmpty || rate == null || rate <= 0) {
248+
List<Holding> _newRateThese({
249+
required Map<String, double?> symbolRate,
250+
required List<Holding> holdings,
251+
}) {
252+
if (holdings.isEmpty) {
247253
return holdings;
248254
}
249255
return holdings
250-
.map((e) => e.symbol == symbol ? e.copyWith(rate: rate) : e)
256+
.map((e) => symbolRate[e.symbol] != null
257+
? e.copyWith(rate: symbolRate[e.symbol])
258+
: e)
251259
.toList();
252260
}
253261

magic/lib/services/prices.dart

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// services/prices.dart
2+
3+
import 'dart:convert';
4+
import 'package:http/http.dart' as http;
5+
6+
class ExchangeFiatValueService {
7+
static final List<String> validTickers = ['EVR', 'RVN', 'SATORI'];
8+
9+
static Future<String> getFiatValue(String ticker, double amount) async {
10+
if (!validTickers.contains(ticker.toUpperCase())) {
11+
return '0';
12+
}
13+
14+
try {
15+
final price = await ExchangeFiatValueRepo.getFiatValue(ticker);
16+
final fiatValue = price * amount;
17+
return fiatValue.toStringAsFixed(2);
18+
} catch (error) {
19+
print('Error getting fiat value: $error');
20+
return '0';
21+
}
22+
}
23+
}
24+
25+
class ExchangeFiatValueRepo {
26+
static const String XEGGEX_BASE_URL =
27+
'https://api.xeggex.com/api/v2/market/getbysymbol/';
28+
static const String BINANCE_BASE_URL =
29+
'https://api.binance.us/api/v3/ticker/price';
30+
static const String SAFETRADE_BASE_URL =
31+
'https://safe.trade/api/v2/trade/public/tickers/satoriusdt';
32+
33+
static Future<double> getFiatValue(String ticker) async {
34+
try {
35+
double lastPrice;
36+
37+
if (ticker.toLowerCase() == 'evr') {
38+
lastPrice = await getXeggexPrice(ticker);
39+
} else if (ticker.toLowerCase() == 'rvn') {
40+
lastPrice = await getBinancePrice(ticker);
41+
} else if (ticker.toLowerCase() == 'satori') {
42+
lastPrice = await getSafeTradePrice(ticker);
43+
} else {
44+
throw Exception('Unsupported ticker: $ticker');
45+
}
46+
47+
print('ExchangeFiatValueRepo $ticker lastPrice: $lastPrice');
48+
return lastPrice;
49+
} catch (error) {
50+
print('Error fetching fiat value: $error');
51+
return 0;
52+
}
53+
}
54+
55+
static Future<double> getXeggexPrice(String ticker) async {
56+
final response = await http
57+
.get(Uri.parse('$XEGGEX_BASE_URL${ticker.toUpperCase()}/USDT'));
58+
final data = jsonDecode(response.body);
59+
return parsePrice(data['lastPrice']);
60+
}
61+
62+
static Future<double> getBinancePrice(String ticker) async {
63+
final response = await http
64+
.get(Uri.parse('$BINANCE_BASE_URL?symbol=${ticker.toUpperCase()}USDT'));
65+
final data = jsonDecode(response.body);
66+
return parsePrice(data['price']);
67+
}
68+
69+
static Future<double> getSafeTradePrice(String ticker) async {
70+
final response = await http.get(Uri.parse(SAFETRADE_BASE_URL));
71+
final data = jsonDecode(response.body);
72+
return parsePrice(data['last']);
73+
}
74+
75+
static double parsePrice(String price) {
76+
final parsedPrice = double.tryParse(price);
77+
return parsedPrice ?? 0;
78+
}
79+
}

magic/lib/services/rate.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import 'package:http/http.dart' as http;
66
import 'package:magic/utils/logger.dart';
77
import 'package:tuple/tuple.dart';
88
import 'package:moontree_utils/moontree_utils.dart';
9+
import 'package:magic/services/prices.dart';
910

1011
abstract class Grabber {
12+
late final String symbol;
1113
Future<double?> get();
1214
}
1315

1416
class RateGrabber implements Grabber {
15-
final String symbol;
17+
@override
18+
late final String symbol;
1619
final String fiat;
1720
Map<String, dynamic> pull = {};
1821

@@ -103,3 +106,14 @@ class RateGrabber implements Grabber {
103106
return price;
104107
}
105108
}
109+
110+
class ExchangeRateGrabber implements Grabber {
111+
@override
112+
late final String symbol;
113+
114+
ExchangeRateGrabber({required this.symbol});
115+
116+
@override
117+
Future<double?> get() async =>
118+
await ExchangeFiatValueRepo.getFiatValue('SATORI');
119+
}

magic/lib/services/services.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void init({
4242
//server = ServerCall();
4343
rates = RateWaiter(
4444
evrGrabber: RateGrabber(symbol: 'EVR'),
45-
rvnGrabber: RateGrabber(symbol: 'RVN'))
45+
rvnGrabber: RateGrabber(symbol: 'RVN'),
46+
satoriGrabber: ExchangeRateGrabber(symbol: 'SATORI'))
4647
..init();
4748
websocket = WebSocketConnection();
4849
initialized = true;

magic/lib/services/triggers/rate.dart

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,25 @@ import 'package:magic/utils/logger.dart';
1111
import 'package:moontree_utils/moontree_utils.dart' show Trigger;
1212

1313
class RateWaiter extends Trigger {
14-
final RateGrabber evrGrabber;
15-
final RateGrabber rvnGrabber;
14+
final Grabber evrGrabber;
15+
final Grabber rvnGrabber;
16+
final Grabber satoriGrabber;
1617
// eventually (once swaps matter) we should push this to the device rather than pull every 10 minutes
1718
static const Duration _rateWait = Duration(minutes: 10);
1819
Rate? rvnUsdRate;
1920
Rate? evrUsdRate;
21+
Rate? satoriUsdRate;
2022

21-
RateWaiter({required this.evrGrabber, required this.rvnGrabber});
23+
RateWaiter(
24+
{required this.evrGrabber,
25+
required this.rvnGrabber,
26+
required this.satoriGrabber});
2227

2328
void init() {
2429
void saveRates() {
2530
_saveRate(evrGrabber);
2631
_saveRate(rvnGrabber);
32+
_saveRate(satoriGrabber);
2733
}
2834

2935
saveRates();
@@ -33,10 +39,10 @@ class RateWaiter extends Trigger {
3339
);
3440
}
3541

36-
Future<void> _saveRate(RateGrabber rateGrabber) async =>
42+
Future<void> _saveRate(Grabber rateGrabber) async =>
3743
_save(rateGrabber: rateGrabber, rate: await _rate(rateGrabber));
3844

39-
Future<double?> _getExistingRate(RateGrabber rateGrabber) async {
45+
Future<double?> _getExistingRate(Grabber rateGrabber) async {
4046
Future<double?> fromCache() async => double.tryParse(await storage.read(
4147
key: StorageKey.rate
4248
.key(_toRate(rateGrabber: rateGrabber, rate: 0)!.id)) ??
@@ -47,12 +53,14 @@ class RateWaiter extends Trigger {
4753
return evrUsdRate?.rate ?? (await fromCache());
4854
case 'RVN':
4955
return rvnUsdRate?.rate ?? (await fromCache());
56+
case 'SATORI':
57+
return satoriUsdRate?.rate ?? (await fromCache());
5058
default:
5159
return null;
5260
}
5361
}
5462

55-
Future<double> _rate(RateGrabber rateGrabber) async {
63+
Future<double> _rate(Grabber rateGrabber) async {
5664
try {
5765
return (await rateGrabber.get()) ??
5866
await _getExistingRate(rateGrabber) ??
@@ -70,10 +78,13 @@ class RateWaiter extends Trigger {
7078
if (symbol == 'RVN') {
7179
return await _rate(rvnGrabber);
7280
}
81+
if (symbol == 'SATORI') {
82+
return await _rate(satoriGrabber);
83+
}
7384
return null;
7485
}
7586

76-
Rate? _toRate({required RateGrabber rateGrabber, required double rate}) {
87+
Rate? _toRate({required Grabber rateGrabber, required double rate}) {
7788
switch (rateGrabber.symbol) {
7889
case 'EVR':
7990
return Rate(
@@ -93,12 +104,21 @@ class RateWaiter extends Trigger {
93104
blockchain: Blockchain.ravencoinMain,
94105
),
95106
);
107+
case 'SATORI':
108+
return Rate(
109+
rate: rate,
110+
quote: currency.Currency.usd,
111+
base: Security(
112+
symbol: rateGrabber.symbol,
113+
blockchain: Blockchain.evrmoreMain,
114+
),
115+
);
96116
default:
97117
return null;
98118
}
99119
}
100120

101-
void _save({required RateGrabber rateGrabber, required double rate}) {
121+
void _save({required Grabber rateGrabber, required double rate}) {
102122
logD('saving ${rateGrabber.symbol}, rate: $rate');
103123
switch (rateGrabber.symbol) {
104124
case 'EVR':
@@ -109,6 +129,10 @@ class RateWaiter extends Trigger {
109129
rvnUsdRate = _toRate(rateGrabber: rateGrabber, rate: rate);
110130
cubits.wallet.newRate(rate: rvnUsdRate!);
111131
return;
132+
case 'SATORI':
133+
satoriUsdRate = _toRate(rateGrabber: rateGrabber, rate: rate);
134+
cubits.wallet.newRate(rate: satoriUsdRate!);
135+
return;
112136
default:
113137
return;
114138
}

0 commit comments

Comments
 (0)