mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-09 13:56:10 +00:00
793aeb15c3
Fixes: 1. Fixing the laggy scrolling on transaction requiests popups. The root cause of this issue was the fees request and also the estimated time request. These periodic requests were blocking. Now we'll call these API async. 2. Fixing the max fees: The fees computation was using 21k as gasLimit. This value was hardcoded in WC. Now we're requesting the gasLimit if it's not provided by the dApp. This call is also async. 3. Fixing the periodicity of the fees computation. The fees were computed by the client only if the tx object didn't already provide the fees. But the tx could fail if when the fees are highly volatile because it was not being overridden. Now Status is computing the fees periodically for all tx requests. 4. Fixing an issue where the loading state of the fees text in the modal was showing text underneath the loading animation. Fixed by updating the AnimatedText to support a custom target property. The text component used for session requests is using `cusomColor` property to set the text color and the `color` for the text must not be overriden.
271 lines
19 KiB
QML
271 lines
19 KiB
QML
import QtQuick 2.15
|
|
import QtTest 1.15
|
|
|
|
import AppLayouts.Wallet.services.dapps 1.0
|
|
import AppLayouts.Wallet.services.dapps.plugins 1.0
|
|
import AppLayouts.Wallet.services.dapps.types 1.0
|
|
|
|
import shared.stores 1.0
|
|
import utils 1.0
|
|
|
|
Item {
|
|
id: root
|
|
|
|
Component {
|
|
id: signRequestPluginComponent
|
|
SignRequestPlugin {
|
|
id: plugin
|
|
property SignalSpy acceptedSpy: SignalSpy { target: plugin; signalName: "accepted" }
|
|
property SignalSpy rejectedSpy: SignalSpy { target: plugin; signalName: "rejected" }
|
|
property SignalSpy signCompletedSpy: SignalSpy { target: plugin; signalName: "signCompleted" }
|
|
|
|
sdk: WalletConnectSDKBase {
|
|
id: sdk
|
|
enabled: true
|
|
projectId: ""
|
|
property bool sdkReady: true
|
|
|
|
property var getActiveSessionsCallbacks: []
|
|
getActiveSessions: function(callback) {
|
|
getActiveSessionsCallbacks.push({callback})
|
|
}
|
|
|
|
property var acceptSessionRequestCalls: []
|
|
acceptSessionRequest: function(topic, id, signature) {
|
|
acceptSessionRequestCalls.push({topic, id, signature})
|
|
}
|
|
|
|
property var rejectSessionRequestCalls: []
|
|
rejectSessionRequest: function(topic, id, error) {
|
|
rejectSessionRequestCalls.push({topic, id, error})
|
|
}
|
|
}
|
|
store: DAppsStore {
|
|
id: dappsStore
|
|
|
|
signal userAuthenticated(string topic, string id, string password, string pin, string payload)
|
|
signal userAuthenticationFailed(string topic, string id)
|
|
signal signingResult(string topic, string id, string data)
|
|
|
|
signal estimatedTimeResponse(string topic, int timeCategory, bool success)
|
|
signal suggestedFeesResponse(string topic, var suggestedFeesJsonObj, bool success)
|
|
signal estimatedGasResponse(string topic, string gasEstimate, bool success)
|
|
|
|
function hexToDec(hex) {
|
|
return parseInt(hex, 16)
|
|
}
|
|
|
|
function getEstimatedTime() {
|
|
return Constants.TransactionEstimatedTime.LessThanThreeMins
|
|
}
|
|
|
|
function convertFeesInfoToHex(feesInfo) {
|
|
return null
|
|
}
|
|
|
|
property var mockedSuggestedFees: ({
|
|
gasPrice: 2.0,
|
|
baseFee: 5.0,
|
|
maxPriorityFeePerGas: 2.0,
|
|
maxFeePerGasL: 1.0,
|
|
maxFeePerGasM: 1.1,
|
|
maxFeePerGasH: 1.2,
|
|
l1GasFee: 0.0,
|
|
eip1559Enabled: true
|
|
})
|
|
function getSuggestedFees() {
|
|
return mockedSuggestedFees
|
|
}
|
|
|
|
property var authenticateUserCalls: []
|
|
function authenticateUser(topic, id, address) {
|
|
authenticateUserCalls.push({topic, id, address})
|
|
}
|
|
|
|
property var signMessageCalls: []
|
|
function signMessage(topic, id, address, message, password, pin) {
|
|
signMessageCalls.push({topic, id, address, password, pin})
|
|
}
|
|
|
|
property var signMessageUnsafeCalls: []
|
|
function signMessageUnsafe(topic, id, address, data, password, pin) {
|
|
signMessageUnsafeCalls.push({topic, id, address, data, password, pin})
|
|
}
|
|
|
|
property var safeSignTypedDataCalls: []
|
|
function safeSignTypedData(topic, id, address, message, chainId, legacy, password, pin) {
|
|
safeSignTypedDataCalls.push({topic, id, address, message, chainId, legacy, password, pin})
|
|
}
|
|
|
|
property var signTransactionCalls: []
|
|
function signTransaction(topic, id, address, chainId, txObj, password, pin) {
|
|
signTransactionCalls.push({topic, id, address, chainId, txObj, password, pin})
|
|
}
|
|
|
|
property var sendTransactionCalls: []
|
|
function sendTransaction(topic, id, address, chainID, txObj, password, pin) {
|
|
sendTransactionCalls.push({topic, id, address, chainID, txObj, password, pin})
|
|
}
|
|
}
|
|
dappsModel: ListModel {
|
|
id: dappsModel
|
|
}
|
|
groupedAccountAssetsModel: ListModel {
|
|
id: groupedAccountAssetsModel
|
|
}
|
|
networksModel: ListModel {
|
|
id: networksModel
|
|
ListElement {
|
|
chainId: 1
|
|
layer: 1
|
|
}
|
|
}
|
|
accountsModel: ListModel {
|
|
id: accountsModel
|
|
ListElement {
|
|
address: "0x123"
|
|
}
|
|
}
|
|
requests: SessionRequestsModel {}
|
|
getFiatValue: (balance, cryptoSymbol) => {
|
|
return parseFloat(balance)
|
|
}
|
|
}
|
|
}
|
|
|
|
TestCase {
|
|
id: signRequestPluginTest
|
|
|
|
property SignRequestPlugin componentUnderTest: null
|
|
|
|
function populateDAppData(topic) {
|
|
const dapp = {
|
|
topic,
|
|
name: "Example",
|
|
url: "https://example.com",
|
|
iconUrl: "https://example.com/icon.png",
|
|
connectorId: 0,
|
|
accountAddresses: [{address: "0x123"}],
|
|
rawSessions: [{session: {topic}}]
|
|
}
|
|
componentUnderTest.dappsModel.append(dapp)
|
|
}
|
|
|
|
function executeRequest(signEvent) {
|
|
populateDAppData(signEvent.topic)
|
|
componentUnderTest.sdk.sessionRequestEvent(signEvent)
|
|
// Execute the request
|
|
const request = componentUnderTest.requests.get(0)
|
|
request.requestItem.execute("passowrd", "pin")
|
|
|
|
componentUnderTest.store.signingResult(signEvent.topic, signEvent.id, "result")
|
|
compare(componentUnderTest.sdk.acceptSessionRequestCalls.length, 1, "Accept session request should be called")
|
|
compare(componentUnderTest.sdk.acceptSessionRequestCalls[0].signature, "result", "Accept session request should be called with the correct signature")
|
|
compare(componentUnderTest.sdk.acceptSessionRequestCalls[0].topic.toString(), signEvent.topic.toString(), "Accept session request should be called with the correct topic")
|
|
compare(componentUnderTest.sdk.acceptSessionRequestCalls[0].id.toString(), signEvent.id.toString(), "Accept session request should be called with the correct id")
|
|
|
|
compare(componentUnderTest.acceptedSpy.count, 1, "Accepted signal should be emitted")
|
|
}
|
|
|
|
function init() {
|
|
componentUnderTest = createTemporaryObject(signRequestPluginComponent, root)
|
|
}
|
|
|
|
function test_signMessage() {
|
|
const signEvent = {"id":1730896110928724,"params":{"chainId":"eip155:1","request":{"method":"personal_sign","params":["0x4578616d706c652060706572736f6e616c5f7369676e60206d657373616765","0x123","Example password"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
// Case 1: DApp not found
|
|
ignoreWarning(`Error finding dapp for topic ${signEvent.topic} id ${signEvent.id}`)
|
|
componentUnderTest.sdk.sessionRequestEvent(signEvent)
|
|
compare(componentUnderTest.sdk.rejectSessionRequestCalls.length, 1, "Reject session request should not be called")
|
|
|
|
// Case 2: DApp found
|
|
executeRequest(signEvent)
|
|
compare(componentUnderTest.store.signMessageCalls.length, 1, "Sign message should be called")
|
|
componentUnderTest.sdk.sessionRequestUserAnswerResult(signEvent.topic, signEvent.id, true, null)
|
|
|
|
const requestItem = componentUnderTest.requests.get(0).requestItem
|
|
compare(requestItem.requestId, signEvent.id.toString(), "Request id should be set")
|
|
compare(requestItem.topic, signEvent.topic.toString(), "Topic should be set")
|
|
compare(requestItem.method, signEvent.params.request.method, "Method should be set")
|
|
compare(requestItem.accountAddress, signEvent.params.request.params[1], "Account address should be set")
|
|
compare(requestItem.chainId, signEvent.params.chainId.split(':').pop().trim(), "Chain id should be set")
|
|
compare(requestItem.sourceId, componentUnderTest.dappsModel.get(0).connectorId, "Source id should be set")
|
|
|
|
compare(componentUnderTest.signCompletedSpy.count, 1, "Sign completed signal should be emitted")
|
|
}
|
|
|
|
function test_signMessageUnsafe() {
|
|
const signEvent = {"id":1730896224189361,"params":{"chainId":"eip155:1","request":{"method":"eth_sign","params":["0x123","0x123"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
|
|
executeRequest(signEvent)
|
|
|
|
compare(componentUnderTest.store.signMessageUnsafeCalls.length, 1, "Sign message unsafe should be called")
|
|
componentUnderTest.sdk.sessionRequestUserAnswerResult(signEvent.topic, signEvent.id, true, null)
|
|
|
|
compare(componentUnderTest.signCompletedSpy.count, 1, "Sign completed signal should be emitted")
|
|
}
|
|
|
|
function test_safeSignTypedData() {
|
|
const signEvent = {"id":1730896495619543,"params":{"chainId":"eip155:1","request":{"method":"eth_signTypedData_v4","params":["0x123","{\"domain\":{\"chainId\":\"1\",\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}],\"attachment\":\"0x\"},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"},{\"name\":\"attachment\",\"type\":\"bytes\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}}"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
|
|
executeRequest(signEvent)
|
|
|
|
compare(componentUnderTest.store.safeSignTypedDataCalls.length, 1, "Safe sign typed data should be called")
|
|
componentUnderTest.sdk.sessionRequestUserAnswerResult(signEvent.topic, signEvent.id, true, null)
|
|
|
|
compare(componentUnderTest.signCompletedSpy.count, 1, "Sign completed signal should be emitted")
|
|
}
|
|
|
|
function test_sendTransaction() {
|
|
const signEvent = {"id":1730899979094571,"params":{"chainId":"eip155:1","request":{"method":"eth_sendTransaction","params":[{"from":"0x123","gasLimit":"0x5028","maxFeePerGas":"0x2540be400","maxPriorityFeePerGas":"0x3b9aca00","to":"0x0c54FcCd2e384b4BB6f2E405Bf5Cbc15a017AaFb","value":"0x0"}]}},"topic":"147fa9ddffcf9d782b5e002eb36b041e43a1db2bad79a598da6926105ce6680f","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
|
|
executeRequest(signEvent)
|
|
|
|
compare(componentUnderTest.store.sendTransactionCalls.length, 1, "Send transaction should be called")
|
|
componentUnderTest.sdk.sessionRequestUserAnswerResult(signEvent.topic, signEvent.id, true, null)
|
|
|
|
compare(componentUnderTest.signCompletedSpy.count, 1, "Sign completed signal should be emitted")
|
|
}
|
|
|
|
function reject_sign() {
|
|
const signEvent = {"id":1730896495619543,"params":{"chainId":"eip155:1","request":{"method":"eth_signTypedData_v4","params":["0x123","{\"domain\":{\"chainId\":\"1\",\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}],\"attachment\":\"0x\"},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"},{\"name\":\"attachment\",\"type\":\"bytes\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}}"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
populateDAppData(signEvent.topic)
|
|
componentUnderTest.sdk.sessionRequestEvent(signEvent)
|
|
// Execute the request
|
|
const request = componentUnderTest.requests.get(0)
|
|
request.requestItem.rejected(false)
|
|
|
|
compare(componentUnderTest.sdk.rejectSessionRequestCalls.length, 1, "Reject session request should be called")
|
|
compare(componentUnderTest.rejectedSpy.count, 1, "Rejected signal should be emitted")
|
|
compare(componentUnderTest.signCompletedSpy.count, 0, "Sign completed signal should not be emitted")
|
|
}
|
|
|
|
function test_authFailed() {
|
|
const signEvent = {"id":1730896495619543,"params":{"chainId":"eip155:1","request":{"method":"eth_signTypedData_v4","params":["0x123","{\"domain\":{\"chainId\":\"1\",\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}],\"attachment\":\"0x\"},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"},{\"name\":\"attachment\",\"type\":\"bytes\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}}"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
populateDAppData(signEvent.topic)
|
|
componentUnderTest.sdk.sessionRequestEvent(signEvent)
|
|
// Execute the request
|
|
const request = componentUnderTest.requests.get(0)
|
|
|
|
request.requestItem.authFailed()
|
|
compare(componentUnderTest.sdk.rejectSessionRequestCalls.length, 1, "Reject session request should be called")
|
|
compare(componentUnderTest.rejectedSpy.count, 1, "Rejected signal should be emitted")
|
|
compare(componentUnderTest.signCompletedSpy.count, 0, "Sign completed signal should not be emitted")
|
|
}
|
|
|
|
function test_signMessageFails() {
|
|
const signEvent = {"id":1730896495619543,"params":{"chainId":"eip155:1","request":{"method":"eth_signTypedData_v4","params":["0x123","{\"domain\":{\"chainId\":\"1\",\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}],\"attachment\":\"0x\"},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"},{\"name\":\"attachment\",\"type\":\"bytes\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}}"]}},"topic":"43a74a4c6c71e3ab67ef80283dc43f392445642c8dce3dabe63f89ab83cfcfc3","verifyContext":{"verified":{"origin":"https://metamask.github.io/test-dapp/","validation":"UNKNOWN","verifyUrl":"https://verify.walletconnect.org"}}}
|
|
|
|
populateDAppData(signEvent.topic)
|
|
componentUnderTest.sdk.sessionRequestEvent(signEvent)
|
|
// Execute the request
|
|
const request = componentUnderTest.requests.get(0)
|
|
request.requestItem.execute("passowrd", "pin")
|
|
|
|
componentUnderTest.store.signingResult(signEvent.topic, signEvent.id, "")
|
|
compare(componentUnderTest.sdk.rejectSessionRequestCalls.length, 1, "Reject session request should be called")
|
|
compare(componentUnderTest.rejectedSpy.count, 1, "Rejected signal should be emitted")
|
|
compare(componentUnderTest.signCompletedSpy.count, 0, "Sign completed signal should not be emitted")
|
|
}
|
|
}
|
|
} |