Skip to content

Commit fe3fd66

Browse files
committed
feat(dapp-browser)_: connected dapps popup
fixes #19223
1 parent 5cb9c69 commit fe3fd66

File tree

16 files changed

+329
-64
lines changed

16 files changed

+329
-64
lines changed

src/app/core/signals/remote_signals/connector.nim

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type ConnectorSendRequestAccountsSignal* = ref object of Signal
88
name*: string
99
iconUrl*: string
1010
requestId*: string
11+
clientId*: string
1112

1213
type ConnectorSendTransactionSignal* = ref object of Signal
1314
url*: string
@@ -16,18 +17,21 @@ type ConnectorSendTransactionSignal* = ref object of Signal
1617
requestId*: string
1718
chainId*: int
1819
txArgs*: string
20+
clientId*: string
1921

2022
type ConnectorGrantDAppPermissionSignal* = ref object of Signal
2123
url*: string
2224
name*: string
2325
iconUrl*: string
2426
chains*: string
2527
sharedAccount*: string
28+
clientId*: string
2629

2730
type ConnectorRevokeDAppPermissionSignal* = ref object of Signal
2831
url*: string
2932
name*: string
3033
iconUrl*: string
34+
clientId*: string
3135

3236
type ConnectorSignSignal* = ref object of Signal
3337
url*: string
@@ -37,10 +41,12 @@ type ConnectorSignSignal* = ref object of Signal
3741
challenge*: string
3842
address*: string
3943
signMethod*: string
44+
clientId*: string
4045

4146
type ConnectorDAppChainIdSwitchedSignal* = ref object of Signal
4247
url*: string
4348
chainId*: string
49+
clientId*: string
4450

4551
type ConnectorAccountChangedSignal* = ref object of Signal
4652
url*: string
@@ -54,6 +60,7 @@ proc fromEvent*(T: type ConnectorSendRequestAccountsSignal, event: JsonNode): Co
5460
result.name = event["event"]{"name"}.getStr()
5561
result.iconUrl = event["event"]{"iconUrl"}.getStr()
5662
result.requestId = event["event"]{"requestId"}.getStr()
63+
result.clientId = event["event"]{"clientId"}.getStr()
5764

5865
proc fromEvent*(T: type ConnectorSendTransactionSignal, event: JsonNode): ConnectorSendTransactionSignal =
5966
result = ConnectorSendTransactionSignal()
@@ -64,6 +71,7 @@ proc fromEvent*(T: type ConnectorSendTransactionSignal, event: JsonNode): Connec
6471
result.requestId = event["event"]{"requestId"}.getStr()
6572
result.chainId = event["event"]{"chainId"}.getInt()
6673
result.txArgs = event["event"]{"txArgs"}.getStr()
74+
result.clientId = event["event"]{"clientId"}.getStr()
6775

6876
proc fromEvent*(T: type ConnectorGrantDAppPermissionSignal, event: JsonNode): ConnectorGrantDAppPermissionSignal =
6977
result = ConnectorGrantDAppPermissionSignal()
@@ -73,13 +81,15 @@ proc fromEvent*(T: type ConnectorGrantDAppPermissionSignal, event: JsonNode): Co
7381
result.iconUrl = event["event"]{"iconUrl"}.getStr()
7482
result.chains = $(event["event"]{"chains"})
7583
result.sharedAccount = event["event"]{"sharedAccount"}.getStr()
84+
result.clientId = event["event"]{"clientId"}.getStr()
7685

7786
proc fromEvent*(T: type ConnectorRevokeDAppPermissionSignal, event: JsonNode): ConnectorRevokeDAppPermissionSignal =
7887
result = ConnectorRevokeDAppPermissionSignal()
7988
result.signalType = SignalType.ConnectorRevokeDAppPermission
8089
result.url = event["event"]{"url"}.getStr()
8190
result.name = event["event"]{"name"}.getStr()
8291
result.iconUrl = event["event"]{"iconUrl"}.getStr()
92+
result.clientId = event["event"]{"clientId"}.getStr()
8393

8494
proc fromEvent*(T: type ConnectorSignSignal, event: JsonNode): ConnectorSignSignal =
8595
result = ConnectorSignSignal()
@@ -91,16 +101,18 @@ proc fromEvent*(T: type ConnectorSignSignal, event: JsonNode): ConnectorSignSign
91101
result.challenge = event["event"]{"challenge"}.getStr()
92102
result.address = event["event"]{"address"}.getStr()
93103
result.signMethod = event["event"]{"method"}.getStr()
104+
result.clientId = event["event"]{"clientId"}.getStr()
94105

