268 lines
19 KiB
QML
268 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)
|
||
|
|
||
|
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"
|
||
|
}
|
||
|
}
|
||
|
currentCurrency: "USD"
|
||
|
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")
|
||
|
}
|
||
|
}
|
||
|
}
|