Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add logger to apps/connector #643

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sharp-cheetahs-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'connector': patch
---

add logger
8 changes: 8 additions & 0 deletions apps/connector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ FLAG_CONNECTOR_ENABLED=1 '/Volumes/Status Desktop/Status.app/Contents/MacOS/nim_
## Testing

Download latest build from last merged PR or build from source. To use the extension see the load steps from [Development](#development) section.

### Logging

Browser > Console

```
await connector.enableLogging(true)
```
5 changes: 5 additions & 0 deletions apps/connector/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import configs, { tailwindcssConfigs } from '@status-im/eslint-config'
export default [
...configs,
...tailwindcssConfigs,
{
rules: {
'no-console': 'error',
},
},
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
Expand Down
1 change: 1 addition & 0 deletions apps/connector/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import type { Provider } from './src/contents/provider'
declare global {
interface Window {
ethereum: Provider
registration?: ServiceWorkerRegistration
}
}
8 changes: 8 additions & 0 deletions apps/connector/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,11 @@ chrome.action.onClicked.addListener(async tab => {
type: 'status:icon:clicked',
} satisfies ServiceWorkerMessage)
})

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.method === 'toggleLogging') {
storage.set('status:logging', message.params[0])

sendResponse(message.params[0])
}
})
73 changes: 73 additions & 0 deletions apps/connector/src/contents/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ProxyMessage } from '~messages/proxy-message'

import type { RequestArguments } from '~lib/request-arguments'
import type { PlasmoCSConfig } from 'plasmo'

export const config: PlasmoCSConfig = {
matches: ['https://*/*'],
world: 'MAIN',
run_at: 'document_start',
all_frames: false,
}

Object.defineProperties(window, {
connector: {
value: {
enableLogging: (value = true) => {
// shared web storage with host page and content scripts (Web Storage API)
window.localStorage.setItem('status:logging', JSON.stringify(value))

// service worker extension storage (extension storage API)
request({
method: 'toggleLogging',
params: [value],
})

return value
},
},
configurable: false,
writable: false,
},
})

async function request(args: RequestArguments) {
const { method, params } = args

const messageChannel = new MessageChannel()

return new Promise((resolve, reject) => {
messageChannel.port1.onmessage = ({ data }) => {
try {
const message = ProxyMessage.parse(data)

messageChannel.port1.close()

switch (message.type) {
case 'status:proxy:success': {
resolve(message.data)

return
}
case 'status:proxy:error': {
reject(new Error(message.error.message))

return
}
}
} catch {
return
}
}

const mainMessage = {
type: 'status:main',
data: {
method,
params,
},
}

window.postMessage(mainMessage, window.origin, [messageChannel.port2])
})
}
21 changes: 19 additions & 2 deletions apps/connector/src/contents/provider.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { logger } from '~lib/logger'
import { ProviderRpcError } from '~lib/provider-rpc-error'
import { RequestArguments } from '~lib/request-arguments'
import { ProxyMessage } from '~messages/proxy-message'
Expand Down Expand Up @@ -96,18 +97,24 @@ export class Provider {
this.#listeners.get('connect')?.({ chainId: '0x1' })
this.#listeners.get('connected')?.({ chainId: '0x1' })
this.connected = true

logger.info('connected::')
}

if (method === 'wallet_switchEthereumChain') {
this.#listeners.get('chainChanged')?.(message.data)
this.#listeners.get('networkChanged')?.(message.data)

logger.info('chainChanged::')
}

resolve(message.data)

