feat(walletconnect): support for auth request
This commit is contained in:
parent
b819bdb574
commit
3854920f54
|
@ -141,7 +141,7 @@ proc newModule*(
|
|||
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
|
||||
result.filter = initFilter(result.controller)
|
||||
|
||||
result.wcController = wcc.newController(events)
|
||||
result.wcController = wcc.newController(events, walletAccountService)
|
||||
|
||||
result.view = newView(result, result.activityController, result.tmpActivityController, result.collectiblesController, result.collectibleDetailsController, result.wcController)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, strutils, logging, json, options
|
||||
import NimQml, strutils, logging, json, options, chronicles
|
||||
|
||||
import backend/wallet as backend_wallet
|
||||
import backend/wallet_connect as backend_wallet_connect
|
||||
|
@ -9,25 +9,33 @@ import app/core/signals/types
|
|||
|
||||
import app_service/common/utils as common_utils
|
||||
from app_service/service/transaction/dto import PendingTransactionTypeDto
|
||||
import app_service/service/wallet_account/service as wallet_account_service
|
||||
|
||||
import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
import constants
|
||||
import tx_response_dto, helper
|
||||
|
||||
const UNIQUE_WALLET_CONNECT_MODULE_SIGNING_IDENTIFIER* = "WalletConnect-Signing"
|
||||
const UNIQUE_WC_SESSION_REQUEST_SIGNING_IDENTIFIER* = "WalletConnect-SessionRequestSigning"
|
||||
const UNIQUE_WC_AUTH_REQUEST_SIGNING_IDENTIFIER* = "WalletConnect-AuthRequestSigning"
|
||||
|
||||
logScope:
|
||||
topics = "wallet-connect"
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Controller* = ref object of QObject
|
||||
events: EventEmitter
|
||||
walletAccountService: wallet_account_service.Service
|
||||
sessionRequestJson: JsonNode
|
||||
txResponseDto: TxResponseDto
|
||||
hasActivePairings: Option[bool]
|
||||
|
||||
## Forward declarations
|
||||
proc onDataSigned(self: Controller, keyUid: string, path: string, r: string, s: string, v: string, pin: string)
|
||||
proc invalidateData(self: Controller)
|
||||
proc onDataSigned(self: Controller, keyUid: string, path: string, r: string, s: string, v: string, pin: string, identifier: string)
|
||||
proc finishSessionRequest(self: Controller, signature: string)
|
||||
proc finishAuthRequest(self: Controller, signature: string)
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
@ -40,24 +48,36 @@ QtObject:
|
|||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_DATA_SIGNED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_WALLET_CONNECT_MODULE_SIGNING_IDENTIFIER:
|
||||
if args.uniqueIdentifier != UNIQUE_WC_SESSION_REQUEST_SIGNING_IDENTIFIER and
|
||||
args.uniqueIdentifier != UNIQUE_WC_AUTH_REQUEST_SIGNING_IDENTIFIER:
|
||||
return
|
||||
self.onDataSigned(args.keyUid, args.path, args.r, args.s, args.v, args.pin)
|
||||
self.onDataSigned(args.keyUid, args.path, args.r, args.s, args.v, args.pin, args.uniqueIdentifier)
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
self.invalidateData()
|
||||
self.QObject.delete
|
||||
|
||||
proc newController*(events: EventEmitter): Controller =
|
||||
proc newController*(events: EventEmitter, walletAccountService: wallet_account_service.Service): Controller =
|
||||
new(result, delete)
|
||||
result.events = events
|
||||
result.walletAccountService = walletAccountService
|
||||
result.setup()
|
||||
|
||||
proc onDataSigned(self: Controller, keyUid: string, path: string, r: string, s: string, v: string, pin: string) =
|
||||
proc invalidateData(self: Controller) =
|
||||
self.sessionRequestJson = nil
|
||||
self.txResponseDto = nil
|
||||
|
||||
proc onDataSigned(self: Controller, keyUid: string, path: string, r: string, s: string, v: string, pin: string, identifier: string) =
|
||||
if keyUid.len == 0 or path.len == 0 or r.len == 0 or s.len == 0 or v.len == 0 or pin.len == 0:
|
||||
error "invalid data signed"
|
||||
return
|
||||
let signature = "0x" & r & s & v
|
||||
if identifier == UNIQUE_WC_SESSION_REQUEST_SIGNING_IDENTIFIER:
|
||||
self.finishSessionRequest(signature)
|
||||
elif identifier == UNIQUE_WC_AUTH_REQUEST_SIGNING_IDENTIFIER:
|
||||
self.finishAuthRequest(signature)
|
||||
else:
|
||||
error "Unknown identifier"
|
||||
|
||||
# supportedNamespaces is a Namespace as defined in status-go: services/wallet/walletconnect/walletconnect.go
|
||||
proc proposeUserPair*(self: Controller, sessionProposalJson: string, supportedNamespacesJson: string) {.signal.}
|
||||
|
@ -117,6 +137,9 @@ QtObject:
|
|||
self.respondSessionRequest($self.sessionRequestJson, txResponseDto.rawTx, false)
|
||||
|
||||
proc finishSessionRequest(self: Controller, signature: string) =
|
||||
if signature.len == 0:
|
||||
self.respondSessionRequest($self.sessionRequestJson, "", true)
|
||||
return
|
||||
let requestMethod = getRequestMethod(self.sessionRequestJson)
|
||||
if requestMethod == RequestMethod.SendTransaction:
|
||||
self.sendTransactionAndRespond(signature)
|
||||
|
@ -130,24 +153,26 @@ QtObject:
|
|||
self.respondSessionRequest($self.sessionRequestJson, signature, false)
|
||||
else:
|
||||
error "Unknown request method"
|
||||
self.respondSessionRequest($self.sessionRequestJson, "", true)
|
||||
|
||||
proc sessionRequest*(self: Controller, sessionRequestJson: string, password: string) {.slot.} =
|
||||
var signature: string
|
||||
try:
|
||||
self.invalidateData()
|
||||
self.sessionRequestJson = parseJson(sessionRequestJson)
|
||||
var sessionRes: JsonNode
|
||||
let err = backend_wallet_connect.sessionRequest(sessionRes, sessionRequestJson)
|
||||
if err.len > 0:
|
||||
error "Failed to request a session"
|
||||
self.respondSessionRequest(sessionRequestJson, "", true)
|
||||
return
|
||||
raise newException(CatchableError, err)
|
||||
|
||||
self.txResponseDto = sessionRes.toTxResponseDto()
|
||||
if self.txResponseDto.signOnKeycard:
|
||||
let data = SharedKeycarModuleSigningArgs(uniqueIdentifier: UNIQUE_WALLET_CONNECT_MODULE_SIGNING_IDENTIFIER,
|
||||
let data = SharedKeycarModuleSigningArgs(uniqueIdentifier: UNIQUE_WC_SESSION_REQUEST_SIGNING_IDENTIFIER,
|
||||
keyUid: self.txResponseDto.keyUid,
|
||||
path: self.txResponseDto.addressPath,
|
||||
dataToSign: singletonInstance.utils.removeHexPrefix(self.txResponseDto.messageToSign))
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_SIGN_DATA, data)
|
||||
return
|
||||
else:
|
||||
let hashedPasssword = common_utils.hashPassword(password)
|
||||
var signMsgRes: JsonNode
|
||||
|
@ -156,14 +181,56 @@ QtObject:
|
|||
self.txResponseDto.address,
|
||||
hashedPasssword)
|
||||
if err.len > 0:
|
||||
error "Failed to sign message on statusgo side"
|
||||
return
|
||||
let signature = signMsgRes.getStr
|
||||
raise newException(CatchableError, err)
|
||||
signature = signMsgRes.getStr
|
||||
except Exception as e:
|
||||
error "session request", msg=e.msg
|
||||
self.finishSessionRequest(signature)
|
||||
except:
|
||||
error "session request action failed"
|
||||
|
||||
proc getProjectId*(self: Controller): string {.slot.} =
|
||||
return constants.WALLET_CONNECT_PROJECT_ID
|
||||
QtProperty[string] projectId:
|
||||
read = getProjectId
|
||||
|
||||
proc getWalletAccounts*(self: Controller): string {.slot.} =
|
||||
let jsonObj = % self.walletAccountService.getWalletAccounts()
|
||||
return $jsonObj
|
||||
|
||||
proc respondAuthRequest*(self: Controller, signature: string, error: bool) {.signal.}
|
||||
|
||||
proc finishAuthRequest(self: Controller, signature: string) =
|
||||
if signature.len == 0:
|
||||
self.respondAuthRequest("", true)
|
||||
return
|
||||
self.respondAuthRequest(signature, false)
|
||||
|
||||
proc authRequest*(self: Controller, selectedAddress: string, authMessage: string, password: string) {.slot.} =
|
||||
var signature: string
|
||||
try:
|
||||
self.invalidateData()
|
||||
var sessionRes: JsonNode
|
||||
let err = backend_wallet_connect.authRequest(sessionRes, selectedAddress, authMessage)
|
||||
if err.len > 0:
|
||||
raise newException(CatchableError, err)
|
||||
|
||||
self.txResponseDto = sessionRes.toTxResponseDto()
|
||||
if self.txResponseDto.signOnKeycard:
|
||||
let data = SharedKeycarModuleSigningArgs(uniqueIdentifier: UNIQUE_WC_AUTH_REQUEST_SIGNING_IDENTIFIER,
|
||||
keyUid: self.txResponseDto.keyUid,
|
||||
path: self.txResponseDto.addressPath,
|
||||
dataToSign: singletonInstance.utils.removeHexPrefix(self.txResponseDto.messageToSign))
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_SIGN_DATA, data)
|
||||
return
|
||||
else:
|
||||
let hashedPasssword = common_utils.hashPassword(password)
|
||||
var signMsgRes: JsonNode
|
||||
let err = backend_wallet.signMessage(signMsgRes,
|
||||
self.txResponseDto.messageToSign,
|
||||
self.txResponseDto.address,
|
||||
hashedPasssword)
|
||||
if err.len > 0:
|
||||
raise newException(CatchableError, err)
|
||||
signature = signMsgRes.getStr
|
||||
except Exception as e:
|
||||
error "auth request", msg=e.msg
|
||||
self.finishAuthRequest(signature)
|
|
@ -174,7 +174,6 @@ QtObject:
|
|||
proc cancelCurrentFlow*(self: Service) =
|
||||
if self.busy:
|
||||
return
|
||||
writeStackTrace()
|
||||
let response = keycard_go.keycardCancelFlow()
|
||||
self.currentFlow = KCSFlowType.NoFlow
|
||||
if self.doLogging:
|
||||
|
|
|
@ -82,3 +82,27 @@ proc `$`*(self: WalletAccountDto): string =
|
|||
testPreferredChainIds: {self.testPreferredChainIds},
|
||||
hideFromTotalBalance: {self.hideFromTotalBalance}
|
||||
]"""
|
||||
|
||||
proc `%`*(x: WalletAccountDto): JsonNode =
|
||||
result = newJobject()
|
||||
result["name"] = % x.name
|
||||
result["address"] = % x.address
|
||||
result["mixedcaseAddress"] = % x.mixedcaseAddress
|
||||
result["keyUid"] = % x.keyUid
|
||||
result["path"] = % x.path
|
||||
result["colorId"] = % x.colorId
|
||||
result["publicKey"] = % x.publicKey
|
||||
result["isWallet"] = % x.isWallet
|
||||
result["isChat"] = % x.isChat
|
||||
result["emoji"] = % x.emoji
|
||||
result["ens"] = % x.ens
|
||||
result["assetsLoading"] = % x.assetsLoading
|
||||
result["hasBalanceCache"] = % x.hasBalanceCache
|
||||
result["hasMarketValuesCache"] = % x.hasMarketValuesCache
|
||||
result["removed"] = % x.removed
|
||||
result["operable"] = % x.operable
|
||||
result["createdAt"] = % x.createdAt
|
||||
result["position"] = % x.position
|
||||
result["prodPreferredChainIds"] = % x.prodPreferredChainIds
|
||||
result["testPreferredChainIds"] = % x.testPreferredChainIds
|
||||
result["hideFromTotalBalance"] = % x.hideFromTotalBalance
|
|
@ -39,6 +39,10 @@ rpc(wCHasActivePairings, "wallet"):
|
|||
rpc(wCSessionRequest, "wallet"):
|
||||
sessionRequestJson: string
|
||||
|
||||
rpc(wCAuthRequest, "wallet"):
|
||||
address: string
|
||||
message: string
|
||||
|
||||
|
||||
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||
return not rpcResponse.error.isNil
|
||||
|
@ -92,3 +96,11 @@ proc sessionRequest*(res: var JsonNode, sessionRequestJson: string): string =
|
|||
except Exception as e:
|
||||
warn e.msg
|
||||
return e.msg
|
||||
|
||||
proc authRequest*(res: var JsonNode, address: string, authMessage: string): string =
|
||||
try:
|
||||
let response = wCAuthRequest(address, authMessage)
|
||||
return prepareResponse(res, response)
|
||||
except Exception as e:
|
||||
warn e.msg
|
||||
return e.msg
|
|
@ -0,0 +1,32 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import "../../../Profile/controls"
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
|
||||
property ButtonGroup buttonGroup
|
||||
|
||||
signal accountSelected(string address)
|
||||
|
||||
delegate: WalletAccountDelegate {
|
||||
implicitWidth: root.width
|
||||
nextIconVisible: false
|
||||
|
||||
account: model
|
||||
totalCount: ListView.view.count
|
||||
|
||||
components: StatusRadioButton {
|
||||
ButtonGroup.group: root.buttonGroup
|
||||
onClicked: {
|
||||
root.accountSelected(model.address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,6 +49,12 @@ Popup {
|
|||
text: qsTr("Debugging UX until design is ready")
|
||||
}
|
||||
|
||||
StatusSwitch {
|
||||
id: testAuthentication
|
||||
checkable: true
|
||||
text: qsTr("Test Authentication")
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: pairLinkInput
|
||||
|
||||
|
@ -61,36 +67,37 @@ Popup {
|
|||
Layout.fillWidth: true
|
||||
|
||||
StatusButton {
|
||||
text: "Pair"
|
||||
text: testAuthentication.checked? "Authentication" : "Pair"
|
||||
|
||||
onClicked: {
|
||||
statusText.text = "Pairing..."
|
||||
sdk.pair(pairLinkInput.text)
|
||||
}
|
||||
enabled: pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
}
|
||||
if (testAuthentication.checked) {
|
||||
d.setStatusText("")
|
||||
d.setDetailsText("")
|
||||
d.state = ""
|
||||
accountsModel.clear()
|
||||
|
||||
StatusButton {
|
||||
text: "Auth"
|
||||
onClicked: {
|
||||
statusText.text = "Authenticating..."
|
||||
sdk.auth()
|
||||
root.sdk.auth(pairLinkInput.text)
|
||||
return
|
||||
}
|
||||
enabled: false && pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
|
||||
statusText.text = "Pairing..."
|
||||
root.sdk.pair(pairLinkInput.text)
|
||||
}
|
||||
enabled: pairLinkInput.text.length > 0 && root.sdk.sdkReady
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
sdk.approvePairSession(d.sessionProposal, d.supportedNamespaces)
|
||||
// Will trigger an onPairAcceptedResult if successful
|
||||
root.sdk.approvePairSession(d.observedData, d.supportedNamespaces)
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectPairSession(d.sessionProposal.id)
|
||||
root.sdk.rejectPairSession(d.observedData.id)
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
|
@ -103,7 +110,7 @@ Popup {
|
|||
}
|
||||
StatusBaseText {
|
||||
text: "Pairings"
|
||||
visible: sdk.pairingsModel.count > 0
|
||||
visible: root.sdk.pairingsModel.count > 0
|
||||
}
|
||||
|
||||
Pairings {
|
||||
|
@ -112,10 +119,29 @@ Popup {
|
|||
Layout.preferredHeight: contentHeight
|
||||
Layout.maximumHeight: 300
|
||||
|
||||
model: sdk.pairingsModel
|
||||
model: root.sdk.pairingsModel
|
||||
|
||||
onDisconnect: function (topic) {
|
||||
sdk.disconnectPairing(topic)
|
||||
root.sdk.disconnectPairing(topic)
|
||||
}
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: selAccBtnGroup
|
||||
}
|
||||
|
||||
SelectAccount {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: count > 0 ? 400 : 0
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.maximumHeight: 300
|
||||
|
||||
model: accountsModel
|
||||
|
||||
buttonGroup: selAccBtnGroup
|
||||
|
||||
onAccountSelected: {
|
||||
root.sdk.formatAuthMessage(d.observedData.params.cacaoPayload, address)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,23 +157,36 @@ Popup {
|
|||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
if (testAuthentication.checked) {
|
||||
root.controller.authRequest(d.selectedAddress, d.authMessage, passwordInput.text)
|
||||
return
|
||||
}
|
||||
|
||||
root.controller.sessionRequest(JSON.stringify(d.sessionRequest), passwordInput.text)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest ||
|
||||
d.state === d.waitingUserResponseToAuthRequest
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
|
||||
if (testAuthentication.checked) {
|
||||
root.sdk.authReject(d.observedData.id, d.selectedAddress)
|
||||
return
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
|
||||
root.sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest ||
|
||||
d.state === d.waitingUserResponseToAuthRequest
|
||||
}
|
||||
StatusInput {
|
||||
id: passwordInput
|
||||
|
||||
text: "1234567890"
|
||||
placeholderText: "Insert account password"
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest ||
|
||||
d.state === d.waitingUserResponseToAuthRequest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,15 +216,10 @@ Popup {
|
|||
}
|
||||
}
|
||||
|
||||
function onPairSessionProposal(success, sessionProposal) {
|
||||
function onPairSessionProposal(sessionProposal) {
|
||||
d.setDetailsText(sessionProposal)
|
||||
if (success) {
|
||||
d.setStatusText("Pair ID: " + sessionProposal.id + "; Topic: " + sessionProposal.params.pairingTopic)
|
||||
root.controller.pairSessionProposal(JSON.stringify(sessionProposal))
|
||||
// Expecting signal onProposeUserPair(..., true, ...) from controller
|
||||
} else {
|
||||
d.setStatusText("Pairing error", "red")
|
||||
}
|
||||
}
|
||||
|
||||
function onPairAcceptedResult(sessionProposal, success, result) {
|
||||
|
@ -230,12 +264,75 @@ Popup {
|
|||
function onStatusChanged(message) {
|
||||
statusText.text = message
|
||||
}
|
||||
|
||||
function onAuthRequest(request) {
|
||||
d.observedData = request
|
||||
d.setStatusText("Select the address you want to sign in with:")
|
||||
|
||||
accountsModel.clear()
|
||||
|
||||
let walletAccounts = root.controller.getWalletAccounts()
|
||||
try {
|
||||
let walletAccountsJsonArr = JSON.parse(walletAccounts)
|
||||
|
||||
for (let i = 0; i < walletAccountsJsonArr.length; i++) {
|
||||
let obj = {
|
||||
preferredSharingChainIds: ""
|
||||
}
|
||||
|
||||
for (var key in walletAccountsJsonArr[i]) {
|
||||
obj[key] = walletAccountsJsonArr[i][key]
|
||||
}
|
||||
|
||||
accountsModel.append(obj)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error("error parsing wallet accounts, error: ", e)
|
||||
d.setStatusText("error parsing walelt accounts", "red")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function onAuthSignMessage(message, address) {
|
||||
let details = ""
|
||||
if (!!d.observedData.verifyContext.verified.isScam) {
|
||||
details = "This website you`re trying to connect is flagged as malicious by multiple security providers.\nApproving may lead to loss of funds."
|
||||
} else {
|
||||
if (d.observedData.verifyContext.verified.validation === "UNKNOWN")
|
||||
details = "Website is Unverified"
|
||||
else if (d.observedData.verifyContext.verified.validation === "INVALID")
|
||||
details = "Website is Mismatched"
|
||||
else
|
||||
details = "Website is Valid"
|
||||
}
|
||||
|
||||
d.selectedAddress = address
|
||||
d.authMessage = message
|
||||
d.setDetailsText(`${details}\n\n${message}`)
|
||||
d.state = d.waitingUserResponseToAuthRequest
|
||||
}
|
||||
|
||||
function onAuthRequestUserAnswerResult(accept, error) {
|
||||
if (error) {
|
||||
d.setStatusText(`Auth Request ${accept ? "Accept" : "Reject"} error`, "red")
|
||||
return
|
||||
}
|
||||
|
||||
if (accept) {
|
||||
d.setStatusText(`Auth Request completed`)
|
||||
} else {
|
||||
d.setStatusText(`Auth Request aborted`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property var sessionProposal: null
|
||||
property string selectedAddress: ""
|
||||
property var observedData: null
|
||||
property var authMessage: null
|
||||
property var supportedNamespaces: null
|
||||
|
||||
property var sessionRequest: null
|
||||
|
@ -245,6 +342,7 @@ Popup {
|
|||
readonly property string sdkReadyState: "sdk_ready"
|
||||
readonly property string waitingPairState: "waiting_pairing"
|
||||
readonly property string waitingUserResponseToSessionRequest: "waiting_user_response_to_session_request"
|
||||
readonly property string waitingUserResponseToAuthRequest: "waiting_user_response_to_auth_request"
|
||||
readonly property string pairedState: "paired"
|
||||
|
||||
function setStatusText(message, textColor) {
|
||||
|
@ -264,13 +362,17 @@ Popup {
|
|||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: accountsModel
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.controller
|
||||
|
||||
function onProposeUserPair(sessionProposalJson, supportedNamespacesJson) {
|
||||
d.setStatusText("Waiting user accept")
|
||||
|
||||
d.sessionProposal = JSON.parse(sessionProposalJson)
|
||||
d.observedData = JSON.parse(sessionProposalJson)
|
||||
d.supportedNamespaces = JSON.parse(supportedNamespacesJson)
|
||||
|
||||
d.setDetailsText(JSON.stringify(d.supportedNamespaces, null, 2))
|
||||
|
@ -282,19 +384,30 @@ Popup {
|
|||
console.log("WC respondSessionRequest", sessionRequestJson, " signedData", signedData, " error: ", error)
|
||||
if (error) {
|
||||
d.setStatusText("Session Request error", "red")
|
||||
sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, true)
|
||||
root.sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, true)
|
||||
return
|
||||
}
|
||||
|
||||
d.sessionRequest = JSON.parse(sessionRequestJson)
|
||||
d.signedData = signedData
|
||||
|
||||
sdk.acceptSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, d.signedData)
|
||||
root.sdk.acceptSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, d.signedData)
|
||||
|
||||
d.state = d.pairedState
|
||||
|
||||
d.setStatusText("Session Request accepted")
|
||||
d.setDetailsText(d.signedData)
|
||||
}
|
||||
|
||||
function onRespondAuthRequest(signature, error) {
|
||||
console.log("WC signature", signature, " error: ", error)
|
||||
if (error) {
|
||||
d.setStatusText("Session Request error", "red")
|
||||
root.sdk.authReject(d.observedData.id, d.selectedAddress)
|
||||
return
|
||||
}
|
||||
|
||||
root.sdk.authApprove(d.observedData, d.selectedAddress, signature)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,32 +24,32 @@ Item {
|
|||
|
||||
signal statusChanged(string message)
|
||||
signal sdkInit(bool success, var result)
|
||||
signal pairSessionProposal(bool success, var sessionProposal)
|
||||
signal pairSessionProposal(var sessionProposal)
|
||||
signal pairSessionProposalExpired()
|
||||
signal pairAcceptedResult(var sessionProposal, bool success, var sessionType)
|
||||
signal pairRejectedResult(bool success, var result)
|
||||
signal sessionRequestEvent(var sessionRequest)
|
||||
signal sessionRequestUserAnswerResult(bool accept, string error)
|
||||
|
||||
signal authRequest(var request)
|
||||
signal authSignMessage(string message, string address)
|
||||
signal authRequestUserAnswerResult(bool accept, string error)
|
||||
|
||||
signal sessionDelete(var deletePayload)
|
||||
|
||||
function pair(pairLink)
|
||||
{
|
||||
function pair(pairLink) {
|
||||
wcCalls.pair(pairLink)
|
||||
}
|
||||
|
||||
function disconnectPairing(topic)
|
||||
{
|
||||
function disconnectPairing(topic) {
|
||||
wcCalls.disconnectPairing(topic)
|
||||
}
|
||||
|
||||
function approvePairSession(sessionProposal, supportedNamespaces)
|
||||
{
|
||||
function approvePairSession(sessionProposal, supportedNamespaces) {
|
||||
wcCalls.approvePairSession(sessionProposal, supportedNamespaces)
|
||||
}
|
||||
|
||||
function rejectPairSession(id)
|
||||
{
|
||||
function rejectPairSession(id) {
|
||||
wcCalls.rejectPairSession(id)
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,22 @@ Item {
|
|||
wcCalls.rejectSessionRequest(topic, id, error)
|
||||
}
|
||||
|
||||
function auth(authLink) {
|
||||
wcCalls.auth(authLink)
|
||||
}
|
||||
|
||||
function formatAuthMessage(cacaoPayload, address) {
|
||||
wcCalls.formatAuthMessage(cacaoPayload, address)
|
||||
}
|
||||
|
||||
function authApprove(authRequest, address, signature) {
|
||||
wcCalls.authApprove(authRequest, address, signature)
|
||||
}
|
||||
|
||||
function authReject(id, address) {
|
||||
wcCalls.authReject(id, address)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -275,6 +291,74 @@ Item {
|
|||
d.resetPairingsModel()
|
||||
})
|
||||
}
|
||||
|
||||
function auth(authLink) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.auth; authLink: ${authLink}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.auth("${authLink}")`, function(result) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.auth; response: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
if (result) {
|
||||
if (!!result.error) {
|
||||
console.error("auth: ", result.error)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function formatAuthMessage(cacaoPayload, address) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.auth; cacaoPayload: ${JSON.stringify(cacaoPayload)}, address: ${address}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.formatAuthMessage(${JSON.stringify(cacaoPayload)}, "${address}")`, function(result) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.formatAuthMessage; response: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
if (result) {
|
||||
if (!!result.error) {
|
||||
console.error("formatAuthMessage: ", result.error)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
root.authSignMessage(result.result, address)
|
||||
})
|
||||
}
|
||||
|
||||
function authApprove(authRequest, address, signature) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.authApprove; authRequest: ${JSON.stringify(authRequest)}, address: ${address}, signature: ${signature}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.approveAuth(${JSON.stringify(authRequest)}, "${address}", "${signature}")`, function(result) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.approveAuth; response: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
if (result) {
|
||||
if (!!result.error)
|
||||
{
|
||||
console.error("approveAuth: ", result.error)
|
||||
root.authRequestUserAnswerResult(true, result.error)
|
||||
return
|
||||
}
|
||||
root.authRequestUserAnswerResult(true, result.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function authReject(id, address) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.authReject; id: ${id}, address: ${address}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.rejectAuth(${id}, "${address}")`, function(result) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.rejectAuth; response: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
if (result) {
|
||||
if (!!result.error)
|
||||
{
|
||||
console.error("rejectAuth: ", result.error)
|
||||
root.authRequestUserAnswerResult(false, result.error)
|
||||
return
|
||||
}
|
||||
root.authRequestUserAnswerResult(false, result.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -303,7 +387,7 @@ Item {
|
|||
function onSessionProposal(details)
|
||||
{
|
||||
console.debug(`WC WalletConnectSDK.onSessionProposal; details: ${JSON.stringify(details, null, 2)}`)
|
||||
root.pairSessionProposal(true, details)
|
||||
root.pairSessionProposal(details)
|
||||
}
|
||||
|
||||
function onSessionUpdate(details)
|
||||
|
@ -353,6 +437,12 @@ Item {
|
|||
console.debug(`WC WalletConnectSDK.onProposalExpire; details: ${JSON.stringify(details, null, 2)}`)
|
||||
root.pairSessionProposalExpired()
|
||||
}
|
||||
|
||||
function onAuthRequest(details)
|
||||
{
|
||||
console.debug(`WC WalletConnectSDK.onAuthRequest; details: ${JSON.stringify(details, null, 2)}`)
|
||||
root.authRequest(details)
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,8 +1,7 @@
|
|||
import { Core } from "@walletconnect/core";
|
||||
import { Web3Wallet } from "@walletconnect/web3wallet";
|
||||
|
||||
// Disabled for now to debug the issue with wrong pairing topic
|
||||
//import AuthClient from '@walletconnect/auth-client'
|
||||
import AuthClient from '@walletconnect/auth-client'
|
||||
|
||||
// import the builder util
|
||||
import { buildApprovedNamespaces, getSdkError } from "@walletconnect/utils";
|
||||
|
@ -49,10 +48,10 @@ window.wc = {
|
|||
},
|
||||
});
|
||||
|
||||
//window.wc.authClient = await AuthClient.init({
|
||||
// projectId: projectId,
|
||||
// metadata: window.wc.web3wallet.metadata,
|
||||
//});
|
||||
window.wc.authClient = await AuthClient.init({
|
||||
projectId: projectId,
|
||||
metadata: window.wc.web3wallet.metadata,
|
||||
});
|
||||
|
||||
// connect session responses https://specs.walletconnect.com/2.0/specs/clients/sign/session-events#events
|
||||
window.wc.web3wallet.on("session_proposal", async (details) => {
|
||||
|
@ -95,6 +94,10 @@ window.wc = {
|
|||
wc.statusObject.onProposalExpire(details)
|
||||
});
|
||||
|
||||
window.wc.authClient.on("auth_request", async (details) => {
|
||||
wc.statusObject.onAuthRequest(details)
|
||||
});
|
||||
|
||||
wc.statusObject.sdkInitialized("");
|
||||
resolve("");
|
||||
});
|
||||
|
@ -130,7 +133,6 @@ window.wc = {
|
|||
supportedNamespaces: supportedNamespaces,
|
||||
});
|
||||
|
||||
wc.statusObject.bubbleConsoleMessage("debug", `web3wallet.approveSession id: ${id} ${JSON.stringify(approvedNamespaces, null, 2)}`)
|
||||
return {
|
||||
result: window.wc.web3wallet.approveSession({
|
||||
id,
|
||||
|
@ -149,45 +151,66 @@ window.wc = {
|
|||
};
|
||||
},
|
||||
|
||||
// auth: function (uri) {
|
||||
// return {
|
||||
// result: window.wc.authClient.core.pairing.pair({ uri }),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
auth: function (uri) {
|
||||
try {
|
||||
return {
|
||||
result: window.wc.authClient.core.pairing.pair({ uri }),
|
||||
error: ""
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
result: "",
|
||||
error: e
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// approveAuth: function (authProposal) {
|
||||
// const { id, params } = authProposal;
|
||||
formatAuthMessage: function (cacaoPayload, address) {
|
||||
const iss = `did:pkh:eip155:1:${address}`;
|
||||
|
||||
// // TODO: source user’s address
|
||||
// const iss = `did:pkh:eip155:1:${"0x0123456789"}`;
|
||||
return {
|
||||
result: window.wc.authClient.formatMessage(cacaoPayload, iss),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
|
||||
// // format the cacao payload with the user’s address
|
||||
// const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss);
|
||||
approveAuth: function (authRequest, address, signature) {
|
||||
const { id, params } = authRequest;
|
||||
|
||||
// // TODO: signature
|
||||
// const signature = "0x123456789"
|
||||
const iss = `did:pkh:eip155:1:${address}`;
|
||||
|
||||
// return {
|
||||
// result: window.wc.authClient.respond(
|
||||
// {
|
||||
// id: id,
|
||||
// signature: {
|
||||
// s: signature,
|
||||
// t: "eip191",
|
||||
// },
|
||||
// },
|
||||
// iss),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss);
|
||||
|
||||
// rejectAuth: function (id) {
|
||||
// return {
|
||||
// result: window.wc.authClient.reject(id),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
return {
|
||||
result: window.wc.authClient.respond(
|
||||
{
|
||||
id: id,
|
||||
signature: {
|
||||
s: signature,
|
||||
t: "eip191",
|
||||
},
|
||||
},
|
||||
iss),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
|
||||
rejectAuth: function (id, address) {
|
||||
const iss = `did:pkh:eip155:1:${address}`;
|
||||
|
||||
return {
|
||||
result: window.wc.authClient.respond(
|
||||
{
|
||||
id: id,
|
||||
error: {
|
||||
code: 4001,
|
||||
message: 'Auth request has been rejected'
|
||||
},
|
||||
},
|
||||
iss),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
|
||||
respondSessionRequest: function (topic, id, signature) {
|
||||
const response = formatJsonRpcResult(id, signature)
|
||||
|
@ -200,7 +223,6 @@ window.wc = {
|
|||
};
|
||||
|
||||
} catch (e) {
|
||||
wc.statusObject.bubbleConsoleMessage("error", `respondSessionRequest error: ${JSON.stringify(e, null, 2)}`)
|
||||
return {
|
||||
result: "",
|
||||
error: e
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 04c533b8d5f1e0249b9edd38ef1304b9e9ef81de
|
||||
Subproject commit 12ba1bdf6987d767cd56bbeb011607659f39d30d
|
Loading…
Reference in New Issue