feat(@desktop/wallet): integrate new onramp status-go api

This commit is contained in:
Dario Gabriel Lipicar 2024-08-06 13:08:08 -03:00 committed by dlipicar
parent b8ffa65113
commit 2688d48d65
24 changed files with 522 additions and 156 deletions

View File

@ -12,6 +12,7 @@ import app_service/service/message/service as message_service
import app_service/service/token/service as token_service
import app_service/service/collectible/service as collectible_service
import app_service/service/currency/service as currency_service
import app_service/service/ramp/service as ramp_service
import app_service/service/transaction/service as transaction_service
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/privacy/service as privacy_service
@ -77,6 +78,7 @@ type
tokenService: token_service.Service
collectibleService: collectible_service.Service
currencyService: currency_service.Service
rampService: ramp_service.Service
transactionService: transaction_service.Service
walletAccountService: wallet_account_service.Service
providerService: provider_service.Service
@ -199,6 +201,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
)
result.communityService = community_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService, result.activityCenterService, result.messageService)
result.rampService = ramp_service.newService(statusFoundation.events, statusFoundation.threadpool)
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool, result.networkService, result.settingsService, result.tokenService)
result.profileService = profile_service.newService(statusFoundation.events, statusFoundation.threadpool, result.settingsService)
result.stickersService = stickers_service.newService(
@ -257,6 +260,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.tokenService,
result.collectibleService,
result.currencyService,
result.rampService,
result.transactionService,
result.walletAccountService,
result.profileService,
@ -317,6 +321,7 @@ proc delete*(self: AppController) =
self.currencyService.delete
self.collectibleService.delete
self.tokenService.delete
self.rampService.delete
self.transactionService.delete
self.walletAccountService.delete
self.aboutService.delete
@ -422,6 +427,7 @@ proc load(self: AppController) =
self.messageService.init()
self.communityService.init()
self.providerService.init()
self.rampService.init()
self.transactionService.init()
self.stickersService.init()
self.activityCenterService.init()

View File

@ -38,6 +38,7 @@ import ../../../app_service/service/message/service as message_service
import ../../../app_service/service/token/service as token_service
import ../../../app_service/service/collectible/service as collectible_service
import ../../../app_service/service/currency/service as currency_service
import ../../../app_service/service/ramp/service as ramp_service
import ../../../app_service/service/transaction/service as transaction_service
import ../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../app_service/service/provider/service as provider_service
@ -140,6 +141,7 @@ proc newModule*[T](
tokenService: token_service.Service,
collectibleService: collectible_service.Service,
currencyService: currency_service.Service,
rampService: ramp_service.Service,
transactionService: transaction_service.Service,
walletAccountService: wallet_account_service.Service,
profileService: profile_service.Service,
@ -208,7 +210,7 @@ proc newModule*[T](
result.chatSectionModules = initOrderedTable[string, chat_section_module.AccessInterface]()
result.walletSectionModule = wallet_section_module.newModule(
result, events, tokenService, collectibleService, currencyService,
transactionService, walletAccountService,
rampService, transactionService, walletAccountService,
settingsService, savedAddressService, networkService, accountsService,
keycardService, nodeService, networkConnectionService, devicesService,
communityTokensService, threadpool

View File

@ -1,31 +1,39 @@
import io_interface
import ../../../../../app_service/service/transaction/service as transaction_service
import app_service/service/ramp/service as ramp_service
import app_service/service/ramp/dto
import ../../../../core/eventemitter
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
transactionService: transaction_service.Service
rampService: ramp_service.Service
events: EventEmitter
proc newController*(
delegate: io_interface.AccessInterface,
events: EventEmitter,
transactionService: transaction_service.Service
rampService: ramp_service.Service
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.transactionService = transactionService
result.rampService = rampService
proc delete*(self: Controller) =
discard
proc init*(self: Controller) =
self.events.on(SIGNAL_CRYPTO_SERVICES_READY) do(e:Args):
let args = CryptoServicesArgs(e)
self.delegate.updateCryptoServices(args.data)
self.events.on(SIGNAL_CRYPTO_RAMP_PROVIDERS_READY) do(e:Args):
let args = CryptoRampProvidersArgs(e)
self.delegate.updateRampProviders(args.data)
proc fetchCryptoServices*(self: Controller) =
self.transactionService.fetchCryptoServices()
self.events.on(SIGNAL_CRYPTO_RAMP_URL_READY) do(e:Args):
let args = CryptoRampUrlArgs(e)
self.delegate.onRampProviderUrlReady(args.uuid, args.url)
proc fetchCryptoRampProviders*(self: Controller) =
self.rampService.fetchCryptoRampProviders()
proc fetchCryptoRampUrl*(self: Controller, uuid: string, providerID: string, parameters: CryptoRampParametersDto) =
self.rampService.fetchCryptoRampUrl(uuid, providerID, parameters)

View File

@ -1,4 +1,4 @@
import ../../../../../app_service/service/transaction/cryptoRampDto
import app_service/service/ramp/dto
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -13,7 +13,16 @@ method load*(self: AccessInterface) {.base.} =
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method updateCryptoServices*(self: AccessInterface, cryptoServices: seq[CryptoRampDto]) {.base.} =
method fetchProviders*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method fetchProviderUrl*(self: AccessInterface, uuid: string, providerID: string, parameters: CryptoRampParametersDto) {.base.} =
raise newException(ValueError, "No implementation available")
method updateRampProviders*(self: AccessInterface, cryptoServices: seq[CryptoRampDto]) {.base.} =
raise newException(ValueError, "No implementation available")
method onRampProviderUrlReady*(self: AccessInterface, uuid: string, url: string) {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface

View File

@ -1,35 +1,60 @@
import stew/shims/strformat
import app/modules/shared_models/contract_model as contract_model
import app/modules/shared_models/contract_item as contract_item
type Item* = object
id: string
name: string
description: string
fees: string
logoUrl: string
siteUrl: string
logoUrl: string
hostname: string
recurrentSiteUrl: string
supportsSinglePurchase: bool
supportsRecurrentPurchase: bool
supportedAssets: contract_model.Model
urlsNeedParameters: bool
proc initItem*(name, description, fees, logoUrl, siteUrl,
hostname, recurrentSiteUrl,: string): Item =
proc initItem*(
id: string,
name: string,
description: string,
fees: string,
logoUrl: string,
hostname: string,
supportsSinglePurchase: bool,
supportsRecurrentPurchase: bool,
supportedAssets: seq[contract_item.Item],
urlsNeedParameters: bool): Item =
result.id = id
result.name = name
result.description = description
result.fees = fees
result.logoUrl = logoUrl
result.siteUrl = siteUrl
result.hostname = hostname
result.recurrentSiteUrl = recurrentSiteUrl
result.supportsSinglePurchase = supportsSinglePurchase
result.supportsRecurrentPurchase = supportsRecurrentPurchase
result.supportedAssets = contract_model.newModel()
result.supportedAssets.setItems(supportedAssets)
result.urlsNeedParameters = urlsNeedParameters
proc `$`*(self: Item): string =
result = "Item("
result &= fmt"id:{self.id}, "
result &= fmt"name:{self.name}, "
result &= fmt"description:{self.description}, "
result &= fmt"fees:{self.fees}, "
result &= fmt"logoUrl:{self.logoUrl}, "
result &= fmt"siteUrl:{self.siteUrl}"
result &= fmt"hostname:{self.hostname}"
result &= fmt"recurrentSiteUrl:{self.recurrentSiteUrl}"
result &= fmt"hostname:{self.hostname}, "
result &= fmt"supportsSinglePurchase:{self.supportsSinglePurchase}, "
result &= fmt"supportsRecurrentPurchase:{self.supportsRecurrentPurchase}, "
result &= fmt"supportedAssets:{self.supportedAssets}, "
result &= fmt"urlsNeedParameters:{self.urlsNeedParameters}, "
result &= ")"
method getId*(self: Item): string {.base.} =
return self.id
method getName*(self: Item): string {.base.} =
return self.name
@ -42,11 +67,17 @@ method getFees*(self: Item): string {.base.} =
method getLogoUrl*(self: Item): string {.base.} =
return self.logoUrl
method getSiteUrl*(self: Item): string {.base.} =
return self.siteUrl
method getHostname*(self: Item): string {.base.} =
return self.hostname
method getRecurrentSiteUrl*(self: Item): string {.base.} =
return self.recurrentSiteUrl
method getSupportsSinglePurchase*(self: Item): bool {.base.} =
return self.supportsSinglePurchase
method getSupportsRecurrentPurchase*(self: Item): bool {.base.} =
return self.supportsRecurrentPurchase
method getSupportedAssets*(self: Item): contract_model.Model {.base.} =
return self.supportedAssets
method getUrlsNeedParameters*(self: Item): bool {.base.} =
return self.urlsNeedParameters

View File

@ -4,13 +4,16 @@ import item
type
ModelRole {.pure.} = enum
Name = UserRole + 1
Id = UserRole + 1
Name
Description
Fees
LogoUrl
SiteUrl
Hostname
RecurrentSiteUrl
SupportsSinglePurchase
SupportsRecurrentPurchase
SupportedAssets
UrlsNeedParameters
QtObject:
type
@ -32,13 +35,16 @@ QtObject:
method roleNames(self: Model): Table[int, string] =
{
ModelRole.Id.int:"id",
ModelRole.Name.int:"name",
ModelRole.Description.int:"description",
ModelRole.Fees.int:"fees",
ModelRole.LogoUrl.int:"logoUrl",
ModelRole.SiteUrl.int:"siteUrl",
ModelRole.Hostname.int:"hostname",
ModelRole.RecurrentSiteUrl.int:"recurrentSiteUrl"
ModelRole.SupportsSinglePurchase.int:"supportsSinglePurchase",
ModelRole.SupportsRecurrentPurchase.int:"supportsRecurrentPurchase",
ModelRole.SupportedAssets.int:"supportedAssets",
ModelRole.UrlsNeedParameters.int:"urlsNeedParameters"
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -52,6 +58,8 @@ QtObject:
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Id:
result = newQVariant(item.getId)
of ModelRole.Name:
result = newQVariant(item.getName)
of ModelRole.Description:
@ -60,12 +68,16 @@ QtObject:
result = newQVariant(item.getFees)
of ModelRole.LogoUrl:
result = newQVariant(item.getLogoUrl)
of ModelRole.SiteUrl:
result = newQVariant(item.getSiteUrl)
of ModelRole.Hostname:
result = newQVariant(item.getHostname)
of ModelRole.RecurrentSiteUrl:
result = newQVariant(item.getRecurrentSiteUrl)
of ModelRole.SupportsSinglePurchase:
result = newQVariant(item.getSupportsSinglePurchase)
of ModelRole.SupportsRecurrentPurchase:
result = newQVariant(item.getSupportsRecurrentPurchase)
of ModelRole.SupportedAssets:
result = newQVariant(item.getSupportedAssets)
of ModelRole.UrlsNeedParameters:
result = newQVariant(item.getUrlsNeedParameters)
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()

View File

@ -1,11 +1,11 @@
import NimQml, sequtils
import NimQml, sequtils, sugar
import ./io_interface, ./view, ./item, ./controller
import ./io_interface, ./view, ./controller, ./utils
import ../io_interface as delegate_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/service/transaction/service as transaction_service
import ../../../../../app_service/service/transaction/cryptoRampDto
import app_service/service/ramp/service as ramp_service
import app_service/service/ramp/dto
export io_interface
@ -21,14 +21,14 @@ type
proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
transactionService: transaction_service.Service,
rampService: ramp_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.events = events
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, transactionService)
result.controller = controller.newController(result, events, rampService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -36,21 +36,23 @@ method delete*(self: Module) =
self.view.delete
self.controller.delete
method updateCryptoServices*(self: Module, cryptoServices: seq[CryptoRampDto]) =
let items = cryptoServices.map(proc (w: CryptoRampDto): item.Item = result = initItem(
w.name,
w.description,
w.fees,
w.logoUrl,
w.siteUrl,
w.hostname,
w.recurrentSiteUrl,
))
method fetchProviders*(self: Module) =
self.controller.fetchCryptoRampProviders()
self.view.setIsFetching(true)
method fetchProviderUrl*(self: Module, uuid: string, providerID: string, parameters: CryptoRampParametersDto) =
self.controller.fetchCryptoRampUrl(uuid, providerID, parameters)
method updateRampProviders*(self: Module, cryptoServices: seq[CryptoRampDto]) =
let items = cryptoServices.map(i => i.dtoToItem())
self.view.setItems(items)
self.view.setIsFetching(false)
method onRampProviderUrlReady*(self: Module, uuid: string, url: string) =
self.view.onProviderUrlReady(uuid, url)
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSectionBuySellCrypto", self.viewVariant)
self.controller.fetchCryptoServices()
self.controller.init()
self.view.load()

View File

@ -0,0 +1,21 @@
import sugar, sequtils
import ./item
import app_service/service/ramp/dto
import app/modules/shared_models/contract_item as contract_item
proc dtoToItem*(dto: CryptoRampDto): item.Item =
let supportedAssets = dto.supportedTokens.map(t => contract_item.initItem(t.chainID, t.address))
return initItem(
dto.id,
dto.name,
dto.description,
dto.fees,
dto.logoUrl,
dto.hostname,
dto.supportsSinglePurchase,
dto.supportsRecurrentPurchase,
supportedAssets,
dto.urlsNeedParameters
)

View File

@ -1,15 +1,19 @@
import NimQml
import options
import ./model
import ./item
import ./io_interface
import app_service/service/ramp/dto
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
model: Model
modelVariant: QVariant
isFetching: bool
proc delete*(self: View) =
self.model.delete
@ -22,6 +26,7 @@ QtObject:
result.delegate = delegate
result.model = newModel()
result.modelVariant = newQVariant(result.model)
result.isFetching = false
proc load*(self: View) =
self.delegate.viewDidLoad()
@ -35,6 +40,49 @@ QtObject:
read = getModel
notify = modelChanged
proc isFetchingChanged*(self: View) {.signal.}
proc getIsFetching*(self: View): bool {.slot.} =
return self.isFetching
QtProperty[bool] isFetching:
read = getIsFetching
notify = isFetchingChanged
proc setIsFetching*(self: View, value: bool) =
if self.isFetching == value:
return
self.isFetching = value
self.isFetchingChanged()
proc setItems*(self: View, items: seq[Item]) =
self.model.setItems(items)
self.modelChanged()
proc fetchProviders*(self: View) {.slot.} =
self.delegate.fetchProviders()
proc fetchProviderUrl*(self: View,
uuid: string,
providerID: string,
isRecurrent: bool,
destinationAccountAddress: string,
chainID: int,
symbol: string) {.slot.} =
let parameters = CryptoRampParametersDto(
isRecurrent: isRecurrent,
)
if destinationAccountAddress.len > 0:
parameters.destinationAddress = some(destinationAccountAddress)
if chainID > 0:
parameters.chainID = some(chainID)
if symbol.len > 0:
parameters.symbol = some(symbol)
self.delegate.fetchProviderUrl(uuid, providerID, parameters)
proc providerUrlReady*(self: View, uuid: string, url: string) {.signal.}
proc onProviderUrlReady*(self: View, uuid: string, url: string) =
self.providerUrlReady(uuid, url)

View File

@ -29,6 +29,7 @@ import app_service/service/keycard/service as keycard_service
import app_service/service/token/service as token_service
import app_service/service/collectible/service as collectible_service
import app_service/service/currency/service as currency_service
import app_service/service/ramp/service as ramp_service
import app_service/service/transaction/service as transaction_service
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/settings/service as settings_service
@ -75,6 +76,7 @@ type
overviewModule: overview_module.AccessInterface
networksModule: networks_module.AccessInterface
networksService: network_service.Service
rampService: ramp_service.Service
transactionService: transaction_service.Service
keycardService: keycard_service.Service
accountsService: accounts_service.Service
@ -107,6 +109,7 @@ proc newModule*(
tokenService: token_service.Service,
collectibleService: collectible_service.Service,
currencyService: currency_service.Service,
rampService: ramp_service.Service,
transactionService: transaction_service.Service,
walletAccountService: wallet_account_service.Service,
settingsService: settings_service.Service,
@ -141,7 +144,7 @@ proc newModule*(
result.sendModule = send_module.newModule(result, events, walletAccountService, networkService, currencyService,
transactionService, keycardService)
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, rampService)
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
result.networksModule = networks_module.newModule(result, events, networkService, walletAccountService, settingsService)
result.networksService = networkService

View File

@ -0,0 +1,28 @@
import stew/shims/strformat
type Item* = ref object
key: string
chainId: int
address: string
proc initItem*(chainID: int, address: string): Item =
result = Item()
result.key = $chainID & address
result.chainID = chainID
result.address = address
proc `$`*(self: Item): string =
result = fmt"""ContractItem(
key: {self.key},
chainId: {$self.chainId},
address: {self.address},
]"""
proc key*(self: Item): string {.inline.} =
self.key
proc chainId*(self: Item): int {.inline.} =
self.chainId
proc address*(self: Item): string {.inline.} =
self.address

View File

@ -0,0 +1,59 @@
import NimQml, Tables, strutils, stew/shims/strformat
import ./contract_item
type
ModelRole {.pure.} = enum
Key = UserRole + 1
ChainId
Address
QtObject:
type Model* = ref object of QAbstractListModel
items: seq[Item]
proc setup(self: Model) =
self.QAbstractListModel.setup
proc delete(self: Model) =
self.items = @[]
self.QAbstractListModel.delete
proc newModel*(): Model =
new(result, delete)
result.setup
result.items = @[]
proc `$`*(self: Model): string =
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:({$self.items[i]})"""
method rowCount(self: Model, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: Model): Table[int, string] =
{
ModelRole.Key.int:"key",
ModelRole.ChainId.int:"chainId",
ModelRole.Address.int:"address",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.rowCount():
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Key:
result = newQVariant(item.key())
of ModelRole.ChainId:
result = newQVariant(item.chainId())
of ModelRole.Address:
result = newQVariant(item.address())
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()

View File

@ -0,0 +1,47 @@
import json
import backend/ramp as ramp_backend
proc getCryptoServicesTask*(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[QObjectTaskArg](argEncoded)
try:
let response = ramp_backend.fetchCryptoRampProviders()
if not response.error.isNil:
raise newException(ValueError, "Error fetching crypto services" & response.error.message)
arg.finish(%* {
"result": response.result,
})
except Exception as e:
error "Error fetching crypto services", message = e.msg
arg.finish(%* {
"result": @[],
})
type
GetCryptoRampUrlTaskArg* = ref object of QObjectTaskArg
uuid: string
providerID: string
parameters: JsonNode
proc getCryptoRampUrlTask*(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetCryptoRampUrlTaskArg](argEncoded)
var data = %* {
"uuid": arg.uuid
}
try:
let parameters = fromJson(arg.parameters, CryptoRampParametersDto)
let response = ramp_backend.fetchCryptoRampUrl(arg.providerID, parameters)
if not response.error.isNil:
raise newException(ValueError, "Error fetching crypto ramp url" & response.error.message)
data["url"] = response.result
arg.finish(data)
except Exception as e:
error "Error fetching crypto ramp url", message = e.msg
arg.finish(data)

View File

@ -0,0 +1,79 @@
import json, json_serialization, stew/shims/strformat
import options
include app_service/common/json_utils
import app_service/service/token/dto
type
CryptoRampDto* = ref object of RootObj
id*: string
name*: string
description*: string
fees*: string
logoUrl*: string
hostname*: string
supportsSinglePurchase*: bool
supportsRecurrentPurchase*: bool
supportedChainIds*: seq[int]
supportedTokens*: seq[TokenDto]
urlsNeedParameters*: bool
type
CryptoRampParametersDto* = ref object of RootObj
isRecurrent*: bool
destinationAddress*: Option[string]
chainID*: Option[int]
symbol*: Option[string]
proc `$`*(self: CryptoRampDto): string =
result = "CryptoRampDto("
result &= fmt"id:{self.id}, "
result &= fmt"name:{self.name}, "
result &= fmt"description:{self.description}, "
result &= fmt"fees:{self.fees}, "
result &= fmt"logoUrl:{self.logoUrl}, "
result &= fmt"hostname:{self.hostname}, "
result &= fmt"supportsSinglePurchase:{self.supportsSinglePurchase}, "
result &= fmt"supportsRecurrentPurchase:{self.supportsRecurrentPurchase}, "
result &= fmt"supportedChainIds:{self.supportedChainIds}, "
result &= fmt"supportedTokens:{self.supportedTokens}, "
result &= fmt"urlsNeedParameters:{self.urlsNeedParameters}"
result &= ")"
proc toCryptoRampDto*(jsonObj: JsonNode): CryptoRampDto =
result = CryptoRampDto()
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("description", result.description)
discard jsonObj.getProp("fees", result.fees)
discard jsonObj.getProp("logoUrl", result.logoUrl)
discard jsonObj.getProp("hostname", result.hostname)
discard jsonObj.getProp("supportsSinglePurchase", result.supportsSinglePurchase)
discard jsonObj.getProp("supportsRecurrentPurchase", result.supportsRecurrentPurchase)
for chainID in jsonObj["supportedChainIds"].getElems():
result.supportedChainIds.add(chainID.getInt())
for token in jsonObj["supportedTokens"].getElems():
let tokenDto = Json.decode($token, TokenDto, allowUnknownFields = true)
result.supportedTokens.add(tokenDto)
discard jsonObj.getProp("urlsNeedParameters", result.urlsNeedParameters)
proc `%`*(self: CryptoRampParametersDto): JsonNode =
result = newJObject()
result["isRecurrent"] = %(self.isRecurrent)
if self.destinationAddress.isSome:
result["destAddress"] = %(self.destinationAddress.get)
if self.chainID.isSome:
result["chainID"] = %(self.chainID.get)
if self.symbol.isSome:
result["symbol"] = %(self.symbol.get)
proc fromJson*(self: JsonNode, T: typedesc[CryptoRampParametersDto]): CryptoRampParametersDto {.inline.} =
result = CryptoRampParametersDto()
discard self.getProp("isRecurrent", result.isRecurrent)
if self.contains("destAddress"):
result.destinationAddress = some(self["destAddress"].getStr())
if self.contains("chainID"):
result.chainID = some(self["chainID"].getInt())
if self.contains("symbol"):
result.symbol = some(self["symbol"].getStr())

View File

@ -0,0 +1,78 @@
import NimQml, sequtils, sugar, chronicles, json
import app/core/[main]
import app/core/signals/types
import app/core/tasks/[qt, threadpool]
import ./dto
export dto
const SIGNAL_CRYPTO_RAMP_PROVIDERS_READY* = "cryptoRampProvidersReady"
const SIGNAL_CRYPTO_RAMP_URL_READY* = "cryptoRampUrlReady"
type
CryptoRampProvidersArgs* = ref object of Args
data*: seq[CryptoRampDto]
type
CryptoRampUrlArgs* = ref object of Args
uuid*: string
url*: string
logScope:
topics = "ramp-service"
include async_tasks
include app_service/common/json_utils
QtObject:
type Service* = ref object of QObject
events: EventEmitter
threadpool: ThreadPool
proc delete*(self: Service) =
self.QObject.delete
proc newService*(
events: EventEmitter,
threadpool: ThreadPool,
): Service =
new(result, delete)
result.QObject.setup
result.events = events
result.threadpool = threadpool
proc init*(self: Service) =
discard
proc onFetchCryptoRampProviders*(self: Service, response: string) {.slot.} =
let cryptoServices = parseJson(response){"result"}.getElems().map(x => x.toCryptoRampDto())
self.events.emit(SIGNAL_CRYPTO_RAMP_PROVIDERS_READY, CryptoRampProvidersArgs(data: cryptoServices))
proc fetchCryptoRampProviders*(self: Service) =
let arg = QObjectTaskArg(
tptr: getCryptoServicesTask,
vptr: cast[ByteAddress](self.vptr),
slot: "onFetchCryptoRampProviders",
)
self.threadpool.start(arg)
proc onFetchCryptoRampURL*(self: Service, response: string) {.slot.} =
let responseJson = parseJson(response)
let uuid = responseJson{"uuid"}.getStr()
let url = responseJson{"url"}.getStr()
self.events.emit(SIGNAL_CRYPTO_RAMP_URL_READY, CryptoRampUrlArgs(
uuid: uuid,
url: url,
))
proc fetchCryptoRampUrl*(self: Service, uuid: string, providerID: string, parameters: CryptoRampParametersDto) =
let arg = GetCryptoRampUrlTaskArg(
tptr: getCryptoRampURLTask,
vptr: cast[ByteAddress](self.vptr),
slot: "onFetchCryptoRampURL",
uuid: uuid,
providerID: providerID,
parameters: %parameters,
)
self.threadpool.start(arg)

View File

@ -46,6 +46,9 @@ proc `$`*(self: TokenDto): string =
image: {self.image}
]"""
proc key*(self: TokenDto): string =
result = self.address
type TokenSourceDto* = ref object of RootObj
name* {.serializedFieldName("name").}: string
tokens* {.serializedFieldName("tokens").}: seq[TokenDto]

View File

@ -11,7 +11,7 @@ import app/core/tasks/[qt, threadpool]
import app/core/signals/types
import app_service/common/cache
import app_service/common/wallet_constants
import ./dto, ./service_items
import ./dto, ./service_items, ./utils
export dto, service_items
@ -228,7 +228,7 @@ QtObject:
let tokenType = TokenType.ERC20
var updated = false
let unique_key = $token.chainID & token.address
let unique_key = token.flatModelKey()
if not any(self.flatTokenList, proc (x: TokenItem): bool = x.key == unique_key):
self.flatTokenList.add(TokenItem(
key: unique_key,
@ -244,7 +244,7 @@ QtObject:
self.flatTokenList.sort(cmpTokenItem)
updated = true
let token_by_symbol_key = token.address
let token_by_symbol_key = token.bySymbolModelKey()
if not any(self.tokenBySymbolList, proc (x: TokenBySymbolItem): bool = x.key == token_by_symbol_key):
self.tokenBySymbolList.add(TokenBySymbolItem(
key: token_by_symbol_key,
@ -298,7 +298,7 @@ QtObject:
# Remove tokens that are not on list of supported status networks
if supportedNetworkChains.contains(token.chainID):
# logic for building flat tokens list
let unique_key = $token.chainID & token.address
let unique_key = token.flatModelKey()
if flatTokensList.hasKey(unique_key):
flatTokensList[unique_key].sources.add(s.name)
else:
@ -321,8 +321,7 @@ QtObject:
# In case this is a community token the only param reliably unique is its address
# as there is always a rare case that a user can create two or more community token
# with same symbol and cannot be avoided
let token_by_symbol_key = if token.communityData.id.isEmptyOrWhitespace: token.symbol
else: token.address
let token_by_symbol_key = token.bySymbolModelKey()
if tokenBySymbolList.hasKey(token_by_symbol_key):
if not tokenBySymbolList[token_by_symbol_key].sources.contains(s.name):
tokenBySymbolList[token_by_symbol_key].sources.add(s.name)

View File

@ -0,0 +1,12 @@
import strutils
import ./dto
proc flatModelKey*(self: TokenDto): string =
result = $self.chainID & self.address
proc bySymbolModelKey*(self: TokenDto): string =
if self.communityData.id.isEmptyOrWhitespace:
result = self.symbol
else:
result = self.address

View File

@ -67,28 +67,6 @@ proc watchTransactionTask*(argEncoded: string) {.gcsafe, nimcall.} =
"isSuccessfull": false
}
type
GetCryptoServicesTaskArg* = ref object of QObjectTaskArg
discard
proc getCryptoServicesTask*(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetCryptoServicesTaskArg](argEncoded)
try:
let response = transactions.fetchCryptoServices()
if not response.error.isNil:
raise newException(ValueError, "Error fetching crypto services" & response.error.message)
arg.finish(%* {
"result": response.result,
})
except Exception as e:
error "Error fetching crypto services", message = e.msg
arg.finish(%* {
"result": @[],
})
type
FetchDecodedTxDataTaskArg* = ref object of QObjectTaskArg
txHash: string

View File

@ -1,53 +0,0 @@
import json, stew/shims/strformat
include ../../common/json_utils
type
CryptoRampDto* = ref object of RootObj
name*: string
description*: string
fees*: string
logoUrl*: string
siteUrl*: string
hostname*: string
recurrentSiteUrl*: string
proc newDto*(
name: string,
description: string,
fees: string,
logoUrl: string,
siteUrl: string,
hostname: string,
recurrentSiteUrl: string
): CryptoRampDto =
return CryptoRampDto(
name: name,
description: description,
fees: fees,
logoUrl: logoUrl,
siteUrl: siteUrl,
hostname: hostname,
recurrentSiteUrl: recurrentSiteUrl
)
proc `$`*(self: CryptoRampDto): string =
result = "CryptoRampDto("
result &= fmt"name:{self.name}, "
result &= fmt"description:{self.description}, "
result &= fmt"fees:{self.fees}, "
result &= fmt"logoUrl:{self.logoUrl}, "
result &= fmt"siteUrl:{self.siteUrl}, "
result &= fmt"hostname:{self.hostname}"
result &= fmt"recurrentSiteUrl:{self.recurrentSiteUrl}"
result &= ")"
proc toCryptoRampDto*(jsonObj: JsonNode): CryptoRampDto =
result = CryptoRampDto()
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("description", result.description)
discard jsonObj.getProp("fees", result.fees)
discard jsonObj.getProp("logoUrl", result.logoUrl)
discard jsonObj.getProp("siteUrl", result.siteUrl)
discard jsonObj.getProp("hostname", result.hostname)
discard jsonObj.getProp("recurrentSiteUrl", result.recurrentSiteUrl)

View File

@ -24,7 +24,6 @@ import app_service/service/eth/dto/[coder, method_dto]
import ./dto as transaction_dto
import ./dtoV2
import ./dto_conversion
import ./cryptoRampDto
import app_service/service/eth/utils as eth_utils
@ -42,7 +41,6 @@ const SIGNAL_TRANSACTION_SENT* = "transactionSent"
const SIGNAL_SUGGESTED_ROUTES_READY* = "suggestedRoutesReady"
const SIGNAL_HISTORY_NON_ARCHIVAL_NODE* = "historyNonArchivalNode"
const SIGNAL_HISTORY_ERROR* = "historyError"
const SIGNAL_CRYPTO_SERVICES_READY* = "cryptoServicesReady"
const SIGNAL_TRANSACTION_DECODED* = "transactionDecoded"
const SIGNAL_OWNER_TOKEN_SENT* = "ownerTokenSent"
const SIGNAL_TRANSACTION_SENDING_COMPLETE* = "transactionSendingComplete"
@ -137,9 +135,6 @@ type
errCode*: string
errDescription*: string
type
CryptoServicesArgs* = ref object of Args
data*: seq[CryptoRampDto]
type
TransactionDecodedArgs* = ref object of Args
dataDecoded*: string
@ -697,18 +692,6 @@ QtObject:
except CatchableError as e:
error "suggestedRoutes", exception=e.msg
proc onFetchCryptoServices*(self: Service, response: string) {.slot.} =
let cryptoServices = parseJson(response){"result"}.getElems().map(x => x.toCryptoRampDto())
self.events.emit(SIGNAL_CRYPTO_SERVICES_READY, CryptoServicesArgs(data: cryptoServices))
proc fetchCryptoServices*(self: Service) =
let arg = GetCryptoServicesTaskArg(
tptr: getCryptoServicesTask,
vptr: cast[ByteAddress](self.vptr),
slot: "onFetchCryptoServices",
)
self.threadpool.start(arg)
proc getEstimatedTime*(self: Service, chainId: int, maxFeePerGas: string): EstimatedTime =
try:
let response = backend.getTransactionEstimatedTime(chainId, maxFeePerGas).result.getInt

14
src/backend/ramp.nim Normal file
View File

@ -0,0 +1,14 @@
import json
import ./core as core
import ./response_type
export response_type
import ../app_service/service/ramp/dto
proc fetchCryptoRampProviders*(): RpcResponse[JsonNode] =
result = core.callPrivateRPC("wallet_getCryptoOnRamps", %* [])
proc fetchCryptoRampUrl*(providerID: string, parameters: CryptoRampParametersDto): RpcResponse[JsonNode] =
let payload = %* [providerID, parameters]
result = core.callPrivateRPC("wallet_getCryptoOnRampURL", payload)

View File

@ -82,9 +82,6 @@ proc getTransfersByAddress*(chainId: int, address: string, toBlock: Uint256, lim
proc getTransactionReceipt*(chainId: int, transactionHash: string): RpcResponse[JsonNode] =
core.callPrivateRPCWithChainId("eth_getTransactionReceipt", chainId, %* [transactionHash])
proc fetchCryptoServices*(): RpcResponse[JsonNode] =
result = core.callPrivateRPC("wallet_getCryptoOnRamps", %* [])
proc createMultiTransaction*(multiTransactionCommand: MultiTransactionCommandDto, data: seq[TransactionBridgeDto], password: string): RpcResponse[JsonNode] =
let payload = %* [multiTransactionCommand, data, password]
result = core.callPrivateRPC("wallet_createMultiTransaction", payload)

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 48ebe24f8e986c174e8e933404b81a7d6a3beb3e
Subproject commit b9d083c6d51befb85978ee3b4927c90bcf092625