Skip to content

Commit

Permalink
Bugfix: Default lowest denomination
Browse files Browse the repository at this point in the history
The main goal for this branch is to set the lowest denomination as default and swap places of token denomination in transaction view. Previous order was from the highest to the lowest. After change, it is from the lowest to the highest. The additional goal for this branch is to globally refactor names of denomination models: defaultTokenDenomination -> networkTokenDenomination and lowestTokenDenomination -> defaultTokenDenomination.

List of changes:
- changed getter method with order of token denomination models to swap from lowest to highest in token_alias_model.dart
- changed factory return in token_form_state.dart from default token denomination to the lowest token denomination
- changed default token denomination model in token_form_cubit.dart and token_form_state.dart to the lowest token denomination model
- updated token amount preview widget, to use calculated token value based on selected denomination. Previously this widget contained simple getters, which didn't update widget when user changed denomination.
- renamed defaultTokenDenomination -> networkTokenDenomination and lowestTokenDenomination -> defaultTokenDenomination throughout the application
  • Loading branch information
aknowak01 committed Jan 11, 2024
1 parent 5a2a78f commit cb015cc
Show file tree
Hide file tree
Showing 74 changed files with 471 additions and 449 deletions.
4 changes: 2 additions & 2 deletions lib/config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class AppConfig {
rpcBrowserUrlController: RpcBrowserUrlController(),
defaultFeeTokenAliasModel: const TokenAliasModel(
name: 'Kira',
lowestTokenDenominationModel: TokenDenominationModel(name: 'ukex', decimals: 0),
defaultTokenDenominationModel: TokenDenominationModel(name: 'KEX', decimals: 6),
defaultTokenDenominationModel: TokenDenominationModel(name: 'ukex', decimals: 0),
networkTokenDenominationModel: TokenDenominationModel(name: 'KEX', decimals: 6),
),
defaultRefreshIntervalSeconds: 60,
defaultNetworkUnknownModel: NetworkUnknownModel(
Expand Down
4 changes: 2 additions & 2 deletions lib/infra/dto/shared/coin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class Coin extends Equatable {

factory Coin.fromTokenAmountModel(TokenAmountModel tokenAmountModel) {
return Coin(
denom: tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name,
amount: tokenAmountModel.getAmountInLowestDenomination().toString(),
denom: tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name,
amount: tokenAmountModel.getAmountInDefaultDenomination().toString(),
);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/infra/services/api_kira/query_balance_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ class QueryBalanceService implements _IQueryBalanceService {
List<BalanceModel> balanceModelList = List<BalanceModel>.empty(growable: true);
for (Balance balance in queryBalanceResp.balances) {
TokenAliasModel tokenAliasModel = tokenAliasModels.firstWhere((TokenAliasModel e) {
return e.lowestTokenDenominationModel.name == balance.denom;
return e.defaultTokenDenominationModel.name == balance.denom;
}, orElse: () => TokenAliasModel.local(balance.denom));

TokenAmountModel tokenAmountModel = TokenAmountModel(
lowestDenominationAmount: Decimal.parse(balance.amount),
defaultDenominationAmount: Decimal.parse(balance.amount),
tokenAliasModel: tokenAliasModel,
);
balanceModelList.add(BalanceModel(tokenAmountModel: tokenAmountModel));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class QueryExecutionFeeService implements _IQueryExecutionFeeService {

QueryExecutionFeeResponse queryExecutionFeeResponse = QueryExecutionFeeResponse.fromJson(response.data as Map<String, dynamic>);
TokenAmountModel feeTokenAmountModel = TokenAmountModel(
lowestDenominationAmount: Decimal.parse(queryExecutionFeeResponse.fee.executionFee),
defaultDenominationAmount: Decimal.parse(queryExecutionFeeResponse.fee.executionFee),
// tokenAliasModel - interx doesn't return denomination used in QueryExecutionFee endpoint, so we assumed that it's always represented in "ukex"
tokenAliasModel: _appConfig.defaultFeeTokenAliasModel,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class BalancesFilterOptions {

static FilterOption<BalanceModel> filterBySmallValues = FilterOption<BalanceModel>(
id: 'small',
filterComparator: (BalanceModel a) => a.tokenAmountModel.getAmountInDefaultDenomination() > _smallValueLimit,
filterComparator: (BalanceModel a) => a.tokenAmountModel.getAmountInNetworkDenomination() > _smallValueLimit,
filterMode: FilterMode.and,
);

Expand All @@ -22,21 +22,21 @@ class BalancesFilterOptions {

static FilterOption<BalanceModel> filterByDerivedTokens = FilterOption<BalanceModel>(
id: 'undelegate',
filterComparator: (BalanceModel a) => a.tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name.contains('/'),
filterComparator: (BalanceModel a) => a.tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name.contains('/'),
filterMode: FilterMode.and,
);

static FilterComparator<BalanceModel> search(String searchText) {
String pattern = searchText.toLowerCase();

return (BalanceModel item) {
bool amountNetworkMatch = item.tokenAmountModel.getAmountInNetworkDenomination().toString().contains(pattern);
bool amountDefaultMatch = item.tokenAmountModel.getAmountInDefaultDenomination().toString().contains(pattern);
bool amountLowestMatch = item.tokenAmountModel.getAmountInLowestDenomination().toString().contains(pattern);
bool amountMatch = amountDefaultMatch || amountLowestMatch;
bool amountMatch = amountNetworkMatch || amountDefaultMatch;

bool denomNetworkMatch = item.tokenAmountModel.tokenAliasModel.networkTokenDenominationModel.name.toLowerCase().contains(pattern);
bool denomDefaultMatch = item.tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name.toLowerCase().contains(pattern);
bool denomLowestMatch = item.tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name.toLowerCase().contains(pattern);
bool denomMatch = denomDefaultMatch || denomLowestMatch;
bool denomMatch = denomNetworkMatch || denomDefaultMatch;

bool nameMatch = item.tokenAmountModel.tokenAliasModel.name.toLowerCase().contains(pattern);
return amountMatch || denomMatch || nameMatch;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class BalancesListController implements IListController<BalanceModel> {
);

return balancesPageData.listItems.where((BalanceModel balanceModel) {
return favouriteBalances.contains(balanceModel.tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name);
return favouriteBalances.contains(balanceModel.tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name);
}).toList();
}
return List<BalanceModel>.empty(growable: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class BalancesSortOptions {
return SortOption<BalanceModel>.asc(
id: 'amount',
comparator: (BalanceModel a, BalanceModel b) =>
a.tokenAmountModel.getAmountInDefaultDenomination().compareTo(b.tokenAmountModel.getAmountInDefaultDenomination()),
a.tokenAmountModel.getAmountInNetworkDenomination().compareTo(b.tokenAmountModel.getAmountInNetworkDenomination()),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class StakingFilterOptions {
String pattern = searchText.toLowerCase();

return (ValidatorStakingModel item) {
bool tokenMatchBool = item.tokens.map((TokenAliasModel e) => e.lowestTokenDenominationModel.name).join(' ').toLowerCase().contains(pattern);
bool tokenMatchBool = item.tokens.map((TokenAliasModel e) => e.defaultTokenDenominationModel.name).join(' ').toLowerCase().contains(pattern);
bool addressMatchBool = item.validatorSimplifiedModel.walletAddress.bech32Address.toLowerCase().contains(pattern);
bool usernameMatchBool = item.validatorSimplifiedModel.moniker?.toLowerCase().contains(pattern) ?? false;
bool websiteMatchBool = item.validatorSimplifiedModel.website?.toLowerCase().contains(pattern) ?? false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class VerificationRequestsSortOptions {
return SortOption<IRInboundVerificationRequestModel>.asc(
id: 'tip',
comparator: (IRInboundVerificationRequestModel a, IRInboundVerificationRequestModel b) =>
a.tipTokenAmountModel.getAmountInLowestDenomination().compareTo(b.tipTokenAmountModel.getAmountInLowestDenomination()),
a.tipTokenAmountModel.getAmountInDefaultDenomination().compareTo(b.tipTokenAmountModel.getAmountInDefaultDenomination()),
);
}
}
2 changes: 1 addition & 1 deletion lib/shared/models/balances/balance_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class BalanceModel extends AListItem {
}) : _favourite = favourite;

@override
String get cacheId => tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name;
String get cacheId => tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name;

@override
bool get isFavourite => _favourite;
Expand Down
4 changes: 2 additions & 2 deletions lib/shared/models/network/network_properties_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class NetworkPropertiesModel extends Equatable {

return NetworkPropertiesModel(
minTxFee: TokenAmountModel(
lowestDenominationAmount: Decimal.parse(properties.minTxFee),
defaultDenominationAmount: Decimal.parse(properties.minTxFee),
tokenAliasModel: appConfig.defaultFeeTokenAliasModel,
),
minIdentityApprovalTip: TokenAmountModel(
lowestDenominationAmount: Decimal.parse(properties.minIdentityApprovalTip),
defaultDenominationAmount: Decimal.parse(properties.minIdentityApprovalTip),
tokenAliasModel: appConfig.defaultFeeTokenAliasModel,
),
);
Expand Down
2 changes: 1 addition & 1 deletion lib/shared/models/staking_pool/staking_pool_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class StakingPoolModel extends Equatable {
totalDelegators: queryStakingPoolResp.totalDelegators,
slashed: '${(double.parse(queryStakingPoolResp.slashed) * 100).toString()}%',
votingPower: queryStakingPoolResp.votingPower
.map((Coin e) => TokenAmountModel(lowestDenominationAmount: Decimal.parse(e.amount), tokenAliasModel: TokenAliasModel.local(e.denom)))
.map((Coin e) => TokenAmountModel(defaultDenominationAmount: Decimal.parse(e.amount), tokenAliasModel: TokenAliasModel.local(e.denom)))
.toList(),
commission: '${(double.parse(queryStakingPoolResp.commission) * 100).toString()}%',
tokens: queryStakingPoolResp.tokens.map(TokenAliasModel.local).toList(),
Expand Down
4 changes: 2 additions & 2 deletions lib/shared/models/tokens/prefixed_token_amount_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class PrefixedTokenAmountModel extends Equatable {
});

String getAmountAsString() {
return '${getPrefix()}${tokenAmountModel.getAmountInLowestDenomination()}';
return '${getPrefix()}${tokenAmountModel.getAmountInDefaultDenomination()}';
}

String getDenominationName() {
return tokenAmountModel.tokenAliasModel.lowestTokenDenominationModel.name;
return tokenAmountModel.tokenAliasModel.defaultTokenDenominationModel.name;
}

String getPrefix() {
Expand Down
22 changes: 11 additions & 11 deletions lib/shared/models/tokens/token_alias_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,48 @@ import 'package:miro/shared/models/tokens/token_denomination_model.dart';

class TokenAliasModel extends Equatable {
final String name;
final TokenDenominationModel lowestTokenDenominationModel;
final TokenDenominationModel defaultTokenDenominationModel;
final TokenDenominationModel networkTokenDenominationModel;
final String? icon;

const TokenAliasModel({
required this.name,
required this.lowestTokenDenominationModel,
TokenDenominationModel? defaultTokenDenominationModel,
required this.defaultTokenDenominationModel,
TokenDenominationModel? networkTokenDenominationModel,
this.icon,
}) : defaultTokenDenominationModel = defaultTokenDenominationModel ?? lowestTokenDenominationModel;
}) : networkTokenDenominationModel = networkTokenDenominationModel ?? defaultTokenDenominationModel;

factory TokenAliasModel.local(String name) {
return TokenAliasModel(
name: name,
lowestTokenDenominationModel: TokenDenominationModel(name: name, decimals: 0),
defaultTokenDenominationModel: TokenDenominationModel(name: name, decimals: 0),
);
}

factory TokenAliasModel.fromDto(TokenAlias tokenAlias) {
TokenDenominationModel defaultTokenDenominationModel = TokenDenominationModel(
TokenDenominationModel networkTokenDenominationModel = TokenDenominationModel(
name: tokenAlias.symbol,
decimals: tokenAlias.decimals,
);
TokenDenominationModel lowestTokenDenominationModel =
tokenAlias.denoms.isNotEmpty ? TokenDenominationModel(name: tokenAlias.denoms.first, decimals: 0) : defaultTokenDenominationModel;
TokenDenominationModel defaultTokenDenominationModel =
tokenAlias.denoms.isNotEmpty ? TokenDenominationModel(name: tokenAlias.denoms.first, decimals: 0) : networkTokenDenominationModel;

return TokenAliasModel(
name: tokenAlias.name,
icon: tokenAlias.icon,
networkTokenDenominationModel: networkTokenDenominationModel,
defaultTokenDenominationModel: defaultTokenDenominationModel,
lowestTokenDenominationModel: lowestTokenDenominationModel,
);
}

List<TokenDenominationModel> get tokenDenominations {
Set<TokenDenominationModel> availableTokenDenominationModelSet = <TokenDenominationModel>{
defaultTokenDenominationModel,
lowestTokenDenominationModel,
networkTokenDenominationModel,
};
return availableTokenDenominationModelSet.toList();
}

@override
List<Object?> get props => <Object>[lowestTokenDenominationModel];
List<Object?> get props => <Object>[defaultTokenDenominationModel];
}
62 changes: 31 additions & 31 deletions lib/shared/models/tokens/token_amount_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import 'package:miro/shared/models/tokens/token_denomination_model.dart';

class TokenAmountModel {
final TokenAliasModel tokenAliasModel;
late Decimal _lowestDenominationAmount;
late Decimal _defaultDenominationAmount;

TokenAmountModel({
required Decimal lowestDenominationAmount,
required Decimal defaultDenominationAmount,
required this.tokenAliasModel,
}) {
if (lowestDenominationAmount < Decimal.zero) {
_lowestDenominationAmount = Decimal.fromInt(-1);
if (defaultDenominationAmount < Decimal.zero) {
_defaultDenominationAmount = Decimal.fromInt(-1);
} else {
_lowestDenominationAmount = lowestDenominationAmount;
_defaultDenominationAmount = defaultDenominationAmount;
}
}

TokenAmountModel.zero({required this.tokenAliasModel}) : _lowestDenominationAmount = Decimal.zero;
TokenAmountModel.zero({required this.tokenAliasModel}) : _defaultDenominationAmount = Decimal.zero;

factory TokenAmountModel.fromString(String value) {
RegExp regExpPattern = RegExp(r'(\d+)([a-zA-Z0-9/]+)');
Expand All @@ -27,62 +27,62 @@ class TokenAmountModel {
String denom = regExpMatch.group(2)!;

return TokenAmountModel(
lowestDenominationAmount: amount,
defaultDenominationAmount: amount,
tokenAliasModel: TokenAliasModel.local(denom),
);
}

TokenAmountModel copy() {
return TokenAmountModel(
lowestDenominationAmount: _lowestDenominationAmount,
defaultDenominationAmount: _defaultDenominationAmount,
tokenAliasModel: tokenAliasModel,
);
}

int compareTo(TokenAmountModel tokenAmountModel) {
return tokenAmountModel._lowestDenominationAmount.compareTo(_lowestDenominationAmount);
return tokenAmountModel._defaultDenominationAmount.compareTo(_defaultDenominationAmount);
}

Decimal getAmountInLowestDenomination() {
return _lowestDenominationAmount;
Decimal getAmountInDefaultDenomination() {
return _defaultDenominationAmount;
}

Decimal getAmountInDefaultDenomination() {
return getAmountInDenomination(tokenAliasModel.defaultTokenDenominationModel);
Decimal getAmountInNetworkDenomination() {
return getAmountInDenomination(tokenAliasModel.networkTokenDenominationModel);
}

Decimal getAmountInDenomination(TokenDenominationModel tokenDenominationModel) {
bool isLowestTokenDenomination = tokenDenominationModel == tokenAliasModel.lowestTokenDenominationModel;
if (isLowestTokenDenomination) {
return _lowestDenominationAmount;
bool defaultTokenDenominationBool = tokenDenominationModel == tokenAliasModel.defaultTokenDenominationModel;
if (defaultTokenDenominationBool) {
return _defaultDenominationAmount;
}
int decimalsDifference = tokenAliasModel.lowestTokenDenominationModel.decimals - tokenDenominationModel.decimals;
Decimal calculatedAmount = _lowestDenominationAmount.shift(decimalsDifference);
int decimalsDifference = tokenAliasModel.defaultTokenDenominationModel.decimals - tokenDenominationModel.decimals;
Decimal calculatedAmount = _defaultDenominationAmount.shift(decimalsDifference);
return calculatedAmount;
}

void setAmount(Decimal amount, {TokenDenominationModel? tokenDenominationModel}) {
if (amount < Decimal.zero) {
throw ArgumentError('Amount must be greater than zero');
}
TokenDenominationModel lowestTokenDenomination = tokenAliasModel.lowestTokenDenominationModel;
TokenDenominationModel defaultTokenDenomination = tokenAliasModel.defaultTokenDenominationModel;

bool isLowestTokenDenomination = tokenDenominationModel == null || tokenDenominationModel == lowestTokenDenomination;
if (isLowestTokenDenomination) {
_lowestDenominationAmount = amount;
bool defaultTokenDenominationBool = tokenDenominationModel == null || tokenDenominationModel == defaultTokenDenomination;
if (defaultTokenDenominationBool) {
_defaultDenominationAmount = amount;
} else {
int decimalsDifference = tokenDenominationModel.decimals - lowestTokenDenomination.decimals;
_lowestDenominationAmount = amount.shift(decimalsDifference);
int decimalsDifference = tokenDenominationModel.decimals - defaultTokenDenomination.decimals;
_defaultDenominationAmount = amount.shift(decimalsDifference);
}
}

TokenAmountModel operator +(TokenAmountModel tokenAmountModel) {
if (tokenAmountModel.tokenAliasModel != tokenAliasModel) {
return this;
}
Decimal newAmount = _lowestDenominationAmount + tokenAmountModel._lowestDenominationAmount;
Decimal newAmount = _defaultDenominationAmount + tokenAmountModel._defaultDenominationAmount;
return TokenAmountModel(
lowestDenominationAmount: newAmount,
defaultDenominationAmount: newAmount,
tokenAliasModel: tokenAliasModel,
);
}
Expand All @@ -91,9 +91,9 @@ class TokenAmountModel {
if (tokenAmountModel.tokenAliasModel != tokenAliasModel) {
return this;
}
Decimal newAmount = _lowestDenominationAmount - tokenAmountModel._lowestDenominationAmount;
Decimal newAmount = _defaultDenominationAmount - tokenAmountModel._defaultDenominationAmount;
return TokenAmountModel(
lowestDenominationAmount: newAmount < Decimal.zero ? Decimal.zero : newAmount,
defaultDenominationAmount: newAmount < Decimal.zero ? Decimal.zero : newAmount,
tokenAliasModel: tokenAliasModel,
);
}
Expand All @@ -103,14 +103,14 @@ class TokenAmountModel {
identical(this, other) ||
other is TokenAmountModel &&
runtimeType == other.runtimeType &&
_lowestDenominationAmount == other._lowestDenominationAmount &&
_defaultDenominationAmount == other._defaultDenominationAmount &&
tokenAliasModel == other.tokenAliasModel;

@override
int get hashCode => _lowestDenominationAmount.hashCode ^ tokenAliasModel.hashCode;
int get hashCode => _defaultDenominationAmount.hashCode ^ tokenAliasModel.hashCode;

@override
String toString() {
return '${_lowestDenominationAmount} ${tokenAliasModel.lowestTokenDenominationModel.name}';
return '${_defaultDenominationAmount} ${tokenAliasModel.defaultTokenDenominationModel.name}';
}
}
2 changes: 1 addition & 1 deletion lib/shared/models/tokens/token_denomination_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class TokenDenominationModel extends Equatable {
/// Example KEX, uKEX
final String name;

/// Contains decimal number from lowest token denomination
/// Contains decimal number from default (lowest) token denomination
/// Example: decimals for uKEX equals 0 and for KEX equals 8
final int decimals;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class IRMsgRequestVerificationFormModel extends AMsgFormModel {
@override
bool canBuildTxMsg() {
bool fieldsFilledBool = _tipTokenAmountModel != null && _requesterWalletAddress != null && _verifierWalletAddress != null;
bool tipAmountNotEmptyBool = _tipTokenAmountModel?.getAmountInDefaultDenomination() != Decimal.zero;
bool tipAmountNotEmptyBool = _tipTokenAmountModel?.getAmountInNetworkDenomination() != Decimal.zero;
return fieldsFilledBool && tipAmountNotEmptyBool;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class MsgSendFormModel extends AMsgFormModel {
@override
bool canBuildTxMsg() {
bool fieldsFilledBool = _senderWalletAddress != null && _recipientWalletAddress != null && _tokenAmountModel != null;
bool tokenAmountNotEmptyBool = _tokenAmountModel?.getAmountInDefaultDenomination() != Decimal.zero;
bool tokenAmountNotEmptyBool = _tokenAmountModel?.getAmountInNetworkDenomination() != Decimal.zero;
if (fieldsFilledBool && tokenAmountNotEmptyBool) {
return true;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class StakingMsgDelegateFormModel extends AMsgFormModel {

@override
bool canBuildTxMsg() {
bool amountZeroBool = tokenAmountModels?.length == 1 && tokenAmountModels?.first.getAmountInLowestDenomination() == Decimal.zero;
bool amountZeroBool = tokenAmountModels?.length == 1 && tokenAmountModels?.first.getAmountInDefaultDenomination() == Decimal.zero;
bool fieldsFilledBool = _delegatorWalletAddress != null && _valoperWalletAddress != null && tokenAmountModels != null && amountZeroBool == false;
return fieldsFilledBool;
}
Expand Down
Loading

0 comments on commit cb015cc

Please sign in to comment.