feat: make token send and eth send work

This commit is contained in:
Jonathan Rainville 2020-07-01 10:04:45 -04:00 committed by Iuri Matias
parent 19f8f8e457
commit 81e7dffaa2
8 changed files with 78 additions and 27 deletions

View File

@ -157,8 +157,8 @@ QtObject:
read = getAccountList
notify = accountListChanged
proc onSendTransaction*(self: WalletView, from_value: string, to: string, value: string, password: string): string {.slot.} =
result = self.status.wallet.sendTransaction(from_value, to, value, password)
proc onSendTransaction*(self: WalletView, from_value: string, to: string, assetAddress: string, value: string, password: string): string {.slot.} =
return self.status.wallet.sendTransaction(from_value, to, assetAddress, value, password)
proc getDefaultAccount*(self: WalletView): string {.slot.} =
self.currentAccount.address

View File

@ -7,6 +7,7 @@ type
Symbol = UserRole + 2,
Value = UserRole + 3,
FiatValue = UserRole + 4
Address = UserRole + 5
QtObject:
type AssetList* = ref object of QAbstractListModel
@ -32,6 +33,7 @@ QtObject:
of "symbol": result = asset.symbol
of "value": result = asset.value
of "fiatValue": result = asset.fiatValue
of "address": result = asset.address
method rowCount(self: AssetList, index: QModelIndex = nil): int =
return self.assets.len
@ -48,12 +50,14 @@ QtObject:
of AssetRoles.Symbol: result = newQVariant(asset.symbol)
of AssetRoles.Value: result = newQVariant(asset.value)
of AssetRoles.FiatValue: result = newQVariant(asset.fiatValue)
of AssetRoles.Address: result = newQVariant(asset.address)
method roleNames(self: AssetList): Table[int, string] =
{ AssetRoles.Name.int:"name",
AssetRoles.Symbol.int:"symbol",
AssetRoles.Value.int:"value",
AssetRoles.FiatValue.int:"fiatValue" }.toTable
AssetRoles.FiatValue.int:"fiatValue",
AssetRoles.Address.int:"address" }.toTable
proc addAssetToList*(self: AssetList, asset: Asset) =
self.beginInsertRows(newQModelIndex(), self.assets.len, self.assets.len)

View File

@ -5,6 +5,8 @@ const SEED* = "seed"
const KEY* = "key"
const WATCH* = "watch"
const ZERO_ADDRESS* = "0x0000000000000000000000000000000000000000"
const PATH_WALLET_ROOT* = "m/44'/60'/0'/0"
# EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived
const PATH_EIP_1581* = "m/43'/60'/1581'"

View File