95106
proc fromEvent*(T: type ConnectorDAppChainIdSwitchedSignal, event: JsonNode): ConnectorDAppChainIdSwitchedSignal =
96107
result = ConnectorDAppChainIdSwitchedSignal()
97108
result.signalType = SignalType.ConnectorDAppChainIdSwitched
98109
result.url = event["event"]{"url"}.getStr()
99110
result.chainId = event["event"]{"chainId"}.getStr()
111+
result.clientId = event["event"]{"clientId"}.getStr()
100112

101113
proc fromEvent*(T: type ConnectorAccountChangedSignal, event: JsonNode): ConnectorAccountChangedSignal =
102114
result = ConnectorAccountChangedSignal()
103115
result.signalType = SignalType.ConnectorAccountChanged
104116
result.url = event["event"]{"url"}.getStr()
105117
result.clientId = event["event"]{"clientId"}.getStr()
106-
result.sharedAccount = event["event"]{"sharedAccount"}.getStr()
118+
result.sharedAccount = event["event"]{"sharedAccount"}.getStr()

src/app/modules/shared_modules/connector/controller.nim

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ QtObject:
7777
"url": params.url,
7878
"chains": params.chains,
7979
"sharedAccount": params.sharedAccount,
80+
"clientId": params.clientId
8081
}
8182

8283
controller.emitConnected(dappInfo.toJson())
@@ -87,6 +88,7 @@ QtObject:
8788
"icon": params.iconUrl,
8889
"name": params.name,
8990
"url": params.url,
91+
"clientId": params.clientId
9092
}
9193

9294
controller.emitDisconnected(dappInfo.toJson())
@@ -113,7 +115,8 @@ QtObject:
113115
let params = ConnectorDAppChainIdSwitchedSignal(e)
114116
let chainInfo = %*{
115117
"url": params.url,
116-
"chainId": params.chainId
118+
"chainId": params.chainId,
119+
"clientId": params.clientId
117120
}
118121
controller.emitChainIdSwitched(chainInfo.toJson())
119122
except Exception as ex:
@@ -206,12 +209,15 @@ QtObject:
206209
result = self.service.rejectTransactionSigning(requestId)
207210
self.rejectTransactionResponse(sessionTopic, requestId, not result)
208211

209-
proc disconnect*(self: Controller, dAppUrl: string): bool {.slot.} =
210-
result = self.service.recallDAppPermission(dAppUrl)
212+
proc disconnect*(self: Controller, dAppUrl: string, clientId: string = ""): bool {.slot.} =
213+
result = self.service.recallDAppPermission(dAppUrl, clientId)
211214

212215
proc getDApps*(self: Controller): string {.slot.} =
213216
return self.service.getDApps()
214217

218+
proc getDAppsByClientId*(self: Controller, clientId: string): string {.slot.} =
219+
return self.service.getDAppsByClientId(clientId)
220+
215221
proc approveSigning*(self: Controller, sessionTopic: string, requestId: string, signature: string): bool {.slot.} =
216222
result = self.service.approveSignRequest(requestId, signature)
217223
self.approveSignResponse(sessionTopic, requestId, not result)

src/app_service/service/connector/service.nim

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ QtObject:
6161

6262
var data = ConnectorSendRequestAccountsSignal(e)
6363

64-
if not data.requestId.len() == 0:
64+
if data.requestId.len() == 0:
6565
error "ConnectorSendRequestAccountsSignal failed, requestId is empty"
6666
return
6767

@@ -73,7 +73,7 @@ QtObject:
7373

7474
var data = ConnectorSendTransactionSignal(e)
7575

76-
if not data.requestId.len() == 0:
76+
if data.requestId.len() == 0:
7777
error "ConnectorSendTransactionSignal failed, requestId is empty"
7878
return
7979

@@ -101,10 +101,13 @@ QtObject:
101101

102102
var data = ConnectorSignSignal(e)
103103

104-
if not data.requestId.len() == 0:
104+
debug "ConnectorSign received", requestId=data.requestId, requestIdLen=data.requestId.len()
105+
106+
if data.requestId.len() == 0:
105107
error "ConnectorSignSignal failed, requestId is empty"
106108
return
107109

