diff --git a/bun.lockb b/bun.lockb
index 4ea0601..93d2a17 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/manifest.config.ts b/manifest.config.ts
index 0da7622..c907e2c 100644
--- a/manifest.config.ts
+++ b/manifest.config.ts
@@ -25,6 +25,9 @@ export const getManifest = ({ dev }: { dev?: boolean }) =>
all_frames: true,
},
],
+ side_panel: {
+ default_path: 'src/entries/iframe/index.html',
+ },
icons: {
'16': `icons/icon${dev ? '-dev' : ''}@16w.png`,
'32': `icons/icon${dev ? '-dev' : ''}@32w.png`,
@@ -36,6 +39,7 @@ export const getManifest = ({ dev }: { dev?: boolean }) =>
'contextMenus',
'declarativeNetRequest',
'scripting',
+ 'sidePanel',
'storage',
'tabs',
'unlimitedStorage',
diff --git a/package.json b/package.json
index a2a9f4c..7336a66 100644
--- a/package.json
+++ b/package.json
@@ -77,7 +77,7 @@
"@biomejs/biome": "1.0.0",
"@samrum/vite-plugin-web-extension": "^5.1.0",
"@types/chroma-js": "^2.4.0",
- "@types/chrome": "^0.0.244",
+ "@types/chrome": "^0.0.266",
"@types/opentype.js": "^1.3.4",
"@types/qs": "^6.9.7",
"@types/react": "^18.2.33",
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 2d79b29..5359d44 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -1,4 +1,4 @@
-import { type ReactNode, useCallback, useMemo } from 'react'
+import { type ReactNode, useMemo } from 'react'
import { Link } from 'react-router-dom'
import { type Hex, formatGwei } from 'viem'
@@ -24,15 +24,12 @@ import { useHost } from '~/hooks/useHost'
import { useMine } from '~/hooks/useMine'
import { useNetworkStatus } from '~/hooks/useNetworkStatus'
import { usePendingBlock } from '~/hooks/usePendingBlock'
-import { getMessenger } from '~/messengers'
import { useAccountStore, useNetworkStore, useSessionsStore } from '~/zustand'
import { useRevert } from '../hooks/useRevert'
import { useSnapshot } from '../hooks/useSnapshot'
import * as styles from './Header.css'
-const contentMessenger = getMessenger('wallet:contentScript')
-
export function Header({ isNetworkOffline }: { isNetworkOffline?: boolean }) {
const { type } = useAppMeta()
return (
@@ -62,12 +59,6 @@ export function Header({ isNetworkOffline }: { isNetworkOffline?: boolean }) {
-
-
-
-
-
-
>
)}
@@ -194,31 +185,6 @@ function DappConnection() {
)
}
-function CollapseButton() {
- const handleClose = useCallback(() => {
- contentMessenger.send('toggleWallet', undefined)
- }, [])
-
- return (
-
-
-
-
-
- )
-}
-
function SettingsButton() {
return (
@@ -232,7 +198,7 @@ function SettingsButton() {
display="flex"
justifyContent="center"
height="full"
- style={{ width: '28px' }}
+ style={{ width: '32px' }}
>
diff --git a/src/design-system/components/Text.tsx b/src/design-system/components/Text.tsx
index 9314525..46700b5 100644
--- a/src/design-system/components/Text.tsx
+++ b/src/design-system/components/Text.tsx
@@ -185,10 +185,15 @@ export const TextTruncated = forwardRef(
}, [])
useLayoutEffect(() => {
- setWidth(
- ((wrapperRef.current as any).getBoundingClientRect() as DOMRectReadOnly)
- .width,
- )
+ setTimeout(() => {
+ setWidth(
+ (
+ (
+ wrapperRef.current as any
+ ).getBoundingClientRect() as DOMRectReadOnly
+ ).width,
+ )
+ }, 16)
}, [])
useResizeObserver(wrapperRef, (entry) =>
mounted ? setWidth(entry.contentRect.width) : undefined,
diff --git a/src/entries/background/context-menu.ts b/src/entries/background/context-menu.ts
index 59117bc..86b71db 100644
--- a/src/entries/background/context-menu.ts
+++ b/src/entries/background/context-menu.ts
@@ -1,11 +1,7 @@
-import { getMessenger } from '~/messengers'
-
-const inpageMessenger = getMessenger('background:inpage')
-
export function setupContextMenu() {
- chrome.action.onClicked.addListener(() => {
- inpageMessenger.send('toggleWallet', undefined)
- })
+ chrome.sidePanel
+ .setPanelBehavior({ openPanelOnActionClick: true })
+ .catch((error) => console.error(error))
// TODO: Only create context menu if selected text is "openable" in Rivet.
// chrome.contextMenus.create({
diff --git a/src/entries/background/index.ts b/src/entries/background/index.ts
index 750d6ad..349ed70 100644
--- a/src/entries/background/index.ts
+++ b/src/entries/background/index.ts
@@ -7,6 +7,7 @@ import { setupExtensionId } from './extension-id'
import { setupInpage } from './inpage'
import { interceptJsonRpcRequests } from './intercept-requests'
import { setupRpcHandler } from './rpc'
+import { setupWalletSidebarHandler } from './wallet-sidebar'
const contentMessenger = getMessenger('background:contentScript')
const inpageMessenger = getMessenger('background:inpage')
@@ -21,4 +22,5 @@ setupExtensionId()
setupInpage()
setupRpcHandler({ messenger: inpageMessenger })
setupRpcHandler({ messenger: walletMessenger })
+setupWalletSidebarHandler()
syncStores()
diff --git a/src/entries/background/rpc.ts b/src/entries/background/rpc.ts
index fcd57bf..11e613d 100644
--- a/src/entries/background/rpc.ts
+++ b/src/entries/background/rpc.ts
@@ -75,6 +75,7 @@ export function getRpcClient({
export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
messenger.reply('request', async ({ request, rpcUrl }, meta) => {
const isInpage =
+ meta.sender.tab &&
!meta.sender.tab?.url?.includes('extension://') &&
(!meta.sender.frameId || meta.sender.frameId === 0)
const rpcClient = getRpcClient({ rpcUrl })
@@ -104,8 +105,6 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
addPendingRequest({ ...request, sender: meta.sender })
- inpageMessenger.send('toggleWallet', { open: true })
-
try {
const response = await new Promise((resolve, reject) => {
walletMessenger.reply(
@@ -137,7 +136,6 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
})
return response as RpcResponse
} finally {
- inpageMessenger.send('toggleWallet', { useStorage: true })
removePendingRequest(request.id)
}
}
@@ -176,8 +174,6 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
addPendingRequest({ ...request, sender: meta.sender })
- inpageMessenger.send('toggleWallet', { open: true })
-
try {
const response = await new Promise((resolve) => {
walletMessenger.reply(
diff --git a/src/entries/background/wallet-sidebar.ts b/src/entries/background/wallet-sidebar.ts
new file mode 100644
index 0000000..1383e22
--- /dev/null
+++ b/src/entries/background/wallet-sidebar.ts
@@ -0,0 +1,20 @@
+import { settingsStore } from '../../zustand'
+
+export function setupWalletSidebarHandler() {
+ chrome.runtime.onMessage.addListener((message, sender) => {
+ if (message.type === 'openWallet') {
+ const { bypassSignatureAuth, bypassTransactionAuth } =
+ settingsStore.getState()
+ const { method } = message.payload
+ if (
+ method === 'eth_requestAccounts' ||
+ (method === 'eth_sendTransaction' && !bypassTransactionAuth) ||
+ (method === 'eth_sign' && !bypassSignatureAuth) ||
+ (method === 'eth_signTypedData_v4' && !bypassSignatureAuth) ||
+ (method === 'personal_sign' && !bypassSignatureAuth)
+ ) {
+ chrome.sidePanel.open({ tabId: sender.tab!.id! })
+ }
+ }
+ })
+}
diff --git a/src/entries/content/index.ts b/src/entries/content/index.ts
index bbf2ce1..72735fb 100644
--- a/src/entries/content/index.ts
+++ b/src/entries/content/index.ts
@@ -1,6 +1,14 @@
+import { getMessenger } from '~/messengers'
import { setupBridgeTransportRelay } from '~/messengers/transports/bridge'
-import { injectWallet } from './injectWallet'
-
setupBridgeTransportRelay()
-injectWallet()
+
+const backgroundMessenger = getMessenger('background:contentScript')
+backgroundMessenger.send('ping', undefined)
+setInterval(() => {
+ backgroundMessenger.send('ping', undefined)
+}, 5000)
+
+window.addEventListener('message', ({ data }) => {
+ if (data.type === 'openWallet') chrome.runtime.sendMessage(data)
+})
diff --git a/src/entries/content/injectWallet.ts b/src/entries/content/injectWallet.ts
deleted file mode 100644
index 13eeb07..0000000
--- a/src/entries/content/injectWallet.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import { getMessenger } from '~/messengers'
-import { windowStorage } from '~/storage'
-
-const backgroundMessenger = getMessenger('background:contentScript')
-const walletMessenger = getMessenger('wallet:contentScript')
-
-backgroundMessenger.send('ping', undefined)
-setInterval(() => {
- backgroundMessenger.send('ping', undefined)
-}, 5000)
-
-export async function injectWallet() {
- const extensionId: string = await backgroundMessenger.send(
- 'extensionId',
- undefined,
- )
-
- if (process.env.NODE_ENV === 'development')
- windowStorage.local.setItem('open', true)
-
- // Inject wallet elements
- const container = await injectContainer()
- injectIframe({ container, extensionId })
-
- const handle = injectHandle({ container })
- setupHandleListeners({ container, handle })
- setupToggleListeners({ container, handle })
-}
-
-/////////////////////////////////////////////////////////////////////
-
-async function injectContainer() {
- const container = document.createElement('div')
- container.id = '__dev-wallet'
- container.style.width = '0px'
- container.style.height = '100vh'
- container.style.position = 'fixed'
- container.style.top = '0'
- container.style.right = '0'
- container.style.border = 'none'
- container.style.zIndex = '2147483646'
-
- if (document.body === null)
- await new Promise((resolve) => {
- document.addEventListener('DOMContentLoaded', () => {
- resolve()
- })
- })
-
- document.body.appendChild(container)
- return container
-}
-
-function injectIframe({
- container,
- extensionId,
-}: { container: HTMLElement; extensionId: string }) {
- const iframe = document.createElement('iframe')
- iframe.src = `chrome-extension://${extensionId}/src/entries/iframe/index.html`
- iframe.allow = 'clipboard-write'
- iframe.style.width = '100%'
- iframe.style.height = '100%'
- iframe.style.border = 'none'
- iframe.style.margin = '0px'
- iframe.style.padding = '0px'
- container.appendChild(iframe)
- return iframe
-}
-
-function injectHandle({ container }: { container: HTMLElement }) {
- const handle = document.createElement('div')
- handle.style.display = 'none'
- handle.style.width = '16px'
- handle.style.height = '100%'
- handle.style.position = 'absolute'
- handle.style.top = '80px'
- handle.style.right = `${parseInt(container.style.width) - 8}px`
- handle.style.cursor = 'ew-resize'
- container.appendChild(handle)
- return handle
-}
-
-function setupHandleListeners({
- container,
- handle,
-}: { container: HTMLElement; handle: HTMLElement }) {
- let isDragging = false
- let startX = 0
- let startWidth = 0
-
- handle.addEventListener('mousedown', (e) => {
- container.style.pointerEvents = 'none'
- isDragging = true
- startX = e.pageX
- startWidth = parseInt(
- document.defaultView?.getComputedStyle(container).width ?? '0',
- 10,
- )
- })
-
- document.addEventListener('mousemove', (e) => {
- if (!isDragging) return
- const width = startWidth + startX - e.pageX
- if (width < 400) return
- container.style.width = `${width}px`
- handle.style.right = `${width - 8}px`
- })
-
- document.addEventListener('mouseup', () => {
- container.style.pointerEvents = 'all'
- isDragging = false
- })
-}
-
-function setupToggleListeners({
- container,
- handle,
-}: {
- container: HTMLElement
- handle: HTMLElement
-}) {
- let open = Boolean(windowStorage.local.getItem('open')) || false
-
- async function listener(
- args: { route?: string; open?: boolean; useStorage?: boolean } | void = {},
- ) {
- if (args?.route) walletMessenger.send('pushRoute', args.route)
-
- if (args?.useStorage && windowStorage.local.getItem('open'))
- open = Boolean(windowStorage.local.getItem('open'))
- else open = args?.open ?? !open
-
- if (!open) {
- container.style.width = '0px'
- handle.style.display = 'none'
- } else {
- container.style.width = '400px'
- handle.style.display = 'block'
- handle.style.right = '392px'
- }
-
- if (typeof args?.open === 'undefined')
- windowStorage.local.setItem('open', open)
- }
-
- backgroundMessenger.reply('toggleWallet', listener)
- listener({ open })
-}
diff --git a/src/messengers/schema.ts b/src/messengers/schema.ts
index fed3cb2..2c3e709 100644
--- a/src/messengers/schema.ts
+++ b/src/messengers/schema.ts
@@ -29,14 +29,5 @@ export type Schema = {
response: RpcResponse,
]
toggleTheme: [payload: void, response: void]
- toggleWallet: [
- payload:
- | ({ route?: string } & (
- | { open: boolean; useStorage?: never }
- | { open?: never; useStorage?: true }
- ))
- | undefined,
- response: void,
- ]
transactionExecuted: [payload: void, response: void]
}
diff --git a/src/provider.ts b/src/provider.ts
index 180c5a6..e19a7a6 100644
--- a/src/provider.ts
+++ b/src/provider.ts
@@ -65,6 +65,12 @@ export function getProvider({
removeListener: emitter.removeListener.bind(emitter),
async request({ method, params }) {
const id = _id++
+
+ window.postMessage({
+ type: 'openWallet',
+ payload: { method },
+ })
+
const { result, error, ...response } = await requestMessenger.send(
'request',
{