mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-29 06:38:45 +01:00
Reformat the whole codebase with 100 line width (#3403)
This commit is contained in:
+107
-107
@@ -6,110 +6,110 @@ defaults:
|
|||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
# lint:
|
||||||
runs-on: [Linux, amd64, android]
|
# runs-on: [Linux, amd64, android]
|
||||||
container:
|
# container:
|
||||||
image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly
|
# image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly
|
||||||
env:
|
# env:
|
||||||
STORE_PASS: test@cake_wallet
|
# STORE_PASS: test@cake_wallet
|
||||||
KEY_PASS: test@cake_wallet
|
# KEY_PASS: test@cake_wallet
|
||||||
MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
|
# MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
|
||||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
# BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||||
ANDROID_AVD_HOME: /root/.android/avd
|
# ANDROID_AVD_HOME: /root/.android/avd
|
||||||
volumes:
|
# volumes:
|
||||||
- /opt/cw_cache_android/root/.cache:/root/.cache
|
# - /opt/cw_cache_android/root/.cache:/root/.cache
|
||||||
- /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
|
# - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
|
||||||
- /opt/cw_cache_android/root/.ccache:/root/.ccache
|
# - /opt/cw_cache_android/root/.ccache:/root/.ccache
|
||||||
- /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
|
# - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
|
||||||
- /opt/cw_cache_android/root/.gradle/:/root/.gradle
|
# - /opt/cw_cache_android/root/.gradle/:/root/.gradle
|
||||||
- /opt/cw_cache_android/root/.android/:/root/.android
|
# - /opt/cw_cache_android/root/.android/:/root/.android
|
||||||
- /opt/cw_cache_android/root/go/pkg:/root/go/pkg
|
# - /opt/cw_cache_android/root/go/pkg:/root/go/pkg
|
||||||
- /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
|
# - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
|
||||||
- /dev/kvm:/dev/kvm
|
# - /dev/kvm:/dev/kvm
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
# - /var/run/docker.sock:/var/run/docker.sock
|
||||||
strategy:
|
# strategy:
|
||||||
matrix:
|
# matrix:
|
||||||
api-level: [ 29 ]
|
# api-level: [ 29 ]
|
||||||
|
#
|
||||||
steps:
|
# steps:
|
||||||
- name: Fix github actions messing up $HOME...
|
# - name: Fix github actions messing up $HOME...
|
||||||
run: "echo HOME=/root | sudo tee -a $GITHUB_ENV"
|
# run: "echo HOME=/root | sudo tee -a $GITHUB_ENV"
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
with:
|
# with:
|
||||||
ref: ${{ inputs.ref }}
|
# ref: ${{ inputs.ref }}
|
||||||
|
#
|
||||||
- name: configure git
|
# - name: configure git
|
||||||
run: |
|
# run: |
|
||||||
git config --global --add safe.directory '*'
|
# git config --global --add safe.directory '*'
|
||||||
git config --global user.email "ci@cakewallet.com"
|
# git config --global user.email "ci@cakewallet.com"
|
||||||
git config --global user.name "CakeWallet CI"
|
# git config --global user.name "CakeWallet CI"
|
||||||
|
#
|
||||||
- name: Fetch prebuilt Torch
|
# - name: Fetch prebuilt Torch
|
||||||
run: |
|
# run: |
|
||||||
set -x -e
|
# set -x -e
|
||||||
pushd scripts
|
# pushd scripts
|
||||||
wget https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
# wget https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
||||||
rm -rf torch_dart
|
# rm -rf torch_dart
|
||||||
mkdir torch_dart
|
# mkdir torch_dart
|
||||||
pushd torch_dart
|
# pushd torch_dart
|
||||||
tar -xzf ../torch_dart.tar.gz
|
# tar -xzf ../torch_dart.tar.gz
|
||||||
popd
|
# popd
|
||||||
rm ./torch_dart.tar.gz
|
# rm ./torch_dart.tar.gz
|
||||||
popd
|
# popd
|
||||||
|
#
|
||||||
- name: Fetch prebuilt Reown
|
# - name: Fetch prebuilt Reown
|
||||||
run: |
|
# run: |
|
||||||
set -x -e
|
# set -x -e
|
||||||
pushd scripts
|
# pushd scripts
|
||||||
# cleaning
|
# # cleaning
|
||||||
rm -rf reown_flutter
|
# rm -rf reown_flutter
|
||||||
rm -f reown_flutter.tar.gz
|
# rm -f reown_flutter.tar.gz
|
||||||
|
#
|
||||||
wget https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
# wget https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
||||||
mkdir reown_flutter
|
# mkdir reown_flutter
|
||||||
pushd reown_flutter
|
# pushd reown_flutter
|
||||||
tar -xzf ../reown_flutter.tar.gz
|
# tar -xzf ../reown_flutter.tar.gz
|
||||||
popd
|
# popd
|
||||||
rm ./reown_flutter.tar.gz
|
# rm ./reown_flutter.tar.gz
|
||||||
popd
|
# popd
|
||||||
|
#
|
||||||
- name: Build Bitbox Flutter
|
# - name: Build Bitbox Flutter
|
||||||
run: |
|
# run: |
|
||||||
set -x -e
|
# set -x -e
|
||||||
pushd scripts
|
# pushd scripts
|
||||||
./build_bitbox_flutter.sh
|
# ./build_bitbox_flutter.sh
|
||||||
popd
|
# popd
|
||||||
|
#
|
||||||
- name: Prepare Zcash
|
# - name: Prepare Zcash
|
||||||
run: |
|
# run: |
|
||||||
set -x -e
|
# set -x -e
|
||||||
scripts/prepare_zcash.sh
|
# scripts/prepare_zcash.sh
|
||||||
|
#
|
||||||
- name: Execute Build and Setup Commands
|
# - name: Execute Build and Setup Commands
|
||||||
run: |
|
# run: |
|
||||||
pushd scripts/android
|
# pushd scripts/android
|
||||||
source ./app_env.sh cakewallet
|
# source ./app_env.sh cakewallet
|
||||||
export GITHUB_HUH=yeah
|
# export GITHUB_HUH=yeah
|
||||||
./app_config.sh
|
# ./app_config.sh
|
||||||
popd
|
# popd
|
||||||
|
#
|
||||||
- name: Install Flutter dependencies
|
# - name: Install Flutter dependencies
|
||||||
run: |
|
# run: |
|
||||||
flutter pub get
|
# flutter pub get
|
||||||
|
#
|
||||||
- name: Build generated code
|
# - name: Build generated code
|
||||||
run: |
|
# run: |
|
||||||
flutter --version
|
# flutter --version
|
||||||
flutter clean
|
# flutter clean
|
||||||
rm -rf .dart_tool
|
# rm -rf .dart_tool
|
||||||
rm pubspec.lock
|
# rm pubspec.lock
|
||||||
flutter pub get
|
# flutter pub get
|
||||||
./model_generator.sh async
|
# ./model_generator.sh async
|
||||||
|
#
|
||||||
- name: Generate localization
|
# - name: Generate localization
|
||||||
run: |
|
# run: |
|
||||||
dart run tool/generate_localization.dart
|
# dart run tool/generate_localization.dart
|
||||||
|
#
|
||||||
- name: Lint
|
# - name: Lint
|
||||||
run: |
|
# run: |
|
||||||
ABORT_ON_CHANGE=yeah scripts/lint.sh
|
# ABORT_ON_CHANGE=yeah scripts/lint.sh
|
||||||
@@ -17,21 +17,16 @@ BitcoinBaseAddress addressFromScript(Script script,
|
|||||||
|
|
||||||
switch (addressType) {
|
switch (addressType) {
|
||||||
case P2pkhAddressType.p2pkh:
|
case P2pkhAddressType.p2pkh:
|
||||||
return P2pkhAddress.fromScriptPubkey(
|
return P2pkhAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
|
||||||
script: script, network: BitcoinNetwork.mainnet);
|
|
||||||
case P2shAddressType.p2pkhInP2sh:
|
case P2shAddressType.p2pkhInP2sh:
|
||||||
case P2shAddressType.p2pkInP2sh:
|
case P2shAddressType.p2pkInP2sh:
|
||||||
return P2shAddress.fromScriptPubkey(
|
return P2shAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
|
||||||
script: script, network: BitcoinNetwork.mainnet);
|
|
||||||
case SegwitAddresType.p2wpkh:
|
case SegwitAddresType.p2wpkh:
|
||||||
return P2wpkhAddress.fromScriptPubkey(
|
return P2wpkhAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
|
||||||
script: script, network: BitcoinNetwork.mainnet);
|
|
||||||
case SegwitAddresType.p2wsh:
|
case SegwitAddresType.p2wsh:
|
||||||
return P2wshAddress.fromScriptPubkey(
|
return P2wshAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
|
||||||
script: script, network: BitcoinNetwork.mainnet);
|
|
||||||
case SegwitAddresType.p2tr:
|
case SegwitAddresType.p2tr:
|
||||||
return P2trAddress.fromScriptPubkey(
|
return P2trAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
|
||||||
script: script, network: BitcoinNetwork.mainnet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ArgumentError("Invalid script");
|
throw ArgumentError("Invalid script");
|
||||||
|
|||||||
@@ -79,10 +79,9 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _legacyDefaultForType(BitcoinAddressType type) {
|
static bool _legacyDefaultForType(BitcoinAddressType type) {
|
||||||
|
|
||||||
// Some address types (p2wpkh, p2wsh) were historically derived from the same account/path as our new standard
|
// Some address types (p2wpkh, p2wsh) were historically derived from the same account/path as our new standard
|
||||||
// but using legacy formats. For these, we default to legacy = false.
|
// but using legacy formats. For these, we default to legacy = false.
|
||||||
if (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh) return false;
|
if (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh) return false;
|
||||||
@@ -154,6 +153,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||||||
}
|
}
|
||||||
return scriptHash!;
|
return scriptHash!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get derivationPath {
|
String get derivationPath {
|
||||||
if (type == SegwitAddresType.mweb) {
|
if (type == SegwitAddresType.mweb) {
|
||||||
@@ -162,9 +162,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||||||
|
|
||||||
final coinType = _coinTypeForNetwork();
|
final coinType = _coinTypeForNetwork();
|
||||||
final purpose = _purposeForType(type);
|
final purpose = _purposeForType(type);
|
||||||
final accountPath = isLegacyDerivation
|
final accountPath = isLegacyDerivation ? electrum_path : "m/$purpose'/$coinType'/0'";
|
||||||
? electrum_path
|
|
||||||
: "m/$purpose'/$coinType'/0'";
|
|
||||||
|
|
||||||
final chain = isHidden ? 1 : 0;
|
final chain = isHidden ? 1 : 0;
|
||||||
return "$accountPath/$chain/$index";
|
return "$accountPath/$chain/$index";
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ final bitcoinAmountFormat = NumberFormat()
|
|||||||
..maximumFractionDigits = bitcoinAmountLength
|
..maximumFractionDigits = bitcoinAmountLength
|
||||||
..minimumFractionDigits = 1;
|
..minimumFractionDigits = 1;
|
||||||
|
|
||||||
String bitcoinAmountToString({required int amount}) => bitcoinAmountFormat.format(
|
String bitcoinAmountToString({required int amount}) =>
|
||||||
cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider));
|
bitcoinAmountFormat.format(cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider));
|
||||||
|
|
||||||
double bitcoinAmountToDouble({required int amount}) =>
|
double bitcoinAmountToDouble({required int amount}) =>
|
||||||
cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider);
|
cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider);
|
||||||
|
|||||||
@@ -5,4 +5,3 @@ class BitcoinCommitTransactionException implements Exception {
|
|||||||
@override
|
@override
|
||||||
String toString() => errorMessage;
|
String toString() => errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import 'package:cw_core/transaction_priority.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class BitcoinTransactionPriority extends TransactionPriority {
|
class BitcoinTransactionPriority extends TransactionPriority {
|
||||||
const BitcoinTransactionPriority({required String title, required int raw, String? description, String? hint})
|
const BitcoinTransactionPriority(
|
||||||
|
{required String title, required int raw, String? description, String? hint})
|
||||||
: super(title: title, raw: raw, description: description, hint: hint);
|
: super(title: title, raw: raw, description: description, hint: hint);
|
||||||
|
|
||||||
static const List<BitcoinTransactionPriority> all = [fast, medium, slow, custom];
|
static const List<BitcoinTransactionPriority> all = [fast, medium, slow, custom];
|
||||||
@@ -10,8 +11,8 @@ class BitcoinTransactionPriority extends TransactionPriority {
|
|||||||
BitcoinTransactionPriority(title: 'Slow', description: "2 sat/byte", hint: "~ 24 h", raw: 0);
|
BitcoinTransactionPriority(title: 'Slow', description: "2 sat/byte", hint: "~ 24 h", raw: 0);
|
||||||
static const BitcoinTransactionPriority medium =
|
static const BitcoinTransactionPriority medium =
|
||||||
BitcoinTransactionPriority(title: 'Medium', description: "3 sat/byte", hint: "~ 1 h", raw: 1);
|
BitcoinTransactionPriority(title: 'Medium', description: "3 sat/byte", hint: "~ 1 h", raw: 1);
|
||||||
static const BitcoinTransactionPriority fast =
|
static const BitcoinTransactionPriority fast = BitcoinTransactionPriority(
|
||||||
BitcoinTransactionPriority(title: 'Fast', description: "4 sat/byte", hint: "~ 30 min", raw: 2);
|
title: 'Fast', description: "4 sat/byte", hint: "~ 30 min", raw: 2);
|
||||||
static const BitcoinTransactionPriority custom =
|
static const BitcoinTransactionPriority custom =
|
||||||
BitcoinTransactionPriority(title: 'Custom', raw: 3);
|
BitcoinTransactionPriority(title: 'Custom', raw: 3);
|
||||||
|
|
||||||
@@ -116,8 +117,8 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
|
|||||||
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
|
class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
|
||||||
const BitcoinCashTransactionPriority({required String title, required int raw})
|
const BitcoinCashTransactionPriority({required String title, required int raw})
|
||||||
: super(title: title, raw: raw);
|
: super(title: title, raw: raw);
|
||||||
@@ -170,4 +171,3 @@ class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -494,7 +494,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||||||
@override
|
@override
|
||||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||||
credentials = credentials as BitcoinTransactionCredentials;
|
credentials = credentials as BitcoinTransactionCredentials;
|
||||||
final lnAddr = credentials.outputs.first.isParsedAddress ? credentials.outputs.first.extractedAddress! : credentials.outputs.first.address;
|
final lnAddr = credentials.outputs.first.isParsedAddress
|
||||||
|
? credentials.outputs.first.extractedAddress!
|
||||||
|
: credentials.outputs.first.address;
|
||||||
|
|
||||||
final isLNCompatible = await lightningWallet?.isCompatible(lnAddr);
|
final isLNCompatible = await lightningWallet?.isCompatible(lnAddr);
|
||||||
if ((credentials.coinTypeToSpendFrom == UnspentCoinType.lightning && lightningWallet != null) ||
|
if ((credentials.coinTypeToSpendFrom == UnspentCoinType.lightning && lightningWallet != null) ||
|
||||||
@@ -506,12 +508,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||||||
amount = credentials.outputs.first.cryptoAmount;
|
amount = credentials.outputs.first.cryptoAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return lightningWallet!.createTransaction(
|
return lightningWallet!.createTransaction(
|
||||||
lnAddr,
|
lnAddr,
|
||||||
amount.amount > BigInt.zero ? amount.amount : null,
|
amount.amount > BigInt.zero ? amount.amount : null,
|
||||||
credentials.priority,
|
credentials.priority,
|
||||||
credentials.outputs.first.sendAll,);
|
credentials.outputs.first.sendAll,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final tx = (await super.createTransaction(credentials)) as PendingBitcoinTransaction;
|
final tx = (await super.createTransaction(credentials)) as PendingBitcoinTransaction;
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool containsAddress(String address) => super.containsAddress(address) || address == lightningAddress;
|
bool containsAddress(String address) =>
|
||||||
|
super.containsAddress(address) || address == lightningAddress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get addressForBuy {
|
String get addressForBuy {
|
||||||
@@ -153,12 +154,9 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get addressForExchange {
|
String get addressForExchange {
|
||||||
|
|
||||||
final current = getFreshAddress();
|
final current = getFreshAddress();
|
||||||
final availableReceiveAddresses = receiveAddresses.where((element) =>
|
final availableReceiveAddresses = receiveAddresses.where((element) =>
|
||||||
!element.isUsed &&
|
!element.isUsed && !element.isHidden && !hiddenAddresses.contains(element.address));
|
||||||
!element.isHidden &&
|
|
||||||
!hiddenAddresses.contains(element.address));
|
|
||||||
|
|
||||||
final bool isSilentPaymentsPage = addressPageType == SilentPaymentsAddresType.p2sp;
|
final bool isSilentPaymentsPage = addressPageType == SilentPaymentsAddresType.p2sp;
|
||||||
final bool isLightningPage = addressPageType == LightningAddressType.p2l;
|
final bool isLightningPage = addressPageType == LightningAddressType.p2l;
|
||||||
|
|||||||
@@ -59,27 +59,27 @@ class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BitcoinWalletFromKeysCredentials extends WalletCredentials {
|
class BitcoinWalletFromKeysCredentials extends WalletCredentials {
|
||||||
BitcoinWalletFromKeysCredentials({
|
BitcoinWalletFromKeysCredentials(
|
||||||
required String name,
|
{required String name,
|
||||||
required String password,
|
required String password,
|
||||||
required this.xpub,
|
required this.xpub,
|
||||||
WalletInfo? walletInfo,
|
WalletInfo? walletInfo,
|
||||||
super.hardwareWalletType
|
super.hardwareWalletType})
|
||||||
}) : super(name: name, password: password, walletInfo: walletInfo);
|
: super(name: name, password: password, walletInfo: walletInfo);
|
||||||
|
|
||||||
final String xpub;
|
final String xpub;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LitecoinWalletFromKeysCredentials extends WalletCredentials {
|
class LitecoinWalletFromKeysCredentials extends WalletCredentials {
|
||||||
LitecoinWalletFromKeysCredentials({
|
LitecoinWalletFromKeysCredentials(
|
||||||
required String name,
|
{required String name,
|
||||||
required String password,
|
required String password,
|
||||||
required this.xpub,
|
required this.xpub,
|
||||||
required this.scanSecret,
|
required this.scanSecret,
|
||||||
required this.spendPubkey,
|
required this.spendPubkey,
|
||||||
WalletInfo? walletInfo,
|
WalletInfo? walletInfo,
|
||||||
super.hardwareWalletType
|
super.hardwareWalletType})
|
||||||
}) : super(name: name, password: password, walletInfo: walletInfo);
|
: super(name: name, password: password, walletInfo: walletInfo);
|
||||||
|
|
||||||
final String xpub;
|
final String xpub;
|
||||||
final String scanSecret;
|
final String scanSecret;
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
class BitcoinWalletKeys {
|
class BitcoinWalletKeys {
|
||||||
const BitcoinWalletKeys({required this.wif, required this.privateKey, required this.publicKey, required this.xpub});
|
const BitcoinWalletKeys(
|
||||||
|
{required this.wif, required this.privateKey, required this.publicKey, required this.xpub});
|
||||||
|
|
||||||
final String wif;
|
final String wif;
|
||||||
final String privateKey;
|
final String privateKey;
|
||||||
final String publicKey;
|
final String publicKey;
|
||||||
final String xpub;
|
final String xpub;
|
||||||
|
|
||||||
Map<String, String> toJson() => {
|
Map<String, String> toJson() =>
|
||||||
'wif': wif,
|
{'wif': wif, 'privateKey': privateKey, 'publicKey': publicKey, 'xpub': xpub};
|
||||||
'privateKey': privateKey,
|
|
||||||
'publicKey': publicKey,
|
|
||||||
'xpub': xpub
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -21,8 +21,7 @@ class BitcoinWalletService extends WalletService<
|
|||||||
BitcoinRestoreWalletFromSeedCredentials,
|
BitcoinRestoreWalletFromSeedCredentials,
|
||||||
BitcoinWalletFromKeysCredentials,
|
BitcoinWalletFromKeysCredentials,
|
||||||
BitcoinRestoreWalletFromHardware> {
|
BitcoinRestoreWalletFromHardware> {
|
||||||
BitcoinWalletService(this.unspentCoinsInfoSource,
|
BitcoinWalletService(this.unspentCoinsInfoSource, this.payjoinSessionSource, this.isDirect);
|
||||||
this.payjoinSessionSource, this.isDirect);
|
|
||||||
|
|
||||||
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
||||||
final Box<PayjoinSession> payjoinSessionSource;
|
final Box<PayjoinSession> payjoinSessionSource;
|
||||||
@@ -38,9 +37,12 @@ class BitcoinWalletService extends WalletService<
|
|||||||
|
|
||||||
final String mnemonic;
|
final String mnemonic;
|
||||||
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
||||||
derivationInfo.derivationType = credentials.derivationInfo?.derivationType ?? derivationInfo.derivationType;
|
derivationInfo.derivationType =
|
||||||
derivationInfo.derivationPath = credentials.derivationInfo?.derivationPath ?? derivationInfo.derivationPath;
|
credentials.derivationInfo?.derivationType ?? derivationInfo.derivationType;
|
||||||
derivationInfo.description = credentials.derivationInfo?.description ?? derivationInfo.description;
|
derivationInfo.derivationPath =
|
||||||
|
credentials.derivationInfo?.derivationPath ?? derivationInfo.derivationPath;
|
||||||
|
derivationInfo.description =
|
||||||
|
credentials.derivationInfo?.description ?? derivationInfo.description;
|
||||||
derivationInfo.scriptType = credentials.derivationInfo?.scriptType ?? derivationInfo.scriptType;
|
derivationInfo.scriptType = credentials.derivationInfo?.scriptType ?? derivationInfo.scriptType;
|
||||||
await derivationInfo.save();
|
await derivationInfo.save();
|
||||||
switch (derivationInfo.derivationType) {
|
switch (derivationInfo.derivationType) {
|
||||||
@@ -119,8 +121,9 @@ class BitcoinWalletService extends WalletService<
|
|||||||
}
|
}
|
||||||
await WalletInfo.delete(walletInfo);
|
await WalletInfo.delete(walletInfo);
|
||||||
|
|
||||||
final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
|
final unspentCoinsToDelete = unspentCoinsInfoSource.values
|
||||||
(unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
|
.where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
|
||||||
|
.toList();
|
||||||
|
|
||||||
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
||||||
|
|
||||||
@@ -135,8 +138,7 @@ class BitcoinWalletService extends WalletService<
|
|||||||
final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
|
final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
|
||||||
credentials.walletInfo?.network = network.value;
|
credentials.walletInfo?.network = network.value;
|
||||||
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
||||||
derivationInfo.derivationPath =
|
derivationInfo.derivationPath = credentials.hwAccountData.derivationPath;
|
||||||
credentials.hwAccountData.derivationPath;
|
|
||||||
|
|
||||||
final xpub = convertAnyToXpub(credentials.hwAccountData.xpub!);
|
final xpub = convertAnyToXpub(credentials.hwAccountData.xpub!);
|
||||||
|
|
||||||
|
|||||||
@@ -483,12 +483,8 @@ class ElectrumClient {
|
|||||||
// Build the Batch Array
|
// Build the Batch Array
|
||||||
final List<Map<String, dynamic>> batchPayload = [];
|
final List<Map<String, dynamic>> batchPayload = [];
|
||||||
for (int i = 0; i < paramsList.length; i++) {
|
for (int i = 0; i < paramsList.length; i++) {
|
||||||
batchPayload.add({
|
batchPayload.add(
|
||||||
"jsonrpc": "2.0",
|
{"jsonrpc": "2.0", "method": method, "params": paramsList[i], "id": "$batchBaseId-$i"});
|
||||||
"method": method,
|
|
||||||
"params": paramsList[i],
|
|
||||||
"id": "$batchBaseId-$i"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the task
|
// Register the task
|
||||||
@@ -775,7 +771,6 @@ class ElectrumClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleResponse(dynamic response) {
|
void _handleResponse(dynamic response) {
|
||||||
|
|
||||||
// Handle batch response
|
// Handle batch response
|
||||||
if (response is List) {
|
if (response is List) {
|
||||||
if (response.isEmpty) return;
|
if (response.isEmpty) return;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
|
||||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||||
import 'package:cw_core/encryption_file_utils.dart';
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
|||||||
@@ -184,15 +184,13 @@ class ElectrumTransactionInfo extends TransactionInfo {
|
|||||||
|
|
||||||
// MWEB HogEx
|
// MWEB HogEx
|
||||||
final isHogExTx = (BtcTransaction tx) {
|
final isHogExTx = (BtcTransaction tx) {
|
||||||
if (tx.inputs.isEmpty || tx.inputs.first.txIndex > 0 || tx.outputs.isEmpty)
|
if (tx.inputs.isEmpty || tx.inputs.first.txIndex > 0 || tx.outputs.isEmpty) return false;
|
||||||
return false;
|
|
||||||
final b = tx.outputs.first.scriptPubKey.toBytes();
|
final b = tx.outputs.first.scriptPubKey.toBytes();
|
||||||
return b.length == 34 && b[0] == 88 && b[1] == 32;
|
return b.length == 34 && b[0] == 88 && b[1] == 32;
|
||||||
};
|
};
|
||||||
final firstInput = bundle.ins.isNotEmpty ? bundle.ins.first : null;
|
final firstInput = bundle.ins.isNotEmpty ? bundle.ins.first : null;
|
||||||
final isHogEx = firstInput != null &&
|
final isHogEx =
|
||||||
isHogExTx(bundle.originalTransaction) &&
|
firstInput != null && isHogExTx(bundle.originalTransaction) && isHogExTx(firstInput);
|
||||||
isHogExTx(firstInput);
|
|
||||||
|
|
||||||
final fee = hasMissingInputTx ? null : inputAmount - totalOutAmount;
|
final fee = hasMissingInputTx ? null : inputAmount - totalOutAmount;
|
||||||
final walletCurrency = walletTypeToCryptoCurrency(type);
|
final walletCurrency = walletTypeToCryptoCurrency(type);
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ abstract class ElectrumWalletBase
|
|||||||
sideHdByType[type] = sideHd;
|
sideHdByType[type] = sideHd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _purposeForType(BitcoinAddressType type) {
|
int _purposeForType(BitcoinAddressType type) {
|
||||||
@@ -195,7 +194,6 @@ abstract class ElectrumWalletBase
|
|||||||
/// For LEGACY addresses, returns the wallet's legacy derivation base (derivationInfo.derivationPath)
|
/// For LEGACY addresses, returns the wallet's legacy derivation base (derivationInfo.derivationPath)
|
||||||
/// which is already the account path used historically (e.g. m/0' or m/84'/0'/0').
|
/// which is already the account path used historically (e.g. m/0' or m/84'/0'/0').
|
||||||
String _accountDerivationPathForRecord(BaseBitcoinAddressRecord record) {
|
String _accountDerivationPathForRecord(BaseBitcoinAddressRecord record) {
|
||||||
|
|
||||||
if (derivationInfo.derivationType == DerivationType.electrum) {
|
if (derivationInfo.derivationType == DerivationType.electrum) {
|
||||||
return derivationInfo.derivationPath ?? electrum_path; // m/0'
|
return derivationInfo.derivationPath ?? electrum_path; // m/0'
|
||||||
}
|
}
|
||||||
@@ -873,7 +871,8 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
BigInt get networkDustAmount => BigInt.from(546);
|
BigInt get networkDustAmount => BigInt.from(546);
|
||||||
|
|
||||||
bool _isBelowDust(BigInt amount) => amount <= networkDustAmount && network != BitcoinNetwork.testnet;
|
bool _isBelowDust(BigInt amount) =>
|
||||||
|
amount <= networkDustAmount && network != BitcoinNetwork.testnet;
|
||||||
|
|
||||||
UtxoDetails _createUTXOS({
|
UtxoDetails _createUTXOS({
|
||||||
required bool sendAll,
|
required bool sendAll,
|
||||||
@@ -961,8 +960,7 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
final baseDerivationPath = _accountDerivationPathForRecord(utx.bitcoinAddressRecord);
|
final baseDerivationPath = _accountDerivationPathForRecord(utx.bitcoinAddressRecord);
|
||||||
|
|
||||||
final derivationPath =
|
final derivationPath = "${_hardenedDerivationPath(baseDerivationPath)}"
|
||||||
"${_hardenedDerivationPath(baseDerivationPath)}"
|
|
||||||
"/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}"
|
"/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}"
|
||||||
"/${utx.bitcoinAddressRecord.index}";
|
"/${utx.bitcoinAddressRecord.index}";
|
||||||
publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath);
|
publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath);
|
||||||
@@ -1139,7 +1137,8 @@ abstract class ElectrumWalletBase
|
|||||||
utxoDetails.utxos.length ==
|
utxoDetails.utxos.length ==
|
||||||
utxoDetails.availableInputs.length - utxoDetails.unconfirmedCoins.length;
|
utxoDetails.availableInputs.length - utxoDetails.unconfirmedCoins.length;
|
||||||
|
|
||||||
final amountLeftForChangeAndFee = utxoDetails.allInputsAmount - credentialsAmount.amount.toInt();
|
final amountLeftForChangeAndFee =
|
||||||
|
utxoDetails.allInputsAmount - credentialsAmount.amount.toInt();
|
||||||
|
|
||||||
if (amountLeftForChangeAndFee <= 0) {
|
if (amountLeftForChangeAndFee <= 0) {
|
||||||
if (!spendingAllCoins) {
|
if (!spendingAllCoins) {
|
||||||
@@ -1175,11 +1174,9 @@ abstract class ElectrumWalletBase
|
|||||||
isChange: true,
|
isChange: true,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
// Must match the address' account root (purpose/coinType) and legacy derivation when applicable.
|
// Must match the address' account root (purpose/coinType) and legacy derivation when applicable.
|
||||||
final changeBaseDerivationPath = _accountDerivationPathForRecord(changeAddress);
|
final changeBaseDerivationPath = _accountDerivationPathForRecord(changeAddress);
|
||||||
final changeDerivationPath =
|
final changeDerivationPath = "${_hardenedDerivationPath(changeBaseDerivationPath)}"
|
||||||
"${_hardenedDerivationPath(changeBaseDerivationPath)}"
|
|
||||||
"/${changeAddress.isHidden ? "1" : "0"}"
|
"/${changeAddress.isHidden ? "1" : "0"}"
|
||||||
"/${changeAddress.index}";
|
"/${changeAddress.index}";
|
||||||
utxoDetails.publicKeys[address.pubKeyHash()] =
|
utxoDetails.publicKeys[address.pubKeyHash()] =
|
||||||
@@ -1242,7 +1239,8 @@ abstract class ElectrumWalletBase
|
|||||||
inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
|
inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
|
||||||
vinOutpoints: utxoDetails.vinOutpoints,
|
vinOutpoints: utxoDetails.vinOutpoints,
|
||||||
);
|
);
|
||||||
final leftover = utxoDetails.allInputsAmount - credentialsAmount.amount.toInt() - feeNoChange;
|
final leftover =
|
||||||
|
utxoDetails.allInputsAmount - credentialsAmount.amount.toInt() - feeNoChange;
|
||||||
|
|
||||||
if (leftover >= 0) {
|
if (leftover >= 0) {
|
||||||
final finalFee = feeNoChange + leftover; // absorb tiny remainder
|
final finalFee = feeNoChange + leftover; // absorb tiny remainder
|
||||||
@@ -1833,7 +1831,6 @@ abstract class ElectrumWalletBase
|
|||||||
return Future.wait(addressFutures);
|
return Future.wait(addressFutures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<List<List<BitcoinUnspent>?>> _fetchUnspentsBatch(
|
Future<List<List<BitcoinUnspent>?>> _fetchUnspentsBatch(
|
||||||
List<BitcoinAddressRecord> addresses,
|
List<BitcoinAddressRecord> addresses,
|
||||||
) async {
|
) async {
|
||||||
@@ -2131,10 +2128,7 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
final hd = _hdFor(record: addressRecord);
|
final hd = _hdFor(record: addressRecord);
|
||||||
|
|
||||||
final privkey = generateECPrivate(
|
final privkey = generateECPrivate(hd: hd, index: addressRecord.index, network: network);
|
||||||
hd: hd,
|
|
||||||
index: addressRecord.index,
|
|
||||||
network: network);
|
|
||||||
|
|
||||||
privateKeys.add(privkey);
|
privateKeys.add(privkey);
|
||||||
|
|
||||||
@@ -2197,8 +2191,7 @@ abstract class ElectrumWalletBase
|
|||||||
final deduction = (outputAmount - networkDustAmount >= remainingFee)
|
final deduction = (outputAmount - networkDustAmount >= remainingFee)
|
||||||
? remainingFee
|
? remainingFee
|
||||||
: outputAmount - networkDustAmount;
|
: outputAmount - networkDustAmount;
|
||||||
outputs[i] = BitcoinOutput(
|
outputs[i] = BitcoinOutput(address: output.address, value: outputAmount - deduction);
|
||||||
address: output.address, value: outputAmount - deduction);
|
|
||||||
remainingFee -= deduction;
|
remainingFee -= deduction;
|
||||||
|
|
||||||
if (remainingFee <= BigInt.zero) break;
|
if (remainingFee <= BigInt.zero) break;
|
||||||
@@ -2464,7 +2457,8 @@ abstract class ElectrumWalletBase
|
|||||||
@override
|
@override
|
||||||
Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
|
Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
|
||||||
try {
|
try {
|
||||||
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};;
|
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
|
||||||
|
;
|
||||||
|
|
||||||
printV('[BATCH_TEST] Fetching transactions with batch: $shouldUseBatchFetching');
|
printV('[BATCH_TEST] Fetching transactions with batch: $shouldUseBatchFetching');
|
||||||
|
|
||||||
@@ -2473,19 +2467,16 @@ abstract class ElectrumWalletBase
|
|||||||
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
||||||
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
} else if (type == WalletType.bitcoinCash) {
|
} else if (type == WalletType.bitcoinCash) {
|
||||||
await Future.wait(BITCOIN_CASH_ADDRESS_TYPES
|
await Future.wait(BITCOIN_CASH_ADDRESS_TYPES.map((type) => shouldUseBatchFetching
|
||||||
.map((type) => shouldUseBatchFetching
|
|
||||||
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
||||||
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
} else if (type == WalletType.litecoin) {
|
} else if (type == WalletType.litecoin) {
|
||||||
await Future.wait(LITECOIN_ADDRESS_TYPES
|
await Future.wait(LITECOIN_ADDRESS_TYPES.where((type) => type != SegwitAddresType.mweb).map(
|
||||||
.where((type) => type != SegwitAddresType.mweb)
|
(type) => shouldUseBatchFetching
|
||||||
.map((type) => shouldUseBatchFetching
|
|
||||||
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
||||||
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
} else if (type == WalletType.dogecoin) {
|
} else if (type == WalletType.dogecoin) {
|
||||||
await Future.wait(DOGECOIN_ADDRESS_TYPES
|
await Future.wait(DOGECOIN_ADDRESS_TYPES.map((type) => shouldUseBatchFetching
|
||||||
.map((type) => shouldUseBatchFetching
|
|
||||||
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
|
||||||
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
: fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
}
|
}
|
||||||
@@ -2633,8 +2624,7 @@ abstract class ElectrumWalletBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchTransactionsForAddressTypeBatch(
|
Future<void> fetchTransactionsForAddressTypeBatch(
|
||||||
Map<String, ElectrumTransactionInfo> historiesWithDetails,
|
Map<String, ElectrumTransactionInfo> historiesWithDetails, BitcoinAddressType type) async {
|
||||||
BitcoinAddressType type) async {
|
|
||||||
final addressesByType =
|
final addressesByType =
|
||||||
walletAddresses.allAddresses.where((addr) => addr.type == type).toList();
|
walletAddresses.allAddresses.where((addr) => addr.type == type).toList();
|
||||||
final receiveAddresses = addressesByType.where((addr) => !addr.isHidden).toList();
|
final receiveAddresses = addressesByType.where((addr) => !addr.isHidden).toList();
|
||||||
@@ -2676,7 +2666,6 @@ abstract class ElectrumWalletBase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> fetchTransactionsForAddressesBranchBatch(
|
Future<void> fetchTransactionsForAddressesBranchBatch(
|
||||||
Map<String, ElectrumTransactionInfo> historiesWithDetails,
|
Map<String, ElectrumTransactionInfo> historiesWithDetails,
|
||||||
BitcoinAddressType type,
|
BitcoinAddressType type,
|
||||||
@@ -2714,7 +2703,6 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
if (!shouldDiscover) return;
|
if (!shouldDiscover) return;
|
||||||
|
|
||||||
|
|
||||||
final newAddresses = await walletAddresses.discoverAddressesBatch(
|
final newAddresses = await walletAddresses.discoverAddressesBatch(
|
||||||
currentBranch,
|
currentBranch,
|
||||||
isHidden,
|
isHidden,
|
||||||
@@ -2756,9 +2744,7 @@ abstract class ElectrumWalletBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, ElectrumTransactionInfo>> _fetchBatchAddressHistory(
|
Future<Map<String, ElectrumTransactionInfo>> _fetchBatchAddressHistory(
|
||||||
List<BitcoinAddressRecord> addressRecords,
|
List<BitcoinAddressRecord> addressRecords, int? currentHeight, int historyChunkSize) async {
|
||||||
int? currentHeight,
|
|
||||||
int historyChunkSize) async {
|
|
||||||
String lastTxId = '';
|
String lastTxId = '';
|
||||||
bool didUpdateHistory = false;
|
bool didUpdateHistory = false;
|
||||||
|
|
||||||
@@ -2770,10 +2756,7 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
final historyByScriptHash =
|
final historyByScriptHash =
|
||||||
await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
|
await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
|
||||||
items: scriptHashes,
|
items: scriptHashes, chunkSize: historyChunkSize, processChunk: _getHistoryBatch);
|
||||||
chunkSize: historyChunkSize,
|
|
||||||
processChunk: _getHistoryBatch
|
|
||||||
);
|
|
||||||
|
|
||||||
// Map scriptHash -> addressRecord
|
// Map scriptHash -> addressRecord
|
||||||
final byScriptHash = <String, BitcoinAddressRecord>{};
|
final byScriptHash = <String, BitcoinAddressRecord>{};
|
||||||
@@ -2869,8 +2852,7 @@ abstract class ElectrumWalletBase
|
|||||||
.toList(growable: false);
|
.toList(growable: false);
|
||||||
|
|
||||||
final heightsByHash = <String, int?>{
|
final heightsByHash = <String, int?>{
|
||||||
for (final e in chunkHistory)
|
for (final e in chunkHistory) (e['tx_hash'] as String): (e['height'] as int?),
|
||||||
(e['tx_hash'] as String): (e['height'] as int?),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
final infosByHash = await fetchTransactionInfoBatch(
|
final infosByHash = await fetchTransactionInfoBatch(
|
||||||
@@ -2909,40 +2891,35 @@ abstract class ElectrumWalletBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, Map<String, dynamic>>> _getTransactionVerboseBatch(
|
Future<Map<String, Map<String, dynamic>>> _getTransactionVerboseBatch(List<String> hashes) {
|
||||||
List<String> hashes) {
|
|
||||||
return electrumClient.getBatchTransactionVerbose(
|
return electrumClient.getBatchTransactionVerbose(
|
||||||
hashes,
|
hashes,
|
||||||
timeout: transactionBatchTimeoutMs,
|
timeout: transactionBatchTimeoutMs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, String?>> _getTransactionHexBatch(
|
Future<Map<String, String?>> _getTransactionHexBatch(List<String> hashes) {
|
||||||
List<String> hashes) {
|
|
||||||
return electrumClient.getBatchTransactionHex(
|
return electrumClient.getBatchTransactionHex(
|
||||||
hashes,
|
hashes,
|
||||||
timeout: transactionBatchTimeoutMs,
|
timeout: transactionBatchTimeoutMs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, List<Map<String, dynamic>>>> _getHistoryBatch(
|
Future<Map<String, List<Map<String, dynamic>>>> _getHistoryBatch(List<String> scriptHashes) {
|
||||||
List<String> scriptHashes) {
|
|
||||||
return electrumClient.getBatchHistory(
|
return electrumClient.getBatchHistory(
|
||||||
scriptHashes,
|
scriptHashes,
|
||||||
timeout: transactionBatchTimeoutMs,
|
timeout: transactionBatchTimeoutMs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, List<Map<String, dynamic>>>> _getListUnspentBatch(
|
Future<Map<String, List<Map<String, dynamic>>>> _getListUnspentBatch(List<String> scriptHashes) {
|
||||||
List<String> scriptHashes) {
|
|
||||||
return electrumClient.getBatchUnspent(
|
return electrumClient.getBatchUnspent(
|
||||||
scriptHashes,
|
scriptHashes,
|
||||||
timeout: transactionBatchTimeoutMs,
|
timeout: transactionBatchTimeoutMs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, Map<String, dynamic>>> _getBalanceBatch(
|
Future<Map<String, Map<String, dynamic>>> _getBalanceBatch(List<String> scriptHashes) {
|
||||||
List<String> scriptHashes) {
|
|
||||||
return electrumClient.getBatchBalance(
|
return electrumClient.getBatchBalance(
|
||||||
scriptHashes,
|
scriptHashes,
|
||||||
timeout: transactionBatchTimeoutMs,
|
timeout: transactionBatchTimeoutMs,
|
||||||
@@ -2956,8 +2933,7 @@ abstract class ElectrumWalletBase
|
|||||||
Duration retryDelay = const Duration(seconds: 2),
|
Duration retryDelay = const Duration(seconds: 2),
|
||||||
}) async {
|
}) async {
|
||||||
final result = <String, ElectrumTransactionInfo?>{};
|
final result = <String, ElectrumTransactionInfo?>{};
|
||||||
final uniqueHashes =
|
final uniqueHashes = hashes.map((h) => h.trim()).where((h) => h.isNotEmpty).toSet().toList();
|
||||||
hashes.map((h) => h.trim()).where((h) => h.isNotEmpty).toSet().toList();
|
|
||||||
|
|
||||||
if (uniqueHashes.isEmpty) return result;
|
if (uniqueHashes.isEmpty) return result;
|
||||||
|
|
||||||
@@ -2990,9 +2966,8 @@ abstract class ElectrumWalletBase
|
|||||||
required Map<String, int?>? heightsByHash,
|
required Map<String, int?>? heightsByHash,
|
||||||
}) async {
|
}) async {
|
||||||
for (var i = 0; i < txIds.length; i += transactionChunkSize) {
|
for (var i = 0; i < txIds.length; i += transactionChunkSize) {
|
||||||
final end = (i + transactionChunkSize < txIds.length)
|
final end =
|
||||||
? i + transactionChunkSize
|
(i + transactionChunkSize < txIds.length) ? i + transactionChunkSize : txIds.length;
|
||||||
: txIds.length;
|
|
||||||
final chunk = txIds.sublist(i, end);
|
final chunk = txIds.sublist(i, end);
|
||||||
|
|
||||||
final bundlesByHash = await getTransactionExpandedBatch(
|
final bundlesByHash = await getTransactionExpandedBatch(
|
||||||
@@ -3024,9 +2999,8 @@ abstract class ElectrumWalletBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, ElectrumTransactionBundle>> getTransactionExpandedBatch({
|
Future<Map<String, ElectrumTransactionBundle>> getTransactionExpandedBatch(
|
||||||
required List<String> hashes,
|
{required List<String> hashes, Map<String, int?>? heightsByHash}) async {
|
||||||
Map<String, int?>? heightsByHash}) async {
|
|
||||||
final bundles = <String, ElectrumTransactionBundle>{};
|
final bundles = <String, ElectrumTransactionBundle>{};
|
||||||
if (hashes.isEmpty) return bundles;
|
if (hashes.isEmpty) return bundles;
|
||||||
|
|
||||||
@@ -3062,8 +3036,8 @@ abstract class ElectrumWalletBase
|
|||||||
|
|
||||||
Future<Map<String, Map<String, dynamic>>> _fetchTransactionVerboseBatch(
|
Future<Map<String, Map<String, dynamic>>> _fetchTransactionVerboseBatch(
|
||||||
List<String> txIds) async {
|
List<String> txIds) async {
|
||||||
|
final verboseTransactionByHash =
|
||||||
final verboseTransactionByHash = await _processChunksToMap<String, String, Map<String, dynamic>>(
|
await _processChunksToMap<String, String, Map<String, dynamic>>(
|
||||||
items: txIds,
|
items: txIds,
|
||||||
chunkSize: transactionChunkSize,
|
chunkSize: transactionChunkSize,
|
||||||
processChunk: _getTransactionVerboseBatch,
|
processChunk: _getTransactionVerboseBatch,
|
||||||
@@ -3116,7 +3090,6 @@ abstract class ElectrumWalletBase
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Map<String, List<String>> _collectInputTxIdsByHash(
|
Map<String, List<String>> _collectInputTxIdsByHash(
|
||||||
Map<String, BtcTransaction> originalByHash,
|
Map<String, BtcTransaction> originalByHash,
|
||||||
) {
|
) {
|
||||||
@@ -3276,7 +3249,6 @@ abstract class ElectrumWalletBase
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> updateTransactions() async {
|
Future<void> updateTransactions() async {
|
||||||
printV("updateTransactions() called!");
|
printV("updateTransactions() called!");
|
||||||
try {
|
try {
|
||||||
@@ -3368,8 +3340,7 @@ abstract class ElectrumWalletBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final balancesByScriptHash =
|
final balancesByScriptHash = await _processChunksToMap<String, String, Map<String, dynamic>>(
|
||||||
await _processChunksToMap<String, String, Map<String, dynamic>>(
|
|
||||||
items: scriptHashes,
|
items: scriptHashes,
|
||||||
chunkSize: addressHistoryChunkSize,
|
chunkSize: addressHistoryChunkSize,
|
||||||
processChunk: _getBalanceBatch,
|
processChunk: _getBalanceBatch,
|
||||||
@@ -3415,7 +3386,8 @@ abstract class ElectrumWalletBase
|
|||||||
? await fetchBalancesBatch(addresses)
|
? await fetchBalancesBatch(addresses)
|
||||||
: await fetchBalancesRegular(addresses);
|
: await fetchBalancesRegular(addresses);
|
||||||
|
|
||||||
printV('Fetched balances for ${addresses.length} addresses. Batch fetching: $shouldUseBatchFetching');
|
printV(
|
||||||
|
'Fetched balances for ${addresses.length} addresses. Batch fetching: $shouldUseBatchFetching');
|
||||||
|
|
||||||
var totalFrozen = 0;
|
var totalFrozen = 0;
|
||||||
var totalConfirmed = 0;
|
var totalConfirmed = 0;
|
||||||
@@ -3545,16 +3517,13 @@ abstract class ElectrumWalletBase
|
|||||||
for (final tx2 in transactionHistory.transactions.values) {
|
for (final tx2 in transactionHistory.transactions.values) {
|
||||||
final heightDiff = ((tx2.height ?? 0) - (tx.height ?? 0)).abs();
|
final heightDiff = ((tx2.height ?? 0) - (tx.height ?? 0)).abs();
|
||||||
// this isn't a perfect matching algorithm since we don't have the right input/output information from these transaction models (the addresses are in different formats), but this should be more than good enough for now as it's extremely unlikely a user receives the EXACT same amount from 2 different sources and one of them is a peg out and the other isn't WITHIN 5 blocks of each other
|
// this isn't a perfect matching algorithm since we don't have the right input/output information from these transaction models (the addresses are in different formats), but this should be more than good enough for now as it's extremely unlikely a user receives the EXACT same amount from 2 different sources and one of them is a peg out and the other isn't WITHIN 5 blocks of each other
|
||||||
if (tx2.additionalInfo["isPegOut"] == true &&
|
if (tx2.additionalInfo["isPegOut"] == true && tx2.amount == tx.amount && heightDiff <= 5) {
|
||||||
tx2.amount == tx.amount &&
|
|
||||||
heightDiff <= 5) {
|
|
||||||
tx.additionalInfo["fromPegOut"] = true;
|
tx.additionalInfo["fromPegOut"] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> checkIfBatchSupported() async {
|
Future<void> checkIfBatchSupported() async {
|
||||||
|
|
||||||
if (_isBatchSupported != null) {
|
if (_isBatchSupported != null) {
|
||||||
printV('[BATCH_TEST] Already checked: $_isBatchSupported');
|
printV('[BATCH_TEST] Already checked: $_isBatchSupported');
|
||||||
return;
|
return;
|
||||||
@@ -3580,9 +3549,7 @@ abstract class ElectrumWalletBase
|
|||||||
);
|
);
|
||||||
|
|
||||||
final hasError = result.any((item) =>
|
final hasError = result.any((item) =>
|
||||||
item is Map<String, dynamic> &&
|
item is Map<String, dynamic> && item.containsKey('error') && item['error'] != null);
|
||||||
item.containsKey('error') &&
|
|
||||||
item['error'] != null);
|
|
||||||
|
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
_isBatchSupported = false;
|
_isBatchSupported = false;
|
||||||
|
|||||||
@@ -199,9 +199,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
"Error: Unable to fetch your Lightning address, please check your network connection.";
|
"Error: Unable to fetch your Lightning address, please check your network connection.";
|
||||||
}
|
}
|
||||||
|
|
||||||
final typeMatchingAddressesAll = _addresses
|
final typeMatchingAddressesAll =
|
||||||
.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr))
|
_addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
// Prefer standard derivation addresses for the current/active address,
|
// Prefer standard derivation addresses for the current/active address,
|
||||||
// but keep legacy addresses present in the overall address lists.
|
// but keep legacy addresses present in the overall address lists.
|
||||||
@@ -210,8 +209,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
...typeMatchingAddressesAll.where((a) => a.isLegacyDerivation),
|
...typeMatchingAddressesAll.where((a) => a.isLegacyDerivation),
|
||||||
];
|
];
|
||||||
|
|
||||||
final typeMatchingReceiveAddressesAll =
|
final typeMatchingReceiveAddressesAll = typeMatchingAddressesAll
|
||||||
typeMatchingAddressesAll.where((addr) => !addr.isUsed && !hiddenAddresses.contains(addr.address)).toList();
|
.where((addr) => !addr.isUsed && !hiddenAddresses.contains(addr.address))
|
||||||
|
.toList();
|
||||||
final typeMatchingReceiveAddresses = <BitcoinAddressRecord>[
|
final typeMatchingReceiveAddresses = <BitcoinAddressRecord>[
|
||||||
...typeMatchingReceiveAddressesAll.where((a) => !a.isLegacyDerivation),
|
...typeMatchingReceiveAddressesAll.where((a) => !a.isLegacyDerivation),
|
||||||
...typeMatchingReceiveAddressesAll.where((a) => a.isLegacyDerivation),
|
...typeMatchingReceiveAddressesAll.where((a) => a.isLegacyDerivation),
|
||||||
@@ -372,7 +372,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh, isLegacyDerivation: true);
|
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh, isLegacyDerivation: true);
|
||||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||||
|
|
||||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh, isLegacyDerivation: true);
|
await _generateInitialAddresses(
|
||||||
|
type: P2shAddressType.p2wpkhInP2sh, isLegacyDerivation: true);
|
||||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
||||||
|
|
||||||
await _generateInitialAddresses(type: SegwitAddresType.p2tr, isLegacyDerivation: true);
|
await _generateInitialAddresses(type: SegwitAddresType.p2tr, isLegacyDerivation: true);
|
||||||
@@ -680,9 +681,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
@action
|
@action
|
||||||
void updateReceiveAddresses() {
|
void updateReceiveAddresses() {
|
||||||
receiveAddresses.removeRange(0, receiveAddresses.length);
|
receiveAddresses.removeRange(0, receiveAddresses.length);
|
||||||
final newAddresses = _addresses.where((addressRecord) =>
|
final newAddresses =
|
||||||
!addressRecord.isHidden &&
|
_addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
|
||||||
!addressRecord.isUsed);
|
|
||||||
receiveAddresses.addAll(newAddresses);
|
receiveAddresses.addAll(newAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,8 +716,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
addAddresses(newAddresses);
|
addAddresses(newAddresses);
|
||||||
addressList.addAll(newAddresses);
|
addressList.addAll(newAddresses);
|
||||||
|
|
||||||
final addressesWithHistory =
|
final addressesWithHistory = await Future.wait(newAddresses.map(getAddressHistory));
|
||||||
await Future.wait(newAddresses.map(getAddressHistory));
|
|
||||||
final isLastAddressUsed = addressesWithHistory.last != null;
|
final isLastAddressUsed = addressesWithHistory.last != null;
|
||||||
|
|
||||||
if (isLastAddressUsed) {
|
if (isLastAddressUsed) {
|
||||||
@@ -750,8 +749,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
|
|
||||||
final usedAddresses = await getUsedAddresses(newAddresses);
|
final usedAddresses = await getUsedAddresses(newAddresses);
|
||||||
|
|
||||||
final hasUsedAddressInGap = newAddresses.any(
|
final hasUsedAddressInGap =
|
||||||
(addressRecord) => usedAddresses.contains(addressRecord.address));
|
newAddresses.any((addressRecord) => usedAddresses.contains(addressRecord.address));
|
||||||
|
|
||||||
if (!hasUsedAddressInGap) {
|
if (!hasUsedAddressInGap) {
|
||||||
return newAddresses;
|
return newAddresses;
|
||||||
@@ -770,11 +769,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
return [...newAddresses, ...moreNewAddresses];
|
return [...newAddresses, ...moreNewAddresses];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _generateInitialAddresses(
|
Future<void> _generateInitialAddresses(
|
||||||
{BitcoinAddressType type = SegwitAddresType.p2wpkh,
|
{BitcoinAddressType type = SegwitAddresType.p2wpkh, bool isLegacyDerivation = false}) async {
|
||||||
bool isLegacyDerivation = false }) async {
|
|
||||||
|
|
||||||
// Legacy derivation produces the same addresses as standard for these types.
|
// Legacy derivation produces the same addresses as standard for these types.
|
||||||
// Don't generate a legacy set to avoid duplicates.
|
// Don't generate a legacy set to avoid duplicates.
|
||||||
if (isLegacyDerivation && (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh)) {
|
if (isLegacyDerivation && (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh)) {
|
||||||
@@ -797,24 +793,32 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
|
if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
|
||||||
final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
|
final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
|
||||||
final newAddresses = await _createNewAddresses(addressesCount,
|
final newAddresses = await _createNewAddresses(addressesCount,
|
||||||
startIndex: countOfReceiveAddresses, isHidden: false, type: type, isLegacyDerivation: isLegacyDerivation);
|
startIndex: countOfReceiveAddresses,
|
||||||
|
isHidden: false,
|
||||||
|
type: type,
|
||||||
|
isLegacyDerivation: isLegacyDerivation);
|
||||||
addAddresses(newAddresses);
|
addAddresses(newAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (countOfHiddenAddresses < defaultChangeAddressesCount) {
|
if (countOfHiddenAddresses < defaultChangeAddressesCount) {
|
||||||
final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
|
final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
|
||||||
final newAddresses = await _createNewAddresses(addressesCount,
|
final newAddresses = await _createNewAddresses(addressesCount,
|
||||||
startIndex: countOfHiddenAddresses, isHidden: true, type: type, isLegacyDerivation: isLegacyDerivation);
|
startIndex: countOfHiddenAddresses,
|
||||||
|
isHidden: true,
|
||||||
|
type: type,
|
||||||
|
isLegacyDerivation: isLegacyDerivation);
|
||||||
addAddresses(newAddresses);
|
addAddresses(newAddresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
|
Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
|
||||||
{int startIndex = 0, bool isHidden = false, BitcoinAddressType? type, bool isLegacyDerivation = false}) async {
|
{int startIndex = 0,
|
||||||
|
bool isHidden = false,
|
||||||
|
BitcoinAddressType? type,
|
||||||
|
bool isLegacyDerivation = false}) async {
|
||||||
final list = <BitcoinAddressRecord>[];
|
final list = <BitcoinAddressRecord>[];
|
||||||
|
|
||||||
for (var i = startIndex; i < count + startIndex; i++) {
|
for (var i = startIndex; i < count + startIndex; i++) {
|
||||||
|
|
||||||
final addrType = type ?? addressPageType;
|
final addrType = type ?? addressPageType;
|
||||||
final hd = _hdFor(isHidden: isHidden, type: addrType, isLegacyDerivation: isLegacyDerivation);
|
final hd = _hdFor(isHidden: isHidden, type: addrType, isLegacyDerivation: isLegacyDerivation);
|
||||||
|
|
||||||
@@ -868,8 +872,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final mainHd = _hdFor(isHidden: false, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
|
final mainHd = _hdFor(
|
||||||
final sideHd = _hdFor(isHidden: true, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
|
isHidden: false, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
|
||||||
|
final sideHd = _hdFor(
|
||||||
|
isHidden: true, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
|
||||||
if (!element.isHidden &&
|
if (!element.isHidden &&
|
||||||
element.address !=
|
element.address !=
|
||||||
await getAddressAsync(index: element.index, hd: mainHd, addressType: element.type)) {
|
await getAddressAsync(index: element.index, hd: mainHd, addressType: element.type)) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class BitcoinTransactionCommitFailed extends TransactionCommitFailed {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return errorMessage??"unknown error";
|
return errorMessage ?? "unknown error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ class BitcoinBitboxService extends HardwareWalletService with BitcoinHardwareWal
|
|||||||
Future<Uint8List> getMasterFingerprint() => manager.getMasterFingerprint();
|
Future<Uint8List> getMasterFingerprint() => manager.getMasterFingerprint();
|
||||||
}
|
}
|
||||||
|
|
||||||
class LitecoinBitboxService extends HardwareWalletService with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
|
class LitecoinBitboxService extends HardwareWalletService
|
||||||
|
with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
|
||||||
LitecoinBitboxService(this.manager);
|
LitecoinBitboxService(this.manager);
|
||||||
|
|
||||||
final BitboxManager manager;
|
final BitboxManager manager;
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import 'package:cw_core/hardware/hardware_wallet_service.dart';
|
|||||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
||||||
import 'package:ledger_litecoin/ledger_litecoin.dart';
|
import 'package:ledger_litecoin/ledger_litecoin.dart';
|
||||||
|
|
||||||
class LitecoinLedgerService extends HardwareWalletService with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
|
class LitecoinLedgerService extends HardwareWalletService
|
||||||
|
with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
|
||||||
LitecoinLedgerService(this.ledgerConnection)
|
LitecoinLedgerService(this.ledgerConnection)
|
||||||
: litecoinLedgerApp = LitecoinLedgerApp(ledgerConnection);
|
: litecoinLedgerApp = LitecoinLedgerApp(ledgerConnection);
|
||||||
|
|
||||||
@@ -53,7 +54,6 @@ class LitecoinLedgerService extends HardwareWalletService with BitcoinHardwareWa
|
|||||||
required List<PSBTReadyUtxoWithAddress> inputs,
|
required List<PSBTReadyUtxoWithAddress> inputs,
|
||||||
required Map<String, PublicKeyWithDerivationPath> publicKeys,
|
required Map<String, PublicKeyWithDerivationPath> publicKeys,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
final readyInputs = <LedgerTransaction>[];
|
final readyInputs = <LedgerTransaction>[];
|
||||||
for (final utxo in inputs) {
|
for (final utxo in inputs) {
|
||||||
final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
|
final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
|
||||||
|
|||||||
@@ -90,8 +90,7 @@ class LightningWallet {
|
|||||||
lnurlDomain: lnurlDomain,
|
lnurlDomain: lnurlDomain,
|
||||||
apiKey: apiKey,
|
apiKey: apiKey,
|
||||||
privateEnabledDefault: true,
|
privateEnabledDefault: true,
|
||||||
maxDepositClaimFee: MaxFee.rate(satPerVbyte: BigInt.from(5))
|
maxDepositClaimFee: MaxFee.rate(satPerVbyte: BigInt.from(5)));
|
||||||
);
|
|
||||||
|
|
||||||
final connectRequest = ConnectRequest(
|
final connectRequest = ConnectRequest(
|
||||||
config: config,
|
config: config,
|
||||||
@@ -105,8 +104,7 @@ class LightningWallet {
|
|||||||
_logStream ??= initLogging().asBroadcastStream();
|
_logStream ??= initLogging().asBroadcastStream();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final logFile = File("$appPath/lightning.log")
|
final logFile = File("$appPath/lightning.log")..createSync();
|
||||||
..createSync();
|
|
||||||
_subscribeToLogStream(logFile);
|
_subscribeToLogStream(logFile);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV(e);
|
||||||
@@ -198,15 +196,17 @@ class LightningWallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<PendingLightningTransaction> createTransaction(
|
Future<PendingLightningTransaction> createTransaction(String address, BigInt? amountSats,
|
||||||
String address, BigInt? amountSats, BitcoinTransactionPriority? priority, bool feesIncluded) async {
|
BitcoinTransactionPriority? priority, bool feesIncluded) async {
|
||||||
final inputType = await sdk.parse(input: address);
|
final inputType = await sdk.parse(input: address);
|
||||||
|
|
||||||
final feePolicy = feesIncluded ? FeePolicy.feesIncluded : FeePolicy.feesExcluded;
|
final feePolicy = feesIncluded ? FeePolicy.feesIncluded : FeePolicy.feesExcluded;
|
||||||
|
|
||||||
if (inputType is InputType_Bolt11Invoice) {
|
if (inputType is InputType_Bolt11Invoice) {
|
||||||
final request = PrepareSendPaymentRequest(
|
final request = PrepareSendPaymentRequest(
|
||||||
paymentRequest: inputType.field0.invoice.bolt11, amount: amountSats, feePolicy: feePolicy);
|
paymentRequest: inputType.field0.invoice.bolt11,
|
||||||
|
amount: amountSats,
|
||||||
|
feePolicy: feePolicy);
|
||||||
final prepareResponse = await sdk.prepareSendPayment(request: request);
|
final prepareResponse = await sdk.prepareSendPayment(request: request);
|
||||||
|
|
||||||
final paymentMethod = prepareResponse.paymentMethod;
|
final paymentMethod = prepareResponse.paymentMethod;
|
||||||
@@ -392,14 +392,16 @@ class LightningWallet {
|
|||||||
return _getElectrumTransactionInfoFromPayment(response.payment);
|
return _getElectrumTransactionInfoFromPayment(response.payment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> refundDeposit(String txId, int vout, String destinationAddress,
|
Future<String> refundDeposit(
|
||||||
BigInt feeRate) async {
|
String txId, int vout, String destinationAddress, BigInt feeRate) async {
|
||||||
final response = await sdk.refundDeposit(request: RefundDepositRequest(
|
final response = await sdk.refundDeposit(
|
||||||
|
request: RefundDepositRequest(
|
||||||
txid: txId,
|
txid: txId,
|
||||||
vout: vout,
|
vout: vout,
|
||||||
destinationAddress: destinationAddress,
|
destinationAddress: destinationAddress,
|
||||||
fee: Fee.rate(satPerVbyte: feeRate),
|
fee: Fee.rate(satPerVbyte: feeRate),
|
||||||
),);
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return response.txHex;
|
return response.txHex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ class PendingLightningTransaction with PendingTransaction {
|
|||||||
required this.commitOverride,
|
required this.commitOverride,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
final bool isSendAll;
|
final bool isSendAll;
|
||||||
Future<String> Function() commitOverride;
|
Future<String> Function() commitOverride;
|
||||||
final List<void Function()> _listeners =[];
|
final List<void Function()> _listeners = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String id;
|
String id;
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
@override
|
@override
|
||||||
bool get hasRescan => true;
|
bool get hasRescan => true;
|
||||||
|
|
||||||
|
|
||||||
final String? scanSecretOverride;
|
final String? scanSecretOverride;
|
||||||
final String? spendPubkeyOverride;
|
final String? spendPubkeyOverride;
|
||||||
List<int> get scanSecret => (scanSecretOverride != null && scanSecretOverride?.isNotEmpty == true)
|
List<int> get scanSecret => (scanSecretOverride != null && scanSecretOverride?.isNotEmpty == true)
|
||||||
@@ -232,8 +231,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletKeysData get walletKeysData =>
|
WalletKeysData get walletKeysData => WalletKeysData(
|
||||||
WalletKeysData(mnemonic: seed, xPub: xpub, passphrase: passphrase, scanSecret: scanSecretOverride, spendPubkey: spendPubkeyOverride);
|
mnemonic: seed,
|
||||||
|
xPub: xpub,
|
||||||
|
passphrase: passphrase,
|
||||||
|
scanSecret: scanSecretOverride,
|
||||||
|
spendPubkey: spendPubkeyOverride);
|
||||||
|
|
||||||
static Future<LitecoinWallet> open({
|
static Future<LitecoinWallet> open({
|
||||||
required String name,
|
required String name,
|
||||||
@@ -1106,12 +1109,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
for (final utxo in transaction.utxos) {
|
for (final utxo in transaction.utxos) {
|
||||||
if (utxo.utxo.scriptType != SegwitAddresType.mweb) {
|
if (utxo.utxo.scriptType != SegwitAddresType.mweb) {
|
||||||
inputs.add(utxo.utxo.toInput());
|
inputs.add(utxo.utxo.toInput());
|
||||||
txouts.add(TxOut(value: Int64(utxo.utxo.value.toInt()),
|
txouts.add(TxOut(
|
||||||
|
value: Int64(utxo.utxo.value.toInt()),
|
||||||
pkScript: utxo.ownerDetails.address.toScriptPubKey().toBytes()));
|
pkScript: utxo.ownerDetails.address.toScriptPubKey().toBytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var resp = await CwMweb.psbtCreate(PsbtCreateRequest(
|
var resp = await CwMweb.psbtCreate(PsbtCreateRequest(
|
||||||
rawTx: inputs.isEmpty ? null : BtcTransaction(
|
rawTx: inputs.isEmpty
|
||||||
|
? null
|
||||||
|
: BtcTransaction(
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
outputs: isMweb ? [] : transaction.outputs,
|
outputs: isMweb ? [] : transaction.outputs,
|
||||||
).toBytes(),
|
).toBytes(),
|
||||||
@@ -1127,7 +1133,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isMweb) for (final output in transaction.outputs) {
|
if (isMweb)
|
||||||
|
for (final output in transaction.outputs) {
|
||||||
var address = addressFromOutputScript(output.scriptPubKey, LitecoinNetwork.mainnet);
|
var address = addressFromOutputScript(output.scriptPubKey, LitecoinNetwork.mainnet);
|
||||||
if (output.scriptPubKey.getAddressType() == SegwitAddresType.mweb) {
|
if (output.scriptPubKey.getAddressType() == SegwitAddresType.mweb) {
|
||||||
address = SegwitBech32Encoder.encode("ltcmweb", 0, output.scriptPubKey.toBytes());
|
address = SegwitBech32Encoder.encode("ltcmweb", 0, output.scriptPubKey.toBytes());
|
||||||
@@ -1203,7 +1210,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
for (final utxo in tx.utxos) {
|
for (final utxo in tx.utxos) {
|
||||||
if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
|
if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
|
||||||
hasMwebInput = true;
|
hasMwebInput = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// check if any of the inputs of this transaction are hog-ex:
|
// check if any of the inputs of this transaction are hog-ex:
|
||||||
// this list is only non-mweb inputs:
|
// this list is only non-mweb inputs:
|
||||||
@@ -1256,9 +1262,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
final utxo = unspentCoins
|
final utxo = unspentCoins
|
||||||
.firstWhere((utxo) => utxo.hash == e.value.txId && utxo.vout == e.value.txIndex);
|
.firstWhere((utxo) => utxo.hash == e.value.txId && utxo.vout == e.value.txIndex);
|
||||||
final key = generateECPrivate(
|
final key = generateECPrivate(
|
||||||
hd: utxo.bitcoinAddressRecord.isHidden
|
hd: utxo.bitcoinAddressRecord.isHidden ? sideHd : mainHd,
|
||||||
? sideHd
|
|
||||||
: mainHd,
|
|
||||||
index: utxo.bitcoinAddressRecord.index,
|
index: utxo.bitcoinAddressRecord.index,
|
||||||
network: network);
|
network: network);
|
||||||
final digest = tx2.getTransactionSegwitDigit(
|
final digest = tx2.getTransactionSegwitDigit(
|
||||||
@@ -1284,8 +1288,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTransactionListener(PendingBitcoinTransaction tx,
|
void addTransactionListener(
|
||||||
List<String> inputAddresses, bool isPegIn, bool isPegOut) {
|
PendingBitcoinTransaction tx, List<String> inputAddresses, bool isPegIn, bool isPegOut) {
|
||||||
tx.addListener((transaction) async {
|
tx.addListener((transaction) async {
|
||||||
final addresses = <String>{};
|
final addresses = <String>{};
|
||||||
transaction.inputAddresses?.addAll(inputAddresses);
|
transaction.inputAddresses?.addAll(inputAddresses);
|
||||||
@@ -1575,7 +1579,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||||||
rawTx: rawTx,
|
rawTx: rawTx,
|
||||||
ownerDetails: utxo.ownerDetails,
|
ownerDetails: utxo.ownerDetails,
|
||||||
ownerDerivationPath: publicKeyAndDerivationPath.derivationPath,
|
ownerDerivationPath: publicKeyAndDerivationPath.derivationPath,
|
||||||
ownerMasterFingerprint:masterFingerprint,
|
ownerMasterFingerprint: masterFingerprint,
|
||||||
ownerPublicKey: publicKeyAndDerivationPath.publicKey,
|
ownerPublicKey: publicKeyAndDerivationPath.publicKey,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,9 +59,11 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||||||
? hex.decode(scanSecretOverride!)
|
? hex.decode(scanSecretOverride!)
|
||||||
: mwebHd?.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw ?? List.filled(32, 0);
|
: mwebHd?.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw ?? List.filled(32, 0);
|
||||||
|
|
||||||
List<int> get spendPubkey => (spendPubkeyOverride != null && spendPubkeyOverride?.isNotEmpty == true)
|
List<int> get spendPubkey =>
|
||||||
|
(spendPubkeyOverride != null && spendPubkeyOverride?.isNotEmpty == true)
|
||||||
? hex.decode(spendPubkeyOverride!)
|
? hex.decode(spendPubkeyOverride!)
|
||||||
: mwebHd?.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed ?? List.filled(32, 0);
|
: mwebHd?.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed ??
|
||||||
|
List.filled(32, 0);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
@@ -230,12 +232,16 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||||||
// don't use mweb addresses for exchange refund address:
|
// don't use mweb addresses for exchange refund address:
|
||||||
|
|
||||||
final current = getFreshAddress();
|
final current = getFreshAddress();
|
||||||
final bool isMweb = receiveAddresses
|
final bool isMweb =
|
||||||
.any((e) => e.address == current && e.type == SegwitAddresType.mweb);
|
receiveAddresses.any((e) => e.address == current && e.type == SegwitAddresType.mweb);
|
||||||
|
|
||||||
if (isMweb) {
|
if (isMweb) {
|
||||||
final segwit = receiveAddresses
|
final segwit = receiveAddresses
|
||||||
.where((e) => e.type == SegwitAddresType.p2wpkh && !e.isUsed && !e.isHidden && !hiddenAddresses.contains(e.address))
|
.where((e) =>
|
||||||
|
e.type == SegwitAddresType.p2wpkh &&
|
||||||
|
!e.isUsed &&
|
||||||
|
!e.isHidden &&
|
||||||
|
!hiddenAddresses.contains(e.address))
|
||||||
.map((e) => e.address)
|
.map((e) => e.address)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ class LitecoinWalletService extends WalletService<
|
|||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
passphrase: credentials.passphrase,
|
passphrase: credentials.passphrase,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
derivationInfo: credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
derivationInfo:
|
||||||
|
credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
@@ -64,7 +65,6 @@ class LitecoinWalletService extends WalletService<
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> openWallet(String name, String password) async {
|
Future<LitecoinWallet> openWallet(String name, String password) async {
|
||||||
|
|
||||||
final walletInfo = await WalletInfo.get(name, getType());
|
final walletInfo = await WalletInfo.get(name, getType());
|
||||||
if (walletInfo == null) {
|
if (walletInfo == null) {
|
||||||
throw Exception('Wallet not found');
|
throw Exception('Wallet not found');
|
||||||
@@ -125,8 +125,9 @@ class LitecoinWalletService extends WalletService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
|
final unspentCoinsToDelete = unspentCoinsInfoSource.values
|
||||||
(unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
|
.where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
|
||||||
|
.toList();
|
||||||
|
|
||||||
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
||||||
|
|
||||||
@@ -150,8 +151,7 @@ class LitecoinWalletService extends WalletService<
|
|||||||
final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
|
final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
|
||||||
credentials.walletInfo?.network = network.value;
|
credentials.walletInfo?.network = network.value;
|
||||||
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
||||||
derivationInfo.derivationPath =
|
derivationInfo.derivationPath = credentials.hwAccountData.derivationPath;
|
||||||
credentials.hwAccountData.derivationPath;
|
|
||||||
await derivationInfo.save();
|
await derivationInfo.save();
|
||||||
credentials.walletInfo!.save();
|
credentials.walletInfo!.save();
|
||||||
|
|
||||||
@@ -202,7 +202,8 @@ class LitecoinWalletService extends WalletService<
|
|||||||
passphrase: credentials.passphrase,
|
passphrase: credentials.passphrase,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
derivationInfo: credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
derivationInfo:
|
||||||
|
credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -108,16 +108,14 @@ class PayjoinManager {
|
|||||||
Future<Sender> initSender(
|
Future<Sender> initSender(
|
||||||
String pjUriString, String originalPsbt, int networkFeesSatPerVb) async {
|
String pjUriString, String originalPsbt, int networkFeesSatPerVb) async {
|
||||||
try {
|
try {
|
||||||
final pjUri =
|
final pjUri = (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
|
||||||
(await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
|
|
||||||
final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250);
|
final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250);
|
||||||
final senderBuilder = await SenderBuilder.fromPsbtAndUri(
|
final senderBuilder = await SenderBuilder.fromPsbtAndUri(
|
||||||
psbtBase64: originalPsbt,
|
psbtBase64: originalPsbt,
|
||||||
pjUri: pjUri,
|
pjUri: pjUri,
|
||||||
);
|
);
|
||||||
final persister = PayjoinSenderPersister.impl();
|
final persister = PayjoinSenderPersister.impl();
|
||||||
final newSender =
|
final newSender = await senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu);
|
||||||
await senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu);
|
|
||||||
final senderToken = await newSender.persist(persister: persister);
|
final senderToken = await newSender.persist(persister: persister);
|
||||||
|
|
||||||
return Sender.load(token: senderToken, persister: persister);
|
return Sender.load(token: senderToken, persister: persister);
|
||||||
@@ -133,8 +131,7 @@ class PayjoinManager {
|
|||||||
bool isTestnet = false,
|
bool isTestnet = false,
|
||||||
}) async {
|
}) async {
|
||||||
final pjUri = Uri.parse(pjUrl).queryParameters['pj']!;
|
final pjUri = Uri.parse(pjUrl).queryParameters['pj']!;
|
||||||
await _payjoinStorage.insertSenderSession(
|
await _payjoinStorage.insertSenderSession(sender, pjUri, _wallet.id, amount);
|
||||||
sender, pjUri, _wallet.id, amount);
|
|
||||||
|
|
||||||
return _spawnSender(isTestnet: isTestnet, sender: sender, pjUri: pjUri);
|
return _spawnSender(isTestnet: isTestnet, sender: sender, pjUri: pjUri);
|
||||||
}
|
}
|
||||||
@@ -207,8 +204,7 @@ class PayjoinManager {
|
|||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Receiver> getUnusedReceiver(String address,
|
Future<Receiver> getUnusedReceiver(String address, [bool isTestnet = false]) async {
|
||||||
[bool isTestnet = false]) async {
|
|
||||||
final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id);
|
final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id);
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
@@ -220,7 +216,8 @@ class PayjoinManager {
|
|||||||
return initReceiver(address);
|
return initReceiver(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Receiver> initReceiver(String address, [bool isTestnet = false, int retryCount = 0]) async {
|
Future<Receiver> initReceiver(String address,
|
||||||
|
[bool isTestnet = false, int retryCount = 0]) async {
|
||||||
if (retryCount > 0) writePayjoinLog("Retrying initReceiver ${retryCount + 1} attempt");
|
if (retryCount > 0) writePayjoinLog("Retrying initReceiver ${retryCount + 1} attempt");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -245,7 +242,6 @@ class PayjoinManager {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
writePayjoinLog(e.toString());
|
writePayjoinLog(e.toString());
|
||||||
if (e.toString().contains("error sending request for url") && retryCount < 5) {
|
if (e.toString().contains("error sending request for url") && retryCount < 5) {
|
||||||
|
|
||||||
return initReceiver(address, isTestnet, ++retryCount);
|
return initReceiver(address, isTestnet, ++retryCount);
|
||||||
} else {
|
} else {
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -273,13 +269,11 @@ class PayjoinManager {
|
|||||||
rawAmount = getOutputAmountFromTx(tx, _wallet);
|
rawAmount = getOutputAmountFromTx(tx, _wallet);
|
||||||
break;
|
break;
|
||||||
case PayjoinReceiverRequestTypes.checkIsOwned:
|
case PayjoinReceiverRequestTypes.checkIsOwned:
|
||||||
(_wallet.walletAddresses as BitcoinWalletAddresses)
|
(_wallet.walletAddresses as BitcoinWalletAddresses).newPayjoinReceiver();
|
||||||
.newPayjoinReceiver();
|
|
||||||
_payjoinStorage.markReceiverSessionInProgress(receiver.id());
|
_payjoinStorage.markReceiverSessionInProgress(receiver.id());
|
||||||
|
|
||||||
final inputScript = message['input_script'] as Uint8List;
|
final inputScript = message['input_script'] as Uint8List;
|
||||||
final isOwned =
|
final isOwned = _wallet.isMine(Script.fromRaw(byteData: inputScript));
|
||||||
_wallet.isMine(Script.fromRaw(byteData: inputScript));
|
|
||||||
mainToIsolateSendPort?.send({
|
mainToIsolateSendPort?.send({
|
||||||
'requestId': message['requestId'],
|
'requestId': message['requestId'],
|
||||||
'result': isOwned,
|
'result': isOwned,
|
||||||
@@ -288,8 +282,7 @@ class PayjoinManager {
|
|||||||
|
|
||||||
case PayjoinReceiverRequestTypes.checkIsReceiverOutput:
|
case PayjoinReceiverRequestTypes.checkIsReceiverOutput:
|
||||||
final outputScript = message['output_script'] as Uint8List;
|
final outputScript = message['output_script'] as Uint8List;
|
||||||
final isReceiverOutput =
|
final isReceiverOutput = _wallet.isMine(Script.fromRaw(byteData: outputScript));
|
||||||
_wallet.isMine(Script.fromRaw(byteData: outputScript));
|
|
||||||
mainToIsolateSendPort?.send({
|
mainToIsolateSendPort?.send({
|
||||||
'requestId': message['requestId'],
|
'requestId': message['requestId'],
|
||||||
'result': isReceiverOutput,
|
'result': isReceiverOutput,
|
||||||
@@ -310,7 +303,8 @@ class PayjoinManager {
|
|||||||
|
|
||||||
case PayjoinReceiverRequestTypes.processPsbt:
|
case PayjoinReceiverRequestTypes.processPsbt:
|
||||||
final psbt = message['psbt'] as String;
|
final psbt = message['psbt'] as String;
|
||||||
writePayjoinLog("Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.processPsbt: $psbt");
|
writePayjoinLog(
|
||||||
|
"Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.processPsbt: $psbt");
|
||||||
|
|
||||||
final signedPsbt = await _wallet.signPsbt(psbt, utxos);
|
final signedPsbt = await _wallet.signPsbt(psbt, utxos);
|
||||||
mainToIsolateSendPort?.send({
|
mainToIsolateSendPort?.send({
|
||||||
@@ -322,7 +316,8 @@ class PayjoinManager {
|
|||||||
case PayjoinReceiverRequestTypes.proposalSent:
|
case PayjoinReceiverRequestTypes.proposalSent:
|
||||||
_cleanupSession(receiver.id());
|
_cleanupSession(receiver.id());
|
||||||
final psbt = message['psbt'] as String;
|
final psbt = message['psbt'] as String;
|
||||||
writePayjoinLog("Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.proposalSent: $psbt");
|
writePayjoinLog(
|
||||||
|
"Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.proposalSent: $psbt");
|
||||||
|
|
||||||
await _payjoinStorage.markReceiverSessionComplete(
|
await _payjoinStorage.markReceiverSessionComplete(
|
||||||
receiver.id(), getTxIdFromPsbtV0(psbt), rawAmount);
|
receiver.id(), getTxIdFromPsbtV0(psbt), rawAmount);
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ class PayjoinReceiverWorker {
|
|||||||
try {
|
try {
|
||||||
final receiver = Receiver.fromJson(json: receiverJson);
|
final receiver = Receiver.fromJson(json: receiverJson);
|
||||||
|
|
||||||
final uncheckedProposal =
|
final uncheckedProposal = await worker.receiveUncheckedProposal(receiver);
|
||||||
await worker.receiveUncheckedProposal(receiver);
|
|
||||||
|
|
||||||
final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast();
|
final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast();
|
||||||
sendPort.send({
|
sendPort.send({
|
||||||
@@ -112,8 +111,7 @@ class PayjoinReceiverWorker {
|
|||||||
final httpRequest = await client.post(url,
|
final httpRequest = await client.post(url,
|
||||||
headers: {'Content-Type': request.contentType}, body: request.body);
|
headers: {'Content-Type': request.contentType}, body: request.body);
|
||||||
|
|
||||||
final proposal = await session.processRes(
|
final proposal = await session.processRes(body: httpRequest.bodyBytes, ctx: extractReq.$2);
|
||||||
body: httpRequest.bodyBytes, ctx: extractReq.$2);
|
|
||||||
if (proposal != null) return proposal;
|
if (proposal != null) return proposal;
|
||||||
sleep(Duration(seconds: 2));
|
sleep(Duration(seconds: 2));
|
||||||
}
|
}
|
||||||
@@ -140,8 +138,7 @@ class PayjoinReceiverWorker {
|
|||||||
return await finalProposal.psbt();
|
return await finalProposal.psbt();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<PayjoinProposal> processPayjoinProposal(
|
Future<PayjoinProposal> processPayjoinProposal(UncheckedProposal proposal) async {
|
||||||
UncheckedProposal proposal) async {
|
|
||||||
await proposal.extractTxToScheduleBroadcast();
|
await proposal.extractTxToScheduleBroadcast();
|
||||||
// TODO Handle this. send to the main port on a timer?
|
// TODO Handle this. send to the main port on a timer?
|
||||||
|
|
||||||
@@ -174,20 +171,17 @@ class PayjoinReceiverWorker {
|
|||||||
);
|
);
|
||||||
final pj5 = await pj4.commitOutputs();
|
final pj5 = await pj4.commitOutputs();
|
||||||
|
|
||||||
final listUnspent =
|
final listUnspent = await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
|
||||||
await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
|
|
||||||
final unspent = listUnspent as List<UtxoWithPrivateKey>;
|
final unspent = listUnspent as List<UtxoWithPrivateKey>;
|
||||||
if (unspent.isEmpty) throw RecoverableError('No unspent outputs available');
|
if (unspent.isEmpty) throw RecoverableError('No unspent outputs available');
|
||||||
|
|
||||||
final candidateInputs =
|
final candidateInputs = await Future.wait(unspent.map(_inputPairFromUtxo));
|
||||||
await Future.wait(unspent.map(_inputPairFromUtxo));
|
|
||||||
|
|
||||||
// Prefer a UTXO that avoids the Unnecessary Input Heuristic (UIH2);
|
// Prefer a UTXO that avoids the Unnecessary Input Heuristic (UIH2);
|
||||||
// fall back to the first candidate if none preserves privacy.
|
// fall back to the first candidate if none preserves privacy.
|
||||||
InputPair selectedUtxo = candidateInputs.first;
|
InputPair selectedUtxo = candidateInputs.first;
|
||||||
try {
|
try {
|
||||||
selectedUtxo =
|
selectedUtxo = await pj5.tryPreservingPrivacy(candidateInputs: candidateInputs);
|
||||||
await pj5.tryPreservingPrivacy(candidateInputs: candidateInputs);
|
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]);
|
final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]);
|
||||||
@@ -196,8 +190,8 @@ class PayjoinReceiverWorker {
|
|||||||
// Finalize proposal
|
// Finalize proposal
|
||||||
final payjoinProposal = await pj7.finalizeProposal(
|
final payjoinProposal = await pj7.finalizeProposal(
|
||||||
processPsbt: (String psbt) async {
|
processPsbt: (String psbt) async {
|
||||||
final result = await _sendRequest(
|
final result =
|
||||||
PayjoinReceiverRequestTypes.processPsbt, {'psbt': psbt});
|
await _sendRequest(PayjoinReceiverRequestTypes.processPsbt, {'psbt': psbt});
|
||||||
return result as String;
|
return result as String;
|
||||||
},
|
},
|
||||||
// TODO set maxFeeRateSatPerVb
|
// TODO set maxFeeRateSatPerVb
|
||||||
@@ -213,15 +207,12 @@ class PayjoinReceiverWorker {
|
|||||||
Future<InputPair> _inputPairFromUtxo(UtxoWithPrivateKey utxo) async {
|
Future<InputPair> _inputPairFromUtxo(UtxoWithPrivateKey utxo) async {
|
||||||
final txout = TxOut(
|
final txout = TxOut(
|
||||||
value: utxo.utxo.value,
|
value: utxo.utxo.value,
|
||||||
scriptPubkey: Uint8List.fromList(
|
scriptPubkey: Uint8List.fromList(utxo.ownerDetails.address.toScriptPubKey().toBytes()),
|
||||||
utxo.ownerDetails.address.toScriptPubKey().toBytes()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final psbtin =
|
final psbtin = PsbtInput(witnessUtxo: txout, redeemScript: null, witnessScript: null);
|
||||||
PsbtInput(witnessUtxo: txout, redeemScript: null, witnessScript: null);
|
|
||||||
|
|
||||||
final previousOutput =
|
final previousOutput = OutPoint(txid: utxo.utxo.txHash, vout: utxo.utxo.vout);
|
||||||
OutPoint(txid: utxo.utxo.txHash, vout: utxo.utxo.vout);
|
|
||||||
|
|
||||||
final txin = TxIn(
|
final txin = TxIn(
|
||||||
previousOutput: previousOutput,
|
previousOutput: previousOutput,
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ class PayjoinSenderWorker {
|
|||||||
sendPort.send(e);
|
sendPort.send(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final client = ProxyWrapper().getHttpIOClient();
|
final client = ProxyWrapper().getHttpIOClient();
|
||||||
|
|
||||||
/// Run a payjoin sender (V2 protocol first, fallback to V1).
|
/// Run a payjoin sender (V2 protocol first, fallback to V1).
|
||||||
Future<String> runSender(Sender sender) async {
|
Future<String> runSender(Sender sender) async {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await _runSenderV2(sender);
|
return await _runSenderV2(sender);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -70,13 +70,11 @@ class PayjoinSenderWorker {
|
|||||||
Future<String> _runSenderV2(Sender sender) async {
|
Future<String> _runSenderV2(Sender sender) async {
|
||||||
try {
|
try {
|
||||||
final postRequest = await sender.extractV2(
|
final postRequest = await sender.extractV2(
|
||||||
ohttpProxyUrl:
|
ohttpProxyUrl: await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()),
|
||||||
await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final postResult = await _postRequest(postRequest.$1);
|
final postResult = await _postRequest(postRequest.$1);
|
||||||
final getContext =
|
final getContext = await postRequest.$2.processResponse(response: postResult);
|
||||||
await postRequest.$2.processResponse(response: postResult);
|
|
||||||
|
|
||||||
sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted, "pj": pjUrl});
|
sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted, "pj": pjUrl});
|
||||||
|
|
||||||
|
|||||||
@@ -23,16 +23,14 @@ class PayjoinStorage {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
PayjoinSession? getUnusedActiveReceiverSession(String walletId) =>
|
PayjoinSession? getUnusedActiveReceiverSession(String walletId) => _payjoinSessionSources.values
|
||||||
_payjoinSessionSources.values
|
|
||||||
.where((session) =>
|
.where((session) =>
|
||||||
session.walletId == walletId &&
|
session.walletId == walletId &&
|
||||||
session.status == PayjoinSessionStatus.created.name &&
|
session.status == PayjoinSessionStatus.created.name &&
|
||||||
!session.isSenderSession)
|
!session.isSenderSession)
|
||||||
.firstOrNull;
|
.firstOrNull;
|
||||||
|
|
||||||
Future<void> markReceiverSessionComplete(
|
Future<void> markReceiverSessionComplete(String sessionId, String txId, String amount) async {
|
||||||
String sessionId, String txId, String amount) async {
|
|
||||||
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
||||||
|
|
||||||
session.status = PayjoinSessionStatus.success.name;
|
session.status = PayjoinSessionStatus.success.name;
|
||||||
@@ -41,8 +39,7 @@ class PayjoinStorage {
|
|||||||
await session.save();
|
await session.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> markReceiverSessionUnrecoverable(
|
Future<void> markReceiverSessionUnrecoverable(String sessionId, String reason) async {
|
||||||
String sessionId, String reason) async {
|
|
||||||
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
||||||
|
|
||||||
session.status = PayjoinSessionStatus.unrecoverable.name;
|
session.status = PayjoinSessionStatus.unrecoverable.name;
|
||||||
@@ -92,13 +89,10 @@ class PayjoinStorage {
|
|||||||
await session.save();
|
await session.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PayjoinSession> readAllOpenSessions(String walletId) =>
|
List<PayjoinSession> readAllOpenSessions(String walletId) => _payjoinSessionSources.values
|
||||||
_payjoinSessionSources.values
|
|
||||||
.where((session) =>
|
.where((session) =>
|
||||||
session.walletId == walletId &&
|
session.walletId == walletId &&
|
||||||
![
|
![PayjoinSessionStatus.success.name, PayjoinSessionStatus.unrecoverable.name]
|
||||||
PayjoinSessionStatus.success.name,
|
.contains(session.status))
|
||||||
PayjoinSessionStatus.unrecoverable.name
|
|
||||||
].contains(session.status))
|
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
return tx.buffer();
|
return tx.buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> signWithUTXO(
|
Future<void> signWithUTXO(List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
|
||||||
List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
|
|
||||||
[UTXOGetterCallBack? getTaprootPair]) async {
|
[UTXOGetterCallBack? getTaprootPair]) async {
|
||||||
final raw = BytesUtils.toHexString(extractUnsignedTX(getSegwit: false));
|
final raw = BytesUtils.toHexString(extractUnsignedTX(getSegwit: false));
|
||||||
final tx = BtcTransaction.fromRaw(raw);
|
final tx = BtcTransaction.fromRaw(raw);
|
||||||
@@ -53,8 +52,8 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
|
|
||||||
if (utxos.any((e) => e.utxo.isP2tr())) {
|
if (utxos.any((e) => e.utxo.isP2tr())) {
|
||||||
for (final input in tx.inputs) {
|
for (final input in tx.inputs) {
|
||||||
final utxo = utxos.firstWhereOrNull(
|
final utxo = utxos
|
||||||
(u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
|
.firstWhereOrNull((u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
|
||||||
|
|
||||||
if (utxo == null) {
|
if (utxo == null) {
|
||||||
final trPair = await getTaprootPair!.call(input.txId, input.txIndex);
|
final trPair = await getTaprootPair!.call(input.txId, input.txIndex);
|
||||||
@@ -81,8 +80,8 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
: BitcoinOpCodeConst.SIGHASH_ALL;
|
: BitcoinOpCodeConst.SIGHASH_ALL;
|
||||||
|
|
||||||
/// We generate transaction digest for current input
|
/// We generate transaction digest for current input
|
||||||
final digest = _generateTransactionDigest(
|
final digest =
|
||||||
script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
|
_generateTransactionDigest(script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
|
||||||
|
|
||||||
/// now we need sign the transaction digest
|
/// now we need sign the transaction digest
|
||||||
final sig = signer(digest, utxo, utxo.privateKey, sighash);
|
final sig = signer(digest, utxo, utxo.privateKey, sighash);
|
||||||
@@ -90,21 +89,14 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
if (utxo.utxo.isP2tr()) {
|
if (utxo.utxo.isP2tr()) {
|
||||||
setInputTapKeySig(i, Uint8List.fromList(BytesUtils.fromHexString(sig)));
|
setInputTapKeySig(i, Uint8List.fromList(BytesUtils.fromHexString(sig)));
|
||||||
} else {
|
} else {
|
||||||
setInputPartialSig(
|
setInputPartialSig(i, Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
|
||||||
i,
|
|
||||||
Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
|
|
||||||
Uint8List.fromList(BytesUtils.fromHexString(sig)));
|
Uint8List.fromList(BytesUtils.fromHexString(sig)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<int> _generateTransactionDigest(
|
List<int> _generateTransactionDigest(Script scriptPubKeys, int input, BitcoinUtxo utxo,
|
||||||
Script scriptPubKeys,
|
BtcTransaction transaction, List<BigInt> taprootAmounts, List<Script> tapRootPubKeys) {
|
||||||
int input,
|
|
||||||
BitcoinUtxo utxo,
|
|
||||||
BtcTransaction transaction,
|
|
||||||
List<BigInt> taprootAmounts,
|
|
||||||
List<Script> tapRootPubKeys) {
|
|
||||||
if (utxo.isSegwit()) {
|
if (utxo.isSegwit()) {
|
||||||
if (utxo.isP2tr()) {
|
if (utxo.isP2tr()) {
|
||||||
return transaction.getTransactionTaprootDigset(
|
return transaction.getTransactionTaprootDigset(
|
||||||
@@ -116,8 +108,7 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
return transaction.getTransactionSegwitDigit(
|
return transaction.getTransactionSegwitDigit(
|
||||||
txInIndex: input, script: scriptPubKeys, amount: utxo.value);
|
txInIndex: input, script: scriptPubKeys, amount: utxo.value);
|
||||||
}
|
}
|
||||||
return transaction.getTransactionDigest(
|
return transaction.getTransactionDigest(txInIndex: input, script: scriptPubKeys);
|
||||||
txInIndex: input, script: scriptPubKeys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Script _findLockingScript(UtxoWithAddress utxo, bool isTaproot) {
|
Script _findLockingScript(UtxoWithAddress utxo, bool isTaproot) {
|
||||||
@@ -172,11 +163,10 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef UTXOSignerCallBack = String Function(List<int> trDigest,
|
typedef UTXOSignerCallBack = String Function(
|
||||||
UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
|
List<int> trDigest, UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
|
||||||
|
|
||||||
typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(
|
typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(String txId, int vout);
|
||||||
String txId, int vout);
|
|
||||||
|
|
||||||
class TaprootAmountScriptPair {
|
class TaprootAmountScriptPair {
|
||||||
final BigInt value;
|
final BigInt value;
|
||||||
@@ -216,23 +206,17 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return UtxoWithPrivateKey(
|
return UtxoWithPrivateKey(
|
||||||
utxo: input.utxo,
|
utxo: input.utxo, ownerDetails: input.ownerDetails, privateKey: key.privkey);
|
||||||
ownerDetails: input.ownerDetails,
|
|
||||||
privateKey: key.privkey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory UtxoWithPrivateKey.fromUnspent(
|
factory UtxoWithPrivateKey.fromUnspent(BitcoinUnspent input, BitcoinWalletBase wallet) {
|
||||||
BitcoinUnspent input, BitcoinWalletBase wallet) {
|
final address = RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
|
||||||
final address =
|
|
||||||
RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
|
|
||||||
|
|
||||||
final newHd =
|
final newHd = input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.mainHd;
|
||||||
input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.mainHd;
|
|
||||||
|
|
||||||
ECPrivate privkey;
|
ECPrivate privkey;
|
||||||
if (input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
|
if (input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
|
||||||
final unspentAddress =
|
final unspentAddress = input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
|
||||||
input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
|
|
||||||
privkey = wallet.walletAddresses.silentAddress!.b_spend.tweakAdd(
|
privkey = wallet.walletAddresses.silentAddress!.b_spend.tweakAdd(
|
||||||
BigintUtils.fromBytes(
|
BigintUtils.fromBytes(
|
||||||
BytesUtils.fromHexString(unspentAddress.silentPaymentTweak!),
|
BytesUtils.fromHexString(unspentAddress.silentPaymentTweak!),
|
||||||
@@ -240,9 +224,7 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
privkey = generateECPrivate(
|
privkey = generateECPrivate(
|
||||||
hd: newHd,
|
hd: newHd, index: input.bitcoinAddressRecord.index, network: BitcoinNetwork.mainnet);
|
||||||
index: input.bitcoinAddressRecord.index,
|
|
||||||
network: BitcoinNetwork.mainnet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return UtxoWithPrivateKey(
|
return UtxoWithPrivateKey(
|
||||||
@@ -251,8 +233,7 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
|
|||||||
value: BigInt.from(input.value),
|
value: BigInt.from(input.value),
|
||||||
vout: input.vout,
|
vout: input.vout,
|
||||||
scriptType: input.bitcoinAddressRecord.type,
|
scriptType: input.bitcoinAddressRecord.type,
|
||||||
isSilentPayment:
|
isSilentPayment: input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
|
||||||
input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
|
|
||||||
),
|
),
|
||||||
ownerDetails: UtxoAddressDetails(
|
ownerDetails: UtxoAddressDetails(
|
||||||
publicKey: privkey.getPublic().toHex(),
|
publicKey: privkey.getPublic().toHex(),
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ class PSBTTransactionBuild {
|
|||||||
final PsbtV2 psbt = PsbtV2();
|
final PsbtV2 psbt = PsbtV2();
|
||||||
|
|
||||||
PSBTTransactionBuild(
|
PSBTTransactionBuild(
|
||||||
{required List<PSBTReadyUtxoWithAddress> inputs, required List<BitcoinBaseOutput> outputs, required List<OutputInfo> cwOutputs, bool enableRBF = true}) {
|
{required List<PSBTReadyUtxoWithAddress> inputs,
|
||||||
|
required List<BitcoinBaseOutput> outputs,
|
||||||
|
required List<OutputInfo> cwOutputs,
|
||||||
|
bool enableRBF = true}) {
|
||||||
psbt.setGlobalTxVersion(2);
|
psbt.setGlobalTxVersion(2);
|
||||||
psbt.setGlobalInputCount(inputs.length);
|
psbt.setGlobalInputCount(inputs.length);
|
||||||
psbt.setGlobalOutputCount(outputs.length);
|
psbt.setGlobalOutputCount(outputs.length);
|
||||||
@@ -23,11 +26,11 @@ class PSBTTransactionBuild {
|
|||||||
printV(input.utxo.isSegwit());
|
printV(input.utxo.isSegwit());
|
||||||
printV(input.utxo.isP2shSegwit());
|
printV(input.utxo.isP2shSegwit());
|
||||||
|
|
||||||
psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
|
psbt.setInputPreviousTxId(
|
||||||
|
i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
|
||||||
psbt.setInputOutputIndex(i, input.utxo.vout);
|
psbt.setInputOutputIndex(i, input.utxo.vout);
|
||||||
psbt.setInputSequence(i, enableRBF ? 0xfffffffd : 0xffffffff);
|
psbt.setInputSequence(i, enableRBF ? 0xfffffffd : 0xffffffff);
|
||||||
|
|
||||||
|
|
||||||
if (input.utxo.isSegwit()) {
|
if (input.utxo.isSegwit()) {
|
||||||
setInputSegwit(i, input);
|
setInputSegwit(i, input);
|
||||||
} else if (input.utxo.isP2shSegwit()) {
|
} else if (input.utxo.isP2shSegwit()) {
|
||||||
@@ -80,20 +83,14 @@ class PSBTTransactionBuild {
|
|||||||
|
|
||||||
void setInputP2pkh(int i, PSBTReadyUtxoWithAddress input) {
|
void setInputP2pkh(int i, PSBTReadyUtxoWithAddress input) {
|
||||||
psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
|
psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
|
||||||
psbt.setInputBip32Derivation(
|
psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
|
||||||
i,
|
input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
|
||||||
Uint8List.fromList(hex.decode(input.ownerPublicKey)),
|
|
||||||
input.ownerMasterFingerprint,
|
|
||||||
BIPPath.fromString(input.ownerDerivationPath).toPathArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInputSegwit(int i, PSBTReadyUtxoWithAddress input) {
|
void setInputSegwit(int i, PSBTReadyUtxoWithAddress input) {
|
||||||
psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
|
psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
|
||||||
psbt.setInputBip32Derivation(
|
psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
|
||||||
i,
|
input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
|
||||||
Uint8List.fromList(hex.decode(input.ownerPublicKey)),
|
|
||||||
input.ownerMasterFingerprint,
|
|
||||||
BIPPath.fromString(input.ownerDerivationPath).toPathArray());
|
|
||||||
|
|
||||||
psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)),
|
psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)),
|
||||||
Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes()));
|
Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes()));
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ import 'package:ledger_bitcoin/psbt.dart';
|
|||||||
String getTxIdFromPsbtV0(String psbt) {
|
String getTxIdFromPsbtV0(String psbt) {
|
||||||
final psbtV2 = PsbtV2()..deserializeV0(base64.decode(psbt));
|
final psbtV2 = PsbtV2()..deserializeV0(base64.decode(psbt));
|
||||||
|
|
||||||
return BtcTransaction.fromRaw(
|
return BtcTransaction.fromRaw(BytesUtils.toHexString(psbtV2.extractUnsignedTX(false))).txId();
|
||||||
BytesUtils.toHexString(psbtV2.extractUnsignedTX(false)))
|
|
||||||
.txId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getOutputAmountFromPsbt(String psbtV0, BitcoinWalletBase wallet) {
|
String getOutputAmountFromPsbt(String psbtV0, BitcoinWalletBase wallet) {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import 'package:ledger_bitcoin/src/utils/buffer_reader.dart';
|
|||||||
import 'package:ledger_bitcoin/src/utils/uint8list_extension.dart' as ext;
|
import 'package:ledger_bitcoin/src/utils/uint8list_extension.dart' as ext;
|
||||||
|
|
||||||
extension PsbtSigner on PsbtV2 {
|
extension PsbtSigner on PsbtV2 {
|
||||||
|
|
||||||
void deserializeV0(Uint8List psbt) {
|
void deserializeV0(Uint8List psbt) {
|
||||||
final bufferReader = BufferReader(psbt);
|
final bufferReader = BufferReader(psbt);
|
||||||
if (!listEquals(bufferReader.readSlice(5), Uint8List.fromList([0x70, 0x73, 0x62, 0x74, 0xff]))) {
|
if (!listEquals(
|
||||||
|
bufferReader.readSlice(5), Uint8List.fromList([0x70, 0x73, 0x62, 0x74, 0xff]))) {
|
||||||
throw Exception("Invalid magic bytes");
|
throw Exception("Invalid magic bytes");
|
||||||
}
|
}
|
||||||
while (_readKeyPair(globalMap, bufferReader)) {}
|
while (_readKeyPair(globalMap, bufferReader)) {}
|
||||||
@@ -26,7 +26,8 @@ extension PsbtSigner on PsbtV2 {
|
|||||||
while (_readKeyPair(inputMaps[i], bufferReader)) {}
|
while (_readKeyPair(inputMaps[i], bufferReader)) {}
|
||||||
final input = tx.inputs[i];
|
final input = tx.inputs[i];
|
||||||
setInputOutputIndex(i, input.txIndex);
|
setInputOutputIndex(i, input.txIndex);
|
||||||
setInputPreviousTxId(i, Uint8List.fromList(BytesUtils.fromHexString(input.txId).reversed.toList()));
|
setInputPreviousTxId(
|
||||||
|
i, Uint8List.fromList(BytesUtils.fromHexString(input.txId).reversed.toList()));
|
||||||
setInputSequence(i, Uint8List.fromList(input.sequence).readUint32LE(0));
|
setInputSequence(i, Uint8List.fromList(input.sequence).readUint32LE(0));
|
||||||
}
|
}
|
||||||
for (var i = 0; i < getGlobalOutputCount(); i++) {
|
for (var i = 0; i < getGlobalOutputCount(); i++) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import "package:ledger_bitcoin/src/utils/buffer_writer.dart";
|
|||||||
/// through PSBT_IN_PARTIAL_SIG or PSBT_IN_TAP_KEY_SIG
|
/// through PSBT_IN_PARTIAL_SIG or PSBT_IN_TAP_KEY_SIG
|
||||||
extension InputFinalizer on PsbtV2 {
|
extension InputFinalizer on PsbtV2 {
|
||||||
void finalizeV0() {
|
void finalizeV0() {
|
||||||
|
|
||||||
// First check that each input has a signature
|
// First check that each input has a signature
|
||||||
for (var i = 0; i < getGlobalInputCount(); i++) {
|
for (var i = 0; i < getGlobalInputCount(); i++) {
|
||||||
if (_isFinalized(i)) continue;
|
if (_isFinalized(i)) continue;
|
||||||
@@ -31,8 +30,7 @@ extension InputFinalizer on PsbtV2 {
|
|||||||
}
|
}
|
||||||
if (legacyPubkeys.isNotEmpty) {
|
if (legacyPubkeys.isNotEmpty) {
|
||||||
if (legacyPubkeys.length > 1) {
|
if (legacyPubkeys.length > 1) {
|
||||||
throw Exception(
|
throw Exception('Expected exactly one signature, got ${legacyPubkeys.length}');
|
||||||
'Expected exactly one signature, got ${legacyPubkeys.length}');
|
|
||||||
}
|
}
|
||||||
if (taprootSig != null) {
|
if (taprootSig != null) {
|
||||||
throw Exception('Both taproot and non-taproot signatures present.');
|
throw Exception('Both taproot and non-taproot signatures present.');
|
||||||
@@ -55,8 +53,7 @@ extension InputFinalizer on PsbtV2 {
|
|||||||
setInputFinalScriptwitness(i, witnessBuf.buffer());
|
setInputFinalScriptwitness(i, witnessBuf.buffer());
|
||||||
if (isWrappedSegwit) {
|
if (isWrappedSegwit) {
|
||||||
if (redeemScript.isEmpty) {
|
if (redeemScript.isEmpty) {
|
||||||
throw Exception(
|
throw Exception("Expected non-empty redeemscript. Can't finalize input $i");
|
||||||
"Expected non-empty redeemscript. Can't finalize input $i");
|
|
||||||
}
|
}
|
||||||
final scriptSigBuf = BufferWriter()
|
final scriptSigBuf = BufferWriter()
|
||||||
..writeUInt8(redeemScript.length) // Push redeemScript length
|
..writeUInt8(redeemScript.length) // Push redeemScript length
|
||||||
|
|||||||
@@ -87,8 +87,9 @@ class BitcoinCashWalletService extends WalletService<
|
|||||||
}
|
}
|
||||||
await WalletInfo.delete(walletInfo);
|
await WalletInfo.delete(walletInfo);
|
||||||
|
|
||||||
final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
|
final unspentCoinsToDelete = unspentCoinsInfoSource.values
|
||||||
(unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
|
.where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
|
||||||
|
.toList();
|
||||||
|
|
||||||
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
||||||
|
|
||||||
@@ -122,8 +123,7 @@ class BitcoinCashWalletService extends WalletService<
|
|||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
passphrase: credentials.passphrase
|
passphrase: credentials.passphrase);
|
||||||
);
|
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
abstract class AccountList<T> {
|
abstract class AccountList<T> {
|
||||||
|
|
||||||
ObservableList<T> get accounts;
|
ObservableList<T> get accounts;
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|||||||
@@ -41,7 +41,5 @@ class AddressInfoAdapter extends TypeAdapter<AddressInfo> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is AddressInfoAdapter &&
|
other is AddressInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ String _smartAmountSanitizer(String amount) {
|
|||||||
return amount.replaceAll(",", ".");
|
return amount.replaceAll(",", ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension SanitizerUserAmounts on String {
|
extension SanitizerUserAmounts on String {
|
||||||
String sanitized() => _smartAmountSanitizer(this);
|
String sanitized() => _smartAmountSanitizer(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class AmountConverter {
|
|||||||
return neg ? '-${res.toString()}' : res.toString();
|
return neg ? '-${res.toString()}' : res.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static String fromBaseUnits(String units, int decimals) {
|
static String fromBaseUnits(String units, int decimals) {
|
||||||
units = units.trim();
|
units = units.trim();
|
||||||
if (units.isEmpty) return '0';
|
if (units.isEmpty) return '0';
|
||||||
|
|||||||
@@ -59,21 +59,17 @@ class BalanceCardStyleSettings {
|
|||||||
int iconStyleIndex = 0,
|
int iconStyleIndex = 0,
|
||||||
int? gradientIndexOverride,
|
int? gradientIndexOverride,
|
||||||
}) {
|
}) {
|
||||||
final int gradientIndex = gradientIndexOverride ??
|
final int gradientIndex =
|
||||||
CardDesign.allGradients.indexOf(design.gradient);
|
gradientIndexOverride ?? CardDesign.allGradients.indexOf(design.gradient);
|
||||||
return BalanceCardStyleSettings(
|
return BalanceCardStyleSettings(
|
||||||
walletInfoId: walletInfoId,
|
walletInfoId: walletInfoId,
|
||||||
accountIndex: accountIndex,
|
accountIndex: accountIndex,
|
||||||
gradientIndex: gradientIndex,
|
gradientIndex: gradientIndex,
|
||||||
useSpecialDesign:
|
useSpecialDesign: design.backgroundType == CardDesignBackgroundTypes.svgFull,
|
||||||
design.backgroundType == CardDesignBackgroundTypes.svgFull,
|
|
||||||
backgroundImagePath:
|
backgroundImagePath:
|
||||||
design.backgroundType == CardDesignBackgroundTypes.image
|
design.backgroundType == CardDesignBackgroundTypes.image ? design.imagePath : "",
|
||||||
? design.imagePath
|
|
||||||
: "",
|
|
||||||
iconStyleIndex: iconStyleIndex,
|
iconStyleIndex: iconStyleIndex,
|
||||||
isGradientOnly:
|
isGradientOnly: design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
|
||||||
design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
|
|
||||||
cardOrder: cardOrder,
|
cardOrder: cardOrder,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-99
@@ -18,8 +18,7 @@ class CardColorCombination {
|
|||||||
static const light = CardColorCombination(
|
static const light = CardColorCombination(
|
||||||
textColor: Color.fromARGB(200, 255, 255, 255),
|
textColor: Color.fromARGB(200, 255, 255, 255),
|
||||||
textColorSecondary: Colors.white54,
|
textColorSecondary: Colors.white54,
|
||||||
backgroundImageColor: Color.fromARGB(200, 0, 0, 0)
|
backgroundImageColor: Color.fromARGB(200, 0, 0, 0));
|
||||||
);
|
|
||||||
|
|
||||||
static const dark = CardColorCombination(
|
static const dark = CardColorCombination(
|
||||||
textColor: Color.fromARGB(200, 0, 0, 0),
|
textColor: Color.fromARGB(200, 0, 0, 0),
|
||||||
@@ -50,7 +49,8 @@ class CardDesign {
|
|||||||
|
|
||||||
const CardDesign(
|
const CardDesign(
|
||||||
{this.backgroundType = CardDesignBackgroundTypes.svgIcon,
|
{this.backgroundType = CardDesignBackgroundTypes.svgIcon,
|
||||||
this.gradient = const LinearGradient(colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
|
this.gradient = const LinearGradient(
|
||||||
|
colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
|
||||||
this.imagePath = "assets/new-ui/blank.svg",
|
this.imagePath = "assets/new-ui/blank.svg",
|
||||||
this.colors = CardColorCombination.dark,
|
this.colors = CardColorCombination.dark,
|
||||||
this.preColoredIcon = false});
|
this.preColoredIcon = false});
|
||||||
@@ -129,71 +129,50 @@ class CardDesign {
|
|||||||
|
|
||||||
static const genericDefault = CardDesign(gradient: gradientBlue);
|
static const genericDefault = CardDesign(gradient: gradientBlue);
|
||||||
|
|
||||||
static const gradientOnlyDesign = CardDesign(
|
static const gradientOnlyDesign =
|
||||||
backgroundType: CardDesignBackgroundTypes.gradientOnly,
|
CardDesign(backgroundType: CardDesignBackgroundTypes.gradientOnly, gradient: gradientBlue);
|
||||||
gradient: gradientBlue);
|
|
||||||
|
|
||||||
static const btc = CardDesign(
|
static const btc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
|
|
||||||
|
|
||||||
static const eth = CardDesign(
|
static const eth = CardDesign(imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
|
|
||||||
|
|
||||||
static const btcln = CardDesign(
|
static const btcln = CardDesign(imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
|
|
||||||
|
|
||||||
static const xmr = CardDesign(
|
static const xmr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/monero.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/monero.svg");
|
|
||||||
|
|
||||||
static const ltc = CardDesign(
|
static const ltc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
|
|
||||||
|
|
||||||
static const bch = CardDesign(
|
static const bch = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
|
|
||||||
|
|
||||||
static const doge = CardDesign(
|
static const doge = CardDesign(imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
|
|
||||||
|
|
||||||
static const base = CardDesign(
|
static const base = CardDesign(imagePath: "assets/new-ui/balance_card_icons/base.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/base.svg");
|
|
||||||
|
|
||||||
static const pol = CardDesign(
|
static const pol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
|
|
||||||
|
|
||||||
static const sol = CardDesign(
|
static const sol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/solana.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/solana.svg");
|
|
||||||
|
|
||||||
static const tron = CardDesign(
|
static const tron = CardDesign(imagePath: "assets/new-ui/balance_card_icons/tron.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/tron.svg");
|
|
||||||
|
|
||||||
static const nano = CardDesign(
|
static const nano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/nano.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/nano.svg");
|
|
||||||
|
|
||||||
static const zano = CardDesign(
|
static const zano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zano.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/zano.svg");
|
|
||||||
|
|
||||||
static const wow = CardDesign(
|
static const wow = CardDesign(imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
|
|
||||||
|
|
||||||
static const dcr = CardDesign(
|
static const dcr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/decred.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/decred.svg");
|
|
||||||
|
|
||||||
static const arbitrum = CardDesign(
|
static const arbitrum = CardDesign(imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
|
||||||
imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
|
|
||||||
|
|
||||||
static const zec = CardDesign(
|
|
||||||
imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
|
|
||||||
|
|
||||||
static const bnb = CardDesign(
|
|
||||||
imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
|
|
||||||
|
|
||||||
|
static const zec = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
|
||||||
|
|
||||||
|
static const bnb = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
|
||||||
|
|
||||||
static const ethSpecial = CardDesign(
|
static const ethSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF6259FF), Color(0xFF3B20E6)],
|
colors: <Color>[Color(0xFF6259FF), Color(0xFF3B20E6)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/ethereum.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/ethereum.svg");
|
||||||
@@ -201,24 +180,24 @@ class CardDesign {
|
|||||||
static const btcSpecial = CardDesign(
|
static const btcSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
|
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin.svg");
|
||||||
|
|
||||||
static const xmrSpecial = CardDesign(
|
static const xmrSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFFF5900), Color(0xFFE62E00)],
|
colors: <Color>[Color(0xFFFF5900), Color(0xFFE62E00)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/monero.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/monero.svg");
|
||||||
|
|
||||||
static const ltcSpecial = CardDesign(
|
static const ltcSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF2145BF), Color(0xFF072071)],
|
colors: <Color>[Color(0xFF2145BF), Color(0xFF072071)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/litecoin.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/litecoin.svg");
|
||||||
@@ -226,8 +205,8 @@ class CardDesign {
|
|||||||
static const lnSpecial = CardDesign(
|
static const lnSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
|
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.dark,
|
colors: CardColorCombination.dark,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/lightning.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/lightning.svg");
|
||||||
@@ -235,8 +214,8 @@ class CardDesign {
|
|||||||
static const tronSpecial = CardDesign(
|
static const tronSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFFF1313), Color(0xFFB40000)],
|
colors: <Color>[Color(0xFFFF1313), Color(0xFFB40000)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/tron.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/tron.svg");
|
||||||
@@ -244,8 +223,8 @@ class CardDesign {
|
|||||||
static const solSpecial = CardDesign(
|
static const solSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF4701AA), Color(0xFF19004B)],
|
colors: <Color>[Color(0xFF4701AA), Color(0xFF19004B)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/solana.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/solana.svg");
|
||||||
@@ -253,40 +232,40 @@ class CardDesign {
|
|||||||
static const bchSpecial = CardDesign(
|
static const bchSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF36DA4C), Color(0xFF008D57)],
|
colors: <Color>[Color(0xFF36DA4C), Color(0xFF008D57)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin-cash.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin-cash.svg");
|
||||||
|
|
||||||
static const wowSpecial = CardDesign(
|
static const wowSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFFF6CD3), Color(0xFFF200A9)],
|
colors: <Color>[Color(0xFFFF6CD3), Color(0xFFF200A9)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/wownero.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/wownero.svg");
|
||||||
|
|
||||||
static const dogeSpecial = CardDesign(
|
static const dogeSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFCBA818), Color(0xFF885D00)],
|
colors: <Color>[Color(0xFFCBA818), Color(0xFF885D00)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/dogecoin.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/dogecoin.svg");
|
||||||
|
|
||||||
static const nanoSpecial = CardDesign(
|
static const nanoSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF209CE9), Color(0xFF0073CB)],
|
colors: <Color>[Color(0xFF209CE9), Color(0xFF0073CB)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/nano.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/nano.svg");
|
||||||
|
|
||||||
static const polSpecial = CardDesign(
|
static const polSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF863FE3), Color(0xFF59098E)],
|
colors: <Color>[Color(0xFF863FE3), Color(0xFF59098E)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/polygon.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/polygon.svg");
|
||||||
@@ -294,8 +273,8 @@ class CardDesign {
|
|||||||
static const dcrSpecial = CardDesign(
|
static const dcrSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF2871FF), Color(0xFF0057FF)],
|
colors: <Color>[Color(0xFF2871FF), Color(0xFF0057FF)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/decred.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/decred.svg");
|
||||||
@@ -303,8 +282,8 @@ class CardDesign {
|
|||||||
static const zanoSpecial = CardDesign(
|
static const zanoSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF0004B4), Color(0xFF170069)],
|
colors: <Color>[Color(0xFF0004B4), Color(0xFF170069)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
colors: CardColorCombination.black,
|
colors: CardColorCombination.black,
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/zano.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/zano.svg");
|
||||||
@@ -312,8 +291,8 @@ class CardDesign {
|
|||||||
static const baseSpecial = CardDesign(
|
static const baseSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF003CFF), Color(0xFF000087)],
|
colors: <Color>[Color(0xFF003CFF), Color(0xFF000087)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/base.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/base.svg");
|
||||||
@@ -321,8 +300,8 @@ class CardDesign {
|
|||||||
static const arbitrumSpecial = CardDesign(
|
static const arbitrumSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF173F76), Color(0xFF031A39)],
|
colors: <Color>[Color(0xFF173F76), Color(0xFF031A39)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/arbitrum.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/arbitrum.svg");
|
||||||
@@ -330,16 +309,16 @@ class CardDesign {
|
|||||||
static const zecSpecial = CardDesign(
|
static const zecSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFFF6C527), Color(0xFFCD8C00)],
|
colors: <Color>[Color(0xFFF6C527), Color(0xFFCD8C00)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/zcash.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/zcash.svg");
|
||||||
|
|
||||||
static const bnbSpecial = CardDesign(
|
static const bnbSpecial = CardDesign(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: <Color>[Color(0xFF603000), Color(0xFFF0B90B)],
|
colors: <Color>[Color(0xFF603000), Color(0xFFF0B90B)],
|
||||||
begin: Alignment.topCenter, end: Alignment.bottomCenter
|
begin: Alignment.topCenter,
|
||||||
),
|
end: Alignment.bottomCenter),
|
||||||
colors: CardColorCombination.light,
|
colors: CardColorCombination.light,
|
||||||
backgroundType: CardDesignBackgroundTypes.svgFull,
|
backgroundType: CardDesignBackgroundTypes.svgFull,
|
||||||
imagePath: "assets/new-ui/balance_card_backgrounds/bnb.svg");
|
imagePath: "assets/new-ui/balance_card_backgrounds/bnb.svg");
|
||||||
@@ -351,7 +330,9 @@ class CardDesign {
|
|||||||
backgroundType: backgroundType,
|
backgroundType: backgroundType,
|
||||||
preColoredIcon: preColoredIcon);
|
preColoredIcon: preColoredIcon);
|
||||||
|
|
||||||
CardDesign withGradientAndColorCombination(Gradient gradient, CardColorCombination cardColorCombination) => CardDesign(
|
CardDesign withGradientAndColorCombination(
|
||||||
|
Gradient gradient, CardColorCombination cardColorCombination) =>
|
||||||
|
CardDesign(
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
colors: cardColorCombination,
|
colors: cardColorCombination,
|
||||||
imagePath: imagePath,
|
imagePath: imagePath,
|
||||||
@@ -374,8 +355,10 @@ class CardDesign {
|
|||||||
|
|
||||||
static const Map<CryptoCurrency, _CurrencyIconNames> _iconNames = {
|
static const Map<CryptoCurrency, _CurrencyIconNames> _iconNames = {
|
||||||
CryptoCurrency.arbEth: _CurrencyIconNames(ticker: 'arb', longName: 'arbitrum'),
|
CryptoCurrency.arbEth: _CurrencyIconNames(ticker: 'arb', longName: 'arbitrum'),
|
||||||
CryptoCurrency.baseEth: _CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
|
CryptoCurrency.baseEth:
|
||||||
CryptoCurrency.bch: _CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
|
_CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
|
||||||
|
CryptoCurrency.bch:
|
||||||
|
_CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
|
||||||
CryptoCurrency.btc: _CurrencyIconNames(ticker: 'btc', longName: 'bitcoin', outlineFile: 'BTC'),
|
CryptoCurrency.btc: _CurrencyIconNames(ticker: 'btc', longName: 'bitcoin', outlineFile: 'BTC'),
|
||||||
CryptoCurrency.bnb: _CurrencyIconNames(ticker: 'bnb', longName: 'bnb'),
|
CryptoCurrency.bnb: _CurrencyIconNames(ticker: 'bnb', longName: 'bnb'),
|
||||||
CryptoCurrency.dcr: _CurrencyIconNames(ticker: 'dcr', longName: 'decred'),
|
CryptoCurrency.dcr: _CurrencyIconNames(ticker: 'dcr', longName: 'decred'),
|
||||||
@@ -383,13 +366,13 @@ class CardDesign {
|
|||||||
CryptoCurrency.eth: _CurrencyIconNames(ticker: 'eth', longName: 'ethereum'),
|
CryptoCurrency.eth: _CurrencyIconNames(ticker: 'eth', longName: 'ethereum'),
|
||||||
CryptoCurrency.btcln: _CurrencyIconNames(ticker: 'ln', longName: 'lightning'),
|
CryptoCurrency.btcln: _CurrencyIconNames(ticker: 'ln', longName: 'lightning'),
|
||||||
CryptoCurrency.ltc: _CurrencyIconNames(ticker: 'ltc', longName: 'litecoin'),
|
CryptoCurrency.ltc: _CurrencyIconNames(ticker: 'ltc', longName: 'litecoin'),
|
||||||
CryptoCurrency.xmr: _CurrencyIconNames(
|
CryptoCurrency.xmr:
|
||||||
ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
|
_CurrencyIconNames(ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
|
||||||
CryptoCurrency.nano: _CurrencyIconNames(ticker: 'xno', longName: 'nano'),
|
CryptoCurrency.nano: _CurrencyIconNames(ticker: 'xno', longName: 'nano'),
|
||||||
CryptoCurrency.maticpoly: _CurrencyIconNames(ticker: 'pol', longName: 'polygon'),
|
CryptoCurrency.maticpoly: _CurrencyIconNames(ticker: 'pol', longName: 'polygon'),
|
||||||
CryptoCurrency.sol: _CurrencyIconNames(ticker: 'sol', longName: 'solana'),
|
CryptoCurrency.sol: _CurrencyIconNames(ticker: 'sol', longName: 'solana'),
|
||||||
CryptoCurrency.trx: _CurrencyIconNames(
|
CryptoCurrency.trx:
|
||||||
ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
|
_CurrencyIconNames(ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
|
||||||
CryptoCurrency.zano: _CurrencyIconNames(ticker: 'zano', longName: 'zano'),
|
CryptoCurrency.zano: _CurrencyIconNames(ticker: 'zano', longName: 'zano'),
|
||||||
CryptoCurrency.zec: _CurrencyIconNames(ticker: 'zec', longName: 'zcash'),
|
CryptoCurrency.zec: _CurrencyIconNames(ticker: 'zec', longName: 'zcash'),
|
||||||
};
|
};
|
||||||
@@ -408,7 +391,40 @@ class CardDesign {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const List<CardDesign> all = [genericDefault, btc, eth, xmr, ltc, eth, pol, doge, base, sol, btcln, tron, zano, dcr, arbitrum, zec, bnb, ethSpecial, btcSpecial, xmrSpecial, ltcSpecial, lnSpecial, tronSpecial, bchSpecial, wowSpecial, dogeSpecial, polSpecial, dcrSpecial, zanoSpecial, arbitrumSpecial, zecSpecial, bnbSpecial];
|
static const List<CardDesign> all = [
|
||||||
|
genericDefault,
|
||||||
|
btc,
|
||||||
|
eth,
|
||||||
|
xmr,
|
||||||
|
ltc,
|
||||||
|
eth,
|
||||||
|
pol,
|
||||||
|
doge,
|
||||||
|
base,
|
||||||
|
sol,
|
||||||
|
btcln,
|
||||||
|
tron,
|
||||||
|
zano,
|
||||||
|
dcr,
|
||||||
|
arbitrum,
|
||||||
|
zec,
|
||||||
|
bnb,
|
||||||
|
ethSpecial,
|
||||||
|
btcSpecial,
|
||||||
|
xmrSpecial,
|
||||||
|
ltcSpecial,
|
||||||
|
lnSpecial,
|
||||||
|
tronSpecial,
|
||||||
|
bchSpecial,
|
||||||
|
wowSpecial,
|
||||||
|
dogeSpecial,
|
||||||
|
polSpecial,
|
||||||
|
dcrSpecial,
|
||||||
|
zanoSpecial,
|
||||||
|
arbitrumSpecial,
|
||||||
|
zecSpecial,
|
||||||
|
bnbSpecial
|
||||||
|
];
|
||||||
|
|
||||||
static CardDesign forCurrencySpecial(CryptoCurrency currency) {
|
static CardDesign forCurrencySpecial(CryptoCurrency currency) {
|
||||||
return specialDesignsForCurrencies[currency] ?? genericDefault;
|
return specialDesignsForCurrencies[currency] ?? genericDefault;
|
||||||
@@ -437,7 +453,6 @@ class CardDesign {
|
|||||||
CryptoCurrency.zec: zec,
|
CryptoCurrency.zec: zec,
|
||||||
CryptoCurrency.dcr: dcr,
|
CryptoCurrency.dcr: dcr,
|
||||||
CryptoCurrency.bnb: bnb,
|
CryptoCurrency.bnb: bnb,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Map<CryptoCurrency, CardDesign> specialDesignsForCurrencies = {
|
static const Map<CryptoCurrency, CardDesign> specialDesignsForCurrencies = {
|
||||||
@@ -504,9 +519,9 @@ class CardDesign {
|
|||||||
|
|
||||||
if (setting.isGradientOnly) {
|
if (setting.isGradientOnly) {
|
||||||
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
|
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
|
||||||
final textColors = preferredColorCombinations[gradient]
|
final textColors = preferredColorCombinations[gradient] ??
|
||||||
?? specialDesignsForCurrencies[walletCurrency]?.colors
|
specialDesignsForCurrencies[walletCurrency]?.colors ??
|
||||||
?? gradientOnlyDesign.colors;
|
gradientOnlyDesign.colors;
|
||||||
return gradientOnlyDesign.withGradientAndColorCombination(gradient, textColors);
|
return gradientOnlyDesign.withGradientAndColorCombination(gradient, textColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,11 +536,9 @@ class CardDesign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!setting.useSpecialDesign && setting.gradientIndex == -1) {
|
if (!setting.useSpecialDesign && setting.gradientIndex == -1) {
|
||||||
final specialColors =
|
final specialColors = specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
|
||||||
specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
|
|
||||||
final design = CardDesign.forCurrencyIcon(walletCurrency)
|
final design = CardDesign.forCurrencyIcon(walletCurrency)
|
||||||
.withGradientAndColorCombination(
|
.withGradientAndColorCombination(specialColors.gradient, specialColors.colors);
|
||||||
specialColors.gradient, specialColors.colors);
|
|
||||||
return design.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
|
return design.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
|
||||||
}
|
}
|
||||||
if (setting.useSpecialDesign) {
|
if (setting.useSpecialDesign) {
|
||||||
@@ -534,9 +547,9 @@ class CardDesign {
|
|||||||
if (setting.gradientIndex != -1) {
|
if (setting.gradientIndex != -1) {
|
||||||
final baseIcon = CardDesign.forCurrencyIcon(walletCurrency);
|
final baseIcon = CardDesign.forCurrencyIcon(walletCurrency);
|
||||||
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
|
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
|
||||||
final textColors = preferredColorCombinations[gradient]
|
final textColors = preferredColorCombinations[gradient] ??
|
||||||
?? specialDesignsForCurrencies[walletCurrency]?.colors
|
specialDesignsForCurrencies[walletCurrency]?.colors ??
|
||||||
?? baseIcon.colors;
|
baseIcon.colors;
|
||||||
return baseIcon
|
return baseIcon
|
||||||
.withGradientAndColorCombination(gradient, textColors)
|
.withGradientAndColorCombination(gradient, textColors)
|
||||||
.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
|
.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ extension MaxDecimals on String {
|
|||||||
return parts.join(".");
|
return parts.join(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Format a stringified number to a localized representation
|
/// Format a stringified number to a localized representation
|
||||||
/// 1.000.000,00 in de_DE
|
/// 1.000.000,00 in de_DE
|
||||||
/// 1’000’000.00 in de_CH
|
/// 1’000’000.00 in de_CH
|
||||||
|
|||||||
+822
-123
@@ -161,139 +161,842 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
|||||||
|
|
||||||
// well technically not currencies but since we had them a long time ago and don't want to break
|
// well technically not currencies but since we had them a long time ago and don't want to break
|
||||||
// the app for users who had contacts saved for them
|
// the app for users who had contacts saved for them
|
||||||
static const zcashCurrencies = [ zec, zaddr, tzec ];
|
static const zcashCurrencies = [zec, zaddr, tzec];
|
||||||
|
|
||||||
// title, tag (if applicable), fullName (if unique), raw, name, iconPath
|
// title, tag (if applicable), fullName (if unique), raw, name, iconPath
|
||||||
static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/new-ui/crypto_full_icons/monero.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/monero.svg");
|
static const xmr = CryptoCurrency(
|
||||||
static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png', decimals: 6);
|
title: 'XMR',
|
||||||
static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
|
fullName: 'Monero',
|
||||||
static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'BNB', raw: 3, name: 'bnb', iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg", chainIconPath: "assets/new-ui/chain_badges/bnb.svg");
|
raw: 0,
|
||||||
static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg' ,decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg");
|
name: 'xmr',
|
||||||
static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/new-ui/crypto_full_icons/dai.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
|
iconPath: 'assets/new-ui/crypto_full_icons/monero.svg',
|
||||||
static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8);
|
decimals: 12,
|
||||||
static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4);
|
flatIconPath: "assets/new-ui/balance_card_icons/monero.svg");
|
||||||
static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg", chainIconPath: "assets/new-ui/chain_badges/ethereum.svg");
|
static const ada = CryptoCurrency(
|
||||||
static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg", chainIconPath: "assets/new-ui/chain_badges/mweb.svg");
|
title: 'ADA',
|
||||||
static const nano = CryptoCurrency(title: 'XNO', fullName: 'Nano', raw: 10, name: 'xno', iconPath: 'assets/new-ui/crypto_full_icons/nano.svg', decimals: 30, flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
|
fullName: 'Cardano',
|
||||||
static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/new-ui/crypto_full_icons/tron.svg', decimals: 6, flatIconPath: "assets/new-ui/balance_card_icons/tron.svg", chainIconPath: "assets/new-ui/chain_badges/tron.svg");
|
raw: 1,
|
||||||
static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'Tether', raw: 12, name: 'usdt', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
name: 'ada',
|
||||||
static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
iconPath: 'assets/images/ada_icon.png',
|
||||||
static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png', decimals: 7);
|
decimals: 6);
|
||||||
static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png', decimals: 6);
|
static const bch = CryptoCurrency(
|
||||||
static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png', decimals: 12);
|
title: 'BCH',
|
||||||
|
fullName: 'Bitcoin Cash',
|
||||||
|
raw: 2,
|
||||||
|
name: 'bch',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg',
|
||||||
|
decimals: 8,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
|
||||||
|
static const bnb = CryptoCurrency(
|
||||||
|
title: 'BNB',
|
||||||
|
tag: 'BSC',
|
||||||
|
fullName: 'BNB',
|
||||||
|
raw: 3,
|
||||||
|
name: 'bnb',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg',
|
||||||
|
decimals: 18,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/bnb.svg");
|
||||||
|
static const btc = CryptoCurrency(
|
||||||
|
title: 'BTC',
|
||||||
|
fullName: 'Bitcoin',
|
||||||
|
raw: 4,
|
||||||
|
name: 'btc',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg',
|
||||||
|
decimals: 8,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg");
|
||||||
|
static const dai = CryptoCurrency(
|
||||||
|
title: 'DAI',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Dai',
|
||||||
|
raw: 5,
|
||||||
|
name: 'dai',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/dai.svg',
|
||||||
|
decimals: 18,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const dash = CryptoCurrency(
|
||||||
|
title: 'DASH',
|
||||||
|
fullName: 'Dash',
|
||||||
|
raw: 6,
|
||||||
|
name: 'dash',
|
||||||
|
iconPath: 'assets/images/dash_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const eos = CryptoCurrency(
|
||||||
|
title: 'EOS',
|
||||||
|
fullName: 'EOS',
|
||||||
|
raw: 7,
|
||||||
|
name: 'eos',
|
||||||
|
iconPath: 'assets/images/eos_icon.png',
|
||||||
|
decimals: 4);
|
||||||
|
static const eth = CryptoCurrency(
|
||||||
|
title: 'ETH',
|
||||||
|
fullName: 'Ethereum',
|
||||||
|
raw: 8,
|
||||||
|
name: 'eth',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
|
||||||
|
decimals: 18,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/ethereum.svg");
|
||||||
|
static const ltc = CryptoCurrency(
|
||||||
|
title: 'LTC',
|
||||||
|
fullName: 'Litecoin',
|
||||||
|
raw: 9,
|
||||||
|
name: 'ltc',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg',
|
||||||
|
decimals: 8,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/mweb.svg");
|
||||||
|
static const nano = CryptoCurrency(
|
||||||
|
title: 'XNO',
|
||||||
|
fullName: 'Nano',
|
||||||
|
raw: 10,
|
||||||
|
name: 'xno',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/nano.svg',
|
||||||
|
decimals: 30,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
|
||||||
|
static const trx = CryptoCurrency(
|
||||||
|
title: 'TRX',
|
||||||
|
fullName: 'TRON',
|
||||||
|
raw: 11,
|
||||||
|
name: 'trx',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/tron.svg',
|
||||||
|
decimals: 6,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/tron.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/tron.svg");
|
||||||
|
static const usdt = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'OMNI',
|
||||||
|
fullName: 'Tether',
|
||||||
|
raw: 12,
|
||||||
|
name: 'usdt',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdterc20 = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Tether',
|
||||||
|
raw: 13,
|
||||||
|
name: 'usdterc20',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const xlm = CryptoCurrency(
|
||||||
|
title: 'XLM',
|
||||||
|
fullName: 'Stellar',
|
||||||
|
raw: 14,
|
||||||
|
name: 'xlm',
|
||||||
|
iconPath: 'assets/images/xlm_icon.png',
|
||||||
|
decimals: 7);
|
||||||
|
static const xrp = CryptoCurrency(
|
||||||
|
title: 'XRP',
|
||||||
|
fullName: 'Ripple',
|
||||||
|
raw: 15,
|
||||||
|
name: 'xrp',
|
||||||
|
iconPath: 'assets/images/xrp_icon.png',
|
||||||
|
decimals: 6);
|
||||||
|
static const xhv = CryptoCurrency(
|
||||||
|
title: 'XHV',
|
||||||
|
fullName: 'Haven Protocol',
|
||||||
|
raw: 16,
|
||||||
|
name: 'xhv',
|
||||||
|
iconPath: 'assets/images/xhv_logo.png',
|
||||||
|
decimals: 12);
|
||||||
|
|
||||||
static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12);
|
static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12);
|
||||||
static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau', decimals: 12);
|
static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau', decimals: 12);
|
||||||
static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12);
|
static const xaud =
|
||||||
static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12);
|
CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12);
|
||||||
static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12);
|
static const xbtc =
|
||||||
static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12);
|
CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12);
|
||||||
static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12);
|
static const xcad =
|
||||||
static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12);
|
CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12);
|
||||||
static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12);
|
static const xchf =
|
||||||
static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12);
|
CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12);
|
||||||
static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12);
|
static const xcny =
|
||||||
static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12);
|
CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12);
|
||||||
static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12);
|
static const xeur =
|
||||||
|
CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12);
|
||||||
|
static const xgbp =
|
||||||
|
CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12);
|
||||||
|
static const xjpy =
|
||||||
|
CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12);
|
||||||
|
static const xnok =
|
||||||
|
CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12);
|
||||||
|
static const xnzd =
|
||||||
|
CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12);
|
||||||
|
static const xusd =
|
||||||
|
CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12);
|
||||||
|
|
||||||
static const ape = CryptoCurrency(title: 'APE', tag: 'ETH', fullName: 'ApeCoin', raw: 30, name: 'ape', iconPath: 'assets/images/ape_icon.png', decimals: 18);
|
static const ape = CryptoCurrency(
|
||||||
static const avaxc = CryptoCurrency(title: 'AVAX', tag: 'AVAXC', fullName: 'Avalanche', raw: 31, name: 'avaxc', iconPath: 'assets/new-ui/crypto_full_icons/avax.svg', decimals: 9);
|
title: 'APE',
|
||||||
static const btt = CryptoCurrency(title: 'BTT', tag: 'ETH', fullName: 'BitTorrent', raw: 32, name: 'btt', iconPath: 'assets/images/btt_icon.png', decimals: 18);
|
tag: 'ETH',
|
||||||
static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png', decimals: 18);
|
fullName: 'ApeCoin',
|
||||||
static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg");
|
raw: 30,
|
||||||
static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8);
|
name: 'ape',
|
||||||
static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
iconPath: 'assets/images/ape_icon.png',
|
||||||
static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', decimals: 8);
|
decimals: 18);
|
||||||
static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png', decimals: 16);
|
static const avaxc = CryptoCurrency(
|
||||||
static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/new-ui/crypto_full_icons/solana.svg', decimals: 9, flatIconPath: "assets/new-ui/balance_card_icons/solana.svg", chainIconPath: "assets/new-ui/chain_badges/solana.svg");
|
title: 'AVAX',
|
||||||
static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USDC', raw: 40, name: 'usdc', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
tag: 'AVAXC',
|
||||||
static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
fullName: 'Avalanche',
|
||||||
static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
|
raw: 31,
|
||||||
static const tzec = CryptoCurrency(title: 'tZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
|
name: 'avaxc',
|
||||||
static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png', decimals: 8);
|
iconPath: 'assets/new-ui/crypto_full_icons/avax.svg',
|
||||||
static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png', decimals: 8);
|
decimals: 9);
|
||||||
|
static const btt = CryptoCurrency(
|
||||||
|
title: 'BTT',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'BitTorrent',
|
||||||
|
raw: 32,
|
||||||
|
name: 'btt',
|
||||||
|
iconPath: 'assets/images/btt_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const bttc = CryptoCurrency(
|
||||||
|
title: 'BTTC',
|
||||||
|
tag: 'TRX',
|
||||||
|
fullName: 'BitTorrent-NEW',
|
||||||
|
raw: 33,
|
||||||
|
name: 'bttc',
|
||||||
|
iconPath: 'assets/images/btt_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const doge = CryptoCurrency(
|
||||||
|
title: 'DOGE',
|
||||||
|
fullName: 'Dogecoin',
|
||||||
|
raw: 34,
|
||||||
|
name: 'doge',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg',
|
||||||
|
decimals: 8,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg");
|
||||||
|
static const firo = CryptoCurrency(
|
||||||
|
title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8);
|
||||||
|
static const usdttrc20 = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'TRX',
|
||||||
|
fullName: 'Tether',
|
||||||
|
raw: 36,
|
||||||
|
name: 'usdttrc20',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const hbar = CryptoCurrency(
|
||||||
|
title: 'HBAR',
|
||||||
|
fullName: 'Hedera',
|
||||||
|
raw: 37,
|
||||||
|
name: 'hbar',
|
||||||
|
iconPath: 'assets/images/hbar_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const sc = CryptoCurrency(
|
||||||
|
title: 'SC',
|
||||||
|
fullName: 'Siacoin',
|
||||||
|
raw: 38,
|
||||||
|
name: 'sc',
|
||||||
|
iconPath: 'assets/images/sc_icon.png',
|
||||||
|
decimals: 16);
|
||||||
|
static const sol = CryptoCurrency(
|
||||||
|
title: 'SOL',
|
||||||
|
fullName: 'Solana',
|
||||||
|
raw: 39,
|
||||||
|
name: 'sol',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/solana.svg',
|
||||||
|
decimals: 9,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/solana.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/solana.svg");
|
||||||
|
static const usdc = CryptoCurrency(
|
||||||
|
title: 'USDC',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'USDC',
|
||||||
|
raw: 40,
|
||||||
|
name: 'usdc',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdcsol = CryptoCurrency(
|
||||||
|
title: 'USDC',
|
||||||
|
tag: 'SOL',
|
||||||
|
fullName: 'USDC Coin',
|
||||||
|
raw: 41,
|
||||||
|
name: 'usdcsol',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const zaddr = CryptoCurrency(
|
||||||
|
title: 'ZZEC',
|
||||||
|
tag: 'ZEC',
|
||||||
|
fullName: 'Shielded Zcash',
|
||||||
|
raw: 42,
|
||||||
|
name: 'zaddr',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
|
||||||
|
decimals: 8);
|
||||||
|
static const tzec = CryptoCurrency(
|
||||||
|
title: 'tZEC',
|
||||||
|
tag: 'ZEC',
|
||||||
|
fullName: 'Transparent Zcash',
|
||||||
|
raw: 43,
|
||||||
|
name: 'zec',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
|
||||||
|
decimals: 8);
|
||||||
|
static const zen = CryptoCurrency(
|
||||||
|
title: 'ZEN',
|
||||||
|
fullName: 'Horizen',
|
||||||
|
raw: 44,
|
||||||
|
name: 'zen',
|
||||||
|
iconPath: 'assets/images/zen_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const xvg = CryptoCurrency(
|
||||||
|
title: 'XVG',
|
||||||
|
fullName: 'Verge',
|
||||||
|
raw: 45,
|
||||||
|
name: 'xvg',
|
||||||
|
iconPath: 'assets/images/xvg_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
|
||||||
static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POL', fullName: 'USDC', raw: 46, name: 'usdcpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
static const usdcpoly = CryptoCurrency(
|
||||||
static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/new-ui/crypto_full_icons/decred.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/decred.svg");
|
title: 'USDC',
|
||||||
static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png', decimals: 8);
|
tag: 'POL',
|
||||||
static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png', decimals: 18);
|
fullName: 'USDC',
|
||||||
static const maticpoly = CryptoCurrency(title: 'POL', tag: 'POL', fullName: 'Polygon', raw: 50, name: 'maticpoly', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg", chainIconPath: "assets/new-ui/chain_badges/polygon.svg");
|
raw: 46,
|
||||||
static const matic = CryptoCurrency(title: 'MATIC', tag: 'ETH', fullName: 'Polygon', raw: 51, name: 'matic', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg");
|
name: 'usdcpoly',
|
||||||
static const mkr = CryptoCurrency(title: 'MKR', tag: 'ETH', fullName: 'Maker', raw: 52, name: 'mkr', iconPath: 'assets/images/mkr_icon.png', decimals: 18);
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
static const near = CryptoCurrency(title: 'NEAR', fullName: 'NEAR Protocol', raw: 53, name: 'near', iconPath: 'assets/images/near_icon.png', decimals: 24);
|
decimals: 6,
|
||||||
static const oxt = CryptoCurrency(title: 'OXT', tag: 'ETH', fullName: 'Orchid', raw: 54, name: 'oxt', iconPath: 'assets/images/oxt_icon.png', decimals: 18);
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
static const paxg = CryptoCurrency(title: 'PAXG', tag: 'ETH', fullName: 'Pax Gold', raw: 55, name: 'paxg', iconPath: 'assets/new-ui/crypto_full_icons/paxg.svg', decimals: 18);
|
static const dcr = CryptoCurrency(
|
||||||
static const pivx = CryptoCurrency(title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8);
|
title: 'DCR',
|
||||||
static const rune = CryptoCurrency(title: 'RUNE', fullName: 'Thorchain', raw: 57, name: 'rune', iconPath: 'assets/images/rune_icon.png', decimals: 18);
|
fullName: 'Decred',
|
||||||
static const rvn = CryptoCurrency(title: 'RVN', fullName: 'Ravencoin', raw: 58, name: 'rvn', iconPath: 'assets/images/rvn_icon.png', decimals: 8);
|
raw: 47,
|
||||||
static const scrt = CryptoCurrency(title: 'SCRT', fullName: 'Secret Network', raw: 59, name: 'scrt', iconPath: 'assets/images/scrt_icon.png', decimals: 6);
|
name: 'dcr',
|
||||||
static const uni = CryptoCurrency(title: 'UNI', tag: 'ETH', fullName: 'Uniswap', raw: 60, name: 'uni', iconPath: 'assets/images/uni_icon.png', decimals: 18);
|
iconPath: 'assets/new-ui/crypto_full_icons/decred.svg',
|
||||||
static const stx = CryptoCurrency(title: 'STX', fullName: 'Stacks', raw: 61, name: 'stx', iconPath: 'assets/images/stx_icon.png', decimals: 8);
|
decimals: 8,
|
||||||
static const btcln = CryptoCurrency(title: 'BTC', tag: 'LN', fullName: 'Bitcoin Lightning Network', raw: 62, name: 'btcln', iconPath: 'assets/new-ui/crypto_full_icons/lightning.svg', chainIconPath: "assets/new-ui/chain_badges/lightning.svg", decimals: 8);
|
flatIconPath: "assets/new-ui/balance_card_icons/decred.svg");
|
||||||
static const shib = CryptoCurrency(title: 'SHIB', tag: 'ETH', fullName: 'Shiba Inu', raw: 63, name: 'shib', iconPath: 'assets/images/shib_icon.png', decimals: 18);
|
static const kmd = CryptoCurrency(
|
||||||
static const aave = CryptoCurrency(title: 'AAVE', tag: 'ETH', fullName: 'Aave', raw: 64, name: 'aave', iconPath: 'assets/images/aave_icon.png', decimals: 18);
|
title: 'KMD',
|
||||||
static const arb = CryptoCurrency(title: 'ARB', fullName: 'Arbitrum', raw: 65, name: 'arb', iconPath: 'assets/new-ui/crypto_full_icons/arbitrum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
|
fullName: 'Komodo',
|
||||||
static const bat = CryptoCurrency(title: 'BAT', tag: 'ETH', fullName: 'Basic Attention Token', raw: 66, name: 'bat', iconPath: 'assets/images/bat_icon.png', decimals: 18);
|
raw: 48,
|
||||||
static const comp = CryptoCurrency(title: 'COMP', tag: 'ETH', fullName: 'Compound', raw: 67, name: 'comp', iconPath: 'assets/images/comp_icon.png', decimals: 18);
|
name: 'kmd',
|
||||||
static const cro = CryptoCurrency(title: 'CRO', tag: 'ETH', fullName: 'Crypto.com Cronos', raw: 68, name: 'cro', iconPath: 'assets/images/cro_icon.png', decimals: 8);
|
iconPath: 'assets/images/kmd_icon.png',
|
||||||
static const ens = CryptoCurrency(title: 'ENS', tag: 'ETH', fullName: 'Ethereum Name Service', raw: 69, name: 'ens', iconPath: 'assets/images/ens_icon.png', decimals: 18);
|
decimals: 8);
|
||||||
static const ftm = CryptoCurrency(title: 'FTM', tag: 'ETH', fullName: 'Fantom', raw: 70, name: 'ftm', iconPath: 'assets/images/ftm_icon.png', decimals: 18);
|
static const mana = CryptoCurrency(
|
||||||
static const frax = CryptoCurrency(title: 'FRAX', tag: 'ETH', fullName: 'Frax', raw: 71, name: 'frax', iconPath: 'assets/images/frax_icon.png', decimals: 18);
|
title: 'MANA',
|
||||||
static const gusd = CryptoCurrency(title: 'GUSD', tag: 'ETH', fullName: 'Gemini USD', raw: 72, name: 'gusd', iconPath: 'assets/images/gusd_icon.png', decimals: 2);
|
tag: 'ETH',
|
||||||
static const gtc = CryptoCurrency(title: 'GTC', tag: 'ETH', fullName: 'Gitcoin', raw: 73, name: 'gtc', iconPath: 'assets/images/gtc_icon.png', decimals: 18);
|
fullName: 'Decentraland',
|
||||||
static const grt = CryptoCurrency(title: 'GRT', tag: 'ETH', fullName: 'The Graph', raw: 74, name: 'grt', iconPath: 'assets/images/grt_icon.png', decimals: 18);
|
raw: 49,
|
||||||
static const ldo = CryptoCurrency(title: 'LDO', tag: 'ETH', fullName: 'Lido DAO', raw: 75, name: 'ldo', iconPath: 'assets/images/ldo_icon.png', decimals: 18);
|
name: 'mana',
|
||||||
static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png', decimals: 18);
|
iconPath: 'assets/images/mana_icon.png',
|
||||||
static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png', decimals: 18);
|
decimals: 18);
|
||||||
static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png', decimals: 18);
|
static const maticpoly = CryptoCurrency(
|
||||||
static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png', decimals: 8);
|
title: 'POL',
|
||||||
static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png', decimals: 18);
|
tag: 'POL',
|
||||||
static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/new-ui/crypto_full_icons/wbtc.svg', decimals: 8);
|
fullName: 'Polygon',
|
||||||
static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
|
raw: 50,
|
||||||
static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png', decimals: 18);
|
name: 'maticpoly',
|
||||||
static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18);
|
iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg',
|
||||||
static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
|
decimals: 18,
|
||||||
static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29,flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
|
flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg",
|
||||||
static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POL', fullName: 'Tether (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
chainIconPath: "assets/new-ui/chain_badges/polygon.svg");
|
||||||
static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POL', fullName: 'USDC (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6);
|
static const matic = CryptoCurrency(
|
||||||
static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
|
title: 'MATIC',
|
||||||
static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8);
|
tag: 'ETH',
|
||||||
static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
fullName: 'Polygon',
|
||||||
static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
raw: 51,
|
||||||
static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
|
name: 'matic',
|
||||||
static const wow = CryptoCurrency(title: 'WOW', fullName: 'Wownero', raw: 94, name: 'wow', iconPath: 'assets/images/crypto/wownero.svg', decimals: 11);
|
iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg',
|
||||||
static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/new-ui/crypto_full_icons/ton.svg', decimals: 8);
|
decimals: 18,
|
||||||
static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/new-ui/crypto_full_icons/zano.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/zano.svg", chainIconPath: "assets/new-ui/chain_badges/zano.svg");
|
flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg");
|
||||||
static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18);
|
static const mkr = CryptoCurrency(
|
||||||
static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png',decimals: 18, groups: const {CurrencyGroups.stablecoin});
|
title: 'MKR',
|
||||||
static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
|
tag: 'ETH',
|
||||||
static const ndeps = CryptoCurrency(title: 'NDEPS', tag: 'ETH', fullName: 'Native Decentralized Euro Protocol Share', raw: 100, name: 'ndeps', iconPath: 'assets/images/ndeps_icon.png', decimals: 18);
|
fullName: 'Maker',
|
||||||
static const deps = CryptoCurrency(title: 'DEPS', tag: 'ETH', fullName: 'Decentralized Euro Protocol Share', raw: 101, name: 'deps', iconPath: 'assets/images/deps_icon.png', decimals: 18);
|
raw: 52,
|
||||||
static const kbtc = CryptoCurrency(title: 'KBTC', tag: 'ETH', fullName: 'Kraken Wrapped Bitcoin', raw: 102, name: 'kbtc', iconPath: 'assets/images/kbtc_icon.png', decimals: 8);
|
name: 'mkr',
|
||||||
static const cbbtc = CryptoCurrency(title: 'CBBTC', tag: 'ETH', fullName: 'Coinbase Wrapped BTC', raw: 103, name: 'cbbtc', iconPath: 'assets/images/cbbtc_icon.png', decimals: 8);
|
iconPath: 'assets/images/mkr_icon.png',
|
||||||
static const baseEth = CryptoCurrency(title: 'ETH', tag: 'BASE', fullName: 'Ethereum', raw: 104, name: 'baseth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/base.svg", chainIconPath: "assets/new-ui/chain_badges/base.svg");
|
decimals: 18);
|
||||||
static const usde = CryptoCurrency(title: 'USDE', tag: 'BASE', fullName: 'Ethena USDE', raw: 105, name: 'usde', iconPath: 'assets/new-ui/crypto_full_icons/usde.svg', decimals: 18);
|
static const near = CryptoCurrency(
|
||||||
static const arbEth = CryptoCurrency(title: 'ETH', tag: 'ARB', fullName: 'Ethereum', raw: 106, name: 'arbeth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
|
title: 'NEAR',
|
||||||
static const zec = CryptoCurrency(title: 'ZEC', fullName: 'Zcash', raw: 107, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8,flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg");
|
fullName: 'NEAR Protocol',
|
||||||
static const usdcArb = CryptoCurrency(title: 'USDC', tag: 'ARB', fullName: 'USDC Coin', raw: 108, name: 'usdcarb', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
raw: 53,
|
||||||
static const usdtArb = CryptoCurrency(title: 'USDT', tag: 'ARB', fullName: 'USDT Tether', raw: 109, name: 'usdtarb', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
|
name: 'near',
|
||||||
static const ltcmweb = CryptoCurrency(title: 'LTC', fullName: 'Litecoin MWeb', raw: 110, name: 'ltcmweb', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8);
|
iconPath: 'assets/images/near_icon.png',
|
||||||
|
decimals: 24);
|
||||||
|
static const oxt = CryptoCurrency(
|
||||||
|
title: 'OXT',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Orchid',
|
||||||
|
raw: 54,
|
||||||
|
name: 'oxt',
|
||||||
|
iconPath: 'assets/images/oxt_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const paxg = CryptoCurrency(
|
||||||
|
title: 'PAXG',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Pax Gold',
|
||||||
|
raw: 55,
|
||||||
|
name: 'paxg',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/paxg.svg',
|
||||||
|
decimals: 18);
|
||||||
|
static const pivx = CryptoCurrency(
|
||||||
|
title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8);
|
||||||
|
static const rune = CryptoCurrency(
|
||||||
|
title: 'RUNE',
|
||||||
|
fullName: 'Thorchain',
|
||||||
|
raw: 57,
|
||||||
|
name: 'rune',
|
||||||
|
iconPath: 'assets/images/rune_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const rvn = CryptoCurrency(
|
||||||
|
title: 'RVN',
|
||||||
|
fullName: 'Ravencoin',
|
||||||
|
raw: 58,
|
||||||
|
name: 'rvn',
|
||||||
|
iconPath: 'assets/images/rvn_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const scrt = CryptoCurrency(
|
||||||
|
title: 'SCRT',
|
||||||
|
fullName: 'Secret Network',
|
||||||
|
raw: 59,
|
||||||
|
name: 'scrt',
|
||||||
|
iconPath: 'assets/images/scrt_icon.png',
|
||||||
|
decimals: 6);
|
||||||
|
static const uni = CryptoCurrency(
|
||||||
|
title: 'UNI',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Uniswap',
|
||||||
|
raw: 60,
|
||||||
|
name: 'uni',
|
||||||
|
iconPath: 'assets/images/uni_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const stx = CryptoCurrency(
|
||||||
|
title: 'STX',
|
||||||
|
fullName: 'Stacks',
|
||||||
|
raw: 61,
|
||||||
|
name: 'stx',
|
||||||
|
iconPath: 'assets/images/stx_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const btcln = CryptoCurrency(
|
||||||
|
title: 'BTC',
|
||||||
|
tag: 'LN',
|
||||||
|
fullName: 'Bitcoin Lightning Network',
|
||||||
|
raw: 62,
|
||||||
|
name: 'btcln',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/lightning.svg',
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/lightning.svg",
|
||||||
|
decimals: 8);
|
||||||
|
static const shib = CryptoCurrency(
|
||||||
|
title: 'SHIB',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Shiba Inu',
|
||||||
|
raw: 63,
|
||||||
|
name: 'shib',
|
||||||
|
iconPath: 'assets/images/shib_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const aave = CryptoCurrency(
|
||||||
|
title: 'AAVE',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Aave',
|
||||||
|
raw: 64,
|
||||||
|
name: 'aave',
|
||||||
|
iconPath: 'assets/images/aave_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const arb = CryptoCurrency(
|
||||||
|
title: 'ARB',
|
||||||
|
fullName: 'Arbitrum',
|
||||||
|
raw: 65,
|
||||||
|
name: 'arb',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/arbitrum.svg',
|
||||||
|
decimals: 18,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
|
||||||
|
static const bat = CryptoCurrency(
|
||||||
|
title: 'BAT',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Basic Attention Token',
|
||||||
|
raw: 66,
|
||||||
|
name: 'bat',
|
||||||
|
iconPath: 'assets/images/bat_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const comp = CryptoCurrency(
|
||||||
|
title: 'COMP',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Compound',
|
||||||
|
raw: 67,
|
||||||
|
name: 'comp',
|
||||||
|
iconPath: 'assets/images/comp_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const cro = CryptoCurrency(
|
||||||
|
title: 'CRO',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Crypto.com Cronos',
|
||||||
|
raw: 68,
|
||||||
|
name: 'cro',
|
||||||
|
iconPath: 'assets/images/cro_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const ens = CryptoCurrency(
|
||||||
|
title: 'ENS',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Ethereum Name Service',
|
||||||
|
raw: 69,
|
||||||
|
name: 'ens',
|
||||||
|
iconPath: 'assets/images/ens_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const ftm = CryptoCurrency(
|
||||||
|
title: 'FTM',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Fantom',
|
||||||
|
raw: 70,
|
||||||
|
name: 'ftm',
|
||||||
|
iconPath: 'assets/images/ftm_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const frax = CryptoCurrency(
|
||||||
|
title: 'FRAX',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Frax',
|
||||||
|
raw: 71,
|
||||||
|
name: 'frax',
|
||||||
|
iconPath: 'assets/images/frax_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const gusd = CryptoCurrency(
|
||||||
|
title: 'GUSD',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Gemini USD',
|
||||||
|
raw: 72,
|
||||||
|
name: 'gusd',
|
||||||
|
iconPath: 'assets/images/gusd_icon.png',
|
||||||
|
decimals: 2);
|
||||||
|
static const gtc = CryptoCurrency(
|
||||||
|
title: 'GTC',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Gitcoin',
|
||||||
|
raw: 73,
|
||||||
|
name: 'gtc',
|
||||||
|
iconPath: 'assets/images/gtc_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const grt = CryptoCurrency(
|
||||||
|
title: 'GRT',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'The Graph',
|
||||||
|
raw: 74,
|
||||||
|
name: 'grt',
|
||||||
|
iconPath: 'assets/images/grt_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const ldo = CryptoCurrency(
|
||||||
|
title: 'LDO',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Lido DAO',
|
||||||
|
raw: 75,
|
||||||
|
name: 'ldo',
|
||||||
|
iconPath: 'assets/images/ldo_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const nexo = CryptoCurrency(
|
||||||
|
title: 'NEXO',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Nexo',
|
||||||
|
raw: 76,
|
||||||
|
name: 'nexo',
|
||||||
|
iconPath: 'assets/images/nexo_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const cake = CryptoCurrency(
|
||||||
|
title: 'CAKE',
|
||||||
|
tag: 'BSC',
|
||||||
|
fullName: 'PancakeSwap',
|
||||||
|
raw: 77,
|
||||||
|
name: 'cake',
|
||||||
|
iconPath: 'assets/images/cake_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const pepe = CryptoCurrency(
|
||||||
|
title: 'PEPE',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Pepe',
|
||||||
|
raw: 78,
|
||||||
|
name: 'pepe',
|
||||||
|
iconPath: 'assets/images/pepe_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const storj = CryptoCurrency(
|
||||||
|
title: 'STORJ',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Storj',
|
||||||
|
raw: 79,
|
||||||
|
name: 'storj',
|
||||||
|
iconPath: 'assets/images/storj_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const tusd = CryptoCurrency(
|
||||||
|
title: 'TUSD',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'TrueUSD',
|
||||||
|
raw: 80,
|
||||||
|
name: 'tusd',
|
||||||
|
iconPath: 'assets/images/tusd_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const wbtc = CryptoCurrency(
|
||||||
|
title: 'WBTC',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Wrapped Bitcoin',
|
||||||
|
raw: 81,
|
||||||
|
name: 'wbtc',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/wbtc.svg',
|
||||||
|
decimals: 8);
|
||||||
|
static const weth = CryptoCurrency(
|
||||||
|
title: 'WETH',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Wrapped Ethereum',
|
||||||
|
raw: 82,
|
||||||
|
name: 'weth',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
|
||||||
|
decimals: 18);
|
||||||
|
static const zrx = CryptoCurrency(
|
||||||
|
title: 'ZRX',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: '0x Protocol',
|
||||||
|
raw: 83,
|
||||||
|
name: 'zrx',
|
||||||
|
iconPath: 'assets/images/zrx_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const dydx = CryptoCurrency(
|
||||||
|
title: 'DYDX',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'dYdX',
|
||||||
|
raw: 84,
|
||||||
|
name: 'dydx',
|
||||||
|
iconPath: 'assets/images/dydx_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const steth = CryptoCurrency(
|
||||||
|
title: 'STETH',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Lido Staked Ethereum',
|
||||||
|
raw: 85,
|
||||||
|
name: 'steth',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
|
||||||
|
decimals: 18);
|
||||||
|
static const banano = CryptoCurrency(
|
||||||
|
title: 'BAN',
|
||||||
|
fullName: 'Banano',
|
||||||
|
raw: 86,
|
||||||
|
name: 'banano',
|
||||||
|
iconPath: 'assets/images/nano_icon.png',
|
||||||
|
decimals: 29,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
|
||||||
|
static const usdtPoly = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'POL',
|
||||||
|
fullName: 'Tether (PoS)',
|
||||||
|
raw: 87,
|
||||||
|
name: 'usdtpoly',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdcEPoly = CryptoCurrency(
|
||||||
|
title: 'USDC.E',
|
||||||
|
tag: 'POL',
|
||||||
|
fullName: 'USDC (PoS)',
|
||||||
|
raw: 88,
|
||||||
|
name: 'usdcepoly',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
|
decimals: 6);
|
||||||
|
static const kaspa = CryptoCurrency(
|
||||||
|
title: 'KAS',
|
||||||
|
fullName: 'Kaspa',
|
||||||
|
raw: 89,
|
||||||
|
name: 'kas',
|
||||||
|
iconPath: 'assets/images/kaspa_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const digibyte = CryptoCurrency(
|
||||||
|
title: 'DGB',
|
||||||
|
fullName: 'DigiByte',
|
||||||
|
raw: 90,
|
||||||
|
name: 'dgb',
|
||||||
|
iconPath: 'assets/images/digibyte.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const usdtSol = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'SOL',
|
||||||
|
fullName: 'Tether',
|
||||||
|
raw: 91,
|
||||||
|
name: 'usdtsol',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdcTrc20 = CryptoCurrency(
|
||||||
|
title: 'USDC',
|
||||||
|
tag: 'TRX',
|
||||||
|
fullName: 'USDC Coin',
|
||||||
|
raw: 92,
|
||||||
|
name: 'usdctrc20',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const tbtc = CryptoCurrency(
|
||||||
|
title: 'tBTC',
|
||||||
|
fullName: 'Testnet Bitcoin',
|
||||||
|
raw: 93,
|
||||||
|
name: 'tbtc',
|
||||||
|
iconPath: 'assets/images/tbtc.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const wow = CryptoCurrency(
|
||||||
|
title: 'WOW',
|
||||||
|
fullName: 'Wownero',
|
||||||
|
raw: 94,
|
||||||
|
name: 'wow',
|
||||||
|
iconPath: 'assets/images/crypto/wownero.svg',
|
||||||
|
decimals: 11);
|
||||||
|
static const ton = CryptoCurrency(
|
||||||
|
title: 'TON',
|
||||||
|
fullName: 'Toncoin',
|
||||||
|
raw: 95,
|
||||||
|
name: 'ton',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ton.svg',
|
||||||
|
decimals: 8);
|
||||||
|
static const zano = CryptoCurrency(
|
||||||
|
title: 'ZANO',
|
||||||
|
tag: 'ZANO',
|
||||||
|
fullName: 'Zano',
|
||||||
|
raw: 96,
|
||||||
|
name: 'zano',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/zano.svg',
|
||||||
|
decimals: 12,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/zano.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/zano.svg");
|
||||||
|
static const flip = CryptoCurrency(
|
||||||
|
title: 'FLIP',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Chainflip',
|
||||||
|
raw: 97,
|
||||||
|
name: 'flip',
|
||||||
|
iconPath: 'assets/images/flip_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const deuro = CryptoCurrency(
|
||||||
|
title: 'DEURO',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Decentralized Euro',
|
||||||
|
raw: 98,
|
||||||
|
name: 'deuro',
|
||||||
|
iconPath: 'assets/images/deuro_icon.png',
|
||||||
|
decimals: 18,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdtbsc = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'BSC',
|
||||||
|
fullName: 'USDT Binance coin',
|
||||||
|
raw: 99,
|
||||||
|
name: 'usdtbsc',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 18,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const ndeps = CryptoCurrency(
|
||||||
|
title: 'NDEPS',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Native Decentralized Euro Protocol Share',
|
||||||
|
raw: 100,
|
||||||
|
name: 'ndeps',
|
||||||
|
iconPath: 'assets/images/ndeps_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const deps = CryptoCurrency(
|
||||||
|
title: 'DEPS',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Decentralized Euro Protocol Share',
|
||||||
|
raw: 101,
|
||||||
|
name: 'deps',
|
||||||
|
iconPath: 'assets/images/deps_icon.png',
|
||||||
|
decimals: 18);
|
||||||
|
static const kbtc = CryptoCurrency(
|
||||||
|
title: 'KBTC',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Kraken Wrapped Bitcoin',
|
||||||
|
raw: 102,
|
||||||
|
name: 'kbtc',
|
||||||
|
iconPath: 'assets/images/kbtc_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const cbbtc = CryptoCurrency(
|
||||||
|
title: 'CBBTC',
|
||||||
|
tag: 'ETH',
|
||||||
|
fullName: 'Coinbase Wrapped BTC',
|
||||||
|
raw: 103,
|
||||||
|
name: 'cbbtc',
|
||||||
|
iconPath: 'assets/images/cbbtc_icon.png',
|
||||||
|
decimals: 8);
|
||||||
|
static const baseEth = CryptoCurrency(
|
||||||
|
title: 'ETH',
|
||||||
|
tag: 'BASE',
|
||||||
|
fullName: 'Ethereum',
|
||||||
|
raw: 104,
|
||||||
|
name: 'baseth',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
|
||||||
|
decimals: 18,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/base.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/base.svg");
|
||||||
|
static const usde = CryptoCurrency(
|
||||||
|
title: 'USDE',
|
||||||
|
tag: 'BASE',
|
||||||
|
fullName: 'Ethena USDE',
|
||||||
|
raw: 105,
|
||||||
|
name: 'usde',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usde.svg',
|
||||||
|
decimals: 18);
|
||||||
|
static const arbEth = CryptoCurrency(
|
||||||
|
title: 'ETH',
|
||||||
|
tag: 'ARB',
|
||||||
|
fullName: 'Ethereum',
|
||||||
|
raw: 106,
|
||||||
|
name: 'arbeth',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
|
||||||
|
decimals: 18,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg",
|
||||||
|
chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
|
||||||
|
static const zec = CryptoCurrency(
|
||||||
|
title: 'ZEC',
|
||||||
|
fullName: 'Zcash',
|
||||||
|
raw: 107,
|
||||||
|
name: 'zec',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
|
||||||
|
decimals: 8,
|
||||||
|
flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg");
|
||||||
|
static const usdcArb = CryptoCurrency(
|
||||||
|
title: 'USDC',
|
||||||
|
tag: 'ARB',
|
||||||
|
fullName: 'USDC Coin',
|
||||||
|
raw: 108,
|
||||||
|
name: 'usdcarb',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const usdtArb = CryptoCurrency(
|
||||||
|
title: 'USDT',
|
||||||
|
tag: 'ARB',
|
||||||
|
fullName: 'USDT Tether',
|
||||||
|
raw: 109,
|
||||||
|
name: 'usdtarb',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
|
||||||
|
decimals: 6,
|
||||||
|
groups: const {CurrencyGroups.stablecoin});
|
||||||
|
static const ltcmweb = CryptoCurrency(
|
||||||
|
title: 'LTC',
|
||||||
|
fullName: 'Litecoin MWeb',
|
||||||
|
raw: 110,
|
||||||
|
name: 'ltcmweb',
|
||||||
|
iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg',
|
||||||
|
decimals: 8);
|
||||||
|
|
||||||
static final Map<int, CryptoCurrency> _rawCurrencyMap =
|
static final Map<int, CryptoCurrency> _rawCurrencyMap = [
|
||||||
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {
|
...all,
|
||||||
|
...havenCurrencies,
|
||||||
|
...zcashCurrencies
|
||||||
|
].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {
|
||||||
acc.addAll({item.raw: item});
|
acc.addAll({item.raw: item});
|
||||||
return acc;
|
return acc;
|
||||||
});
|
});
|
||||||
|
|
||||||
static final Map<String, CryptoCurrency> _nameCurrencyMap =
|
static final Map<String, CryptoCurrency> _nameCurrencyMap = [
|
||||||
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
|
...all,
|
||||||
|
...havenCurrencies,
|
||||||
|
...zcashCurrencies
|
||||||
|
].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
|
||||||
acc.addAll({item.name: item});
|
acc.addAll({item.name: item});
|
||||||
return acc;
|
return acc;
|
||||||
});
|
});
|
||||||
|
|
||||||
static final Map<String, CryptoCurrency> _fullNameCurrencyMap =
|
static final Map<String, CryptoCurrency> _fullNameCurrencyMap = [
|
||||||
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
|
...all,
|
||||||
if(item.fullName != null){
|
...havenCurrencies,
|
||||||
|
...zcashCurrencies
|
||||||
|
].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
|
||||||
|
if (item.fullName != null) {
|
||||||
acc.addAll({item.fullName!.toLowerCase(): item});
|
acc.addAll({item.fullName!.toLowerCase(): item});
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
@@ -334,10 +1037,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
|||||||
return _rawCurrencyMap[raw];
|
return _rawCurrencyMap[raw];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: refactor this
|
// TODO: refactor this
|
||||||
static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) {
|
static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) {
|
||||||
|
|
||||||
final schemeMatch = _schemeCurrencyMap[name.toLowerCase()];
|
final schemeMatch = _schemeCurrencyMap[name.toLowerCase()];
|
||||||
if (schemeMatch != null) return schemeMatch;
|
if (schemeMatch != null) return schemeMatch;
|
||||||
|
|
||||||
@@ -378,7 +1079,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
|||||||
}) {
|
}) {
|
||||||
if (raw == null || raw.isEmpty) return null;
|
if (raw == null || raw.isEmpty) return null;
|
||||||
|
|
||||||
if(tag?.toLowerCase() == "lightning") tag = "LN";
|
if (tag?.toLowerCase() == "lightning") tag = "LN";
|
||||||
|
|
||||||
if (tag != null && tag.isNotEmpty) {
|
if (tag != null && tag.isNotEmpty) {
|
||||||
final match = CryptoCurrency.all.firstWhereOrNull(
|
final match = CryptoCurrency.all.firstWhereOrNull(
|
||||||
@@ -390,12 +1091,10 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Try for native currency with same title and tag
|
// Try for native currency with same title and tag
|
||||||
if (tag == null || tag.isEmpty) {
|
if (tag == null || tag.isEmpty) {
|
||||||
final match = CryptoCurrency.all.firstWhereOrNull(
|
final match = CryptoCurrency.all.firstWhereOrNull(
|
||||||
(e) =>
|
(e) => e.title.toUpperCase() == raw.toUpperCase() && (e.tag == raw.toUpperCase()),
|
||||||
e.title.toUpperCase() == raw.toUpperCase() && (e.tag == raw.toUpperCase()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (match != null) return match;
|
if (match != null) return match;
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ int? getChainIdByCryptoCurrency(CryptoCurrency currency) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type, {bool isTestnet = false, int? chainId}) {
|
CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type,
|
||||||
|
{bool isTestnet = false, int? chainId}) {
|
||||||
if (type == WalletType.arbitrum) {
|
if (type == WalletType.arbitrum) {
|
||||||
return CryptoCurrency.arb;
|
return CryptoCurrency.arb;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ import 'dart:typed_data';
|
|||||||
import 'package:cw_core/utils/file.dart' as file;
|
import 'package:cw_core/utils/file.dart' as file;
|
||||||
import 'package:cake_backup/backup.dart' as cwb;
|
import 'package:cake_backup/backup.dart' as cwb;
|
||||||
|
|
||||||
EncryptionFileUtils encryptionFileUtilsFor(bool direct)
|
EncryptionFileUtils encryptionFileUtilsFor(bool direct) =>
|
||||||
=> direct
|
direct ? XChaCha20EncryptionFileUtils() : Salsa20EncryhptionFileUtils();
|
||||||
? XChaCha20EncryptionFileUtils()
|
|
||||||
: Salsa20EncryhptionFileUtils();
|
|
||||||
|
|
||||||
abstract class EncryptionFileUtils {
|
abstract class EncryptionFileUtils {
|
||||||
Future<void> write({required String path, required String password, required String data});
|
Future<void> write({required String path, required String password, required String data});
|
||||||
@@ -16,13 +14,14 @@ abstract class EncryptionFileUtils {
|
|||||||
class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
|
class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
|
||||||
// Requires legacy complex key + iv as password
|
// Requires legacy complex key + iv as password
|
||||||
@override
|
@override
|
||||||
Future<void> write({required String path, required String password, required String data}) async
|
Future<void> write(
|
||||||
=> await file.write(path: path, password: password, data: data);
|
{required String path, required String password, required String data}) async =>
|
||||||
|
await file.write(path: path, password: password, data: data);
|
||||||
|
|
||||||
// Requires legacy complex key + iv as password
|
// Requires legacy complex key + iv as password
|
||||||
@override
|
@override
|
||||||
Future<String> read({required String path, required String password}) async
|
Future<String> read({required String path, required String password}) async =>
|
||||||
=> await file.read(path: path, password: password);
|
await file.read(path: path, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
|
class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'erc20_token.dart';
|
part of 'erc20_token.dart';
|
||||||
|
|
||||||
@@ -55,7 +55,5 @@ class Erc20TokenAdapter extends TypeAdapter<Erc20Token> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is Erc20TokenAdapter &&
|
other is Erc20TokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
String formatAmount(String amount) {
|
String formatAmount(String amount) {
|
||||||
if ((!amount.contains('.'))&&(!amount.contains(','))) {
|
if ((!amount.contains('.')) && (!amount.contains(','))) {
|
||||||
return amount + '.00';
|
return amount + '.00';
|
||||||
} else if ((amount.endsWith('.'))||(amount.endsWith(','))) {
|
} else if ((amount.endsWith('.')) || (amount.endsWith(','))) {
|
||||||
return amount + '00';
|
return amount + '00';
|
||||||
}
|
}
|
||||||
return amount;
|
return amount;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:cw_core/parse_fixed.dart';
|
import 'package:cw_core/parse_fixed.dart';
|
||||||
|
|
||||||
String formatFixed(BigInt value, int? decimals,
|
String formatFixed(BigInt value, int? decimals, {int? fractionalDigits, bool trimZeros = true}) {
|
||||||
{int? fractionalDigits, bool trimZeros = true}) {
|
|
||||||
decimals ??= 0;
|
decimals ??= 0;
|
||||||
fractionalDigits ??= decimals;
|
fractionalDigits ??= decimals;
|
||||||
|
|
||||||
@@ -10,10 +9,8 @@ String formatFixed(BigInt value, int? decimals,
|
|||||||
var negative = value.isNegative;
|
var negative = value.isNegative;
|
||||||
if (negative) value = value * BigInt.from(-1);
|
if (negative) value = value * BigInt.from(-1);
|
||||||
|
|
||||||
var fraction = value
|
var fraction =
|
||||||
.modPow(BigInt.one, BigInt.parse(multiplier))
|
value.modPow(BigInt.one, BigInt.parse(multiplier)).toString().padLeft(decimals, "0");
|
||||||
.toString()
|
|
||||||
.padLeft(decimals, "0");
|
|
||||||
|
|
||||||
if (fractionalDigits < 0) fractionalDigits = 0;
|
if (fractionalDigits < 0) fractionalDigits = 0;
|
||||||
if (fractionalDigits > decimals) fractionalDigits = decimals;
|
if (fractionalDigits > decimals) fractionalDigits = decimals;
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import 'dart:convert';
|
|||||||
|
|
||||||
// FIXME: Hardcoded values; Works only for monero
|
// FIXME: Hardcoded values; Works only for monero
|
||||||
|
|
||||||
int getMoneroHeigthByDate({required DateTime date}) => MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
|
int getMoneroHeigthByDate({required DateTime date}) =>
|
||||||
|
MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
|
||||||
|
|
||||||
const havenDates = {
|
const havenDates = {
|
||||||
"2023-05": 1352995,
|
"2023-05": 1352995,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
class MoneroHeight {
|
class MoneroHeight {
|
||||||
// for i in $(seq 1 364); do echo "_Checkpoint(_t($(curl https://xmrchain.net/block/${i}0000 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}' | xargs | sed 's/ /\n/g' | head -5 | tail -1 | tr '()' ' ' | sed 's/ /\n/g' | head -2 | xargs)), ${i}0000),"; done > points.txt
|
// for i in $(seq 1 364); do echo "_Checkpoint(_t($(curl https://xmrchain.net/block/${i}0000 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}' | xargs | sed 's/ /\n/g' | head -5 | tail -1 | tr '()' ' ' | sed 's/ /\n/g' | head -2 | xargs)), ${i}0000),"; done > points.txt
|
||||||
static final List<_Checkpoint> _points = [
|
static final List<_Checkpoint> _points = [
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ List<String> extractKeys(String key) {
|
|||||||
return [_key, iv];
|
return [_key, iv];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> encode({required encrypt.Key key, required encrypt.IV iv, required String data}) async {
|
Future<String> encode(
|
||||||
|
{required encrypt.Key key, required encrypt.IV iv, required String data}) async {
|
||||||
final encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
|
final encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
|
||||||
final encrypted = encrypter.encrypt(data, iv: iv);
|
final encrypted = encrypter.encrypt(data, iv: iv);
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,11 @@ bool isBolt11ZeroInvoice(String invoice) {
|
|||||||
try {
|
try {
|
||||||
final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
|
final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
|
||||||
|
|
||||||
|
final prefix =
|
||||||
final prefix = _BOLT_PREFIXES
|
_BOLT_PREFIXES.firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
|
||||||
.firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
|
|
||||||
|
|
||||||
return request.hrp.length == prefix.length;
|
return request.hrp.length == prefix.length;
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,8 +85,7 @@ class LNURL {
|
|||||||
final maxSendable = body["maxSendable"] as int?;
|
final maxSendable = body["maxSendable"] as int?;
|
||||||
|
|
||||||
// if minSendable and maxSendable are the same we assume a specific payment request
|
// if minSendable and maxSendable are the same we assume a specific payment request
|
||||||
if (msat != maxSendable)
|
if (msat != maxSendable) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
if (msat == null || msat % 1000 != 0) return null;
|
if (msat == null || msat % 1000 != 0) return null;
|
||||||
return Money.fromInt(msat ~/ 1000, CryptoCurrency.btcln);
|
return Money.fromInt(msat ~/ 1000, CryptoCurrency.btcln);
|
||||||
@@ -136,8 +134,7 @@ class LNURL {
|
|||||||
String _findLnUrl(String input) {
|
String _findLnUrl(String input) {
|
||||||
final res = RegExp(r',*?((lnurl)([0-9]+[a-z0-9]+))').allMatches(input.toLowerCase());
|
final res = RegExp(r',*?((lnurl)([0-9]+[a-z0-9]+))').allMatches(input.toLowerCase());
|
||||||
|
|
||||||
if (res.length != 1)
|
if (res.length != 1) throw ArgumentError('Not a valid lnurl string');
|
||||||
throw ArgumentError('Not a valid lnurl string');
|
|
||||||
return res.first.group(0)!;
|
return res.first.group(0)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,5 @@ class MwebUtxoAdapter extends TypeAdapter<MwebUtxo> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is MwebUtxoAdapter &&
|
other is MwebUtxoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,5 @@ class NanoAccountAdapter extends TypeAdapter<NanoAccount> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is NanoAccountAdapter &&
|
other is NanoAccountAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-23
@@ -25,11 +25,9 @@ Future<void> validateBuiltinNodes() async {
|
|||||||
for (final listNode in builtinFromList) {
|
for (final listNode in builtinFromList) {
|
||||||
// preserve proxy settings from user
|
// preserve proxy settings from user
|
||||||
try {
|
try {
|
||||||
final matchedDbNode = builtinFromDb.firstWhere(
|
final matchedDbNode = builtinFromDb.firstWhere((dbNode) => dbNode.uri == listNode.uri);
|
||||||
(dbNode) => dbNode.uri == listNode.uri
|
|
||||||
);
|
|
||||||
listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
|
listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
final dbSet = builtinFromDb.toSet();
|
final dbSet = builtinFromDb.toSet();
|
||||||
@@ -121,7 +119,7 @@ class Node {
|
|||||||
"label": label,
|
"label": label,
|
||||||
'password': password,
|
'password': password,
|
||||||
"isPow": isPow ? 1 : 0,
|
"isPow": isPow ? 1 : 0,
|
||||||
'useSSL': (useSSL??false) ? 1 : 0,
|
'useSSL': (useSSL ?? false) ? 1 : 0,
|
||||||
"typeRaw": typeRaw,
|
"typeRaw": typeRaw,
|
||||||
'trusted': trusted ? 1 : 0,
|
'trusted': trusted ? 1 : 0,
|
||||||
'socksProxyAddress': socksProxyAddress,
|
'socksProxyAddress': socksProxyAddress,
|
||||||
@@ -165,7 +163,6 @@ class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<int> save() async {
|
Future<int> save() async {
|
||||||
|
|
||||||
final json = toMap();
|
final json = toMap();
|
||||||
if (json[selfIdColumn] == 0) {
|
if (json[selfIdColumn] == 0) {
|
||||||
json[selfIdColumn] = null;
|
json[selfIdColumn] = null;
|
||||||
@@ -174,9 +171,9 @@ class Node {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<Node>> selectList(String where, List<dynamic> whereArgs,
|
||||||
static Future<List<Node>> selectList(String where, List<dynamic> whereArgs, {String? orderBy}) async {
|
{String? orderBy}) async {
|
||||||
if(orderBy == null) {
|
if (orderBy == null) {
|
||||||
orderBy = selfIdColumn;
|
orderBy = selfIdColumn;
|
||||||
}
|
}
|
||||||
final list = await db!.query(
|
final list = await db!.query(
|
||||||
@@ -189,7 +186,7 @@ class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<Node?> select(String where, List<dynamic> whereArgs, {String? orderBy}) async {
|
static Future<Node?> select(String where, List<dynamic> whereArgs, {String? orderBy}) async {
|
||||||
if(orderBy == null) {
|
if (orderBy == null) {
|
||||||
orderBy = selfIdColumn;
|
orderBy = selfIdColumn;
|
||||||
}
|
}
|
||||||
final list = await db!.query(
|
final list = await db!.query(
|
||||||
@@ -201,7 +198,6 @@ class Node {
|
|||||||
return list.isEmpty ? null : Node.fromMap(list.first);
|
return list.isEmpty ? null : Node.fromMap(list.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Future<List<Node>> getAll() async {
|
static Future<List<Node>> getAll() async {
|
||||||
return selectList("isPow = ?", [0]);
|
return selectList("isPow = ?", [0]);
|
||||||
}
|
}
|
||||||
@@ -219,11 +215,15 @@ class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<Node?> getDefaultForWalletType(WalletType type) async {
|
static Future<Node?> getDefaultForWalletType(WalletType type) async {
|
||||||
return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1])).firstOrNull;
|
return (await selectList(
|
||||||
|
"typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1]))
|
||||||
|
.firstOrNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
|
static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
|
||||||
return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1])).firstOrNull;
|
return (await selectList(
|
||||||
|
"typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1]))
|
||||||
|
.firstOrNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
|
static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
|
||||||
@@ -238,7 +238,6 @@ class Node {
|
|||||||
return select("${selfIdColumn} = ?", [id]);
|
return select("${selfIdColumn} = ?", [id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
late String uriRaw;
|
late String uriRaw;
|
||||||
String? login;
|
String? login;
|
||||||
@@ -262,7 +261,6 @@ class Node {
|
|||||||
static String get tableName => "Node";
|
static String get tableName => "Node";
|
||||||
static String get selfIdColumn => "${tableName}Id";
|
static String get selfIdColumn => "${tableName}Id";
|
||||||
|
|
||||||
|
|
||||||
bool get isSSL => useSSL ?? false;
|
bool get isSSL => useSSL ?? false;
|
||||||
|
|
||||||
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
|
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
|
||||||
@@ -333,7 +331,6 @@ class Node {
|
|||||||
socksProxyAddress.hashCode ^
|
socksProxyAddress.hashCode ^
|
||||||
path.hashCode;
|
path.hashCode;
|
||||||
|
|
||||||
|
|
||||||
WalletType get type => deserializeFromInt(typeRaw);
|
WalletType get type => deserializeFromInt(typeRaw);
|
||||||
|
|
||||||
set type(WalletType type) => typeRaw = serializeToInt(type);
|
set type(WalletType type) => typeRaw = serializeToInt(type);
|
||||||
@@ -387,7 +384,6 @@ class Node {
|
|||||||
body: jsonBody,
|
body: jsonBody,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
final resBody = json.decode(response.body) as Map<String, dynamic>;
|
final resBody = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
|
||||||
return resBody['result']['height'] != null;
|
return resBody['result']['height'] != null;
|
||||||
@@ -407,15 +403,13 @@ class Node {
|
|||||||
final body = {'jsonrpc': '2.0', 'id': '0', 'method': methodName};
|
final body = {'jsonrpc': '2.0', 'id': '0', 'method': methodName};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final jsonBody = json.encode(body);
|
final jsonBody = json.encode(body);
|
||||||
|
|
||||||
final response = await ProxyWrapper().post(
|
final response = await ProxyWrapper().post(
|
||||||
clearnetUri: rpcUri,
|
clearnetUri: rpcUri,
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: jsonBody,
|
body: jsonBody,
|
||||||
allowMitmMoneroBypassSSLCheck: true
|
allowMitmMoneroBypassSSLCheck: true);
|
||||||
);
|
|
||||||
// Check if we received a 401 Unauthorized response
|
// Check if we received a 401 Unauthorized response
|
||||||
if (response.statusCode == 401) {
|
if (response.statusCode == 401) {
|
||||||
final daemonRpc = DaemonRpc(
|
final daemonRpc = DaemonRpc(
|
||||||
@@ -494,7 +488,6 @@ class Node {
|
|||||||
final ProxySocket socket;
|
final ProxySocket socket;
|
||||||
socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port);
|
socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port);
|
||||||
|
|
||||||
|
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
return true;
|
return true;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
@@ -531,8 +524,11 @@ class Node {
|
|||||||
|
|
||||||
Future<bool> requestEthereumServer() async {
|
Future<bool> requestEthereumServer() async {
|
||||||
try {
|
try {
|
||||||
final req = await ProxyWrapper().getHttpClient()
|
final req = await ProxyWrapper()
|
||||||
.getUrl(uri,)
|
.getHttpClient()
|
||||||
|
.getUrl(
|
||||||
|
uri,
|
||||||
|
)
|
||||||
.timeout(Duration(seconds: 15));
|
.timeout(Duration(seconds: 15));
|
||||||
final response = await req.close();
|
final response = await req.close();
|
||||||
|
|
||||||
|
|||||||
@@ -19,17 +19,15 @@ import 'node.dart' as node_new;
|
|||||||
part 'node_legacy.part.dart';
|
part 'node_legacy.part.dart';
|
||||||
|
|
||||||
Future<void> performNodeHiveMigration() async {
|
Future<void> performNodeHiveMigration() async {
|
||||||
if(!CakeHive.isAdapterRegistered(Node.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Node.typeId)) {
|
||||||
CakeHive.registerAdapter(NodeAdapter());
|
CakeHive.registerAdapter(NodeAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
final nodeBox = await CakeHive.openBox<Node>(Node.boxName);
|
final nodeBox = await CakeHive.openBox<Node>(Node.boxName);
|
||||||
final powNodeBox = await CakeHive.openBox<Node>(Node.boxName+"pow");
|
final powNodeBox = await CakeHive.openBox<Node>(Node.boxName + "pow");
|
||||||
final builtinNodes = await loadAllDefaultNodes();
|
final builtinNodes = await loadAllDefaultNodes();
|
||||||
final builtinPowNodes = await loadDefaultNanoPowNodes();
|
final builtinPowNodes = await loadDefaultNanoPowNodes();
|
||||||
await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
|
await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri createUriFromElectrumAddress(String address, String path) =>
|
Uri createUriFromElectrumAddress(String address, String path) =>
|
||||||
@@ -62,31 +60,26 @@ class Node extends HiveObject with Keyable {
|
|||||||
final list = nodeBox.values.toList();
|
final list = nodeBox.values.toList();
|
||||||
final powList = powNodeBox.values.toList();
|
final powList = powNodeBox.values.toList();
|
||||||
for (final node in list) {
|
for (final node in list) {
|
||||||
if(defaultNodes.any((item)=>item.uri == node.uri)) {
|
if (defaultNodes.any((item) => item.uri == node.uri)) {
|
||||||
// default nodes will be added by validateBuiltinNodes(), no need to migrate them.
|
// default nodes will be added by validateBuiltinNodes(), no need to migrate them.
|
||||||
await node.delete();
|
await node.delete();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await node.migrateToSqlite(
|
await node.migrateToSqlite(isPow: false, isBuiltin: false, isOfficial: false);
|
||||||
isPow: false,
|
|
||||||
isBuiltin: false,
|
|
||||||
isOfficial: false);
|
|
||||||
await node.delete();
|
await node.delete();
|
||||||
}
|
}
|
||||||
for (final node in powList) {
|
for (final node in powList) {
|
||||||
if(defaultPowNodes.any((item)=>item.uri == node.uri)) {
|
if (defaultPowNodes.any((item) => item.uri == node.uri)) {
|
||||||
await node.delete();
|
await node.delete();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await node.migrateToSqlite(
|
await node.migrateToSqlite(isPow: true, isBuiltin: false, isOfficial: false);
|
||||||
isPow: true,
|
|
||||||
isBuiltin: false,
|
|
||||||
isOfficial: false);
|
|
||||||
await node.delete();
|
await node.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrateToSqlite({required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
|
Future<void> migrateToSqlite(
|
||||||
|
{required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
|
||||||
final newNode = node_new.Node(
|
final newNode = node_new.Node(
|
||||||
id: key as int,
|
id: key as int,
|
||||||
login: login,
|
login: login,
|
||||||
@@ -106,7 +99,6 @@ class Node extends HiveObject with Keyable {
|
|||||||
await newNode.save();
|
await newNode.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node.fromMap(Map<String, Object?> map)
|
Node.fromMap(Map<String, Object?> map)
|
||||||
: uriRaw = map['uri'] as String? ?? '',
|
: uriRaw = map['uri'] as String? ?? '',
|
||||||
path = map['path'] as String? ?? '',
|
path = map['path'] as String? ?? '',
|
||||||
@@ -241,6 +233,4 @@ class Node extends HiveObject with Keyable {
|
|||||||
set type(WalletType type) => typeRaw = serializeToInt(type);
|
set type(WalletType type) => typeRaw = serializeToInt(type);
|
||||||
|
|
||||||
dynamic _keyIndex;
|
dynamic _keyIndex;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,7 @@ class NodeAdapter extends TypeAdapter<Node> {
|
|||||||
trusted: fields[5] == null ? false : fields[5] as bool,
|
trusted: fields[5] == null ? false : fields[5] as bool,
|
||||||
socksProxyAddress: fields[6] as String?,
|
socksProxyAddress: fields[6] as String?,
|
||||||
path: fields[7] == null ? '' : fields[7] as String?,
|
path: fields[7] == null ? '' : fields[7] as String?,
|
||||||
isEnabledForAutoSwitching:
|
isEnabledForAutoSwitching: fields[11] == null ? false : fields[11] as bool,
|
||||||
fields[11] == null ? false : fields[11] as bool,
|
|
||||||
)
|
)
|
||||||
..uriRaw = fields[0] == null ? '' : fields[0] as String
|
..uriRaw = fields[0] == null ? '' : fields[0] as String
|
||||||
..typeRaw = fields[3] == null ? 0 : fields[3] as int
|
..typeRaw = fields[3] == null ? 0 : fields[3] as int
|
||||||
@@ -72,7 +71,5 @@ class NodeAdapter extends TypeAdapter<Node> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is NodeAdapter &&
|
other is NodeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ Future<List<Node>> loadAllDefaultNodes() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> resetToDefault() async {
|
Future<void> resetToDefault() async {
|
||||||
|
|
||||||
final nodes = await loadAllDefaultNodes();
|
final nodes = await loadAllDefaultNodes();
|
||||||
|
|
||||||
final currentNodes = await Node.getAll();
|
final currentNodes = await Node.getAll();
|
||||||
@@ -160,12 +159,11 @@ Future<void> resetToDefault() async {
|
|||||||
(item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
|
(item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
|
||||||
);
|
);
|
||||||
node.id = curr.id;
|
node.id = curr.id;
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Node.deleteAll();
|
await Node.deleteAll();
|
||||||
for(final node in nodes) {
|
for (final node in nodes) {
|
||||||
await node.save();
|
await node.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +171,7 @@ Future<void> resetToDefault() async {
|
|||||||
Future<void> resetPowToDefault() async {
|
Future<void> resetPowToDefault() async {
|
||||||
final nanoPowNodes = await loadDefaultNanoPowNodes();
|
final nanoPowNodes = await loadDefaultNanoPowNodes();
|
||||||
await Node.deleteAllPow();
|
await Node.deleteAllPow();
|
||||||
for(final node in nanoPowNodes) {
|
for (final node in nanoPowNodes) {
|
||||||
node.save();
|
node.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,12 +179,9 @@ Future<void> resetPowToDefault() async {
|
|||||||
Future<Node> getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
|
Future<Node> getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
|
||||||
final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
|
final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
|
||||||
try {
|
try {
|
||||||
return nodes.firstWhere((item)=>item.isDefault);
|
return nodes.firstWhere((item) => item.isDefault);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
// ideally the yamls would always have a default, but this is better than nothing
|
// ideally the yamls would always have a default, but this is better than nothing
|
||||||
return nodes.first;
|
return nodes.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ BigInt parseFixed(String value, int decimals) {
|
|||||||
var fraction = (comps.length == 2 ? comps[1] : "0").padRight(decimals, "0");
|
var fraction = (comps.length == 2 ? comps[1] : "0").padRight(decimals, "0");
|
||||||
|
|
||||||
if (fraction.length > multiplier.length - 1) {
|
if (fraction.length > multiplier.length - 1) {
|
||||||
throw FormatException("fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
|
throw FormatException(
|
||||||
|
"fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
|
||||||
}
|
}
|
||||||
|
|
||||||
final wholeValue = BigInt.parse(whole);
|
final wholeValue = BigInt.parse(whole);
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ Future<String> pathForWalletDir({required String name, required WalletType type}
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> pathForWallet({required String name, required WalletType type}) async =>
|
Future<String> pathForWallet({required String name, required WalletType type}) async =>
|
||||||
await pathForWalletDir(name: name, type: type)
|
await pathForWalletDir(name: name, type: type).then((path) => path + '/$name');
|
||||||
.then((path) => path + '/$name');
|
|
||||||
|
|
||||||
Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
|
Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
|
||||||
final directory = await getAppDir();
|
final directory = await getAppDir();
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ class PayjoinSession extends HiveObject {
|
|||||||
|
|
||||||
BigInt get amount => BigInt.parse(rawAmount ?? "0");
|
BigInt get amount => BigInt.parse(rawAmount ?? "0");
|
||||||
set amount(BigInt amount) => rawAmount = amount.toString();
|
set amount(BigInt amount) => rawAmount = amount.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PayjoinSessionStatus {
|
enum PayjoinSessionStatus {
|
||||||
|
|||||||
@@ -59,7 +59,5 @@ class PayjoinSessionAdapter extends TypeAdapter<PayjoinSession> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is PayjoinSessionAdapter &&
|
other is PayjoinSessionAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -508,4 +508,3 @@ class LightningPaymentRequest extends PaymentURI {
|
|||||||
@override
|
@override
|
||||||
String toString() => bolt11Invoice ?? "lightning:$lnURL";
|
String toString() => bolt11Invoice ?? "lightning:$lnURL";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ bool get isNonAmnesticTails {
|
|||||||
|
|
||||||
bool showNotice = true;
|
bool showNotice = true;
|
||||||
|
|
||||||
void setRootDirFromEnv() =>
|
void setRootDirFromEnv() => _rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
|
||||||
_rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
|
|
||||||
|
|
||||||
void copyDirectory(Directory source, Directory destination) {
|
void copyDirectory(Directory source, Directory destination) {
|
||||||
source.listSync(recursive: false).forEach((var entity) {
|
source.listSync(recursive: false).forEach((var entity) {
|
||||||
@@ -41,7 +40,8 @@ void copyDirectory(Directory source, Directory destination) {
|
|||||||
|
|
||||||
Future<void> linuxSymlinkSharedPreferences() async {
|
Future<void> linuxSymlinkSharedPreferences() async {
|
||||||
if (!Platform.isLinux) return; // nuh-uh
|
if (!Platform.isLinux) return; // nuh-uh
|
||||||
final dataHome = Platform.environment["XDG_DATA_HOME"] ?? p.join(Platform.environment["HOME"] ?? "", ".local", "share");
|
final dataHome = Platform.environment["XDG_DATA_HOME"] ??
|
||||||
|
p.join(Platform.environment["HOME"] ?? "", ".local", "share");
|
||||||
var cakeNames = ['com.example.cake_wallet', 'cake_wallet'];
|
var cakeNames = ['com.example.cake_wallet', 'cake_wallet'];
|
||||||
for (String name in cakeNames) {
|
for (String name in cakeNames) {
|
||||||
final oldPath = p.join(dataHome, name);
|
final oldPath = p.join(dataHome, name);
|
||||||
@@ -54,7 +54,7 @@ Future<void> linuxSymlinkSharedPreferences() async {
|
|||||||
printV("not creating, link exists");
|
printV("not creating, link exists");
|
||||||
} else {
|
} else {
|
||||||
if (newDir.existsSync()) {
|
if (newDir.existsSync()) {
|
||||||
newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch~/1000}");
|
newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch ~/ 1000}");
|
||||||
}
|
}
|
||||||
copyDirectory(oldDir, newDir);
|
copyDirectory(oldDir, newDir);
|
||||||
oldDir.deleteSync(recursive: true);
|
oldDir.deleteSync(recursive: true);
|
||||||
@@ -94,9 +94,11 @@ Future<Directory> getAppDir() async {
|
|||||||
// for storing things that users in general back-up
|
// for storing things that users in general back-up
|
||||||
var linuxAppPath = [
|
var linuxAppPath = [
|
||||||
if (appDirPath != null) appDirPath, // old preferred
|
if (appDirPath != null) appDirPath, // old preferred
|
||||||
p.join('/home', Platform.environment['USER']??"null", appName), // old fallback
|
p.join('/home', Platform.environment['USER'] ?? "null", appName), // old fallback
|
||||||
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
|
if (Platform.environment['HOME'] != null)
|
||||||
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
|
p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
|
||||||
|
if (Platform.environment['HOME'] != null)
|
||||||
|
p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
|
||||||
if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
|
if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -109,8 +111,10 @@ Future<Directory> getAppDir() async {
|
|||||||
if (useThisOne) {
|
if (useThisOne) {
|
||||||
if (showNotice) {
|
if (showNotice) {
|
||||||
showNotice = false;
|
showNotice = false;
|
||||||
printV("Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
|
printV(
|
||||||
printV("Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
|
"Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
|
||||||
|
printV(
|
||||||
|
"Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
|
||||||
printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
|
printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
|
||||||
}
|
}
|
||||||
preferredPath = notSoPreferredPath;
|
preferredPath = notSoPreferredPath;
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ Future<Uint8List> secRandom(int count) async {
|
|||||||
final rng = Random.secure();
|
final rng = Random.secure();
|
||||||
return Uint8List.fromList(List<int>.generate(count, (_) => rng.nextInt(byteSize)));
|
return Uint8List.fromList(List<int>.generate(count, (_) => rng.nextInt(byteSize)));
|
||||||
}
|
}
|
||||||
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
|
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ??
|
||||||
|
Uint8List.fromList([]);
|
||||||
} on PlatformException catch (_) {
|
} on PlatformException catch (_) {
|
||||||
return Uint8List.fromList([]);
|
return Uint8List.fromList([]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,12 @@ import 'package:on_chain/solana/solana.dart';
|
|||||||
|
|
||||||
class SolanaRPCHTTPService implements SolanaJSONRPCService {
|
class SolanaRPCHTTPService implements SolanaJSONRPCService {
|
||||||
SolanaRPCHTTPService(
|
SolanaRPCHTTPService(
|
||||||
{required this.url,
|
{required this.url, this.defaultRequestTimeout = const Duration(seconds: 30)});
|
||||||
this.defaultRequestTimeout = const Duration(seconds: 30)});
|
|
||||||
@override
|
@override
|
||||||
final String url;
|
final String url;
|
||||||
final Duration defaultRequestTimeout;
|
final Duration defaultRequestTimeout;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> call(SolanaRequestDetails params,
|
Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
|
||||||
[Duration? timeout]) async {
|
|
||||||
final response = await ProxyWrapper().post(
|
final response = await ProxyWrapper().post(
|
||||||
clearnetUri: Uri.parse(url),
|
clearnetUri: Uri.parse(url),
|
||||||
body: params.toRequestBody(),
|
body: params.toRequestBody(),
|
||||||
|
|||||||
@@ -58,7 +58,5 @@ class SPLTokenAdapter extends TypeAdapter<SPLToken> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is SPLTokenAdapter &&
|
other is SPLTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ TransactionDirection parseTransactionDirectionFromInt(int raw) {
|
|||||||
case 1:
|
case 1:
|
||||||
return TransactionDirection.outgoing;
|
return TransactionDirection.outgoing;
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
|
throw Exception(
|
||||||
|
'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ TransactionDirection parseTransactionDirectionFromNumber(String raw) {
|
|||||||
case "1":
|
case "1":
|
||||||
return TransactionDirection.outgoing;
|
return TransactionDirection.outgoing;
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
|
throw Exception(
|
||||||
|
'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,7 @@ import 'package:mobx/mobx.dart';
|
|||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
|
|
||||||
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
|
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
|
||||||
TransactionHistoryBase()
|
TransactionHistoryBase() : transactions = ObservableMap<String, TransactionType>();
|
||||||
: transactions = ObservableMap<String, TransactionType>();
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
ObservableMap<String, TransactionType> transactions;
|
ObservableMap<String, TransactionType> transactions;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:cw_core/enumerable_item.dart';
|
import 'package:cw_core/enumerable_item.dart';
|
||||||
|
|
||||||
abstract class TransactionPriority extends EnumerableItem<int>
|
abstract class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
|
||||||
with Serializable<int> {
|
|
||||||
final String? description;
|
final String? description;
|
||||||
final String? hint;
|
final String? hint;
|
||||||
|
|
||||||
const TransactionPriority({required String title, required int raw, this.description, this.hint}) : super(title: title, raw: raw);
|
const TransactionPriority({required String title, required int raw, this.description, this.hint})
|
||||||
|
: super(title: title, raw: raw);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,5 @@ class TronTokenAdapter extends TypeAdapter<TronToken> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is TronTokenAdapter &&
|
other is TronTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ Future<void> write({required String path, required String password, required Str
|
|||||||
writeData(path: path, password: password, data: data);
|
writeData(path: path, password: password, data: data);
|
||||||
|
|
||||||
Future<void> writeData(
|
Future<void> writeData(
|
||||||
{required String path,
|
{required String path, required String password, required String data}) async {
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
final keys = extractKeys(password);
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
final key = encrypt.Key.fromBase64(keys.first);
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
final iv = encrypt.IV.fromBase64(keys.last);
|
||||||
|
|||||||
@@ -50,14 +50,16 @@ class MemoryProxyLogger implements ProxyLogger {
|
|||||||
required String? error,
|
required String? error,
|
||||||
}) {
|
}) {
|
||||||
final trace = StackTrace.current;
|
final trace = StackTrace.current;
|
||||||
logs.add(MemoryProxyLoggerEntry(
|
logs.add(
|
||||||
|
MemoryProxyLoggerEntry(
|
||||||
method: method,
|
method: method,
|
||||||
trace: trace,
|
trace: trace,
|
||||||
uri: uri,
|
uri: uri,
|
||||||
body: body,
|
body: body,
|
||||||
network: network,
|
network: network,
|
||||||
response: response,
|
response: response,
|
||||||
error: error,),
|
error: error,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,8 @@ class ProxyAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class ProxySocket {
|
abstract class ProxySocket {
|
||||||
static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address, {Duration? connectionTimeout}) async {
|
static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address,
|
||||||
|
{Duration? connectionTimeout}) async {
|
||||||
if (CakeTor.instance!.started) {
|
if (CakeTor.instance!.started) {
|
||||||
var socksSocket = await SOCKSSocket.create(
|
var socksSocket = await SOCKSSocket.create(
|
||||||
proxyHost: InternetAddress.loopbackIPv4.address,
|
proxyHost: InternetAddress.loopbackIPv4.address,
|
||||||
@@ -28,7 +29,8 @@ abstract class ProxySocket {
|
|||||||
return ProxySocketSocks(socksSocket);
|
return ProxySocketSocks(socksSocket);
|
||||||
}
|
}
|
||||||
if (sslEnabled == false) {
|
if (sslEnabled == false) {
|
||||||
return ProxySocketInsecure(await Socket.connect(address.host, address.port, timeout: connectionTimeout));
|
return ProxySocketInsecure(
|
||||||
|
await Socket.connect(address.host, address.port, timeout: connectionTimeout));
|
||||||
} else {
|
} else {
|
||||||
return ProxySocketSecure(await SecureSocket.connect(
|
return ProxySocketSecure(await SecureSocket.connect(
|
||||||
address.host,
|
address.host,
|
||||||
@@ -43,6 +45,7 @@ abstract class ProxySocket {
|
|||||||
void destroy();
|
void destroy();
|
||||||
void write(String data);
|
void write(String data);
|
||||||
bool get isClosed;
|
bool get isClosed;
|
||||||
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function (Object error)? onError, Function ()? onDone, bool cancelOnError = true});
|
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
|
||||||
|
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true});
|
||||||
ProxyAddress get address;
|
ProxyAddress get address;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_core/utils/proxy_socket/abstract.dart';
|
import 'package:cw_core/utils/proxy_socket/abstract.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
@@ -12,7 +11,8 @@ class ProxySocketInsecure implements ProxySocket {
|
|||||||
|
|
||||||
bool isClosed = false;
|
bool isClosed = false;
|
||||||
|
|
||||||
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
|
ProxyAddress get address =>
|
||||||
|
ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
@@ -53,7 +53,8 @@ class ProxySocketInsecure implements ProxySocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
|
||||||
|
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
||||||
return socket.listen(
|
return socket.listen(
|
||||||
(data) {
|
(data) {
|
||||||
onData(Uint8List.fromList(data));
|
onData(Uint8List.fromList(data));
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ class ProxySocketSecure implements ProxySocket {
|
|||||||
|
|
||||||
ProxySocketSecure(this.socket);
|
ProxySocketSecure(this.socket);
|
||||||
|
|
||||||
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
|
ProxyAddress get address =>
|
||||||
|
ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
@@ -59,7 +60,8 @@ class ProxySocketSecure implements ProxySocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
|
||||||
|
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
||||||
return socket.listen(
|
return socket.listen(
|
||||||
(data) {
|
(data) {
|
||||||
onData(Uint8List.fromList(data));
|
onData(Uint8List.fromList(data));
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ class ProxySocketSocks implements ProxySocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
|
||||||
|
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
|
||||||
return socket.listen(
|
return socket.listen(
|
||||||
(data) {
|
(data) {
|
||||||
onData(Uint8List.fromList(data));
|
onData(Uint8List.fromList(data));
|
||||||
@@ -54,4 +55,3 @@ class ProxySocketSocks implements ProxySocket {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class ProxyWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProxyWrapper._internal();
|
ProxyWrapper._internal();
|
||||||
Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port, {Duration? connectionTimeout}) async {
|
Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port,
|
||||||
|
{Duration? connectionTimeout}) async {
|
||||||
logger?.log(
|
logger?.log(
|
||||||
uri: Uri(
|
uri: Uri(
|
||||||
scheme: sslEnabled ? "https" : "http",
|
scheme: sslEnabled ? "https" : "http",
|
||||||
@@ -29,9 +30,9 @@ class ProxyWrapper {
|
|||||||
body: Uint8List(0),
|
body: Uint8List(0),
|
||||||
response: null,
|
response: null,
|
||||||
network: requestNetwork(),
|
network: requestNetwork(),
|
||||||
error: null
|
error: null);
|
||||||
);
|
return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port),
|
||||||
return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port), connectionTimeout: connectionTimeout);
|
connectionTimeout: connectionTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestNetwork requestNetwork() {
|
RequestNetwork requestNetwork() {
|
||||||
@@ -56,7 +57,8 @@ class ProxyWrapper {
|
|||||||
|
|
||||||
int getPort() => CakeTor.instance!.port;
|
int getPort() => CakeTor.instance!.port;
|
||||||
|
|
||||||
@Deprecated('Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
|
@Deprecated(
|
||||||
|
'Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
|
||||||
HttpClient getHttpClient({int? portOverride, bool internal = false}) {
|
HttpClient getHttpClient({int? portOverride, bool internal = false}) {
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
logger?.log(
|
logger?.log(
|
||||||
@@ -65,8 +67,7 @@ class ProxyWrapper {
|
|||||||
body: Uint8List(0),
|
body: Uint8List(0),
|
||||||
response: null,
|
response: null,
|
||||||
network: requestNetwork(),
|
network: requestNetwork(),
|
||||||
error: null
|
error: null);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (CakeTor.instance!.started) {
|
if (CakeTor.instance!.started) {
|
||||||
// Assign connection factory.
|
// Assign connection factory.
|
||||||
@@ -84,8 +85,6 @@ class ProxyWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Future<Response> _make({
|
Future<Response> _make({
|
||||||
required RequestMethod method,
|
required RequestMethod method,
|
||||||
required ioc.IOClient client,
|
required ioc.IOClient client,
|
||||||
@@ -217,7 +216,6 @@ class ProxyWrapper {
|
|||||||
throw Exception("Unable to connect to server");
|
throw Exception("Unable to connect to server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<Response> post({
|
Future<Response> post({
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
int? portOverride,
|
int? portOverride,
|
||||||
@@ -235,7 +233,6 @@ class ProxyWrapper {
|
|||||||
|
|
||||||
ioc.IOClient clearnetClient = ioc.IOClient(cleatnetHttpClient);
|
ioc.IOClient clearnetClient = ioc.IOClient(cleatnetHttpClient);
|
||||||
|
|
||||||
|
|
||||||
bool torEnabled = CakeTor.instance!.started;
|
bool torEnabled = CakeTor.instance!.started;
|
||||||
|
|
||||||
if (torEnabled) {
|
if (torEnabled) {
|
||||||
@@ -439,7 +436,6 @@ class ProxyWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CakeTor {
|
class CakeTor {
|
||||||
static CakeTorInstance? instance;
|
static CakeTorInstance? instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
@@ -31,8 +30,9 @@ String convertZpubToXpub(String zpub) {
|
|||||||
return zpub;
|
return zpub;
|
||||||
}
|
}
|
||||||
|
|
||||||
final xpubVersionBytes = isZpub ?
|
final xpubVersionBytes = isZpub
|
||||||
[0x04, 0x88, 0xb2, 0x1e] : // xpub mainnet
|
? [0x04, 0x88, 0xb2, 0x1e]
|
||||||
|
: // xpub mainnet
|
||||||
[0x04, 0x35, 0x87, 0xcf]; // tpub testnet
|
[0x04, 0x35, 0x87, 0xcf]; // tpub testnet
|
||||||
|
|
||||||
final newExtendedKey = Uint8List.fromList([
|
final newExtendedKey = Uint8List.fromList([
|
||||||
|
|||||||
@@ -349,11 +349,11 @@ class WalletInfo {
|
|||||||
this.addressPageType,
|
this.addressPageType,
|
||||||
this.receiveInfoboxDismissed,
|
this.receiveInfoboxDismissed,
|
||||||
this.showCombinedBalance,
|
this.showCombinedBalance,
|
||||||
this.favoriteTokenAddress
|
this.favoriteTokenAddress)
|
||||||
) : _yatLastUsedAddressController = StreamController<String>.broadcast();
|
: _yatLastUsedAddressController = StreamController<String>.broadcast();
|
||||||
|
|
||||||
factory WalletInfo.external({
|
factory WalletInfo.external(
|
||||||
required String id,
|
{required String id,
|
||||||
required String name,
|
required String name,
|
||||||
required WalletType type,
|
required WalletType type,
|
||||||
required bool isRecovery,
|
required bool isRecovery,
|
||||||
@@ -373,8 +373,7 @@ class WalletInfo {
|
|||||||
int? sortOrder,
|
int? sortOrder,
|
||||||
bool? receiveInfoboxDismissed,
|
bool? receiveInfoboxDismissed,
|
||||||
bool? showCombinedBalance,
|
bool? showCombinedBalance,
|
||||||
String? favoriteTokenAddress
|
String? favoriteTokenAddress}) {
|
||||||
}) {
|
|
||||||
return WalletInfo(
|
return WalletInfo(
|
||||||
0,
|
0,
|
||||||
id,
|
id,
|
||||||
@@ -398,8 +397,7 @@ class WalletInfo {
|
|||||||
null,
|
null,
|
||||||
receiveInfoboxDismissed ?? false,
|
receiveInfoboxDismissed ?? false,
|
||||||
showCombinedBalance ?? true,
|
showCombinedBalance ?? true,
|
||||||
favoriteTokenAddress
|
favoriteTokenAddress);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get tableName => 'walletInfo';
|
static String get tableName => 'walletInfo';
|
||||||
@@ -577,7 +575,8 @@ class WalletInfo {
|
|||||||
"address": address,
|
"address": address,
|
||||||
"yatEid": yatEid,
|
"yatEid": yatEid,
|
||||||
"yatLastUsedAddressRaw": yatLastUsedAddressRaw,
|
"yatLastUsedAddressRaw": yatLastUsedAddressRaw,
|
||||||
"showIntroCakePayCard": showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
|
"showIntroCakePayCard":
|
||||||
|
showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
|
||||||
"walletInfoDerivationInfoId": derivationInfoId,
|
"walletInfoDerivationInfoId": derivationInfoId,
|
||||||
"hardwareWalletType": hardwareWalletType?.index,
|
"hardwareWalletType": hardwareWalletType?.index,
|
||||||
"parentAddress": parentAddress,
|
"parentAddress": parentAddress,
|
||||||
@@ -616,8 +615,7 @@ class WalletInfo {
|
|||||||
json['addressPageType'] as String? ?? null,
|
json['addressPageType'] as String? ?? null,
|
||||||
json['receiveInfoboxDismissed'] != 0,
|
json['receiveInfoboxDismissed'] != 0,
|
||||||
json["showCombinedBalance"] != 0,
|
json["showCombinedBalance"] != 0,
|
||||||
json["favoriteTokenAddress"] as String? ?? null
|
json["favoriteTokenAddress"] as String? ?? null);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> save() async {
|
Future<int> save() async {
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ class DerivationInfoAdapter extends TypeAdapter<DerivationInfo> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is DerivationInfoAdapter &&
|
other is DerivationInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
|
class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
|
||||||
@@ -88,8 +86,8 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
|
|||||||
fields[26] == null ? false : fields[26] as bool,
|
fields[26] == null ? false : fields[26] as bool,
|
||||||
)
|
)
|
||||||
..addresses = (fields[10] as Map?)?.cast<String, String>()
|
..addresses = (fields[10] as Map?)?.cast<String, String>()
|
||||||
..addressInfos = (fields[14] as Map?)?.map((dynamic k, dynamic v) =>
|
..addressInfos = (fields[14] as Map?)
|
||||||
MapEntry(k as int, (v as List).cast<AddressInfo>()))
|
?.map((dynamic k, dynamic v) => MapEntry(k as int, (v as List).cast<AddressInfo>()))
|
||||||
..usedAddresses = (fields[15] as List?)?.cast<String>()
|
..usedAddresses = (fields[15] as List?)?.cast<String>()
|
||||||
..derivationType = fields[16] as newWi.DerivationType?
|
..derivationType = fields[16] as newWi.DerivationType?
|
||||||
..derivationPath = fields[17] as String?
|
..derivationPath = fields[17] as String?
|
||||||
@@ -163,9 +161,7 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is WalletInfoAdapter &&
|
other is WalletInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
|
class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
|
||||||
@@ -217,9 +213,7 @@ class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is DerivationTypeAdapter &&
|
other is DerivationTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HardwareWalletTypeAdapter extends TypeAdapter<newWi.HardwareWalletType> {
|
class HardwareWalletTypeAdapter extends TypeAdapter<newWi.HardwareWalletType> {
|
||||||
|
|||||||
@@ -101,7 +101,14 @@ class WalletKeysData {
|
|||||||
final String? scanSecret;
|
final String? scanSecret;
|
||||||
final String? spendPubkey;
|
final String? spendPubkey;
|
||||||
|
|
||||||
WalletKeysData({this.privateKey, this.mnemonic, this.altMnemonic, this.passphrase, this.xPub, this.scanSecret, this.spendPubkey});
|
WalletKeysData(
|
||||||
|
{this.privateKey,
|
||||||
|
this.mnemonic,
|
||||||
|
this.altMnemonic,
|
||||||
|
this.passphrase,
|
||||||
|
this.xPub,
|
||||||
|
this.scanSecret,
|
||||||
|
this.spendPubkey});
|
||||||
|
|
||||||
String toJSON() => jsonEncode({
|
String toJSON() => jsonEncode({
|
||||||
"privateKey": privateKey,
|
"privateKey": privateKey,
|
||||||
|
|||||||
@@ -334,17 +334,18 @@ WalletType? _cryptoCurrencyToWalletType(CryptoCurrency type) {
|
|||||||
|
|
||||||
WalletType? cryptoCurrencyOrTokenToWalletType(CryptoCurrency type) {
|
WalletType? cryptoCurrencyOrTokenToWalletType(CryptoCurrency type) {
|
||||||
try {
|
try {
|
||||||
if(type.tag == CryptoCurrency.bnb.tag) {
|
if (type.tag == CryptoCurrency.bnb.tag) {
|
||||||
return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
|
return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type.tag != null && ![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
|
if (type.tag != null &&
|
||||||
|
![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
|
||||||
return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
|
return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
|
||||||
} else {
|
} else {
|
||||||
return _cryptoCurrencyToWalletType(type);
|
return _cryptoCurrencyToWalletType(type);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,5 @@ class WalletTypeAdapter extends TypeAdapter<WalletType> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is WalletTypeAdapter &&
|
other is WalletTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,5 @@ class ZanoAssetAdapter extends TypeAdapter<ZanoAsset> {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is ZanoAssetAdapter &&
|
other is ZanoAssetAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
|
||||||
runtimeType == other.runtimeType &&
|
|
||||||
typeId == other.typeId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,27 +3,27 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('smartAmountSanitizer', () {
|
group('smartAmountSanitizer', () {
|
||||||
test('sanitize decimal dot', (){
|
test('sanitize decimal dot', () {
|
||||||
final amount = "1,000.00".sanitized();
|
final amount = "1,000.00".sanitized();
|
||||||
expect(amount, "1000.00");
|
expect(amount, "1000.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sanitize decimal comma', (){
|
test('sanitize decimal comma', () {
|
||||||
final amount = "1.000,00".sanitized();
|
final amount = "1.000,00".sanitized();
|
||||||
expect(amount, "1000.00");
|
expect(amount, "1000.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('general case', (){
|
test('general case', () {
|
||||||
final amount = "1000.00".sanitized();
|
final amount = "1000.00".sanitized();
|
||||||
expect(amount, "1000.00");
|
expect(amount, "1000.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('no decimals', (){
|
test('no decimals', () {
|
||||||
final amount = "1,000".sanitized();
|
final amount = "1,000".sanitized();
|
||||||
expect(amount, "1.000");
|
expect(amount, "1.000");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('no decimals', (){
|
test('no decimals', () {
|
||||||
final amount = "1.000".sanitized();
|
final amount = "1.000".sanitized();
|
||||||
expect(amount, "1.000");
|
expect(amount, "1.000");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group("toStringWithPrecision", (){
|
group("toStringWithPrecision", () {
|
||||||
test("with fractionalDigits and padded with zeros", () {
|
test("with fractionalDigits and padded with zeros", () {
|
||||||
final money = Money.parse("1", CryptoCurrency.btc);
|
final money = Money.parse("1", CryptoCurrency.btc);
|
||||||
expect(money.amount, equals(BigInt.parse("100000000")));
|
expect(money.amount, equals(BigInt.parse("100000000")));
|
||||||
@@ -332,7 +332,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group("toStringWithSymbol", (){
|
group("toStringWithSymbol", () {
|
||||||
test("with fractionalDigits and padded with zeros", () {
|
test("with fractionalDigits and padded with zeros", () {
|
||||||
final money = Money.parse("1", CryptoCurrency.btc);
|
final money = Money.parse("1", CryptoCurrency.btc);
|
||||||
expect(money.amount, equals(BigInt.parse("100000000")));
|
expect(money.amount, equals(BigInt.parse("100000000")));
|
||||||
|
|||||||
@@ -14,14 +14,12 @@ void main() {
|
|||||||
group('formatFixed, different fractional digits and trimming zeros', () {
|
group('formatFixed, different fractional digits and trimming zeros', () {
|
||||||
test(
|
test(
|
||||||
'should format 1000001 into 1',
|
'should format 1000001 into 1',
|
||||||
() => expect(
|
() => expect(formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
|
||||||
formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'should format 1000000 into 1, fractionalDigits > decimals',
|
'should format 1000000 into 1, fractionalDigits > decimals',
|
||||||
() => expect(
|
() => expect(formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
|
||||||
formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
@@ -45,8 +43,7 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'should format 1000001 into 1.00000',
|
'should format 1000001 into 1.00000',
|
||||||
() => expect(
|
() => expect(
|
||||||
formatFixed(BigInt.parse("1000001"), 6,
|
formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5, trimZeros: false),
|
||||||
fractionalDigits: 5, trimZeros: false),
|
|
||||||
'1.00000',
|
'1.00000',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -54,8 +51,7 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'should format 1000000 into 1.000000',
|
'should format 1000000 into 1.000000',
|
||||||
() => expect(
|
() => expect(
|
||||||
formatFixed(BigInt.parse("1000000"), 6,
|
formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12, trimZeros: false),
|
||||||
fractionalDigits: 12, trimZeros: false),
|
|
||||||
'1.000000',
|
'1.000000',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,49 +39,58 @@ void main() {
|
|||||||
|
|
||||||
group("isBolt11ZeroInvoice", () {
|
group("isBolt11ZeroInvoice", () {
|
||||||
test("should identify a zero amount invoice", () {
|
test("should identify a zero amount invoice", () {
|
||||||
final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
final invoice =
|
||||||
|
"lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
||||||
expect(isBolt11ZeroInvoice(invoice), true);
|
expect(isBolt11ZeroInvoice(invoice), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should identify a non zero amount invoice", () {
|
test("should identify a non zero amount invoice", () {
|
||||||
final invoice = "lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
|
final invoice =
|
||||||
|
"lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
|
||||||
expect(isBolt11ZeroInvoice(invoice), false);
|
expect(isBolt11ZeroInvoice(invoice), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should identify a zero amount prefixed invoice", () {
|
test("should identify a zero amount prefixed invoice", () {
|
||||||
final invoice = "lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
final invoice =
|
||||||
|
"lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
||||||
expect(isBolt11ZeroInvoice(invoice), true);
|
expect(isBolt11ZeroInvoice(invoice), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should identify a non zero amount prefixed invoice", () {
|
test("should identify a non zero amount prefixed invoice", () {
|
||||||
final invoice = "lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
|
final invoice =
|
||||||
|
"lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
|
||||||
expect(isBolt11ZeroInvoice(invoice), false);
|
expect(isBolt11ZeroInvoice(invoice), false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group("getBolt11Amount", () {
|
group("getBolt11Amount", () {
|
||||||
test("should identify a zero amount invoice", () {
|
test("should identify a zero amount invoice", () {
|
||||||
final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
final invoice =
|
||||||
|
"lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
|
||||||
expect(getBolt11Amount(invoice), null);
|
expect(getBolt11Amount(invoice), null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should get the amount 1 BTC encoded as bitcoin", () {
|
test("should get the amount 1 BTC encoded as bitcoin", () {
|
||||||
final invoice = "lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
|
final invoice =
|
||||||
|
"lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
|
||||||
expect(getBolt11Amount(invoice), Money.fromInt(100000000, CryptoCurrency.btcln));
|
expect(getBolt11Amount(invoice), Money.fromInt(100000000, CryptoCurrency.btcln));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should get the amount 0,1 BTC encoded as millibitcoin", () {
|
test("should get the amount 0,1 BTC encoded as millibitcoin", () {
|
||||||
final invoice = "lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
|
final invoice =
|
||||||
|
"lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
|
||||||
expect(getBolt11Amount(invoice), Money.fromInt(10000000, CryptoCurrency.btcln));
|
expect(getBolt11Amount(invoice), Money.fromInt(10000000, CryptoCurrency.btcln));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should get the amount 1000 SATS encoded as microbitcoin", () {
|
test("should get the amount 1000 SATS encoded as microbitcoin", () {
|
||||||
final invoice = "lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
|
final invoice =
|
||||||
|
"lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
|
||||||
expect(getBolt11Amount(invoice), Money.fromInt(1000, CryptoCurrency.btcln));
|
expect(getBolt11Amount(invoice), Money.fromInt(1000, CryptoCurrency.btcln));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should get the amount 1 SAT encoded as nanobitcoin", () {
|
test("should get the amount 1 SAT encoded as nanobitcoin", () {
|
||||||
final invoice = "lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
|
final invoice =
|
||||||
|
"lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
|
||||||
expect(getBolt11Amount(invoice), Money.fromInt(1, CryptoCurrency.btcln));
|
expect(getBolt11Amount(invoice), Money.fromInt(1, CryptoCurrency.btcln));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ class _Visitor extends SimpleAstVisitor<void> {
|
|||||||
|
|
||||||
if (uriString.startsWith("package:http")) {
|
if (uriString.startsWith("package:http")) {
|
||||||
final prefixNode = node.prefix;
|
final prefixNode = node.prefix;
|
||||||
if (prefixNode != null &&
|
if (prefixNode != null && prefixNode.name == "very_insecure_http_do_not_use") {
|
||||||
prefixNode.name == "very_insecure_http_do_not_use") {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ class ReplaceWithPrintV extends ResolvedCorrectionProducer {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CorrectionApplicability get applicability =>
|
CorrectionApplicability get applicability => CorrectionApplicability.singleLocation;
|
||||||
CorrectionApplicability.singleLocation;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FixKind get fixKind => _fixKind;
|
FixKind get fixKind => _fixKind;
|
||||||
|
|||||||
@@ -3,4 +3,3 @@ export 'src/dogecoin_wallet_addresses.dart';
|
|||||||
export 'src/dogecoin_wallet_creation_credentials.dart';
|
export 'src/dogecoin_wallet_creation_credentials.dart';
|
||||||
export 'src/dogecoin_wallet_service.dart';
|
export 'src/dogecoin_wallet_service.dart';
|
||||||
export 'src/dogecoin_transaction_priority.dart';
|
export 'src/dogecoin_transaction_priority.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -53,4 +53,3 @@ class DogecoinTransactionPriority extends BitcoinTransactionPriority {
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ abstract class DogeCoinWalletBase extends ElectrumWallet with Store {
|
|||||||
int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) =>
|
int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) =>
|
||||||
feeRate * (size ?? estimatedDogeCoinTransactionSize(inputsCount, outputsCount));
|
feeRate * (size ?? estimatedDogeCoinTransactionSize(inputsCount, outputsCount));
|
||||||
|
|
||||||
|
|
||||||
static Future<DogeCoinWallet> create(
|
static Future<DogeCoinWallet> create(
|
||||||
{required String mnemonic,
|
{required String mnemonic,
|
||||||
required String password,
|
required String password,
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ import 'package:mobx/mobx.dart';
|
|||||||
|
|
||||||
part 'dogecoin_wallet_addresses.g.dart';
|
part 'dogecoin_wallet_addresses.g.dart';
|
||||||
|
|
||||||
class DogeCoinWalletAddresses = DogeCoinWalletAddressesBase
|
class DogeCoinWalletAddresses = DogeCoinWalletAddressesBase with _$DogeCoinWalletAddresses;
|
||||||
with _$DogeCoinWalletAddresses;
|
|
||||||
|
|
||||||
abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses
|
abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||||
with Store {
|
|
||||||
DogeCoinWalletAddressesBase(
|
DogeCoinWalletAddressesBase(
|
||||||
WalletInfo walletInfo, {
|
WalletInfo walletInfo, {
|
||||||
required super.mainHdByType,
|
required super.mainHdByType,
|
||||||
@@ -36,6 +34,5 @@ abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses
|
|||||||
generateP2PKHAddress(hd: hd, index: index, network: network);
|
generateP2PKHAddress(hd: hd, index: index, network: network);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PaymentURI getPaymentUri(String amount) =>
|
PaymentURI getPaymentUri(String amount) => DogeURI(address: address, amount: amount);
|
||||||
DogeURI(address: address, amount: amount);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,5 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:cw_dogecoin/cw_dogecoin.dart';
|
import 'package:cw_dogecoin/cw_dogecoin.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('adds one to input values', () {
|
test('adds one to input values', () {});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,4 +43,3 @@ class ArbitrumClient extends EVMChainClient {
|
|||||||
@override
|
@override
|
||||||
int get chainId => 42161;
|
int get chainId => 42161;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,3 @@ class BaseClient extends EVMChainClient {
|
|||||||
@override
|
@override
|
||||||
int get chainId => 8453;
|
int get chainId => 8453;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,4 +44,3 @@ class BSCClient extends EVMChainClient {
|
|||||||
@override
|
@override
|
||||||
int get chainId => 56;
|
int get chainId => 56;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,3 @@ class EthereumClient extends EVMChainClient {
|
|||||||
Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) =>
|
Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) =>
|
||||||
prependTransactionType(0x02, signedTransaction);
|
prependTransactionType(0x02, signedTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,9 @@ class EVMChainClient {
|
|||||||
|
|
||||||
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
|
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
|
||||||
if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0 &&
|
if (response.statusCode >= 200 &&
|
||||||
|
response.statusCode < 300 &&
|
||||||
|
jsonResponse['status'] != 0 &&
|
||||||
jsonResponse['result'] is List) {
|
jsonResponse['result'] is List) {
|
||||||
final symbol = EVMChainUtils.getFeeCurrency(chainId);
|
final symbol = EVMChainUtils.getFeeCurrency(chainId);
|
||||||
|
|
||||||
@@ -520,9 +522,11 @@ class EVMChainClient {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<EVMChainERC20Balance> fetchERC20Balances(EthereumAddress userAddress, Erc20Token token) async {
|
Future<EVMChainERC20Balance> fetchERC20Balances(
|
||||||
|
EthereumAddress userAddress, Erc20Token token) async {
|
||||||
try {
|
try {
|
||||||
final erc20 = ERC20(address: EthereumAddress.fromHex(token.contractAddress), client: _client!);
|
final erc20 =
|
||||||
|
ERC20(address: EthereumAddress.fromHex(token.contractAddress), client: _client!);
|
||||||
final balance = await erc20.balanceOf(userAddress);
|
final balance = await erc20.balanceOf(userAddress);
|
||||||
|
|
||||||
return EVMChainERC20Balance(Money(balance, token));
|
return EVMChainERC20Balance(Money(balance, token));
|
||||||
@@ -659,9 +663,8 @@ class EVMChainClient {
|
|||||||
final tokenData = item;
|
final tokenData = item;
|
||||||
|
|
||||||
final nativeRaw = tokenData['native_token'];
|
final nativeRaw = tokenData['native_token'];
|
||||||
final nativeToken = nativeRaw is bool
|
final nativeToken =
|
||||||
? nativeRaw
|
nativeRaw is bool ? nativeRaw : (nativeRaw?.toString().toLowerCase() == 'true');
|
||||||
: (nativeRaw?.toString().toLowerCase() == 'true');
|
|
||||||
if (nativeToken) continue;
|
if (nativeToken) continue;
|
||||||
|
|
||||||
final balanceStr = tokenData['balance'] as String? ?? '0';
|
final balanceStr = tokenData['balance'] as String? ?? '0';
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user