feat(@desktop/stickers): support buying stickers if profile keypair is migrated to a keycard
Closes part 1 of #12556
This commit is contained in:
parent
82a829de0c
commit
a057e93901
|
@ -220,7 +220,8 @@ proc newModule*[T](
|
||||||
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService,
|
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService,
|
||||||
networkService, keycardService, keychainService, tokenService
|
networkService, keycardService, keychainService, tokenService
|
||||||
)
|
)
|
||||||
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService, tokenService)
|
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService,
|
||||||
|
networkService, tokenService, keycardService)
|
||||||
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
||||||
messageService, chatService, communityService)
|
messageService, chatService, communityService)
|
||||||
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService,
|
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService,
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import Tables, stint, json
|
import Tables, os, uuids, stint, json
|
||||||
|
|
||||||
import ./io_interface
|
import ./io_interface
|
||||||
|
|
||||||
import ../../../core/eventemitter
|
import app/core/eventemitter
|
||||||
import ../../../../app_service/service/stickers/service as stickers_service
|
import app_service/service/node/service as node_service
|
||||||
import ../../../../app_service/service/token/service
|
import app_service/service/stickers/service as stickers_service
|
||||||
import ../../../../app_service/service/settings/service as settings_service
|
import app_service/service/token/service
|
||||||
import ../../../../app_service/service/network/service as network_service
|
import app_service/service/settings/service as settings_service
|
||||||
import ../../../../app_service/service/eth/utils as eth_utils
|
import app_service/service/network/service as network_service
|
||||||
import ../../../../app_service/service/wallet_account/service as wallet_account_service
|
import app_service/service/eth/utils as eth_utils
|
||||||
import ../../../../app_service/service/token/service as token_service
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
import ../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
import app_service/service/token/service as token_service
|
||||||
|
import app_service/service/keycard/service as keycard_service
|
||||||
|
import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||||
|
|
||||||
const UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER* = "StickersSection-TransactionModule"
|
const UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER* = "StickersSection-TransactionModule"
|
||||||
|
|
||||||
|
@ -23,6 +25,8 @@ type
|
||||||
networkService: network_service.Service
|
networkService: network_service.Service
|
||||||
walletAccountService: wallet_account_service.Service
|
walletAccountService: wallet_account_service.Service
|
||||||
tokenService: token_service.Service
|
tokenService: token_service.Service
|
||||||
|
keycardService: keycard_service.Service
|
||||||
|
connectionKeycardResponse: UUID
|
||||||
disconnected: bool
|
disconnected: bool
|
||||||
|
|
||||||
proc newController*(
|
proc newController*(
|
||||||
|
@ -33,6 +37,7 @@ proc newController*(
|
||||||
walletAccountService: wallet_account_service.Service,
|
walletAccountService: wallet_account_service.Service,
|
||||||
networkService: network_service.Service,
|
networkService: network_service.Service,
|
||||||
tokenService: token_service.Service,
|
tokenService: token_service.Service,
|
||||||
|
keycardService: keycard_service.Service
|
||||||
): Controller =
|
): Controller =
|
||||||
result = Controller()
|
result = Controller()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
|
@ -42,6 +47,7 @@ proc newController*(
|
||||||
result.networkService = networkService
|
result.networkService = networkService
|
||||||
result.walletAccountService = walletAccountService
|
result.walletAccountService = walletAccountService
|
||||||
result.tokenService = tokenService
|
result.tokenService = tokenService
|
||||||
|
result.keycardService = keycardService
|
||||||
result.disconnected = false
|
result.disconnected = false
|
||||||
|
|
||||||
proc delete*(self: Controller) =
|
proc delete*(self: Controller) =
|
||||||
|
@ -90,14 +96,23 @@ proc init*(self: Controller) =
|
||||||
let args = SharedKeycarModuleArgs(e)
|
let args = SharedKeycarModuleArgs(e)
|
||||||
if args.uniqueIdentifier != UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER:
|
if args.uniqueIdentifier != UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER:
|
||||||
return
|
return
|
||||||
self.delegate.onUserAuthenticated(args.password)
|
self.delegate.onKeypairAuthenticated(args.password, args.pin)
|
||||||
|
|
||||||
self.events.on(SIGNAL_STICKER_PACK_INSTALLED) do(e: Args):
|
self.events.on(SIGNAL_STICKER_PACK_INSTALLED) do(e: Args):
|
||||||
let args = StickerPackInstalledArgs(e)
|
let args = StickerPackInstalledArgs(e)
|
||||||
self.delegate.onStickerPackInstalled(args.packId)
|
self.delegate.onStickerPackInstalled(args.packId)
|
||||||
|
|
||||||
proc buy*(self: Controller, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): StickerBuyResultArgs =
|
proc prepareTxForBuyingStickers*(self: Controller, chainId: int, packId: string, address: string, gas: string, gasPrice: string,
|
||||||
self.stickerService.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool): JsonNode =
|
||||||
|
return self.stickerService.prepareTxForBuyingStickers(chainId, packId, address, gas, gasPrice, maxPriorityFeePerGas,
|
||||||
|
maxFeePerGas, eip1559Enabled)
|
||||||
|
|
||||||
|
proc signBuyingStickersTxLocally*(self: Controller, data, account, hashedPasssword: string): string =
|
||||||
|
return self.stickerService.signBuyingStickersTxLocally(data, account, hashedPasssword)
|
||||||
|
|
||||||
|
proc sendBuyingStickersTxWithSignatureAndWatch*(self: Controller, chainId: int, txData: JsonNode, packId: string,
|
||||||
|
signature: string): StickerBuyResultArgs =
|
||||||
|
return self.stickerService.sendBuyingStickersTxWithSignatureAndWatch(chainId, txData, packId, signature)
|
||||||
|
|
||||||
proc getRecentStickers*(self: Controller): seq[StickerDto] =
|
proc getRecentStickers*(self: Controller): seq[StickerDto] =
|
||||||
return self.stickerService.getRecentStickers()
|
return self.stickerService.getRecentStickers()
|
||||||
|
@ -152,6 +167,9 @@ proc getSNTBalance*(self: Controller): string =
|
||||||
proc getWalletDefaultAddress*(self: Controller): string =
|
proc getWalletDefaultAddress*(self: Controller): string =
|
||||||
return self.walletAccountService.getWalletAccount(0).address
|
return self.walletAccountService.getWalletAccount(0).address
|
||||||
|
|
||||||
|
proc getKeypairByAccountAddress*(self: Controller, address: string): KeypairDto =
|
||||||
|
return self.walletAccountService.getKeypairByAccountAddress(address)
|
||||||
|
|
||||||
proc getCurrentCurrency*(self: Controller): string =
|
proc getCurrentCurrency*(self: Controller): string =
|
||||||
return self.settingsService.getCurrency()
|
return self.settingsService.getCurrency()
|
||||||
|
|
||||||
|
@ -174,7 +192,31 @@ proc getStatusToken*(self: Controller): string =
|
||||||
}
|
}
|
||||||
return $jsonObj
|
return $jsonObj
|
||||||
|
|
||||||
proc authenticateUser*(self: Controller, keyUid = "") =
|
proc authenticate*(self: Controller, keyUid = "") =
|
||||||
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER,
|
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER,
|
||||||
keyUid: keyUid)
|
keyUid: keyUid)
|
||||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||||
|
|
||||||
|
proc disconnectKeycardReponseSignal(self: Controller) =
|
||||||
|
self.events.disconnect(self.connectionKeycardResponse)
|
||||||
|
|
||||||
|
proc connectKeycardReponseSignal(self: Controller) =
|
||||||
|
self.connectionKeycardResponse = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
|
||||||
|
let args = KeycardLibArgs(e)
|
||||||
|
self.disconnectKeycardReponseSignal()
|
||||||
|
let currentFlow = self.keycardService.getCurrentFlow()
|
||||||
|
if currentFlow != KCSFlowType.Sign:
|
||||||
|
self.delegate.onTransactionSigned("", KeycardEvent())
|
||||||
|
return
|
||||||
|
self.delegate.onTransactionSigned(args.flowType, args.flowEvent)
|
||||||
|
|
||||||
|
proc cancelCurrentFlow*(self: Controller) =
|
||||||
|
self.keycardService.cancelCurrentFlow()
|
||||||
|
# in most cases we're running another flow after canceling the current one,
|
||||||
|
# this way we're giving to the keycard some time to cancel the current flow
|
||||||
|
sleep(200)
|
||||||
|
|
||||||
|
proc runSignFlow*(self: Controller, pin, bip44Path, txHash: string) =
|
||||||
|
self.cancelCurrentFlow()
|
||||||
|
self.connectKeycardReponseSignal()
|
||||||
|
self.keycardService.startSignFlow(bip44Path, txHash, pin)
|
|
@ -1,6 +1,9 @@
|
||||||
import Tables, stint
|
import Tables, stint
|
||||||
import ./item
|
import ./item
|
||||||
import ../../../../app_service/service/stickers/service as stickers_service
|
|
||||||
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
import app_service/service/stickers/service as stickers_service
|
||||||
|
from app_service/service/keycard/service import KeycardEvent
|
||||||
|
|
||||||
type
|
type
|
||||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||||
|
@ -109,5 +112,8 @@ method stickerTransactionConfirmed*(self: AccessInterface, trxType: string, pack
|
||||||
method stickerTransactionReverted*(self: AccessInterface, trxType: string, packID: string, transactionHash: string) {.base.} =
|
method stickerTransactionReverted*(self: AccessInterface, trxType: string, packID: string, transactionHash: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
method onKeypairAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onTransactionSigned*(self: AccessInterface, keycardFlowType: string, keycardEvent: KeycardEvent) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
|
@ -1,14 +1,18 @@
|
||||||
import NimQml, Tables, stint, sugar, sequtils, json, strutils, strformat, parseutils
|
import NimQml, Tables, stint, sugar, sequtils, json, strutils, strformat, parseutils, chronicles
|
||||||
import ./io_interface, ./view, ./controller, ./item, ./models/sticker_pack_list
|
import ./io_interface, ./view, ./controller, ./item, ./models/sticker_pack_list
|
||||||
import ../io_interface as delegate_interface
|
import ../io_interface as delegate_interface
|
||||||
import ../../../global/global_singleton
|
import app/global/global_singleton
|
||||||
import ../../../core/eventemitter
|
import app/core/eventemitter
|
||||||
import ../../../../app_service/service/stickers/service as stickers_service
|
import app_service/service/stickers/service as stickers_service
|
||||||
import ../../../../app_service/service/settings/service as settings_service
|
import app_service/service/settings/service as settings_service
|
||||||
import ../../../../app_service/service/network/service as network_service
|
import app_service/service/network/service as network_service
|
||||||
import ../../../../app_service/common/conversion as service_conversion
|
import app_service/common/conversion as service_conversion
|
||||||
import ../../../../app_service/service/wallet_account/service as wallet_account_service
|
import app_service/common/utils as common_utils
|
||||||
import ../../../../app_service/service/token/service as token_service
|
import app_service/common/wallet_constants as common_wallet_constants
|
||||||
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
import app_service/service/token/service as token_service
|
||||||
|
import app_service/service/keycard/service as keycard_service
|
||||||
|
import app_service/service/keycard/constants as keycard_constants
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
|
@ -18,12 +22,13 @@ const cancelledRequest* = "cancelled"
|
||||||
type TmpBuyStickersTransactionDetails = object
|
type TmpBuyStickersTransactionDetails = object
|
||||||
packId: string
|
packId: string
|
||||||
address: string
|
address: string
|
||||||
|
addressPath: string
|
||||||
gas: string
|
gas: string
|
||||||
gasPrice: string
|
gasPrice: string
|
||||||
maxPriorityFeePerGas: string
|
maxPriorityFeePerGas: string
|
||||||
maxFeePerGas: string
|
maxFeePerGas: string
|
||||||
eip1559Enabled: bool
|
eip1559Enabled: bool
|
||||||
|
txData: JsonNode
|
||||||
|
|
||||||
type
|
type
|
||||||
Module* = ref object of io_interface.AccessInterface
|
Module* = ref object of io_interface.AccessInterface
|
||||||
|
@ -42,12 +47,14 @@ proc newModule*(
|
||||||
walletAccountService: wallet_account_service.Service,
|
walletAccountService: wallet_account_service.Service,
|
||||||
networkService: network_service.Service,
|
networkService: network_service.Service,
|
||||||
tokenService: token_service.Service,
|
tokenService: token_service.Service,
|
||||||
|
keycardService: keycard_service.Service
|
||||||
): Module =
|
): Module =
|
||||||
result = Module()
|
result = Module()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.view = newView(result)
|
result.view = newView(result)
|
||||||
result.viewVariant = newQVariant(result.view)
|
result.viewVariant = newQVariant(result.view)
|
||||||
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService, networkService, tokenService)
|
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService,
|
||||||
|
networkService, tokenService, keycardService)
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
|
|
||||||
singletonInstance.engine.setRootContextProperty("stickersModule", result.viewVariant)
|
singletonInstance.engine.setRootContextProperty("stickersModule", result.viewVariant)
|
||||||
|
@ -55,6 +62,13 @@ proc newModule*(
|
||||||
method delete*(self: Module) =
|
method delete*(self: Module) =
|
||||||
self.view.delete
|
self.view.delete
|
||||||
|
|
||||||
|
proc clear(self: Module) =
|
||||||
|
self.tmpBuyStickersTransactionDetails = TmpBuyStickersTransactionDetails()
|
||||||
|
|
||||||
|
proc finish(self: Module, chainId: int, txHash: string, error: string) =
|
||||||
|
self.clear()
|
||||||
|
self.view.transactionWasSent(chainId, txHash, error)
|
||||||
|
|
||||||
method load*(self: Module) =
|
method load*(self: Module) =
|
||||||
self.controller.init()
|
self.controller.init()
|
||||||
let signingPhrase = self.controller.getSigningPhrase()
|
let signingPhrase = self.controller.getSigningPhrase()
|
||||||
|
@ -76,53 +90,100 @@ method authenticateAndBuy*(self: Module, packId: string, address: string, gas: s
|
||||||
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||||
self.tmpBuyStickersTransactionDetails.maxFeePerGas = maxFeePerGas
|
self.tmpBuyStickersTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||||
self.tmpBuyStickersTransactionDetails.eip1559Enabled = eip1559Enabled
|
self.tmpBuyStickersTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||||
|
self.tmpBuyStickersTransactionDetails.txData = nil
|
||||||
|
|
||||||
if singletonInstance.userProfile.getIsKeycardUser():
|
let kp = self.controller.getKeypairByAccountAddress(address)
|
||||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
if kp.migratedToKeycard():
|
||||||
self.controller.authenticateUser(keyUid)
|
let accounts = kp.accounts.filter(acc => cmpIgnoreCase(acc.address, address) == 0)
|
||||||
|
if accounts.len != 1:
|
||||||
|
error "cannot resolve selected account to send from among known keypair accounts"
|
||||||
|
return
|
||||||
|
self.tmpBuyStickersTransactionDetails.addressPath = accounts[0].path
|
||||||
|
self.controller.authenticate(kp.keyUid)
|
||||||
else:
|
else:
|
||||||
self.controller.authenticateUser()
|
self.controller.authenticate()
|
||||||
|
|
||||||
##################################
|
proc sendBuyingStickersTxWithSignatureAndWatch(self: Module, signature: string) =
|
||||||
## Do Not Delete
|
if self.tmpBuyStickersTransactionDetails.txData.isNil:
|
||||||
##
|
let errMsg = "unexpected error while sending buying stickers tx"
|
||||||
## Once we start with signing a transactions we shold check if the address we want to send a transaction from is migrated
|
error "error", msg=errMsg, methodName="sendBuyingStickersTxWithSignatureAndWatch"
|
||||||
## or not. In case it's not we should just authenticate logged in user, otherwise we should use one of the keycards that
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
## address (key pair) is migrated to and sign the transaction using it.
|
return
|
||||||
##
|
|
||||||
## The code bellow is an example how we can achieve that in future, when we start with signing transactions.
|
|
||||||
##
|
|
||||||
## let acc = self.controller.getAccountByAddress(from_addr)
|
|
||||||
## if acc.isNil:
|
|
||||||
## echo "error: selected account to send a transaction from is not known"
|
|
||||||
## return
|
|
||||||
## let keyPair = self.controller.getKeycardsWithSameKeyUid(acc.keyUid)
|
|
||||||
## if keyPair.len == 0:
|
|
||||||
## self.controller.authenticateUser()
|
|
||||||
## else:
|
|
||||||
## self.controller.authenticateUser(acc.keyUid, acc.path)
|
|
||||||
##
|
|
||||||
##################################
|
|
||||||
|
|
||||||
method onUserAuthenticated*(self: Module, password: string) =
|
let response = self.controller.sendBuyingStickersTxWithSignatureAndWatch(
|
||||||
|
self.getChainIdForStickers(),
|
||||||
|
self.tmpBuyStickersTransactionDetails.txData,
|
||||||
|
self.tmpBuyStickersTransactionDetails.packId,
|
||||||
|
signature
|
||||||
|
)
|
||||||
|
|
||||||
|
if not response.error.isEmptyOrWhitespace():
|
||||||
|
error "sending buying stickers tx failed", errMsg=response.error, methodName="sendBuyingStickersTxWithSignatureAndWatch"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = response.error)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.view.stickerPacks.updateStickerPackInList(self.tmpBuyStickersTransactionDetails.packId, installed = false, pending = true)
|
||||||
|
self.finish(response.chainId, response.txHash, response.error)
|
||||||
|
|
||||||
|
method onKeypairAuthenticated*(self: Module, password: string, pin: string) =
|
||||||
if password.len == 0:
|
if password.len == 0:
|
||||||
let response = %* {"success": false, "error": cancelledRequest}
|
self.finish(chainId = 0, txHash = "", error = cancelledRequest)
|
||||||
self.view.transactionWasSent(chainId = 0, txHash = "", error = cancelledRequest)
|
return
|
||||||
else:
|
|
||||||
let response = self.controller.buy(
|
let chainId = self.getChainIdForStickers()
|
||||||
|
let txDataJson = self.controller.prepareTxForBuyingStickers(
|
||||||
|
chainId,
|
||||||
self.tmpBuyStickersTransactionDetails.packId,
|
self.tmpBuyStickersTransactionDetails.packId,
|
||||||
self.tmpBuyStickersTransactionDetails.address,
|
self.tmpBuyStickersTransactionDetails.address,
|
||||||
self.tmpBuyStickersTransactionDetails.gas,
|
self.tmpBuyStickersTransactionDetails.gas,
|
||||||
self.tmpBuyStickersTransactionDetails.gasPrice,
|
self.tmpBuyStickersTransactionDetails.gasPrice,
|
||||||
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas,
|
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas,
|
||||||
self.tmpBuyStickersTransactionDetails.maxFeePerGas,
|
self.tmpBuyStickersTransactionDetails.maxFeePerGas,
|
||||||
password,
|
|
||||||
self.tmpBuyStickersTransactionDetails.eip1559Enabled
|
self.tmpBuyStickersTransactionDetails.eip1559Enabled
|
||||||
)
|
)
|
||||||
if response.error.isEmptyOrWhitespace():
|
|
||||||
self.view.stickerPacks.updateStickerPackInList(self.tmpBuyStickersTransactionDetails.packId, installed = false,
|
if txDataJson.isNil or
|
||||||
pending = true)
|
txDataJson.kind != JsonNodeKind.JObject or
|
||||||
self.view.transactionWasSent(chainId = response.chainId, txHash = response.txHash, error = response.error)
|
not txDataJson.hasKey("txArgs") or
|
||||||
|
not txDataJson.hasKey("messageToSign"):
|
||||||
|
let errMsg = "unexpected response format preparing tx for buying stickers"
|
||||||
|
error "error", msg=errMsg, methodName="onKeypairAuthenticated"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
|
return
|
||||||
|
|
||||||
|
var txToBeSigned = txDataJson["messageToSign"].getStr
|
||||||
|
if txToBeSigned.len != common_wallet_constants.TX_HASH_LEN_WITH_PREFIX:
|
||||||
|
let errMsg = "unexpected tx hash length"
|
||||||
|
error "error", msg=errMsg, methodName="onKeypairAuthenticated"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.tmpBuyStickersTransactionDetails.txData = txDataJson["txArgs"]
|
||||||
|
|
||||||
|
if txDataJson.hasKey("signOnKeycard") and txDataJson["signOnKeycard"].getBool:
|
||||||
|
if pin.len != PINLengthForStatusApp:
|
||||||
|
let errMsg = "cannot proceed with keycard signing, unexpected pin"
|
||||||
|
error "error", msg=errMsg, methodName="onKeypairAuthenticated"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
|
return
|
||||||
|
var txForKcFlow = txToBeSigned
|
||||||
|
if txForKcFlow.startsWith("0x"):
|
||||||
|
txForKcFlow = txForKcFlow[2..^1]
|
||||||
|
self.controller.runSignFlow(pin, self.tmpBuyStickersTransactionDetails.addressPath, txForKcFlow)
|
||||||
|
return
|
||||||
|
|
||||||
|
var finalPassword = password
|
||||||
|
if pin.len == 0:
|
||||||
|
finalPassword = common_utils.hashPassword(password)
|
||||||
|
|
||||||
|
let signature = self.controller.signBuyingStickersTxLocally(txToBeSigned, self.tmpBuyStickersTransactionDetails.address, finalPassword)
|
||||||
|
if signature.len == 0:
|
||||||
|
let errMsg = "couldn't sign tx locally"
|
||||||
|
error "error", msg=errMsg, methodName="onKeypairAuthenticated"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.sendBuyingStickersTxWithSignatureAndWatch(signature)
|
||||||
|
|
||||||
method obtainMarketStickerPacks*(self: Module) =
|
method obtainMarketStickerPacks*(self: Module) =
|
||||||
self.controller.obtainMarketStickerPacks()
|
self.controller.obtainMarketStickerPacks()
|
||||||
|
@ -258,3 +319,12 @@ method stickerTransactionConfirmed*(self: Module, trxType: string, packID: strin
|
||||||
method stickerTransactionReverted*(self: Module, trxType: string, packID: string, transactionHash: string) =
|
method stickerTransactionReverted*(self: Module, trxType: string, packID: string, transactionHash: string) =
|
||||||
self.view.stickerPacks.updateStickerPackInList(packID, installed = false, pending = false)
|
self.view.stickerPacks.updateStickerPackInList(packID, installed = false, pending = false)
|
||||||
self.view.emitTransactionCompletedSignal(false, transactionHash, packID, trxType)
|
self.view.emitTransactionCompletedSignal(false, transactionHash, packID, trxType)
|
||||||
|
|
||||||
|
method onTransactionSigned*(self: Module, keycardFlowType: string, keycardEvent: KeycardEvent) =
|
||||||
|
if keycardFlowType != keycard_constants.ResponseTypeValueKeycardFlowResult:
|
||||||
|
let errMsg = "unexpected error while keycard signing transaction"
|
||||||
|
error "error", msg=errMsg, methodName="onTransactionSigned"
|
||||||
|
self.finish(chainId = 0, txHash = "", error = errMsg)
|
||||||
|
return
|
||||||
|
let signature = "0x" & keycardEvent.txSignature.r & keycardEvent.txSignature.s & keycardEvent.txSignature.v
|
||||||
|
self.sendBuyingStickersTxWithSignatureAndWatch(signature)
|
|
@ -1,3 +1,7 @@
|
||||||
const ETH_TRANSACTION_TYPE* = "eth"
|
const
|
||||||
const ERC20_TRANSACTION_TYPE* = "erc20"
|
ETH_TRANSACTION_TYPE* = "eth"
|
||||||
const ERC721_TRANSACTION_TYPE* = "erc721"
|
ERC20_TRANSACTION_TYPE* = "erc20"
|
||||||
|
ERC721_TRANSACTION_TYPE* = "erc721"
|
||||||
|
|
||||||
|
TX_HASH_LEN* = 32 * 2
|
||||||
|
TX_HASH_LEN_WITH_PREFIX* = TX_HASH_LEN + 2
|
|
@ -13,6 +13,8 @@ import ../../../backend/chat as status_chat
|
||||||
import ../../../backend/response_type
|
import ../../../backend/response_type
|
||||||
import ../../../backend/eth as status_eth
|
import ../../../backend/eth as status_eth
|
||||||
import ../../../backend/backend as status_go_backend
|
import ../../../backend/backend as status_go_backend
|
||||||
|
import ../../../backend/wallet_connect as status_wallet_connect
|
||||||
|
import ../../../backend/wallet as status_wallet
|
||||||
import ./dto/stickers
|
import ./dto/stickers
|
||||||
import ../ens/utils as ens_utils
|
import ../ens/utils as ens_utils
|
||||||
import ../token/service as token_service
|
import ../token/service as token_service
|
||||||
|
@ -181,68 +183,10 @@ QtObject:
|
||||||
else:
|
else:
|
||||||
self.revertTransaction($PendingTransactionTypeDto.BuyStickerPack, receivedData.data, receivedData.transactionHash)
|
self.revertTransaction($PendingTransactionTypeDto.BuyStickerPack, receivedData.data, receivedData.transactionHash)
|
||||||
|
|
||||||
proc buildTransaction*(
|
|
||||||
source: Address,
|
|
||||||
gas = "",
|
|
||||||
gasPrice = "",
|
|
||||||
isEIP1559Enabled = false,
|
|
||||||
maxPriorityFeePerGas = "",
|
|
||||||
maxFeePerGas = "",
|
|
||||||
): TransactionDataDto =
|
|
||||||
result = TransactionDataDto(
|
|
||||||
source: source,
|
|
||||||
value: (0.u256).some,
|
|
||||||
gas: (if gas.isEmptyOrWhitespace: Quantity.none else: Quantity(cast[uint64](parseFloat(gas).toUInt64)).some)
|
|
||||||
)
|
|
||||||
if isEIP1559Enabled:
|
|
||||||
result.maxPriorityFeePerGas = if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxPriorityFeePerGas)).some
|
|
||||||
result.maxFeePerGas = (if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxFeePerGas)).some)
|
|
||||||
else:
|
|
||||||
result.gasPrice = (if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some)
|
|
||||||
|
|
||||||
proc getStatusToken*(self: Service): TokenDto =
|
proc getStatusToken*(self: Service): TokenDto =
|
||||||
let networkDto = self.networkService.getNetworkForStickers()
|
let networkDto = self.networkService.getNetworkForStickers()
|
||||||
|
|
||||||
return self.tokenService.findTokenBySymbol(networkDto.chainId, networkDto.sntSymbol())
|
return self.tokenService.findTokenBySymbol(networkDto.chainId, networkDto.sntSymbol())
|
||||||
|
|
||||||
proc buyPack*(self: Service, packId: string, address, gas, gasPrice: string, eip1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): tuple[txHash: string, error: string] =
|
|
||||||
let
|
|
||||||
chainId = self.networkService.getNetworkForStickers().chainId
|
|
||||||
txData = buildTransaction(parseAddress(address), gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
|
||||||
try:
|
|
||||||
let transactionResponse = status_stickers.buy(chainId, %txData, packId, common_utils.hashPassword(password))
|
|
||||||
let transactionHash = transactionResponse.result.getStr()
|
|
||||||
let sntContract = self.getStatusToken()
|
|
||||||
self.transactionService.watchTransaction(
|
|
||||||
transactionHash,
|
|
||||||
address,
|
|
||||||
$sntContract.address,
|
|
||||||
$PendingTransactionTypeDto.BuyStickerPack,
|
|
||||||
packId,
|
|
||||||
chainId,
|
|
||||||
)
|
|
||||||
return (txHash: transactionHash, error: "")
|
|
||||||
except ValueError:
|
|
||||||
let message = getCurrentExceptionMsg()
|
|
||||||
var error = message
|
|
||||||
if message.contains("could not decrypt key with given password"):
|
|
||||||
error = "could not decrypt key with given password"
|
|
||||||
error "Error sending transaction", message
|
|
||||||
return (txHash: "", error: error)
|
|
||||||
except RpcException:
|
|
||||||
error "Error sending transaction", message = getCurrentExceptionMsg()
|
|
||||||
|
|
||||||
proc buy*(self: Service, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): StickerBuyResultArgs =
|
|
||||||
try:
|
|
||||||
status_utils.validateTransactionInput(address, address, "", "0", gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, "ok")
|
|
||||||
except Exception as e:
|
|
||||||
error "Error buying sticker pack", msg = e.msg
|
|
||||||
return StickerBuyResultArgs(chainId: 0, txHash: "", error: e.msg)
|
|
||||||
|
|
||||||
var (txHash, err) = self.buyPack(packId, address, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password)
|
|
||||||
|
|
||||||
return StickerBuyResultArgs(chainId: self.networkService.getNetworkForStickers().chainId, txHash: txHash, error: err)
|
|
||||||
|
|
||||||
proc setMarketStickerPacks*(self: Service, strickersJSON: string) {.slot.} =
|
proc setMarketStickerPacks*(self: Service, strickersJSON: string) {.slot.} =
|
||||||
let stickersResult = Json.decode(strickersJSON, tuple[packs: seq[StickerPackDto], error: string])
|
let stickersResult = Json.decode(strickersJSON, tuple[packs: seq[StickerPackDto], error: string])
|
||||||
|
|
||||||
|
@ -263,7 +207,6 @@ QtObject:
|
||||||
isPending: false
|
isPending: false
|
||||||
))
|
))
|
||||||
|
|
||||||
# TODO move this to be async
|
|
||||||
let pendingStickerPacksResponse = status_stickers.pending()
|
let pendingStickerPacksResponse = status_stickers.pending()
|
||||||
for (packID, stickerPackJson) in pendingStickerPacksResponse.result.pairs():
|
for (packID, stickerPackJson) in pendingStickerPacksResponse.result.pairs():
|
||||||
if self.marketStickerPacks.contains(packID): continue
|
if self.marketStickerPacks.contains(packID): continue
|
||||||
|
@ -453,3 +396,98 @@ QtObject:
|
||||||
|
|
||||||
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.address]).result
|
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.address]).result
|
||||||
return ens_utils.hex2Token(balances{account}{token.address}.getStr, token.decimals)
|
return ens_utils.hex2Token(balances{account}{token.address}.getStr, token.decimals)
|
||||||
|
|
||||||
|
# proc prepareTxForBuyingStickers*(self: Service, chainId: int, packId: string, address: string): JsonNode =
|
||||||
|
proc prepareTxForBuyingStickers*(self: Service, chainId: int, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
|
||||||
|
maxFeePerGas: string, eip1559Enabled: bool): JsonNode =
|
||||||
|
try:
|
||||||
|
var prepareTxResponse = status_stickers.prepareTxForBuyingStickers(chainId, address, packId)
|
||||||
|
if not prepareTxResponse.error.isNil:
|
||||||
|
error "error occurred", procName="prepareTxForBuyingStickers", msg = prepareTxResponse.error.message
|
||||||
|
return
|
||||||
|
|
||||||
|
prepareTxResponse.result["gas"] = %* (if gas.isEmptyOrWhitespace: Quantity.none else: Quantity(cast[uint64](parseFloat(gas).toUInt64)).some)
|
||||||
|
if eip1559Enabled:
|
||||||
|
let maxPriorityFeePerGasFinal = if maxPriorityFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxPriorityFeePerGas)).some
|
||||||
|
let maxFeePerGasFinal = if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxFeePerGas)).some
|
||||||
|
prepareTxResponse.result["maxPriorityFeePerGas"] = %* ("0x" & maxPriorityFeePerGasFinal.unsafeGet.toHex)
|
||||||
|
prepareTxResponse.result["maxFeePerGas"] = %* ("0x" & maxFeePerGasFinal.unsafeGet.toHex)
|
||||||
|
else:
|
||||||
|
let gasPriceFinal = if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some
|
||||||
|
prepareTxResponse.result["gasPrice"] = %* ("0x" & gasPriceFinal.unsafeGet.toHex.stripLeadingZeros)
|
||||||
|
|
||||||
|
var buildTxResponse: JsonNode
|
||||||
|
let err = status_wallet.buildTransaction(buildTxResponse, chainId, $prepareTxResponse.result)
|
||||||
|
if err.len > 0:
|
||||||
|
error "error occurred", procName="prepareTxForBuyingStickers", msg = err
|
||||||
|
return
|
||||||
|
|
||||||
|
return buildTxResponse
|
||||||
|
except Exception as e:
|
||||||
|
error "error occurred", procName="prepareTxForBuyingStickers", msg = e.msg
|
||||||
|
|
||||||
|
proc signBuyingStickersTxLocally*(self: Service, data, account, hashedPasssword: string): string =
|
||||||
|
try:
|
||||||
|
var response: JsonNode
|
||||||
|
let err = status_wallet.signMessage(response, data, account, hashedPasssword)
|
||||||
|
if err.len > 0 or response.isNil:
|
||||||
|
error "error occurred", procName="signBuyingStickersTxLocally", msg = err
|
||||||
|
return
|
||||||
|
return response.getStr()
|
||||||
|
except Exception as e:
|
||||||
|
error "error occurred", procName="signBuyingStickersTxLocally", msg = e.msg
|
||||||
|
|
||||||
|
proc sendBuyingStickersTxWithSignatureAndWatch*(self: Service, chainId: int, txData: JsonNode, packId: string,
|
||||||
|
signature: string): StickerBuyResultArgs =
|
||||||
|
result = StickerBuyResultArgs(chainId: chainId)
|
||||||
|
try:
|
||||||
|
if txData.isNil:
|
||||||
|
result.error = "txData is nil"
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
||||||
|
return
|
||||||
|
if not txData.hasKey("from") or txData["from"].getStr().len == 0:
|
||||||
|
result.error = "from address is empty"
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
||||||
|
return
|
||||||
|
if not txData.hasKey("to") or txData["to"].getStr().len == 0:
|
||||||
|
result.error = "to address is empty"
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
||||||
|
return
|
||||||
|
|
||||||
|
var finalSignature = signature
|
||||||
|
if finalSignature.startsWith("0x"):
|
||||||
|
finalSignature = finalSignature[2..^1]
|
||||||
|
|
||||||
|
var txResponse: JsonNode
|
||||||
|
let err = status_wallet.sendTransactionWithSignature(txResponse, chainId, $PendingTransactionTypeDto.BuyStickerPack,
|
||||||
|
$txData, finalSignature)
|
||||||
|
if err.len > 0 or txResponse.isNil:
|
||||||
|
result.error = err
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
||||||
|
return
|
||||||
|
|
||||||
|
let
|
||||||
|
transactionHash = txResponse.getStr()
|
||||||
|
fromAddress = txData["from"].getStr()
|
||||||
|
toAddress = txData["to"].getStr()
|
||||||
|
|
||||||
|
let addPendingResponse = status_stickers.addPending(chainId, packId)
|
||||||
|
if not addPendingResponse.error.isNil:
|
||||||
|
result.error = addPendingResponse.error.message
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
||||||
|
return
|
||||||
|
|
||||||
|
let sntContract = self.getStatusToken()
|
||||||
|
self.transactionService.watchTransaction(
|
||||||
|
transactionHash,
|
||||||
|
fromAddress,
|
||||||
|
toAddress,
|
||||||
|
$PendingTransactionTypeDto.BuyStickerPack,
|
||||||
|
packId,
|
||||||
|
chainId,
|
||||||
|
)
|
||||||
|
|
||||||
|
result.txHash = transactionHash
|
||||||
|
except Exception as e:
|
||||||
|
result.error = e.msg
|
||||||
|
error "error occurred", procName="sendBuyingStickersTxWithSignatureAndWatch", msg = result.error
|
|
@ -61,23 +61,6 @@ proc callPrivateRPC*(
|
||||||
}
|
}
|
||||||
return makePrivateRpcCall(methodName, inputJSON)
|
return makePrivateRpcCall(methodName, inputJSON)
|
||||||
|
|
||||||
proc signMessage*(rpcParams: string): string =
|
|
||||||
return $status_go.signMessage(rpcParams)
|
|
||||||
|
|
||||||
proc signTypedData*(data: string, address: string, password: string): string =
|
|
||||||
return $status_go.signTypedData(data, address, password)
|
|
||||||
|
|
||||||
proc sendTransaction*(chainId: int, inputJSON: string, password: string): RpcResponse[JsonNode]
|
|
||||||
{.raises: [RpcException, ValueError, Defect, SerializationError].} =
|
|
||||||
try:
|
|
||||||
var hashed_password = "0x" & $keccak_256.digest(password)
|
|
||||||
let rpcResponseRaw = status_go.sendTransactionWithChainId(chainId, inputJSON, hashed_password)
|
|
||||||
result = Json.decode(rpcResponseRaw, RpcResponse[JsonNode])
|
|
||||||
except Exception as e:
|
|
||||||
error "error sending tx", inputJSON, exception=e.msg
|
|
||||||
raise newException(RpcException, e.msg)
|
|
||||||
|
|
||||||
|
|
||||||
proc migrateKeyStoreDir*(account: string, hashedPassword: string, oldKeystoreDir: string, multiaccountKeystoreDir: string)
|
proc migrateKeyStoreDir*(account: string, hashedPassword: string, oldKeystoreDir: string, multiaccountKeystoreDir: string)
|
||||||
{.raises: [RpcException, ValueError, Defect, SerializationError].} =
|
{.raises: [RpcException, ValueError, Defect, SerializationError].} =
|
||||||
try:
|
try:
|
||||||
|
@ -85,5 +68,3 @@ proc migrateKeyStoreDir*(account: string, hashedPassword: string, oldKeystoreDir
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "error migrating keystore dir", account, exception=e.msg
|
error "error migrating keystore dir", account, exception=e.msg
|
||||||
raise newException(RpcException, e.msg)
|
raise newException(RpcException, e.msg)
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,6 @@ proc getNativeChainBalance*(chainId: int, address: string): RpcResponse[JsonNode
|
||||||
let payload = %* [address, "latest"]
|
let payload = %* [address, "latest"]
|
||||||
return core.callPrivateRPCWithChainId("eth_getBalance", chainId, payload)
|
return core.callPrivateRPCWithChainId("eth_getBalance", chainId, payload)
|
||||||
|
|
||||||
proc sendTransaction*(chainId: int, transactionData: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
||||||
core.sendTransaction(chainId, transactionData, password)
|
|
||||||
|
|
||||||
# This is the replacement of the `call` function
|
# This is the replacement of the `call` function
|
||||||
proc doEthCall*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc doEthCall*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
core.callPrivateRPC("eth_call", payload)
|
core.callPrivateRPC("eth_call", payload)
|
||||||
|
|
|
@ -11,6 +11,10 @@ proc pending*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
let payload = %* []
|
let payload = %* []
|
||||||
return core.callPrivateRPC("stickers_pending", payload)
|
return core.callPrivateRPC("stickers_pending", payload)
|
||||||
|
|
||||||
|
proc addPending*(chainId: int, packId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
let payload = %* [chainId, packId]
|
||||||
|
result = core.callPrivateRPC("stickers_addPending", payload)
|
||||||
|
|
||||||
proc installed*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc installed*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
let payload = %* []
|
let payload = %* []
|
||||||
return core.callPrivateRPC("stickers_installed", payload)
|
return core.callPrivateRPC("stickers_installed", payload)
|
||||||
|
@ -50,3 +54,7 @@ proc clearRecentStickers*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
proc removePending*(packId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc removePending*(packId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
let payload = %* [packId]
|
let payload = %* [packId]
|
||||||
return core.callPrivateRPC("stickers_removePending", payload)
|
return core.callPrivateRPC("stickers_removePending", payload)
|
||||||
|
|
||||||
|
proc prepareTxForBuyingStickers*(chainId: int, address: string, packId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
let payload = %* [chainId, address, packId]
|
||||||
|
result = core.callPrivateRPC("stickers_buyPrepareTx", payload)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
import json, json_serialization, logging
|
||||||
|
import core, response_type
|
||||||
|
from ./gen import rpc
|
||||||
|
import status_go
|
||||||
|
|
||||||
|
rpc(signMessage, "wallet"):
|
||||||
|
message: string
|
||||||
|
address: string
|
||||||
|
hashedPassword: string
|
||||||
|
|
||||||
|
rpc(buildTransaction, "wallet"):
|
||||||
|
chainId: int
|
||||||
|
sendTxArgsJson: string
|
||||||
|
|
||||||
|
rpc(sendTransactionWithSignature, "wallet"):
|
||||||
|
chainId: int
|
||||||
|
txType: string
|
||||||
|
sendTxArgsJson: string
|
||||||
|
signature: string
|
||||||
|
|
||||||
|
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||||
|
if not rpcResponse.error.isNil:
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc prepareResponse(resultOut: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string =
|
||||||
|
if isErrorResponse(rpcResponse):
|
||||||
|
return rpcResponse.error.message
|
||||||
|
if rpcResponse.result.isNil:
|
||||||
|
return "no result"
|
||||||
|
resultOut = rpcResponse.result
|
||||||
|
|
||||||
|
## Signs the provided message with the provided account using the provided hashed password, performs `crypto.Sign`
|
||||||
|
## `resultOut` represents a json object that contains the signature if the call was successful, or `nil`
|
||||||
|
## `message` is the message to sign
|
||||||
|
## `address` is the address to sign with
|
||||||
|
## `hashedPassword` is the hashed password to sign with
|
||||||
|
## returns the error message if any, or an empty string
|
||||||
|
proc signMessage*(resultOut: var JsonNode, message: string, address: string, hashedPassword: string): string =
|
||||||
|
try:
|
||||||
|
let response = signMessage(message, address, hashedPassword)
|
||||||
|
return prepareResponse(resultOut, response)
|
||||||
|
except Exception as e:
|
||||||
|
warn e.msg
|
||||||
|
return e.msg
|
||||||
|
|
||||||
|
|
||||||
|
## Builds the tx with the provided tx args and chain id
|
||||||
|
## `resultOut` represents a json object that corresponds to the status go `transfer.TxResponse` type, or `nil` if the call was unsuccessful
|
||||||
|
## `chainId` is the chain id of the network
|
||||||
|
## `txArgsJSON` is the json string of the tx, corresponds to the status go `transactions.SendTxArgs` type
|
||||||
|
## returns the error message if any, or an empty string
|
||||||
|
proc buildTransaction*(resultOut: var JsonNode, chainId: int, sendTxArgsJson: string): string =
|
||||||
|
try:
|
||||||
|
let response = buildTransaction(chainId, sendTxArgsJson)
|
||||||
|
return prepareResponse(resultOut, response)
|
||||||
|
except Exception as e:
|
||||||
|
warn e.msg
|
||||||
|
return e.msg
|
||||||
|
|
||||||
|
|
||||||
|
## Sends the tx with signature on provided chain, setting tx type
|
||||||
|
## `resultOut` represents a json object that contains the tx hash if the call was successful, or `nil`
|
||||||
|
## `chainId` is the chain id of the network
|
||||||
|
## `txType` is the type of the tx, corresponds to the status go `transactions.PendingTrxType` type
|
||||||
|
## `txArgsJSON` is the json string of the tx, corresponding to the status go `transactions.SendTxArgs` type
|
||||||
|
## `signature` is the signature of the tx
|
||||||
|
## returns the error message if any, or an empty string
|
||||||
|
proc sendTransactionWithSignature*(resultOut: var JsonNode, chainId: int, txType: string, sendTxArgsJson: string,
|
||||||
|
signature: string): string =
|
||||||
|
try:
|
||||||
|
let response = sendTransactionWithSignature(chainId, txType, sendTxArgsJson, signature)
|
||||||
|
return prepareResponse(resultOut, response)
|
||||||
|
except Exception as e:
|
||||||
|
warn e.msg
|
||||||
|
return e.msg
|
Loading…
Reference in New Issue