feat(dapps) implement eth_sendTransaction support for wallet
Add `Fees` section to request modal Closes: #15126
This commit is contained in:
parent
e2949ad6e7
commit
97413d99d1
|
@ -58,3 +58,6 @@ QtObject:
|
||||||
|
|
||||||
proc signTransaction*(self: Controller, address: string, chainId: int, password: string, txJson: string): string {.slot.} =
|
proc signTransaction*(self: Controller, address: string, chainId: int, password: string, txJson: string): string {.slot.} =
|
||||||
return self.service.signTransaction(address, chainId, password, txJson)
|
return self.service.signTransaction(address, chainId, password, txJson)
|
||||||
|
|
||||||
|
proc sendTransaction*(self: Controller, address: string, chainId: int, password: string, txJson: string): string {.slot.} =
|
||||||
|
return self.service.sendTransaction(address, chainId, password, txJson)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import backend/wallet
|
||||||
|
|
||||||
import app_service/service/settings/service as settings_service
|
import app_service/service/settings/service as settings_service
|
||||||
import app_service/common/wallet_constants
|
import app_service/common/wallet_constants
|
||||||
|
from app_service/service/transaction/dto import PendingTransactionTypeDto
|
||||||
|
|
||||||
import app/global/global_singleton
|
import app/global/global_singleton
|
||||||
|
|
||||||
|
@ -129,3 +130,39 @@ QtObject:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
return txResponse["rawTx"].getStr
|
return txResponse["rawTx"].getStr
|
||||||
|
|
||||||
|
proc sendTransaction*(self: Service, address: string, chainId: int, password: string, txJson: string): string =
|
||||||
|
var buildTxResponse: JsonNode
|
||||||
|
var err = wallet.buildTransaction(buildTxResponse, chainId, txJson)
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - wallet_buildTransaction failed", err=err
|
||||||
|
return ""
|
||||||
|
if buildTxResponse.isNil or buildTxResponse.kind != JsonNodeKind.JObject or
|
||||||
|
not buildTxResponse.hasKey("txArgs") or not buildTxResponse.hasKey("messageToSign"):
|
||||||
|
error "unexpected wallet_buildTransaction response"
|
||||||
|
return ""
|
||||||
|
var txToBeSigned = buildTxResponse["messageToSign"].getStr
|
||||||
|
if txToBeSigned.len != wallet_constants.TX_HASH_LEN_WITH_PREFIX:
|
||||||
|
error "unexpected tx hash length"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
var signMsgRes: JsonNode
|
||||||
|
err = wallet.signMessage(signMsgRes,
|
||||||
|
txToBeSigned,
|
||||||
|
address,
|
||||||
|
hashPassword(password))
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - wallet_signMessage failed", err=err
|
||||||
|
let signature = singletonInstance.utils.removeHexPrefix(signMsgRes.getStr)
|
||||||
|
|
||||||
|
var txResponse: JsonNode
|
||||||
|
err = wallet.sendTransactionWithSignature(txResponse, chainId,
|
||||||
|
$PendingTransactionTypeDto.WalletConnectTransfer, $buildTxResponse["txArgs"], signature)
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - sendTransactionWithSignature failed", err=err
|
||||||
|
return ""
|
||||||
|
if txResponse.isNil or txResponse.kind != JsonNodeKind.JString:
|
||||||
|
error "unexpected sendTransactionWithSignature response"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return txResponse.getStr
|
||||||
|
|
|
@ -20,6 +20,7 @@ import shared.popups.walletconnect 1.0
|
||||||
import SortFilterProxyModel 0.2
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
import AppLayouts.Wallet.panels 1.0
|
import AppLayouts.Wallet.panels 1.0
|
||||||
|
import AppLayouts.Wallet.services.dapps.types 1.0
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared.stores 1.0
|
import shared.stores 1.0
|
||||||
|
@ -53,6 +54,8 @@ Item {
|
||||||
payloadData: d.currentPayload ? d.currentPayload.payloadData : null
|
payloadData: d.currentPayload ? d.currentPayload.payloadData : null
|
||||||
method: d.currentPayload ? d.currentPayload.method : ""
|
method: d.currentPayload ? d.currentPayload.method : ""
|
||||||
maxFeesText: d.currentPayload ? d.currentPayload.maxFeesText : ""
|
maxFeesText: d.currentPayload ? d.currentPayload.maxFeesText : ""
|
||||||
|
maxFeesEthText: d.currentPayload ? d.currentPayload.maxFeesEthText : ""
|
||||||
|
enoughFunds: settings.enoughFunds
|
||||||
estimatedTimeText: d.currentPayload ? d.currentPayload.estimatedTimeText : ""
|
estimatedTimeText: d.currentPayload ? d.currentPayload.estimatedTimeText : ""
|
||||||
|
|
||||||
account: d.selectedAccount
|
account: d.selectedAccount
|
||||||
|
@ -119,6 +122,13 @@ Item {
|
||||||
d.currentPayload = d.payloadOptions[currentIndex]
|
d.currentPayload = d.payloadOptions[currentIndex]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StatusCheckBox {
|
||||||
|
id: enoughFundsCheckBox
|
||||||
|
|
||||||
|
text: "Enough funds"
|
||||||
|
checked: settings.enoughFunds
|
||||||
|
onCheckedChanged: settings.enoughFunds = checked
|
||||||
|
}
|
||||||
|
|
||||||
Item { Layout.fillHeight: true }
|
Item { Layout.fillHeight: true }
|
||||||
}
|
}
|
||||||
|
@ -132,6 +142,7 @@ Item {
|
||||||
property string dappIcon: "https://opensea.io/static/images/logos/opensea-logo.svg"
|
property string dappIcon: "https://opensea.io/static/images/logos/opensea-logo.svg"
|
||||||
property string accountDisplay: "helloworld"
|
property string accountDisplay: "helloworld"
|
||||||
property int payloadMethod: 0
|
property int payloadMethod: 0
|
||||||
|
property bool enoughFunds: true
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
@ -152,21 +163,31 @@ Item {
|
||||||
readonly property var payloadOptions: [
|
readonly property var payloadOptions: [
|
||||||
{
|
{
|
||||||
payloadData: {"message":"This is a message to sign.\nSigning this will prove ownership of the account."},
|
payloadData: {"message":"This is a message to sign.\nSigning this will prove ownership of the account."},
|
||||||
method: "personal_sign",
|
method: SessionRequest.methods.personalSign.name,
|
||||||
maxFeesText: "",
|
maxFeesText: "",
|
||||||
|
maxFeesEthText: "",
|
||||||
estimatedTimeText: ""
|
estimatedTimeText: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
payloadData: {"message": "{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}"},
|
payloadData: {"message": "{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}"},
|
||||||
method: "eth_signTypedData_v4",
|
method: SessionRequest.methods.signTypedData_v4.name,
|
||||||
maxFeesText: "",
|
maxFeesText: "",
|
||||||
|
maxFeesEthText: "",
|
||||||
estimatedTimeText: ""
|
estimatedTimeText: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
payloadData: {"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}},
|
payloadData: {"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}},
|
||||||
method: "eth_signTransaction",
|
method: SessionRequest.methods.signTransaction.name,
|
||||||
maxFeesText: "1.82 EUR",
|
maxFeesText: "1.82 EUR",
|
||||||
|
maxFeesEthText: "0.0001 ETH",
|
||||||
estimatedTimeText: "3-5 mins"
|
estimatedTimeText: "3-5 mins"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
payloadData: {"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}},
|
||||||
|
method: SessionRequest.methods.sendTransaction.name,
|
||||||
|
maxFeesText: "0.92 EUR",
|
||||||
|
maxFeesEthText: "0.00005 ETH",
|
||||||
|
estimatedTimeText: "1-2 mins"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,11 @@ Item {
|
||||||
console.info(`calling mocked DAppsStore.signTransaction(${topic}, ${id}, ${address}, ${chainId}, ${password}, ${tx})`)
|
console.info(`calling mocked DAppsStore.signTransaction(${topic}, ${id}, ${address}, ${chainId}, ${password}, ${tx})`)
|
||||||
return "0xf8672a8402fb7acf82520894e2d622c817878da5143bbe06866ca8e35273ba8a80808401546d71a04fc89c2f007c3b27d0fcff07d3e69c29f940967fab4caf525f9af72dadb48befa00c5312a3cb6f50328889ad361a0c88bb9d1b1a4fc510f6783b287930b4e187b5"
|
return "0xf8672a8402fb7acf82520894e2d622c817878da5143bbe06866ca8e35273ba8a80808401546d71a04fc89c2f007c3b27d0fcff07d3e69c29f940967fab4caf525f9af72dadb48befa00c5312a3cb6f50328889ad361a0c88bb9d1b1a4fc510f6783b287930b4e187b5"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendTransaction(topic, id, address, chainId, password, tx) {
|
||||||
|
console.info(`calling mocked DAppsStore.sendTransaction(${topic}, ${id}, ${address}, ${chainId}, ${password}, ${tx})`)
|
||||||
|
return "0xf8672a8402fb7acf82520894e2d622c817878da5143bbe068"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walletStore: WalletStore {
|
walletStore: WalletStore {
|
||||||
|
|
|
@ -130,6 +130,8 @@ ConnectedDappsButton {
|
||||||
payloadData: request.data
|
payloadData: request.data
|
||||||
method: request.method
|
method: request.method
|
||||||
maxFeesText: request.maxFeesText
|
maxFeesText: request.maxFeesText
|
||||||
|
maxFeesEthText: request.maxFeesEthText
|
||||||
|
enoughFunds: request.enoughFunds
|
||||||
estimatedTimeText: request.estimatedTimeText
|
estimatedTimeText: request.estimatedTimeText
|
||||||
|
|
||||||
visible: true
|
visible: true
|
||||||
|
@ -153,8 +155,14 @@ ConnectedDappsButton {
|
||||||
Connections {
|
Connections {
|
||||||
target: root.wcService.requestHandler
|
target: root.wcService.requestHandler
|
||||||
|
|
||||||
function onMaxFeesUpdated(maxFees, symbol) {
|
function onMaxFeesUpdated(maxFees, maxFeesWei, haveEnoughFunds, symbol) {
|
||||||
maxFeesText = `${maxFees.toFixed(2)} ${symbol}`
|
maxFeesText = `${maxFees.toFixed(2)} ${symbol}`
|
||||||
|
var ethStr = "?"
|
||||||
|
if (globalUtils) {
|
||||||
|
ethStr = globalUtils.wei2Eth(maxFeesWei, 9)
|
||||||
|
}
|
||||||
|
maxFeesEthText = `${ethStr} ETH`
|
||||||
|
enoughFunds = haveEnoughFunds
|
||||||
}
|
}
|
||||||
function onEstimatedTimeUpdated(minMinutes, maxMinutes) {
|
function onEstimatedTimeUpdated(minMinutes, maxMinutes) {
|
||||||
estimatedTimeText = qsTr("%1-%2mins").arg(minMinutes).arg(maxMinutes)
|
estimatedTimeText = qsTr("%1-%2mins").arg(minMinutes).arg(maxMinutes)
|
||||||
|
|
|
@ -32,7 +32,7 @@ QObject {
|
||||||
signal sessionRequest(SessionRequestResolved request)
|
signal sessionRequest(SessionRequestResolved request)
|
||||||
signal displayToastMessage(string message, bool error)
|
signal displayToastMessage(string message, bool error)
|
||||||
signal sessionRequestResult(/*model entry of SessionRequestResolved*/ var request, bool isSuccess)
|
signal sessionRequestResult(/*model entry of SessionRequestResolved*/ var request, bool isSuccess)
|
||||||
signal maxFeesUpdated(real maxFees, string symbol)
|
signal maxFeesUpdated(real maxFees, int maxFeesWei, bool haveEnoughFunds, string symbol)
|
||||||
signal estimatedTimeUpdated(int minMinutes, int maxMinutes)
|
signal estimatedTimeUpdated(int minMinutes, int maxMinutes)
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -134,8 +134,10 @@ QObject {
|
||||||
account,
|
account,
|
||||||
network,
|
network,
|
||||||
data,
|
data,
|
||||||
maxFeesText: "-",
|
maxFeesText: "?",
|
||||||
estimatedTimeText: "-"
|
maxFeesEthText: "?",
|
||||||
|
enoughFunds: false,
|
||||||
|
estimatedTimeText: "?"
|
||||||
})
|
})
|
||||||
if (obj === null) {
|
if (obj === null) {
|
||||||
console.error("Error creating SessionRequestResolved for event")
|
console.error("Error creating SessionRequestResolved for event")
|
||||||
|
@ -143,9 +145,7 @@ QObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check later to have a valid request object
|
// Check later to have a valid request object
|
||||||
if (!SessionRequest.getSupportedMethods().includes(method)
|
if (!SessionRequest.getSupportedMethods().includes(method)) {
|
||||||
// TODO #14927: support method eth_sendTransaction
|
|
||||||
|| method == SessionRequest.methods.sendTransaction.name) {
|
|
||||||
console.error("Unsupported method", method)
|
console.error("Unsupported method", method)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -160,9 +160,10 @@ QObject {
|
||||||
// TODO #15192: update maxFees
|
// TODO #15192: update maxFees
|
||||||
let gasLimit = parseFloat(parseInt(event.params.request.params[0].gasLimit, 16));
|
let gasLimit = parseFloat(parseInt(event.params.request.params[0].gasLimit, 16));
|
||||||
let gasPrice = parseFloat(parseInt(event.params.request.params[0].gasPrice, 16));
|
let gasPrice = parseFloat(parseInt(event.params.request.params[0].gasPrice, 16));
|
||||||
root.maxFeesUpdated((gasLimit * gasPrice)/1000000000, "Gwei")
|
let maxFees = gasLimit * gasPrice
|
||||||
|
root.maxFeesUpdated(maxFees/1000000000, maxFees, true, "Gwei")
|
||||||
// TODO #15192: update estimatedTime
|
// TODO #15192: update estimatedTime
|
||||||
root.estimatedTimeUpdated(3, 12)
|
root.estimatedTimeUpdated(1, 12)
|
||||||
})
|
})
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
@ -181,7 +182,8 @@ QObject {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
address = event.params.request.params[0]
|
address = event.params.request.params[0]
|
||||||
} else if (method === SessionRequest.methods.signTransaction.name) {
|
} else if (method === SessionRequest.methods.signTransaction.name
|
||||||
|
|| method === SessionRequest.methods.sendTransaction.name) {
|
||||||
if (event.params.request.params.length == 0) {
|
if (event.params.request.params.length == 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -233,6 +235,12 @@ QObject {
|
||||||
}
|
}
|
||||||
let tx = event.params.request.params[0]
|
let tx = event.params.request.params[0]
|
||||||
return SessionRequest.methods.signTransaction.buildDataObject(tx)
|
return SessionRequest.methods.signTransaction.buildDataObject(tx)
|
||||||
|
} else if (method === SessionRequest.methods.sendTransaction.name) {
|
||||||
|
if (event.params.request.params.length == 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
let tx = event.params.request.params[0]
|
||||||
|
return SessionRequest.methods.sendTransaction.buildDataObject(tx)
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -256,26 +264,30 @@ QObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password !== "") {
|
if (password !== "") {
|
||||||
var signedMessage = ""
|
var actionResult = ""
|
||||||
if (request.method === SessionRequest.methods.personalSign.name) {
|
if (request.method === SessionRequest.methods.personalSign.name) {
|
||||||
// TODO #14756: clarify why prefixing the message fails the test app https://react-app.walletconnect.com/
|
// TODO #14756: clarify why prefixing the message fails the test app https://react-app.walletconnect.com/
|
||||||
//let finalMessage = "\x19Ethereum Signed Message:\n" + originalMessage.length + originalMessage
|
//let finalMessage = "\x19Ethereum Signed Message:\n" + originalMessage.length + originalMessage
|
||||||
signedMessage = store.signMessage(request.topic, request.id,
|
actionResult = store.signMessage(request.topic, request.id,
|
||||||
request.account.address, password,
|
request.account.address, password,
|
||||||
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
||||||
} else if (request.method === SessionRequest.methods.signTypedData_v4.name) {
|
} else if (request.method === SessionRequest.methods.signTypedData_v4.name) {
|
||||||
signedMessage = store.signTypedDataV4(request.topic, request.id,
|
actionResult = store.signTypedDataV4(request.topic, request.id,
|
||||||
request.account.address, password,
|
request.account.address, password,
|
||||||
SessionRequest.methods.signTypedData_v4.getMessageFromData(request.data))
|
SessionRequest.methods.signTypedData_v4.getMessageFromData(request.data))
|
||||||
} else if (request.method === SessionRequest.methods.signTransaction.name) {
|
} else if (request.method === SessionRequest.methods.signTransaction.name) {
|
||||||
let txObj = SessionRequest.methods.signTransaction.getTxObjFromData(request.data)
|
let txObj = SessionRequest.methods.signTransaction.getTxObjFromData(request.data)
|
||||||
signedMessage = store.signTransaction(request.topic, request.id,
|
actionResult = store.signTransaction(request.topic, request.id,
|
||||||
|
request.account.address, request.network.chainId, password, txObj)
|
||||||
|
} else if (request.method === SessionRequest.methods.sendTransaction.name) {
|
||||||
|
let txObj = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data)
|
||||||
|
actionResult = store.sendTransaction(request.topic, request.id,
|
||||||
request.account.address, request.network.chainId, password, txObj)
|
request.account.address, request.network.chainId, password, txObj)
|
||||||
}
|
}
|
||||||
let isSuccessful = (signedMessage != "")
|
let isSuccessful = (actionResult != "")
|
||||||
if (isSuccessful) {
|
if (isSuccessful) {
|
||||||
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
||||||
sdk.acceptSessionRequest(request.topic, request.id, signedMessage)
|
sdk.acceptSessionRequest(request.topic, request.id, actionResult)
|
||||||
} else {
|
} else {
|
||||||
root.sessionRequestResult(request, isSuccessful)
|
root.sessionRequestResult(request, isSuccessful)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import utils 1.0
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
/// Supported methods
|
/// Supported methods
|
||||||
|
/// userString is used in the context `dapp.url #{userString} <accepted/rejected>`
|
||||||
|
/// requestDisplay is used in the context `dApp wants you to ${requestDisplay} with <Account Name Here>`
|
||||||
property QtObject methods: QtObject {
|
property QtObject methods: QtObject {
|
||||||
readonly property QtObject personalSign: QtObject {
|
readonly property QtObject personalSign: QtObject {
|
||||||
readonly property string name: Constants.personal_sign
|
readonly property string name: Constants.personal_sign
|
||||||
|
@ -35,8 +37,11 @@ QtObject {
|
||||||
|
|
||||||
readonly property QtObject sendTransaction: QtObject {
|
readonly property QtObject sendTransaction: QtObject {
|
||||||
readonly property string name: "eth_sendTransaction"
|
readonly property string name: "eth_sendTransaction"
|
||||||
readonly property string userString: qsTr("send transaction")
|
readonly property string userString: qsTr("transaction")
|
||||||
//function buildDataObject(message) { return {/* TODO #15126 */}}
|
readonly property string requestDisplay: qsTr("sign this transaction")
|
||||||
|
|
||||||
|
function buildDataObject(tx) { return {tx}}
|
||||||
|
function getTxObjFromData(data) { return data.tx }
|
||||||
}
|
}
|
||||||
readonly property var all: [personalSign, signTypedData_v4, signTransaction, sendTransaction]
|
readonly property var all: [personalSign, signTypedData_v4, signTransaction, sendTransaction]
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ QObject {
|
||||||
readonly property alias dappIcon: d.dappIcon
|
readonly property alias dappIcon: d.dappIcon
|
||||||
|
|
||||||
readonly property string maxFeesText: ""
|
readonly property string maxFeesText: ""
|
||||||
|
readonly property string maxFeesEthText: ""
|
||||||
|
readonly property bool enoughFunds: false
|
||||||
readonly property string estimatedTimeText: ""
|
readonly property string estimatedTimeText: ""
|
||||||
|
|
||||||
function resolveDappInfoFromSession(session) {
|
function resolveDappInfoFromSession(session) {
|
||||||
|
|
|
@ -25,8 +25,10 @@ StatusDialog {
|
||||||
required property url dappIcon
|
required property url dappIcon
|
||||||
required property string method
|
required property string method
|
||||||
required property var payloadData
|
required property var payloadData
|
||||||
required property string maxFeesText
|
property string maxFeesText: ""
|
||||||
required property string estimatedTimeText
|
property string maxFeesEthText: ""
|
||||||
|
property bool enoughFunds: false
|
||||||
|
property string estimatedTimeText: ""
|
||||||
|
|
||||||
required property var account
|
required property var account
|
||||||
property var network: null
|
property var network: null
|
||||||
|
@ -126,6 +128,13 @@ StatusDialog {
|
||||||
Item {Layout.fillWidth: true }
|
Item {Layout.fillWidth: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("Network")
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
|
||||||
// TODO #14762: implement proper control to display the chain
|
// TODO #14762: implement proper control to display the chain
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -163,6 +172,62 @@ StatusDialog {
|
||||||
Item {Layout.fillWidth: true }
|
Item {Layout.fillWidth: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("Fees")
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
visible: d.isTransaction()
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 76
|
||||||
|
|
||||||
|
visible: root.network !== null && d.isTransaction()
|
||||||
|
|
||||||
|
radius: 8
|
||||||
|
border.width: 1
|
||||||
|
border.color: Theme.palette.baseColor2
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 12
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 16
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("Max. fees on %1").arg(!!root.network && root.network.chainName)
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
|
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
StatusBaseText {
|
||||||
|
text: root.maxFeesText
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: root.enoughFunds ? Theme.palette.directColor1 : Theme.palette.dangerColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: root.maxFeesEthText
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: root.enoughFunds ? Theme.palette.baseColor1 : Theme.palette.dangerColor1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +313,7 @@ StatusDialog {
|
||||||
visible: !!root.maxFeesText
|
visible: !!root.maxFeesText
|
||||||
|
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
font.weight: Font.DemiBold
|
color: root.enoughFunds ? Theme.palette.directColor1 : Theme.palette.dangerColor1
|
||||||
}
|
}
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("No fees")
|
text: qsTr("No fees")
|
||||||
|
@ -269,7 +334,6 @@ StatusDialog {
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: root.estimatedTimeText
|
text: root.estimatedTimeText
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
font.weight: Font.DemiBold
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +490,10 @@ StatusDialog {
|
||||||
property string payloadToDisplay: ""
|
property string payloadToDisplay: ""
|
||||||
property string userDisplayNaming: ""
|
property string userDisplayNaming: ""
|
||||||
|
|
||||||
|
function isTransaction() {
|
||||||
|
return root.method === SessionRequest.methods.signTransaction.name || root.method === SessionRequest.methods.sendTransaction.name
|
||||||
|
}
|
||||||
|
|
||||||
function updateDisplay() {
|
function updateDisplay() {
|
||||||
if (!root.payloadData)
|
if (!root.payloadData)
|
||||||
return
|
return
|
||||||
|
@ -448,6 +516,12 @@ StatusDialog {
|
||||||
userDisplayNaming = SessionRequest.methods.signTransaction.requestDisplay
|
userDisplayNaming = SessionRequest.methods.signTransaction.requestDisplay
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case SessionRequest.methods.sendTransaction.name: {
|
||||||
|
let tx = SessionRequest.methods.sendTransaction.getTxObjFromData(root.payloadData)
|
||||||
|
payloadToDisplay = JSON.stringify(tx, null, 2)
|
||||||
|
userDisplayNaming = SessionRequest.methods.sendTransaction.requestDisplay
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,9 @@ QObject {
|
||||||
return fixed == '0x' ? '0x0' : fixed;
|
return fixed == '0x' ? '0x0' : fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hex encoded signature of the transaction or empty string if error
|
|
||||||
function signTransaction(topic, id, address, chainId, password, txObj) {
|
|
||||||
// Strip leading zeros from numbers as expected by status-go
|
// Strip leading zeros from numbers as expected by status-go
|
||||||
let tx = {
|
function prepareTxForStatusGo(txObj) {
|
||||||
|
return {
|
||||||
data: txObj.data,
|
data: txObj.data,
|
||||||
from: txObj.from,
|
from: txObj.from,
|
||||||
gasLimit: stripLeadingZeros(txObj.gasLimit),
|
gasLimit: stripLeadingZeros(txObj.gasLimit),
|
||||||
|
@ -51,9 +50,19 @@ QObject {
|
||||||
to: txObj.to,
|
to: txObj.to,
|
||||||
value: stripLeadingZeros(txObj.value)
|
value: stripLeadingZeros(txObj.value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Returns the hex encoded signature of the transaction or empty string if error
|
||||||
|
function signTransaction(topic, id, address, chainId, password, txObj) {
|
||||||
|
let tx = prepareTxForStatusGo(txObj)
|
||||||
return controller.signTransaction(address, chainId, password, JSON.stringify(tx))
|
return controller.signTransaction(address, chainId, password, JSON.stringify(tx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the hash of the transaction or empty string if error
|
||||||
|
function sendTransaction(topic, id, address, chainId, password, txObj) {
|
||||||
|
let tx = prepareTxForStatusGo(txObj)
|
||||||
|
return controller.sendTransaction(address, chainId, password, JSON.stringify(tx))
|
||||||
|
}
|
||||||
|
|
||||||
/// \c getDapps triggers an async response to \c dappsListReceived
|
/// \c getDapps triggers an async response to \c dappsListReceived
|
||||||
function getDapps() {
|
function getDapps() {
|
||||||
return controller.getDapps()
|
return controller.getDapps()
|
||||||
|
|
Loading…
Reference in New Issue