Skip to content

Commit df65fd8

Browse files
authored
feat: cheats (#80)
1 parent c6ff9f8 commit df65fd8

File tree

15 files changed

+235
-139
lines changed

15 files changed

+235
-139
lines changed

src/app.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,21 @@ import { getTheme, setTheme } from '~/design-system'
1313
import '~/design-system/styles/global.css'
1414
import { useClient } from '~/hooks/useClient'
1515
import { useNetworkStatus } from '~/hooks/useNetworkStatus'
16-
import { usePendingBlock } from '~/hooks/usePendingBlock'
16+
import {
17+
getPendingBlockQueryKey,
18+
usePendingBlock,
19+
} from '~/hooks/usePendingBlock'
20+
import { getPendingTransactionsQueryKey } from '~/hooks/usePendingTransactions'
1721
import { usePrevious } from '~/hooks/usePrevious'
22+
import { getTxpoolQueryKey } from '~/hooks/useTxpool'
1823
import { getMessenger } from '~/messengers'
1924
import { QueryClientProvider, queryClient } from '~/react-query'
2025
import { deepEqual } from '~/utils'
26+
import { getClient } from '~/viem'
2127
import {
2228
type AccountState,
2329
type NetworkState,
30+
networkStore,
2431
syncStores,
2532
useAccountStore,
2633
useNetworkStore,
@@ -40,6 +47,7 @@ import OnboardingDownload from './screens/onboarding/download'
4047
import OnboardingRun from './screens/onboarding/run'
4148
import OnboardingStart from './screens/onboarding/start'
4249
import Session from './screens/session'
50+
import Settings from './screens/settings'
4351
import TransactionDetails from './screens/transaction-details'
4452

4553
export function init({ type = 'standalone' }: { type?: AppMeta['type'] } = {}) {
@@ -87,6 +95,10 @@ export function init({ type = 'standalone' }: { type?: AppMeta['type'] } = {}) {
8795
path: 'session',
8896
element: <Session />,
8997
},
98+
{
99+
path: 'settings',
100+
element: <Settings />,
101+
},
90102
{
91103
path: 'onboarding',
92104
children: [
@@ -112,14 +124,33 @@ export function init({ type = 'standalone' }: { type?: AppMeta['type'] } = {}) {
112124
},
113125
])
114126

115-
// Handle requests from background to toggle the theme.
116127
const backgroundMessenger = getMessenger('background:wallet')
128+
129+
// Handle requests from background to toggle the theme.
117130
backgroundMessenger.reply('toggleTheme', async () => {
118131
const { storageTheme, systemTheme } = getTheme()
119132
const theme = storageTheme || systemTheme
120133
setTheme(theme === 'dark' ? 'light' : 'dark')
121134
})
122135

136+
// Handle executed transactions to invalidate stale queries.
137+
backgroundMessenger.reply('transactionExecuted', async () => {
138+
const {
139+
network: { rpcUrl },
140+
} = networkStore.getState()
141+
const client = getClient({ rpcUrl })
142+
143+
queryClient.invalidateQueries({
144+
queryKey: getPendingBlockQueryKey([client.key]),
145+
})
146+
queryClient.invalidateQueries({
147+
queryKey: getPendingTransactionsQueryKey([client.key]),
148+
})
149+
queryClient.invalidateQueries({
150+
queryKey: getTxpoolQueryKey([client.key]),
151+
})
152+
})
153+
123154
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
124155
<AppMetaContext.Provider value={{ type }}>
125156
<QueryClientProvider>

src/components/Header.tsx

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type ReactNode, useCallback, useMemo } from 'react'
2-
import { Link, useLocation, useNavigate } from 'react-router-dom'
2+
import { Link } from 'react-router-dom'
33
import { formatGwei } from 'viem'
44

55
import { Tooltip } from '~/components'
@@ -30,7 +30,6 @@ import { useAccountStore, useNetworkStore, useSessionsStore } from '~/zustand'
3030
import * as styles from './Header.css'
3131

3232
const contentMessenger = getMessenger('wallet:contentScript')
33-
const inpageMessenger = getMessenger('wallet:inpage')
3433

3534
export function Header({ isNetworkOffline }: { isNetworkOffline?: boolean }) {
3635
const { type } = useAppMeta()
@@ -59,8 +58,7 @@ export function Header({ isNetworkOffline }: { isNetworkOffline?: boolean }) {
5958
<Separator orientation="vertical" />
6059
</Column>
6160
<Column width="content">
62-
{/** TODO: Remove this once EIP-6963 is widely adopted across wallets & dapps. */}
63-
<ReinjectButton />
61+
<SettingsButton />
6462
</Column>
6563
<Column width="content">
6664
<Separator orientation="vertical" />
@@ -219,27 +217,24 @@ function CollapseButton() {
219217
)
220218
}
221219

222-
function ReinjectButton() {
223-
const handleInject = useCallback(() => {
224-
inpageMessenger.send('injectProvider', undefined)
225-
}, [])
226-
220+
function SettingsButton() {
227221
return (
228-
<Tooltip label="Re-inject Wallet into Dapp" height="full">
229-
<Box
230-
alignItems="center"
231-
as="button"
232-
backgroundColor={{
233-
hover: 'surface/fill/quarternary',
234-
}}
235-
display="flex"
236-
justifyContent="center"
237-
height="full"
238-
onClick={handleInject}
239-
style={{ width: '28px' }}
240-
>
241-
<SFSymbol size="14px" symbol="square.and.arrow.down" weight="medium" />
242-
</Box>
222+
<Tooltip label="Settings" height="full">
223+
<Link to="/settings">
224+
<Box
225+
alignItems="center"
226+
as="button"
227+
backgroundColor={{
228+
hover: 'surface/fill/quarternary',
229+
}}
230+
display="flex"
231+
justifyContent="center"
232+
height="full"
233+
style={{ width: '28px' }}
234+
>
235+
<SFSymbol size="14px" symbol="gear" weight="medium" />
236+
</Box>
237+
</Link>
243238
</Tooltip>
244239
)
245240
}
@@ -248,9 +243,6 @@ function ReinjectButton() {
248243
// Middle Bar
249244

250245
function Network() {
251-
const { pathname } = useLocation()
252-
const navigate = useNavigate()
253-
const { network } = useNetworkStore()
254246
return (
255247
<Link to="networks" style={{ height: '100%', width: '100%' }}>
256248
<Box
@@ -273,22 +265,6 @@ function Network() {
273265
<Chain />
274266
</Inset>
275267
</Column>
276-
<Column width="content">
277-
<Button.Symbol
278-
label="Network Settings"
279-
onClick={(e) => {
280-
e.preventDefault()
281-
navigate(`/networks/${encodeURIComponent(network.rpcUrl)}`, {
282-
replace: pathname.includes(
283-
`/networks/${encodeURIComponent(network.rpcUrl)}`,
284-
),
285-
})
286-
}}
287-
variant="ghost primary"
288-
height="24px"
289-
symbol="gearshape.fill"
290-
/>
291-
</Column>
292268
</Columns>
293269
</Inset>
294270
</Box>

src/design-system/symbols/generated/index.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/design-system/tokens.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ export const symbolNames = [
653653
'gearshape.fill',
654654
'square.and.pencil',
655655
'plus',
656+
'gear',
656657
] as const
657658
export type SymbolName = typeof symbolNames[number]
658659

src/entries/background/rpc.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ import {
2020
networkStore,
2121
pendingRequestsStore,
2222
sessionsStore,
23+
settingsStore,
2324
} from '~/zustand'
2425

26+
const inpageMessenger = getMessenger('background:inpage')
27+
const walletMessenger = getMessenger('background:wallet')
28+
2529
const clientCache = new Map()
2630
export function getRpcClient({
2731
rpcUrl: rpcUrl_,
@@ -49,12 +53,17 @@ export function getRpcClient({
4953
},
5054
timeout: 5_000,
5155
})
56+
57+
if (method === 'eth_sendTransaction')
58+
walletMessenger.send('transactionExecuted', undefined)
59+
5260
if ((response as { success?: boolean }).success === false)
5361
return {
5462
id,
5563
jsonrpc: '2.0',
5664
error: 'An unknown error occurred.',
5765
} as RpcResponse
66+
5867
return response
5968
},
6069
}),
@@ -63,9 +72,6 @@ export function getRpcClient({
6372
return client
6473
}
6574

66-
const inpageMessenger = getMessenger('background:inpage')
67-
const walletMessenger = getMessenger('background:wallet')
68-
6975
export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
7076
messenger.reply('request', async ({ request, rpcUrl }, meta) => {
7177
const isInpage =
@@ -74,7 +80,6 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
7480
const rpcClient = getRpcClient({ rpcUrl })
7581

7682
const hasOnboarded = isInpage ? networkStore.getState().onboarded : rpcUrl
77-
7883
if (!hasOnboarded)
7984
return {
8085
id: request.id,
@@ -85,12 +90,14 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
8590
},
8691
} as RpcResponse
8792

93+
const { bypassSignatureAuth, bypassTransactionAuth } =
94+
settingsStore.getState()
8895
// If the method is a "signable" method, request approval from the user.
8996
if (
90-
request.method === 'eth_sendTransaction' ||
91-
request.method === 'eth_sign' ||
92-
request.method === 'eth_signTypedData_v4' ||
93-
request.method === 'personal_sign'
97+
(request.method === 'eth_sendTransaction' && !bypassTransactionAuth) ||
98+
(request.method === 'eth_sign' && !bypassSignatureAuth) ||
99+
(request.method === 'eth_signTypedData_v4' && !bypassSignatureAuth) ||
100+
(request.method === 'personal_sign' && !bypassSignatureAuth)
94101
) {
95102
const { addPendingRequest, removePendingRequest } =
96103
pendingRequestsStore.getState()
@@ -136,14 +143,10 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
136143
}
137144

138145
if (isInpage && request.method === 'eth_requestAccounts') {
139-
const { addPendingRequest, removePendingRequest } =
140-
pendingRequestsStore.getState()
141-
142-
const { addSession, instantAuth } = sessionsStore.getState()
143-
144146
const authorize = () => {
145147
const { accountsForRpcUrl } = accountStore.getState()
146148
const { network } = networkStore.getState()
149+
const { addSession } = sessionsStore.getState()
147150

148151
const accounts = accountsForRpcUrl({
149152
activeFirst: true,
@@ -165,7 +168,11 @@ export function setupRpcHandler({ messenger }: { messenger: Messenger }) {
165168
} as RpcResponse
166169
}
167170

168-
if (instantAuth) return authorize()
171+
const { bypassConnectAuth } = settingsStore.getState()
172+
if (bypassConnectAuth) return authorize()
173+
174+
const { addPendingRequest, removePendingRequest } =
175+
pendingRequestsStore.getState()
169176

170177
addPendingRequest({ ...request, sender: meta.sender })
171178

src/messengers/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ export type Schema = {
3838
| undefined,
3939
response: void,
4040
]
41+
transactionExecuted: [payload: void, response: void]
4142
}

src/screens/index.tsx

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@ import type { Account } from '~/zustand/account'
6363
import OnboardingStart from './onboarding/start'
6464

6565
export default function Index() {
66+
const defaultTab = 'accounts'
67+
6668
const { setPosition } = useScrollPositionStore()
67-
const [params, setParams] = useSearchParams({ tab: 'accounts' })
69+
const [params, setParams] = useSearchParams({ tab: defaultTab })
6870
const { onboarded } = useNetworkStore()
6971
if (!onboarded) return <OnboardingStart />
7072
return (
7173
<Container scrollable={false} verticalInset={false}>
72-
<Tabs.Root asChild value={params.get('tab')!}>
74+
<Tabs.Root asChild value={params.get('tab') || defaultTab}>
7375
<Box display="flex" flexDirection="column" height="full">
7476
<TabsList
7577
items={[
@@ -823,7 +825,6 @@ function Contracts() {
823825
const contracts = contracts_.filter((contract) => contract.visible)
824826

825827
const VirtualList = useVirtualList({
826-
// rome-ignore lint/nursery/useExhaustiveDependencies:
827828
layout: useMemo(
828829
() => [
829830
{ size: 40, sticky: true, type: 'search' },
@@ -837,7 +838,7 @@ function Contracts() {
837838
}) as const,
838839
),
839840
],
840-
[contracts.length],
841+
[contracts],
841842
),
842843
})
843844

@@ -911,9 +912,15 @@ function Contracts() {
911912
>
912913
<Columns alignHorizontal="justify" gap="4px" width="full">
913914
<Column alignVertical="center">
914-
<Text size="11px" wrap={false}>
915-
{contract.address}
916-
</Text>
915+
{contract.address !== '0x' ? (
916+
<Text size="11px" wrap={false}>
917+
{contract.address}
918+
</Text>
919+
) : (
920+
<Text color="text/tertiary" size="11px" wrap={false}>
921+
Deploying...
922+
</Text>
923+
)}
917924
</Column>
918925
<Column alignVertical="center" width="content">
919926
<Button.Symbol
@@ -1001,24 +1008,13 @@ function ImportContract() {
10011008
if (bytecode) {
10021009
if (!account?.address) throw new Error()
10031010

1004-
const hash = await client.deployContract({
1011+
await client.deployContract({
10051012
abi: [],
10061013
bytecode,
10071014
account: account.address,
10081015
chain: null,
10091016
})
1010-
await client.mine({ blocks: 1 })
1011-
const receipt = await client.getTransactionReceipt({ hash })
1012-
1013-
if (!receipt.contractAddress) throw new Error()
10141017

1015-
updateContract({
1016-
address: receipt.contractAddress,
1017-
bytecode,
1018-
key,
1019-
receipt,
1020-
state: 'loaded',
1021-
})
10221018
return
10231019
}
10241020
} catch {

0 commit comments

Comments
 (0)