110+
debug "ConnectorSign emitting signal", requestId=data.requestId
108111
self.events.emit(SIGNAL_CONNECTOR_EVENT_CONNECTOR_SIGN, data)
109112
)
110113
self.events.on(SignalType.ConnectorDAppChainIdSwitched.event, proc(e: Args) =
@@ -175,9 +178,9 @@ QtObject:
175178
proc rejectDappConnect*(self: Service, requestId: string): bool =
176179
rejectRequest(self, requestId, status_go.requestAccountsRejectedFinishedRpc, "requestAccountsRejectedFinishedRpc failed: ")
177180

178-
proc recallDAppPermission*(self: Service, dAppUrl: string): bool =
181+
proc recallDAppPermission*(self: Service, dAppUrl: string, clientId: string = ""): bool =
179182
try:
180-
return status_go.recallDAppPermissionFinishedRpc(dAppUrl)
183+
return status_go.recallDAppPermissionFinishedRpc(dAppUrl, clientId)
181184

182185
except Exception as e:
183186
error "recallDAppPermissionFinishedRpc failed: ", err=e.msg
@@ -196,6 +199,29 @@ QtObject:
196199
error "getDApps failed: ", err=e.msg
197200
return "[]"
198201

202+
proc getDAppsByClientId*(self: Service, clientId: string): string =
203+
try:
204+
let response = status_go.getPermittedDAppsList()
205+
if not response.error.isNil:
206+
raise newException(Exception, "Error getting connector dapp list: " & response.error.message)
207+
208+
let jsonArray = $response.result
209+
if jsonArray == "null":
210+
return "[]"
211+
212+
# Parse and filter by clientId
213+
let allDapps = parseJson(jsonArray)
214+
var filteredDapps = newJArray()
215+
216+
for dapp in allDapps:
217+
if dapp.hasKey("clientId") and dapp["clientId"].getStr() == clientId:
218+
filteredDapps.add(dapp)
219+
220+
return $filteredDapps
221+
except Exception as e:
222+
error "getDAppsByClientId failed: ", err=e.msg
223+
return "[]"
224+
199225
proc approveSignRequest*(self: Service, requestId: string, signature: string): bool =
200226
try:
201227
var args = SignAcceptedArgs()

src/backend/connector.nim

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ type SendTransactionAcceptedArgs* = ref object of RootObj
2424
type RejectedArgs* = ref object of RootObj
2525
requestId* {.serializedFieldName("requestId").}: string
2626

27-
type RecallDAppPermissionArgs* = ref object of RootObj
28-
dAppUrl* {.serializedFieldName("dAppUrl").}: string
29-
3027
type SignAcceptedArgs* = ref object of RootObj
3128
requestId* {.serializedFieldName("requestId").}: string
3229
signature* {.serializedFieldName("signature").}: string
@@ -48,8 +45,9 @@ rpc(sendTransactionRejected, "connector"):
4845
rpc(requestAccountsRejected, "connector"):
4946
args: RejectedArgs
5047

51-
rpc(recallDAppPermission, "connector"):
52-
dAppUrl: string
48+
rpc(recallDAppPermissionV2, "connector"):
49+
url: string
50+
clientId: string
5351

5452
rpc(getPermittedDAppsList, "connector"):
5553
discard
@@ -81,8 +79,8 @@ proc sendTransactionAcceptedFinishedRpc*(args: SendTransactionAcceptedArgs): boo
8179
proc sendTransactionRejectedFinishedRpc*(args: RejectedArgs): bool =
8280
return isSuccessResponse(sendTransactionRejected(args))
8381

84-
proc recallDAppPermissionFinishedRpc*(dAppUrl: string): bool =
85-
return isSuccessResponse(recallDAppPermission(dAppUrl))
82+
proc recallDAppPermissionFinishedRpc*(dAppUrl: string, clientId: string): bool =
83+
return isSuccessResponse(recallDAppPermissionV2(dAppUrl, clientId))
8684

8785
proc sendSignAcceptedFinishedRpc*(args: SignAcceptedArgs): bool =
8886
return isSuccessResponse(signAccepted(args))

ui/app/AppLayouts/Browser/BrowserLayout.qml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import shared.popups.send
1717
import shared.stores.send
1818

1919
import AppLayouts.Browser.stores as BrowserStores
20+
import AppLayouts.Wallet.services.dapps
2021

2122
import "provider/qml"
2223
import "popups"
@@ -40,6 +41,7 @@ StatusSectionLayout {
4041
required property BrowserStores.BrowserRootStore browserRootStore
4142
required property BrowserStores.BrowserWalletStore browserWalletStore
4243
required property var connectorController
44+
property bool isDebugEnabled: false
4345

4446
signal sendToRecipientRequested(string address)
4547

@@ -62,6 +64,12 @@ StatusSectionLayout {
6264
}
6365
}
6466

67+
BCBrowserDappsProvider {
68+
id: browserDappsProvider
69+
connectorController: root.connectorController
70+
clientId: connectorBridge.clientId // "status-desktop/dapp-browser"
71+
}
72+
6573
QtObject {
6674
id: _internal
6775

@@ -163,11 +171,21 @@ StatusSectionLayout {
163171
canGoBack: (!!_internal.currentWebView && _internal.currentWebView.canGoBack)
164172
canGoForward: (!!_internal.currentWebView && _internal.currentWebView.canGoForward)
165173
currentTabConnected: root.browserRootStore.currentTabConnected
174+
browserDappsModel: browserDappsProvider.model
175+
browserDappsCount: browserDappsProvider.model ? browserDappsProvider.model.count : 0
166176
onOpenHistoryPopup: (xPos, yPos) => historyMenu.popup(xPos, yPos)
167177
onGoBack: _internal.currentWebView.goBack()
168178
onGoForward: _internal.currentWebView.goForward()
169179
onReload: _internal.currentWebView.reload()
170180
onStopLoading: _internal.currentWebView.stop()
181+
onOpenDappUrl: function(url) {
182+
if (_internal.currentWebView) {
183+
_internal.currentWebView.url = _internal.determineRealURL(url)
184+
}
185+
}
186+
onDisconnectDapp: function(dappUrl) {
187+
connectorBridge.disconnect(dappUrl)
188+
}
171189
onAddNewFavoriteClicked: function(xPos) {
172190
Global.openPopup(addFavoriteModal,
173191
{
@@ -360,6 +378,7 @@ StatusSectionLayout {
360378
}
361379
}
362380
onDisconnect: {
381+
connectorBridge.disconnectCurrentTab()
363382
_internal.currentWebView.reload()
364383
close()
365384
}
@@ -451,6 +470,8 @@ StatusSectionLayout {
451470
favMenu: favoriteMenu
452471
addFavModal: addFavoriteModal
453472
downloadsMenu: downloadMenu
473+
enableJsLogs: root.isDebugEnabled
474+
454475
determineRealURLFn: function(url) {
455476
return _internal.determineRealURL(url)
456477
}
@@ -532,12 +553,23 @@ StatusSectionLayout {
532553
target: _internal.currentWebView
533554
function onUrlChanged() {
534555
browserHeader.addressBar.text = root.browserRootStore.obtainAddress(_internal.currentWebView.url)
535-
root.browserRootStore.currentTabConnected = false // TODO: Will be handled by connector https://github.com/status-im/status-desktop/issues/19223
536556

557+
if (_internal.currentWebView && _internal.currentWebView.url) {
558+
const urlStr = _internal.currentWebView.url.toString()
559+
const hostname = Utils.getHostname(urlStr)
560+
561+
root.browserRootStore.currentTabConnected = connectorBridge.hasWalletConnected(
562+
hostname,
563+
root.browserWalletStore.dappBrowserAccount.address
564+
)
565+
} else {
566+
root.browserRootStore.currentTabConnected = false
567+
}
568+
537569
// Update ConnectorBridge with current dApp metadata
538570
if (_internal.currentWebView && _internal.currentWebView.url) {
539571
connectorBridge.connectorManager.updateDAppUrl(
540-
_internal.currentWebView.url,
572+
_internal.currentWebView.url,
541573
_internal.currentWebView.title,
542574
_internal.currentWebView.icon
543575
)

ui/app/AppLayouts/Browser/panels/BrowserHeader.qml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import StatusQ.Core.Theme
77
import StatusQ.Core.Utils as SQUtils
88

99
import shared.controls
10+
import AppLayouts.Wallet.controls
1011

1112
import utils
1213

@@ -29,6 +30,9 @@ Rectangle {
2930
property string dappBrowserAccIcon: ""
3031
property var settingMenu
3132

33+
property var browserDappsModel: null
34+
property int browserDappsCount: 0
35+
3236
signal addNewFavoriteClicked(int xPos)
3337
signal launchInBrowser(string url)
3438
signal openHistoryPopup(int xPos, int yPos)
@@ -37,6 +41,8 @@ Rectangle {
3741
signal reload()
3842
signal stopLoading()
3943
signal openWalletMenu()
44+
signal openDappUrl(string url)
45+
signal disconnectDapp(string dappUrl)
4046

4147
QtObject {
4248
id: _internal
@@ -158,6 +164,30 @@ Rectangle {
158164
}
159165
}
160166

167+
DappsComboBox {
168+
Layout.preferredWidth: 38
169+
Layout.preferredHeight: 38
170+
spacing: 8
171+
172+
visible: true
173+
enabled: true
174+
model: root.browserDappsModel
175+
showConnectButton: false
176+
177+
onDisconnectDapp: function(dappUrl) {
178+
root.disconnectDapp(dappUrl)
179+
}
180+
181+
onDappClicked: function(dappUrl) {
182+
root.openDappUrl(dappUrl)
183+
}
184+
185+
onConnectDapp: {
186+
console.log("[Browser] Connect new dApp requested")
187+
// Can open a modal or use DAppsWorkflow in the future
188+
}
189+
}
190+
161191
Loader {
162192
Layout.preferredWidth: 44
163193
Layout.preferredHeight: 44

0 commit comments

Comments
 (0)