return
}
case 'status:proxy:error': {
logger.error(message.error)

// note: for those dApps that make call after having permissions revoked
if (
message.error.message === 'dApp is not permitted by user' &&
Expand Down Expand Up @@ -148,15 +155,21 @@ export class Provider {
}

public on(event: Event, handler: (args: unknown) => void): void {
logger.info('on::', event, handler)

this.#listeners.set(event, handler)
}

/** @deprecated */
public async close(): Promise<void> {
public async close(...args: unknown[]): Promise<void> {
logger.info('close::', args)

this.disconnect()
}

public removeListener(event: Event): void {
public removeListener(event: Event, handler: (args: unknown) => void): void {
logger.info('removeListener::', event, handler)

// note: not all dapps remove these on disconnect
if (event === 'close' || event === 'disconnect') {
this.disconnect()
Expand All @@ -166,6 +179,8 @@ export class Provider {
}

public async enable() {
logger.info('enable::')

return true
}

Expand All @@ -176,6 +191,8 @@ export class Provider {

this.connected = false

logger.info('disconnect::')

await this.request({
method: 'wallet_revokePermissions',
params: [
Expand Down
55 changes: 49 additions & 6 deletions apps/connector/src/contents/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { getFaviconUrl } from '~lib/get-favicon-url'
import { logger } from '~lib/logger'
import { MainMessage } from '~messages/main-message'
import { ProviderMessage } from '~messages/provider-message'

import { DesktopClient } from '../lib/desktop-client'
Expand All @@ -13,7 +15,7 @@ export const config: PlasmoCSConfig = {

const desktopClient = new DesktopClient()

const handleMessage = async (event: MessageEvent) => {
const handleProviderMessage = async (event: MessageEvent) => {
if (event.origin !== window.origin) {
return
}
Expand All @@ -39,13 +41,17 @@ const handleMessage = async (event: MessageEvent) => {
}

try {
logger.info('request::', message.data)

const response = await desktopClient.send({
...message.data,
name: window.location.hostname,
url: window.origin,
iconUrl: getFaviconUrl() ?? '',
})

logger.info('response::', response)

event.ports[0].postMessage({
type: 'status:proxy:success',
data: response,
Expand All @@ -71,12 +77,10 @@ const handleMessage = async (event: MessageEvent) => {
}
}

const proxyMessage: ProxyMessage = {
event.ports[0].postMessage({
type: 'status:proxy:error',
error: proxyError,
}

event.ports[0].postMessage(proxyMessage)
} satisfies ProxyMessage)
}
}

Expand Down Expand Up @@ -108,4 +112,43 @@ function isRpcError(
)
}

window.addEventListener('message', handleMessage)
window.addEventListener('message', handleProviderMessage)

const handleMainMessage = async (event: MessageEvent) => {
if (event.origin !== window.origin) {
return
}

let message: MainMessage
try {
message = MainMessage.parse(event.data)
} catch {
return
}

if (message.type !== 'status:main') {
return
}

try {
const response = await chrome.runtime.sendMessage(
chrome.runtime.id,
message.data,
)

event.ports[0].postMessage({
type: 'status:proxy:success',
data: response,
} satisfies ProxyMessage)
} catch (error) {
event.ports[0].postMessage({
type: 'status:proxy:error',
error: {
code: -32603,
message: isError(error) ? error.message : 'Internal error',
},
} satisfies ProxyMessage)
}
}

window.addEventListener('message', handleMainMessage)
9 changes: 7 additions & 2 deletions apps/connector/src/hooks/use-local-storage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect, useState } from 'react'

import { logger } from '~lib/logger'

export function useLocalStorage<T>(
key: string,
initialValue: T,
Expand All @@ -10,7 +12,8 @@ export function useLocalStorage<T>(
try {
const item = window.localStorage.getItem(key)
setStoredValue(item ? JSON.parse(item) : initialValue)
} catch {
} catch (error) {
logger.error(error)
setStoredValue(initialValue)
}
}, [])
Expand Down Expand Up @@ -39,7 +42,9 @@ export function useLocalStorage<T>(
setStoredValue(valueToStore)
window.localStorage.setItem(key, JSON.stringify(valueToStore))
window.dispatchEvent(new Event('storage'))
} catch {}
} catch (error) {
logger.error(error)
}
}

return [storedValue, setValue]
Expand Down
13 changes: 13 additions & 0 deletions apps/connector/src/lib/desktop-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { WebSocketProvider } from 'ethers'

import { config } from '~config'

import { logger } from './logger'

import type { RequestArguments } from '~lib/request-arguments'
import type { WebSocketLike } from 'ethers'

Expand All @@ -19,6 +21,7 @@ export class DesktopClient {
return
}

logger.info('stop::')
this.#rpcClient?.destroy()
this.#rpcClient = null

Expand All @@ -27,6 +30,7 @@ export class DesktopClient {

public async send(args: DesktopRequestArguments) {
if (!this.#rpcClient) {
logger.info('start::')
this.#rpcClient = new WebSocketProvider(
config.desktop.rpc.url,
'mainnet',
Expand All @@ -41,6 +45,11 @@ export class DesktopClient {

await waitUntilOpen(this.#rpcClient.websocket)

logger.info('client::', {
method: config.desktop.rpc.method,
params: [JSON.stringify(args)],
})

return await this.#rpcClient.send(config.desktop.rpc.method, [
JSON.stringify(args),
])
Expand Down Expand Up @@ -71,6 +80,10 @@ async function waitUntilOpen(websocket: WebSocketLike) {
reject(new Error('Timed out to connect to the RPC server'))
}, 30 * 1000)

if (websocket.readyState === WebSocket.CONNECTING) {
logger.warn('Waiting for the RPC server to connect')
}

const onopen = websocket.onopen?.bind(websocket)
websocket.onopen = event => {
onopen?.(event)
Expand Down
Loading
Loading