@ -7,10 +7,10 @@ type
Mainnet,
Testnet
type Method = object
name: string
signature: string
noPadding: bool
type Method* = object
name*: string
signature*: string
noPadding*: bool
type Contract* = ref object
name*: string
@ -21,7 +21,8 @@ type Contract* = ref object
let CONTRACTS: seq[Contract] = @[
Contract(name: "snt", network: Network.Mainnet, address: parseAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"),
methods: [
("approveAndCall", Method(signature: "approveAndCall(address,uint256,bytes)"))
("approveAndCall", Method(signature: "approveAndCall(address,uint256,bytes)")),
("transfer", Method(signature: "transfer(address,uint256)"))
].toTable
),
Contract(name: "snt", network: Network.Testnet, address: parseAddress("0xc55cf4b03948d7ebc8b9e8bad92643703811d162")),
@ -77,6 +78,8 @@ proc encodeParam[T](value: T): string =
result = toHex(value, 64)
elif T is EthAddress:
result = value.toHex()
else:
result = align(value, 64, '0')
macro encodeAbi*(self: Method, params: varargs[untyped]): untyped =
result = quote do:

View File

@ -1,6 +1,9 @@
import json, json, strformat, stint, strutils, chronicles
import json, httpclient, json, strformat, stint, strutils, sequtils, chronicles, parseutils, tables
import libstatus, core, types
import ../wallet/account
from ./accounts/constants import ZERO_ADDRESS
import ./contracts as contractMethods
from eth/common/utils import parseAddress
proc getWalletAccounts*(): seq[WalletAccount] =
try:
@ -26,17 +29,17 @@ proc getWalletAccounts*(): seq[WalletAccount] =
let msg = getCurrentExceptionMsg()
error "Failed getting wallet accounts", msg
proc getTransfersByAddress*(address: string): seq[Transaction] =
proc getTransfersByAddress*(address: string): seq[types.Transaction] =
try:
let response = getBlockByNumber("latest")
let latestBlock = parseJson(response)["result"]
let transactionsResponse = getTransfersByAddress(address, latestBlock["number"].getStr, "0x14")
let transactions = parseJson(transactionsResponse)["result"]
var accountTransactions: seq[Transaction] = @[]
var accountTransactions: seq[types.Transaction] = @[]
for transaction in transactions:
accountTransactions.add(Transaction(
accountTransactions.add(types.Transaction(
typeValue: transaction["type"].getStr,
address: transaction["address"].getStr,
contract: transaction["contract"].getStr,
@ -58,14 +61,42 @@ proc getTransfersByAddress*(address: string): seq[Transaction] =
error "Failed getting wallet account transactions", msg
proc sendTransaction*(from_address: string, to: string, value: string, password: string): string =
var args = %* {
"value": fmt"0x{toHex(value)}",
"from": from_address,
"to": to
}
var response = sendTransaction($args, password)
result = response
proc sendTransaction*(from_address: string, to: string, assetAddress: string, value: string, password: string): string =
try:
var args: JsonNode
if (assetAddress == ZERO_ADDRESS or assetAddress == ""):
var weiValue = value.parseFloat() * float(1000000000000000000)
var stringValue = fmt"{weiValue:<.0f}"
stringValue.removeSuffix('.')
var hexValue = parseBiggestInt(stringValue).toHex()
hexValue.removePrefix('0')
args = %* {
"value": fmt"0x{hexValue}",
"from": from_address,
"to": to
}
else:
var bigIntValue = u256(value)
# TODO get decimals from the token
bigIntValue = bigIntValue * u256(1000000000000000000)
# Just using mainnet SNT to get the method ABI
let contract = getContract(Network.Mainnet, "snt")
let transferEncoded = contract.methods["transfer"].encodeAbi(parseAddress(to), bigIntValue.toHex())
args = %* {
"from": from_address,
"to": assetAddress,
"data": transferEncoded
}
let response = sendTransaction($args, password)
let parsedResponse = parseJson(response)
result = parsedResponse["result"].getStr
trace "Transaction sent succesfully", hash=result
except Exception as e:
error "Error submitting transaction", msg=e.msg
result = e.msg
proc getBalance*(address: string): string =
let payload = %* [address, "latest"]

View File

@ -44,8 +44,8 @@ proc initEvents*(self: WalletModel) =
proc delete*(self: WalletModel) =
discard
proc sendTransaction*(self: WalletModel, from_value: string, to: string, value: string, password: string): string =
status_wallet.sendTransaction(from_value, to, value, password)
proc sendTransaction*(self: WalletModel, from_value: string, to: string, assetAddress: string, value: string, password: string): string =
status_wallet.sendTransaction(from_value, to, assetAddress, value, password)
proc getDefaultCurrency*(self: WalletModel): string =
# TODO: this should come from a model? It is going to be used too in the

View File

@ -15,7 +15,6 @@ ModalPopup {
onOpened: {
sendModalContent.amountInput.text = ""
sendModalContent.amountInput.forceActiveFocus(Qt.MouseFocusReason)
sendModalContent.defaultAccount = walletModel.getDefaultAccount()
const accounts = walletModel.accounts
const numAccounts = accounts.rowCount()
const accountsData = []
@ -35,7 +34,8 @@ ModalPopup {
assetsData.push({
name: assets.rowData(f, 'name'),
symbol: assets.rowData(f, 'symbol'),
value: assets.rowData(f, 'value')
value: assets.rowData(f, 'value'),
address: assets.rowData(f, 'address')
})
}
sendModalContent.assets = assetsData

View File

@ -7,7 +7,7 @@ Item {
property alias amountInput: txtAmount
property var accounts: []
property var assets: []
property string defaultAccount: "0x1234"
property string defaultAccount: "0x8558BFe81d00333379Af1Cd4c07F3dc50081FEC4"
property int selectedAccountIndex: 0
property string selectedAccountAddress: accounts && accounts.length ? accounts[selectedAccountIndex].address : ""
@ -16,6 +16,7 @@ Item {
property int selectedAssetIndex: 0
property string selectedAssetName: assets && assets.length ? assets[selectedAssetIndex].name : ""
property string selectedAssetAddress: assets && assets.length ? assets[selectedAssetIndex].address : ""
property string selectedAssetSymbol: assets && assets.length ? assets[selectedAssetIndex].symbol : ""
property string selectedAccountValue: assets && assets.length ? assets[selectedAssetIndex].value : ""
@ -27,12 +28,22 @@ Item {
if (!validate()) {
return;
}
// Convert to Wei
// TODO use the decimal value fo the token, it's not always 18
// TODO add big number support
// const weiValue = parseFloat(txtAmount.text, 10) * 1000000000000000000
console.log('SENDING', selectedAccountAddress,
txtTo.text,
selectedAssetAddress,
txtAmount.text,
txtPassword.text)
let result = walletModel.onSendTransaction(selectedAccountAddress,
txtTo.text,
selectedAssetAddress,
txtAmount.text,
txtPassword.text)
console.log(result)
console.log('hash', result)
}
function validate() {
@ -56,7 +67,7 @@ Item {
amountValidationError = qsTr("You need to enter an amount")
} else if (isNaN(txtAmount.text)) {
amountValidationError = qsTr("This needs to be a number")
} else if (parseInt(txtAmount.text, 10) > parseInt(selectedAccountValue, 10)) {
} else if (parseFloat(txtAmount.text) > parseFloat(selectedAccountValue)) {
amountValidationError = qsTr("Amount needs to be lower than your balance (%1)").arg(selectedAccountValue)
} else {
amountValidationError = ""