Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@edgeandnode/graph-auth-kit
Advanced tools
Wallet authentication connect kit in The Graph suite of applications
Authentication Kit for connecting The Graph apps/dapps to a wallet.
Relies on/requires wagmi
+ viem
for allowing users to connect their wallets and interact with the connected auth state context.
Exposes a simple useGraphAuthKit
hook that lets the app open the connect modal, letting users connect to their wallet of choice (one of: injected/MetaMask, coinbase, WalletConnect, Safe). See integration example below.
Currently, graph-auth-kit
has a lot of peer deps needed to interact with the library. But this may change after testing. At the very least, wagmi, viem, @tanstack/react-query
will be needed.
# with bun
bun add @edgeandnode/graph-auth-kit \
@edgeandnode/common \
@edgeandnode/gds \
@edgeandnode/go \
@emotion/react \
@safe-global/api-kit \
@safe-global/protocol-kit \
@safe-global/safe-core-sdk-types \
@tanstack/react-query \
cookies-next \
ethers@5.7.2 \
theme-ui \
viem@2.x \
wagmi
# with pnpm
pnpm add @edgeandnode/graph-auth-kit \
@edgeandnode/common \
@edgeandnode/gds \
@edgeandnode/go \
@emotion/react \
@safe-global/api-kit \
@safe-global/protocol-kit \
@safe-global/safe-core-sdk-types \
@tanstack/react-query \
cookies-next \
ethers@5.7.2 \
theme-ui \
viem@2.x \
wagmi
Properties:
config
-> [REQUIRED]. The instantiated wagmi config instance.queryClient
-> [OPTIONAL]. The GraphAuthKitProvider
renders a QueryClientProvider
instance. Pass in an instantiated QueryClient
to use, otherwise, GraphAuthKit
will instantiate its own.initialStateCookie
-> [OPTIONAL] wagmi auth state cookie. passed to the GraphAuthKitProvider
-> WagmiProvider
AUTH_STORAGE_KEY
from @edgeandnode/graph-auth-kit
for our wagmi cookie storage.infuraKey
-> [REQUIRED]GraphAuthKitProvider
.
ConnectModal
component, the GraphAuthKitProvider
renders it for usQueryClientProvider
as GraphAuthKitProvider
instantiates and renders it
QueryClient
instance to the GraphAuthKitProvider
, otherwise, it will instantiate its own// _app.tsx
import { QueryClient } from '@tanstack/react-query'
import { getCookie } from 'cookies-next'
import { AppProps } from 'next'
import { useRef } from 'react'
import { createClient } from 'viem'
import { cookieStorage, createConfig, createStorage } from 'wagmi'
import { coinbaseWallet, injected, walletConnect } from 'wagmi/connectors'
import { AnalyticsProvider, GDSProvider } from '@edgeandnode/gds'
import {
AUTH_STORAGE_KEY,
buildInfuraHttpTransport,
chainIsSupportedChain,
DefChain,
GraphAuthKitProvider,
L1Chain,
L1ChainTestnet,
L2Chain,
L2ChainTestnet,
} from '@edgeandnode/graph-auth-kit'
import { FutureNextLink } from '../components/FutureNextLink'
import { Layout } from '../components/Layout'
const infuraKey = process.env.INFURA_KEY!
const walletConnectProjectID = process.env.WALLETCONNECT_PROJECT_ID!
import '@edgeandnode/gds/style.css'
import '../app.css'
const config = createConfig({
chains: [L2Chain, L2ChainTestnet, L1Chain, L1ChainTestnet] as const,
ssr: typeof window !== 'undefined',
client(params) {
const chain = chainIsSupportedChain(params.chain) ? params.chain : DefChain
const transport = buildInfuraHttpTransport({
chain: chain.id,
infuraKey,
})
return createClient({
chain,
transport,
})
},
connectors: [
injected(),
coinbaseWallet({
appName: 'Boom',
}),
walletConnect({
projectId: env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID,
qrModalOptions: {
themeMode: 'dark',
},
}),
],
storage: createStorage({
storage: cookieStorage,
key: AUTH_STORAGE_KEY,
}),
})
declare module 'wagmi' {
interface Register {
config: typeof config
}
}
export default function App({ Component, router, pageProps }: AppProps) {
const queryClient = useRef<QueryClient>()
if (!queryClient.current) {
queryClient.current = new QueryClient({
defaultOptions: {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
staleTime: 60 * 1000,
},
},
})
}
const cookies = getCookies()
const initialStateCookie =
// The nextjs pages router does not make it trivial to retrieve the cookies (app router does though).
// But, `getServerSideProps` _can_ be used to retrieve the cookies from the request headers,
// and then passed down as props, which would be available here as `pageProps.cookies`.
// Otherwise, can parse the cookies uing `getCookies`.
pageProps.cookies ||
Object.entries(cookies)
.filter(([key]) => key.toLowerCase().startsWith(AUTH_STORAGE_KEY.toLowerCase()))
.reduce<string>(
(accum, [key, val], idx) => (val == null ? accum : idx === 0 ? `${key}=${val}` : `${accum}; ${key}=${val}`),
'',
)
return (
<GDSProvider clientRouter={router} clientLink={FutureNextLink} useLegacyTheme>
<AnalyticsProvider
app="EXPLORER"
clientRouter={router}
mixpanel={{
sdk: mixpanel,
token: process.env.MIXPANEL_TOKEN ?? null,
}}
googleAnalytics={{
sdk: googleAnalytics,
measurementId: process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID ?? null,
}}
>
<GraphAuthKitProvider
config={config}
queryClient={queryClient.current}
initialStateCookie={initialStateCookie || undefined}
infuraKey={infuraKey}
>
<Layout>
<DefaultSeo {...defaultSEO} />
<Component {...pageProps} />
</Layout>
<ReactQueryDevtools initialIsOpen={false} />
</GraphAuthKitProvider>
</AnalyticsProvider>
</GDSProvider>
)
}
// components/Layout.tsx
import { ReactNode } from 'react'
import { useAccountEffect, useEnsName } from 'wagmi'
import { Layout as GDSLayout, UserProfile } from '@edgeandnode/gds'
import { GlobalFooter, GlobalHeader, NPSForm } from '@edgeandnode/go'
import { L1Chain, useGraphAuthKitConnector, useGraphAuthKit, useGraphAuthKitAccount } from '@edgeandnode/graph-auth-kit/hooks'
import { NavDropDownMenu } from './NavDropDownMenu'
export function Layout({ children }: Readonly<{ children: ReactNode }>) {
const authkit = useGraphAuthKit()
const { address } = useGraphAuthKitAccount()
const { data: ens } = useEnsName({ address, blockTag: 'latest', chainId: L1Chain.id })
const connector = useGraphAuthKitConnector()
const walletConnected = Boolean(address)
useAccountEffect({
onConnect(data) {
console.log('user connected wallet', {data})
},
onDisconnect() {
console.log('user disconnected wallet')
},
})
return (
<GDSLayout
header={
<GlobalHeader
activeProduct="EXPLORER"
basePath="/explorer"
showSupportButton={walletConnected}
rigtContent={(defaultContent) => (
<>
{!walletConnected ?
<GlobalHeader.ConnectButton onClick={() => authkit.openConnectModal()} />
) : (
<UserProfile
ethereumAccount={address}
graphAccount={...}
ens={ens}
profileUrl={`/profile/${address}?view=Overview`}
profileUrlAs={`/profile/${address}?view=Overview`}
onConnect={() => authkit.openConnectModal()}
onDisconnect={() => authkit.disconnect()}
userDropDownMenu={<NavDropDownMenu />}
accountTag={connector === 'safe' ? 'multisig' : undefined}
/>
)}
</>
)}
/>
}
footer={
<>
<NPSForm sx={{ mb: Spacing['64px'] }} />
<GlobalFooter />
</>
}
>
{children}
</GDSLayout>
)
}
useGraphAuthKitAccount
-> This is an override of the wagmi useAccount hook. The reason is, if the user connects with a multisig, the wagmi context is connected with the user-selected EoA, so all of the wagmi context hooks reference this EoA and not the Safe. This returns the wagmi UseAccountReturnType
but the address
and addresses
values include the entered Safe address. It also adds an eoa
property that is the connected EoA address.useGraphAuthKitConnector
-> The user selected wallet/connector option.useClientToEthersSigner
-> Returns the ethers@5.x.x JsonRpcSigner or SafeEthersSigner if the user is connected via a multisiguseAuthAccount
-> similar to the useGraphAuthKitAccount
but requires the user to be authenticated and throws an error if notuseGraphAuthKitAccountEffect
-> Override of the wagmi useAccountEffect hook that listens to account changes and the _enteredMultisigInfo
on the inner context instance. If the account data changes, emits a onConnect
or onDisconnect
event, but in the onConnect
also checks the useGraphAuthKitInnerContext()._enteredMultisigInfo
value and if the user has connected via a multisig, returns the mutlsig as the address
value and the connected EoA as the eoa
value.useGraphAuthKitWalletClient
-> Override of the wagmi useWalletClient hook that returns the extended Safe viem actions if the user is connected to a multisig.useGraphAuthKitWriteContract
-> Override of the wagmi useWriteContract hook that creates the transaction on the Safe if the user is connected via multisig; otherwise, returns the useWriteContract
mutation hook.Connected
-> renders the passed in children
only if the user is connected.import { Connected } from '@edgeandnode/graph-auth-kit'
export function ShowMeConnected() {
return <Connected>{(account) => <div>Connected Wallet: {account.address}</div>}</Connected>
}
Disconnected
-> renders the passed in children
only if the user id disconnected. Useful for rendering components like a "Connect Wallet" CTA that should only render if the user is not authenticated.import { ExperimentalButton as Button } from '@edgeandnode/gds'
import { Disconnected, useGraphAuthKit } from '@edgeandnode/graph-auth-kit'
export function ShowMeDisconnected() {
const authkit = useGraphAuthKit()
return (
<Disconnected>
<Button variant="primary" onClick={() => authkit.openConnectModal()}>
Connect Wallet
</Button>
</Disconnected>
)
}
SwitchChain
-> Similar to the SwitchNetwork
component from GDS, but uses the wagmi useSwitchChain hook.import { ExperimentalButton as Button } from '@edgeandnode/gds'
import { L2Chain, SwitchChain } from '@edgeandnode/graph-auth-kit'
export function LetMeSwitchChain() {
return <SwitchChain requestedChain={L2Chain} />
}
FAQs
Wallet authentication connect kit in The Graph suite of applications
We found that @edgeandnode/graph-auth-kit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.