fix(@desktop/permissions): Handle correct values in permissions

Add new field AmountInWeis to token criteria dto.
Keep strings instead of floats in token_criteria_item.
HoldingSelectionModel keeps amount in wei-like units but they are displayed in permissions as floats (divided by decimals).

Issue #11588
This commit is contained in:
Michal Iskierko 2024-02-13 11:24:24 +01:00 committed by Michał Iskierko
parent 6de7032d65
commit 3b5d55090d
11 changed files with 45 additions and 23 deletions

View File

@ -19,6 +19,7 @@ import ../../../global/global_singleton
import ../../../core/eventemitter import ../../../core/eventemitter
import ../../../core/unique_event_emitter import ../../../core/unique_event_emitter
import ../../../core/notifications/details as notification_details import ../../../core/notifications/details as notification_details
import ../../../../app_service/common/conversion
import ../../../../app_service/common/types import ../../../../app_service/common/types
import ../../../../app_service/service/settings/service as settings_service import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/node_configuration/service as node_configuration_service import ../../../../app_service/service/node_configuration/service as node_configuration_service
@ -1307,10 +1308,8 @@ method createOrEditCommunityTokenPermission*(self: Module, communityId: string,
tokenPermission.chatIDs = @[] tokenPermission.chatIDs = @[]
let tokenCriteriaJsonObj = tokenCriteriaJson.parseJson let tokenCriteriaJsonObj = tokenCriteriaJson.parseJson
for tokenCriteria in tokenCriteriaJsonObj: for tokenCriteria in tokenCriteriaJsonObj:
let viewAmount = tokenCriteria{"amount"}.getFloat
var tokenCriteriaDto = tokenCriteria.toTokenCriteriaDto var tokenCriteriaDto = tokenCriteria.toTokenCriteriaDto
if tokenCriteriaDto.`type` == TokenType.ERC20: if tokenCriteriaDto.`type` == TokenType.ERC20:
tokenCriteriaDto.decimals = self.controller.getTokenDecimals(tokenCriteriaDto.symbol) tokenCriteriaDto.decimals = self.controller.getTokenDecimals(tokenCriteriaDto.symbol)
@ -1323,7 +1322,7 @@ method createOrEditCommunityTokenPermission*(self: Module, communityId: string,
self.onCommunityTokenPermissionUpdateFailed(communityId) self.onCommunityTokenPermissionUpdateFailed(communityId)
return return
tokenCriteriaDto.amount = viewAmount.formatBiggestFloat(ffDecimal) tokenCriteriaDto.amountInWei = tokenCriteria{"amount"}.getStr
tokenCriteriaDto.contractAddresses = contractAddresses tokenCriteriaDto.contractAddresses = contractAddresses
tokenPermission.tokenCriteria.add(tokenCriteriaDto) tokenPermission.tokenCriteria.add(tokenCriteriaDto)

View File

@ -549,6 +549,7 @@ method requestCancelDiscordChannelImport*(self: Module, discordChannelId: string
proc createCommunityTokenItem(self: Module, token: CommunityTokensMetadataDto, communityId: string, supply: string, proc createCommunityTokenItem(self: Module, token: CommunityTokensMetadataDto, communityId: string, supply: string,
infiniteSupply: bool): TokenListItem = infiniteSupply: bool): TokenListItem =
let communityTokenDecimals = if token.tokenType == TokenType.ERC20: 18 else: 0
result = initTokenListItem( result = initTokenListItem(
key = token.symbol, key = token.symbol,
name = token.name, name = token.name,
@ -559,6 +560,7 @@ proc createCommunityTokenItem(self: Module, token: CommunityTokensMetadataDto, c
communityId = communityId, communityId = communityId,
supply, supply,
infiniteSupply, infiniteSupply,
communityTokenDecimals
) )
proc buildTokensAndCollectiblesFromCommunities(self: Module) = proc buildTokensAndCollectiblesFromCommunities(self: Module) =
@ -613,6 +615,7 @@ proc buildTokensAndCollectiblesFromWallet(self: Module) =
communityId = token.communityId, communityId = token.communityId,
image = "", image = "",
category = ord(TokenListItemCategory.General), category = ord(TokenListItemCategory.General),
decimals = token.decimals
) )
tokenListItems.add(tokenListItem) tokenListItems.add(tokenListItem)

View File

@ -4,7 +4,7 @@ type
TokenCriteriaItem* = object TokenCriteriaItem* = object
symbol*: string symbol*: string
name*: string name*: string
amount*: float64 amount*: string
`type`*: int `type`*: int
ensPattern*: string ensPattern*: string
criteriaMet*: bool criteriaMet*: bool
@ -12,7 +12,7 @@ type
proc initTokenCriteriaItem*( proc initTokenCriteriaItem*(
symbol: string, symbol: string,
name: string, name: string,
amount: float64, amount: string,
`type`: int, `type`: int,
ensPattern: string, ensPattern: string,
criteriaMet: bool criteriaMet: bool
@ -43,7 +43,7 @@ proc getSymbol*(self: TokenCriteriaItem): string =
proc getName*(self: TokenCriteriaItem): string = proc getName*(self: TokenCriteriaItem): string =
return self.name return self.name
proc getAmount*(self: TokenCriteriaItem): float64 = proc getAmount*(self: TokenCriteriaItem): string =
return self.amount return self.amount
proc getEnsPattern*(self: TokenCriteriaItem): string = proc getEnsPattern*(self: TokenCriteriaItem): string =

View File

@ -16,6 +16,7 @@ type
communityId*: string communityId*: string
supply*: string supply*: string
infiniteSupply*: bool infiniteSupply*: bool
decimals*: int
proc initTokenListItem*( proc initTokenListItem*(
key: string, key: string,
@ -27,6 +28,7 @@ proc initTokenListItem*(
communityId: string = "", communityId: string = "",
supply: string = "1", supply: string = "1",
infiniteSupply: bool = true, infiniteSupply: bool = true,
decimals: int
): TokenListItem = ): TokenListItem =
result.key = key result.key = key
result.symbol = symbol result.symbol = symbol
@ -37,6 +39,7 @@ proc initTokenListItem*(
result.communityId = communityId result.communityId = communityId
result.supply = supply result.supply = supply
result.infiniteSupply = infiniteSupply result.infiniteSupply = infiniteSupply
result.decimals = decimals
proc `$`*(self: TokenListItem): string = proc `$`*(self: TokenListItem): string =
result = fmt"""TokenListItem( result = fmt"""TokenListItem(
@ -48,6 +51,7 @@ proc `$`*(self: TokenListItem): string =
communityId: {self.communityId}, communityId: {self.communityId},
supply: {self.supply}, supply: {self.supply},
infiniteSupply: {self.infiniteSupply}, infiniteSupply: {self.infiniteSupply},
decimals: {self.decimals},
]""" ]"""
proc getKey*(self: TokenListItem): string = proc getKey*(self: TokenListItem): string =
@ -76,3 +80,6 @@ proc getSupply*(self: TokenListItem): string =
proc getInfiniteSupply*(self: TokenListItem): bool = proc getInfiniteSupply*(self: TokenListItem): bool =
return self.infiniteSupply return self.infiniteSupply
proc getDecimals*(self: TokenListItem): int =
return self.decimals

View File

@ -13,6 +13,7 @@ type
CommunityId CommunityId
Supply Supply
InfiniteSupply InfiniteSupply
Decimals
QtObject: QtObject:
type TokenListModel* = ref object of QAbstractListModel type TokenListModel* = ref object of QAbstractListModel
@ -91,6 +92,7 @@ QtObject:
ModelRole.CommunityId.int:"communityId", ModelRole.CommunityId.int:"communityId",
ModelRole.Supply.int:"supply", ModelRole.Supply.int:"supply",
ModelRole.InfiniteSupply.int:"infiniteSupply", ModelRole.InfiniteSupply.int:"infiniteSupply",
ModelRole.Decimals.int:"decimals",
}.toTable }.toTable
method rowCount(self: TokenlistModel, index: QModelIndex = nil): int = method rowCount(self: TokenlistModel, index: QModelIndex = nil): int =
@ -124,3 +126,5 @@ QtObject:
result = newQVariant(item.getSupply()) result = newQVariant(item.getSupply())
of ModelRole.InfiniteSupply: of ModelRole.InfiniteSupply:
result = newQVariant(item.getInfiniteSupply()) result = newQVariant(item.getInfiniteSupply())
of ModelRole.Decimals:
result = newQVariant(item.getDecimals())

View File

@ -80,7 +80,7 @@ proc buildTokenPermissionItem*(tokenPermission: CommunityTokenPermissionDto, cha
let tokenCriteriaItem = initTokenCriteriaItem( let tokenCriteriaItem = initTokenCriteriaItem(
tc.symbol, tc.symbol,
tc.name, tc.name,
tc.amount.parseFloat, tc.amountInWei,
tc.`type`.int, tc.`type`.int,
tc.ensPattern, tc.ensPattern,
false # tokenCriteriaMet will be updated by a call to checkPermissionsToJoin false # tokenCriteriaMet will be updated by a call to checkPermissionsToJoin

View File

@ -82,6 +82,7 @@ type TokenCriteriaDto* = object
decimals* {.serializedFieldName("decimals").}: int decimals* {.serializedFieldName("decimals").}: int
tokenIds* {.serializedFieldName("tokenIds").}: seq[string] tokenIds* {.serializedFieldName("tokenIds").}: seq[string]
ensPattern* {.serializedFieldName("ens_pattern").}: string ensPattern* {.serializedFieldName("ens_pattern").}: string
amountInWei* {.serializedFieldName("amountInWei").}: string
type CommunityTokenPermissionDto* = object type CommunityTokenPermissionDto* = object
id*: string id*: string
@ -258,6 +259,7 @@ proc toDiscordImportTaskProgress*(jsonObj: JsonNode): DiscordImportTaskProgress
proc toTokenCriteriaDto*(jsonObj: JsonNode): TokenCriteriaDto = proc toTokenCriteriaDto*(jsonObj: JsonNode): TokenCriteriaDto =
result = TokenCriteriaDto() result = TokenCriteriaDto()
discard jsonObj.getProp("amount", result.amount) discard jsonObj.getProp("amount", result.amount)
discard jsonObj.getProp("amountInWei", result.amountInWei)
discard jsonObj.getProp("decimals", result.decimals) discard jsonObj.getProp("decimals", result.decimals)
discard jsonObj.getProp("symbol", result.symbol) discard jsonObj.getProp("symbol", result.symbol)
discard jsonObj.getProp("name", result.name) discard jsonObj.getProp("name", result.name)

View File

@ -82,9 +82,10 @@ QtObject {
return Internal.PermissionUtils.getUniquePermissionChannels(model, channelKey) return Internal.PermissionUtils.getUniquePermissionChannels(model, channelKey)
} }
function setHoldingsTextFormat(type, name, amount) { function setHoldingsTextFormat(type, name, amount, decimals) {
if (typeof amount === "string") if (typeof amount === "string") {
amount = AmountsArithmetic.toNumber(AmountsArithmetic.fromString(amount)) amount = AmountsArithmetic.toNumber(AmountsArithmetic.fromString(amount), decimals)
}
switch (type) { switch (type) {
case Constants.TokenType.ERC20: case Constants.TokenType.ERC20:

View File

@ -50,10 +50,6 @@ Control {
readonly property string channelMembershipRequestPendingText: qsTr("Channel Membership Request Pending...") readonly property string channelMembershipRequestPendingText: qsTr("Channel Membership Request Pending...")
readonly property string memberchipRequestRejectedText: qsTr("Membership Request Rejected") readonly property string memberchipRequestRejectedText: qsTr("Membership Request Rejected")
function holdingsTextFormat(name, amount) {
return PermissionsHelpers.setHoldingsTextFormat(Constants.TokenType.ERC20, name, amount)
}
function getInvitationPendingText() { function getInvitationPendingText() {
return root.joinCommunity ? d.communityMembershipRequestPendingText : d.channelMembershipRequestPendingText return root.joinCommunity ? d.communityMembershipRequestPendingText : d.channelMembershipRequestPendingText
} }

View File

@ -246,7 +246,7 @@ StatusScrollView {
const key = item.key const key = item.key
d.dirtyValues.selectedHoldingsModel.append( d.dirtyValues.selectedHoldingsModel.append(
{ type, key, amount: parseFloat(amount) }) { type, key, amount })
} }
function prepareUpdateIndex(key) { function prepareUpdateIndex(key) {
@ -275,7 +275,7 @@ StatusScrollView {
const modelItem = PermissionsHelpers.getTokenByKey( const modelItem = PermissionsHelpers.getTokenByKey(
root.assetsModel, key) root.assetsModel, key)
addItem(Constants.TokenType.ERC20, modelItem, amount) addItem(Constants.TokenType.ERC20, modelItem, String(AmountsArithmetic.fromNumber(amount, modelItem.decimals)))
dropdown.close() dropdown.close()
} }
@ -283,13 +283,13 @@ StatusScrollView {
const modelItem = PermissionsHelpers.getTokenByKey( const modelItem = PermissionsHelpers.getTokenByKey(
root.collectiblesModel, key) root.collectiblesModel, key)
addItem(Constants.TokenType.ERC721, modelItem, amount) addItem(Constants.TokenType.ERC721, modelItem, String(amount))
dropdown.close() dropdown.close()
} }
onAddEns: { onAddEns: {
d.dirtyValues.selectedHoldingsModel.append( d.dirtyValues.selectedHoldingsModel.append(
{ type: Constants.TokenType.ENS, key: domain, amount: 1 }) { type: Constants.TokenType.ENS, key: domain, amount: "1" })
dropdown.close() dropdown.close()
} }
@ -298,7 +298,7 @@ StatusScrollView {
const modelItem = PermissionsHelpers.getTokenByKey(root.assetsModel, key) const modelItem = PermissionsHelpers.getTokenByKey(root.assetsModel, key)
d.dirtyValues.selectedHoldingsModel.set( d.dirtyValues.selectedHoldingsModel.set(
itemIndex, { type: Constants.TokenType.ERC20, key, amount: parseFloat(amount) }) itemIndex, { type: Constants.TokenType.ERC20, key, amount: String(AmountsArithmetic.fromNumber(amount, modelItem.decimals)) })
dropdown.close() dropdown.close()
} }
@ -309,14 +309,14 @@ StatusScrollView {
d.dirtyValues.selectedHoldingsModel.set( d.dirtyValues.selectedHoldingsModel.set(
itemIndex, itemIndex,
{ type: Constants.TokenType.ERC721, key, amount: parseFloat(amount) }) { type: Constants.TokenType.ERC721, key, amount: String(amount) })
dropdown.close() dropdown.close()
} }
onUpdateEns: { onUpdateEns: {
d.dirtyValues.selectedHoldingsModel.set( d.dirtyValues.selectedHoldingsModel.set(
tokensSelector.editedIndex, tokensSelector.editedIndex,
{ type: Constants.TokenType.ENS, key: domain, amount: 1 }) { type: Constants.TokenType.ENS, key: domain, amount: "1" })
dropdown.close() dropdown.close()
} }
@ -353,7 +353,8 @@ StatusScrollView {
switch(modelItem.type) { switch(modelItem.type) {
case Constants.TokenType.ERC20: case Constants.TokenType.ERC20:
dropdown.assetKey = modelItem.key dropdown.assetKey = modelItem.key
dropdown.assetAmount = modelItem.amount const decimals = PermissionsHelpers.getTokenByKey(root.assetsModel, modelItem.key).decimals
dropdown.assetAmount = AmountsArithmetic.toNumber(modelItem.amount, decimals)
break break
case Constants.TokenType.ERC721: case Constants.TokenType.ERC721:
dropdown.collectibleKey = modelItem.key dropdown.collectibleKey = modelItem.key

View File

@ -37,11 +37,20 @@ SortFilterProxyModel {
return item ? item.symbol || item.shortName || item.name : "" return item ? item.symbol || item.shortName || item.name : ""
} }
function getDecimals(type, key) {
if (type !== Constants.TokenType.ERC20) {
return 0
}
const item = PermissionsHelpers.getTokenByKey(assetsModel, key)
return item.decimals
}
function getText(type, key, amount) { function getText(type, key, amount) {
const name = getName(type, key) const name = getName(type, key)
const decimals = getDecimals(type, key)
return PermissionsHelpers.setHoldingsTextFormat( return PermissionsHelpers.setHoldingsTextFormat(
type, name, amount) type, name, amount, decimals)
} }
// Direct call for singleton function is not handled properly by // Direct call for singleton function is not handled properly by