mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
fetching thorChain traid info
This commit is contained in:
parent
a941014fc2
commit
571c9fd82a
8 changed files with 67 additions and 47 deletions
|
@ -1,7 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
||||
import 'package:bitbox/src/utils/opcodes.dart' as bitboxOPCodes;
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
|
@ -258,7 +257,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
txb.addOutput(changeAddress, changeValue);
|
||||
}
|
||||
|
||||
if (opReturnMemo != null) txb.addOutput(createOpReturnScript(opReturnMemo), 0);
|
||||
if (opReturnMemo != null) txb.addOutputData(opReturnMemo);
|
||||
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
final input = inputs[i];
|
||||
|
@ -333,11 +332,4 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
final HD = index == null ? hd : hd.derive(index);
|
||||
return base64Encode(HD.signMessage(message));
|
||||
}
|
||||
|
||||
Uint8List createOpReturnScript(String data) {
|
||||
List<int> script = [];
|
||||
script.add(bitboxOPCodes.Opcodes.OP_RETURN);
|
||||
script.addAll(utf8.encode(data));
|
||||
return Uint8List.fromList(script);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,9 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
|
||||
static const _baseURL = 'https://thornode.ninerealms.com';
|
||||
static const _quotePath = '/thorchain/quote/swap';
|
||||
static const _txInfoPath = '/thorchain/tx/';
|
||||
static const _affiliateName = 'cakewallet';
|
||||
static const _affiliateBps = '10';
|
||||
static const _affiliateBps = '0';
|
||||
|
||||
final Box<Trade> tradesStore;
|
||||
|
||||
|
@ -68,6 +69,8 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
'from_asset': _normalizeCurrency(from),
|
||||
'to_asset': _normalizeCurrency(to),
|
||||
'amount': _doubleToThorChainString(amount),
|
||||
'affiliate': _affiliateName,
|
||||
'affiliate_bps': _affiliateBps
|
||||
};
|
||||
|
||||
final responseJSON = await _getSwapQuote(params);
|
||||
|
@ -95,7 +98,7 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
};
|
||||
|
||||
final responseJSON = await _getSwapQuote(params);
|
||||
final minAmountIn = responseJSON['recommended_min_amount_in'] as String?;
|
||||
final minAmountIn = responseJSON['recommended_min_amount_in'] as String? ?? '0.0';
|
||||
|
||||
return Limits(min: _thorChainAmountToDouble(minAmountIn));
|
||||
}
|
||||
|
@ -121,27 +124,58 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
|
||||
final inputAddress = responseJSON['inbound_address'] as String?;
|
||||
final memo = responseJSON['memo'] as String?;
|
||||
final tradeId = await getNextTradeCounter();
|
||||
|
||||
return Trade(
|
||||
id: tradeId.toString(),
|
||||
id: '',
|
||||
from: request.fromCurrency,
|
||||
to: request.toCurrency,
|
||||
provider: description,
|
||||
inputAddress: inputAddress,
|
||||
createdAt: DateTime.now(),
|
||||
amount: request.fromAmount,
|
||||
state: TradeState.created,
|
||||
state: TradeState.pending,
|
||||
payoutAddress: request.toAddress,
|
||||
memo: memo);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Trade> findTradeById({required String id}) async {
|
||||
final foundTrade = tradesStore.values.firstWhereOrNull((element) => element.id == id);
|
||||
if (foundTrade == null) {
|
||||
throw Exception('Trade with id $id not found');
|
||||
if (id.isEmpty) throw Exception('Trade id is empty');
|
||||
final uri = Uri.parse('$_baseURL$_txInfoPath$id');
|
||||
final response = await http.get(uri);
|
||||
|
||||
if (response.statusCode == 404) {
|
||||
throw Exception('Trade not found for id: $id');
|
||||
} else if (response.statusCode != 200) {
|
||||
throw Exception('Unexpected HTTP status: ${response.statusCode}');
|
||||
}
|
||||
return foundTrade;
|
||||
|
||||
final responseJSON = json.decode(response.body);
|
||||
final observedTx = responseJSON['observed_tx'];
|
||||
if (observedTx == null) {
|
||||
throw Exception('No observed transaction found for id: $id');
|
||||
}
|
||||
|
||||
final tx = observedTx['tx'];
|
||||
final String fromAddress = tx['from_address'] as String? ?? '';
|
||||
final String toAddress = tx['to_address'] as String? ?? '';
|
||||
final List<dynamic> coins = tx['coins'] as List<dynamic>;
|
||||
final String? memo = tx['memo'] as String?;
|
||||
final String toAsset = memo != null ? (memo.split(':')[1]).split('.')[0] : '';
|
||||
final status = observedTx['status'] as String?;
|
||||
final formattedStatus = status ?? 'pending';
|
||||
|
||||
return Trade(
|
||||
id: id,
|
||||
from: CryptoCurrency.fromString(tx['chain'] as String? ?? ''),
|
||||
to: CryptoCurrency.fromString(toAsset),
|
||||
provider: description,
|
||||
inputAddress: fromAddress,
|
||||
payoutAddress: toAddress,
|
||||
amount: coins.first['amount'] as String? ?? '0.0',
|
||||
state: TradeState.deserialize(raw: formattedStatus),
|
||||
memo: memo,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _getSwapQuote(Map<String, String> params) async {
|
||||
|
@ -160,31 +194,9 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
return json.decode(response.body) as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
String _normalizeCurrency(CryptoCurrency currency) {
|
||||
switch (currency) {
|
||||
case CryptoCurrency.btc:
|
||||
return 'BTC.BTC';
|
||||
case CryptoCurrency.eth:
|
||||
return 'ETH.ETH';
|
||||
case CryptoCurrency.ltc:
|
||||
return 'LTC.LTC';
|
||||
case CryptoCurrency.bch:
|
||||
return 'BCH.BCH';
|
||||
default:
|
||||
return currency.title.toLowerCase();
|
||||
}
|
||||
}
|
||||
String _normalizeCurrency(CryptoCurrency currency) => '${currency.title}.${currency.title}';
|
||||
|
||||
String _doubleToThorChainString(double amount) => (amount * 1e8).toInt().toString();
|
||||
|
||||
double _thorChainAmountToDouble(String? amount) =>
|
||||
amount == null ? 0.0 : double.parse(amount) / 1e8;
|
||||
|
||||
Future<int> getNextTradeCounter() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
int currentCounter = prefs.getInt(PreferencesKey.thorChainTradeCounter) ?? 0;
|
||||
currentCounter++;
|
||||
await prefs.setInt(PreferencesKey.thorChainTradeCounter, currentCounter);
|
||||
return currentCounter;
|
||||
}
|
||||
double _thorChainAmountToDouble(String amount) => double.parse(amount) / 1e8;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class Trade extends HiveObject {
|
|||
this.providerName,
|
||||
this.fromWalletAddress,
|
||||
this.memo,
|
||||
this.txId
|
||||
}) {
|
||||
if (provider != null) providerRaw = provider.raw;
|
||||
|
||||
|
@ -109,6 +110,9 @@ class Trade extends HiveObject {
|
|||
@HiveField(18)
|
||||
String? memo;
|
||||
|
||||
@HiveField(19)
|
||||
String? txId;
|
||||
|
||||
static Trade fromMap(Map<String, Object?> map) {
|
||||
return Trade(
|
||||
id: map['id'] as String,
|
||||
|
@ -120,7 +124,8 @@ class Trade extends HiveObject {
|
|||
amount: map['amount'] as String,
|
||||
walletId: map['wallet_id'] as String,
|
||||
fromWalletAddress: map['from_wallet_address'] as String?,
|
||||
memo: map['memo'] as String?
|
||||
memo: map['memo'] as String?,
|
||||
txId: map['tx_id'] as String?
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -134,7 +139,8 @@ class Trade extends HiveObject {
|
|||
'amount': amount,
|
||||
'wallet_id': walletId,
|
||||
'from_wallet_address': fromWalletAddress,
|
||||
'memo': memo
|
||||
'memo': memo,
|
||||
'tx_id': txId
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
|
|||
case 'sending':
|
||||
return sending;
|
||||
case 'success':
|
||||
case 'done':
|
||||
return success;
|
||||
default:
|
||||
throw Exception('Unexpected token: $raw in TradeState deserialize');
|
||||
|
|
|
@ -20,6 +20,7 @@ class SyncIndicatorIcon extends StatelessWidget {
|
|||
static const String created = 'created';
|
||||
static const String fetching = 'fetching';
|
||||
static const String finished = 'finished';
|
||||
static const String success = 'success';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -45,6 +46,7 @@ class SyncIndicatorIcon extends StatelessWidget {
|
|||
indicatorColor = Colors.red;
|
||||
break;
|
||||
case finished:
|
||||
case success:
|
||||
indicatorColor = PaletteDark.brightGreen;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -106,7 +106,11 @@ abstract class ExchangeTradeViewModelBase with Store {
|
|||
output.setCryptoAmount(trade.amount);
|
||||
if (_provider is ThorChainExchangeProvider) output.memo = trade.memo;
|
||||
sendViewModel.selectedCryptoCurrency = trade.from;
|
||||
await sendViewModel.createTransaction();
|
||||
final pendingTransaction = await sendViewModel.createTransaction();
|
||||
if (_provider is ThorChainExchangeProvider) {
|
||||
trade.id = pendingTransaction?.id ?? '';
|
||||
trades.add(trade);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
|||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/wallet_contact.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||
import 'package:cake_wallet/exchange/exchange_template.dart';
|
||||
import 'package:cake_wallet/exchange/exchange_trade_state.dart';
|
||||
import 'package:cake_wallet/exchange/limits.dart';
|
||||
|
@ -495,7 +496,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
trade.walletId = wallet.id;
|
||||
trade.fromWalletAddress = wallet.walletAddresses.address;
|
||||
tradesStore.setTrade(trade);
|
||||
await trades.add(trade);
|
||||
if(trade.provider != ExchangeProviderDescription.thorChain) await trades.add(trade);
|
||||
tradeState = TradeIsCreatedSuccessfully(trade: trade);
|
||||
|
||||
/// return after the first successful trade
|
||||
|
|
|
@ -291,13 +291,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
|||
}
|
||||
|
||||
@action
|
||||
Future<void> createTransaction() async {
|
||||
Future<PendingTransaction?> createTransaction() async {
|
||||
try {
|
||||
state = IsExecutingState();
|
||||
pendingTransaction = await wallet.createTransaction(_credentials());
|
||||
state = ExecutedSuccessfullyState();
|
||||
return pendingTransaction;
|
||||
} catch (e) {
|
||||
state = FailureState(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue