Skip to content

Commit

Permalink
Merge branch 'main' into gamification-removal
Browse files Browse the repository at this point in the history
  • Loading branch information
kkosiorowska authored Dec 5, 2024
2 parents 8ccb337 + 1452d52 commit a39e8e9
Show file tree
Hide file tree
Showing 21 changed files with 237 additions and 46 deletions.
5 changes: 5 additions & 0 deletions dapp/.env
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ VITE_GELATO_RELAY_API_KEY="htaJCy_XHj8WsE3w53WBMurfySDtjLP_TrNPPa6IPIc_" # this
# Get the API key from: https://thegraph.com/studio/apikeys/.
VITE_SUBGRAPH_API_KEY=""

# Posthog
VITE_POSTHOG_API_HOST="https://us.i.posthog.com"
VITE_POSTHOG_API_KEY=""

# Feature flags
VITE_FEATURE_FLAG_WITHDRAWALS_ENABLED="false"
VITE_FEATURE_FLAG_OKX_WALLET_ENABLED="false"
VITE_FEATURE_FLAG_XVERSE_WALLET_ENABLED="false"
VITE_FEATURE_FLAG_ACRE_POINTS_ENABLED="true"
VITE_FEATURE_FLAG_TVL_ENABLED="true"
VITE_FEATURE_GATING_DAPP_ENABLED="true"
VITE_FEATURE_POSTHOG_ENABLED="true"
VITE_FEATURE_MOBILE_MODE_ENABLED="true"

1 change: 1 addition & 0 deletions dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"framer-motion": "^10.16.5",
"luxon": "^3.5.0",
"mustache": "^4.2.0",
"posthog-js": "^1.186.1",
"react": "^18.2.0",
"react-confetti-explosion": "^2.1.2",
"react-dom": "^18.2.0",
Expand Down
5 changes: 4 additions & 1 deletion dapp/src/DApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import getWagmiConfig from "./wagmiConfig"
import queryClient from "./queryClient"
import { delay, logPromiseFailure } from "./utils"
import { AcreLogo } from "./assets/icons"
import PostHogProvider from "./posthog/PostHogProvider"

function SplashPage() {
return (
Expand Down Expand Up @@ -69,7 +70,9 @@ function DAppProviders() {
<SidebarContextProvider>
<WalletConnectionAlertContextProvider>
<ReduxProvider store={store}>
<DApp />
<PostHogProvider>
<DApp />
</PostHogProvider>
</ReduxProvider>
</WalletConnectionAlertContextProvider>
</SidebarContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from "@chakra-ui/react"
import { IconArrowNarrowRight } from "@tabler/icons-react"
import { AnimatePresence, Variants, motion } from "framer-motion"
import { usePostHogIdentity } from "#/hooks/posthog"
import ArrivingSoonTooltip from "../ArrivingSoonTooltip"
import { TextLg, TextMd } from "../shared/Typography"
import ConnectWalletStatusLabel from "./ConnectWalletStatusLabel"
Expand Down Expand Up @@ -72,6 +73,7 @@ export default function ConnectWalletButton({
const { closeModal } = useModal()
const dispatch = useAppDispatch()
const isMounted = useRef(false)
const { handleIdentification } = usePostHogIdentity()

const [isLoading, setIsLoading] = useState<boolean>(false)

Expand Down Expand Up @@ -118,8 +120,11 @@ export default function ConnectWalletButton({
if (!btcAddress) return

await handleSignMessageAndCreateSession(connector, btcAddress)
handleIdentification(btcAddress, {
connector: connectedConnector.id,
})
},
[connector, handleSignMessageAndCreateSession],
[connector, handleSignMessageAndCreateSession, handleIdentification],
)

const handleConnection = useCallback(() => {
Expand Down
18 changes: 18 additions & 0 deletions dapp/src/components/Header/ConnectWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
IconChevronUp,
} from "@tabler/icons-react"
import { useMatch } from "react-router-dom"
import { usePostHogIdentity } from "#/hooks/posthog"
import Tooltip from "../shared/Tooltip"

function isChangeAccountFeatureSupported(embeddedApp: string | undefined) {
Expand All @@ -45,12 +46,18 @@ export default function ConnectWallet() {
size: "lg",
})
const isDashboardPage = useMatch("/dashboard")
const { resetIdentity } = usePostHogIdentity()
const isMobile = useMobileMode()

const handleConnectWallet = (isReconnecting: boolean = false) => {
openModal(MODAL_TYPES.CONNECT_WALLET, { isReconnecting })
}

const handleDisconnectWallet = () => {
onDisconnect()
resetIdentity()
}

if (!address) {
return (
<Button
Expand Down Expand Up @@ -184,6 +191,17 @@ export default function ConnectWallet() {
</Tooltip>
),
)}

<Tooltip size="xs" label="Disconnect">
<IconButton
variant="ghost"
aria-label="Disconnect"
icon={<Icon as={IconLogout} boxSize={5} />}
px={2}
boxSize={5}
onClick={handleDisconnectWallet}
/>
</Tooltip>
</HStack>
</Flex>
</HStack>
Expand Down
5 changes: 5 additions & 0 deletions dapp/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Outlet } from "react-router-dom"
import { Flex, VStack } from "@chakra-ui/react"
import { useIsEmbed, useMobileMode } from "#/hooks"
import { DappMode } from "#/types"
import { usePostHogPageViewCapture } from "#/hooks/posthog"
import DocsDrawer from "./DocsDrawer"
import Header from "./Header"
import ModalRoot from "./ModalRoot"
Expand All @@ -24,6 +25,10 @@ function Layout() {
const isMobileMode = useMobileMode()
const { isEmbed, embeddedApp } = useIsEmbed()

// It needs to be called here because the scope of `RouterProvider` is
// required to get `location` from `useLocation` hook.
usePostHogPageViewCapture()

if (!isEmbed && isMobileMode) return <MobileModeBanner forceOpen />

const maxWidth = embeddedApp
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useCallback, useRef } from "react"
import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants"
import {
useActionFlowPause,
useActionFlowTokenAmount,
Expand All @@ -9,10 +10,11 @@ import {
useStakeFlowContext,
useVerifyDepositAddress,
} from "#/hooks"
import { eip1193, logPromiseFailure } from "#/utils"
import { PROCESS_STATUSES } from "#/types"
import { usePostHogCapture } from "#/hooks/posthog/usePostHogCapture"
import { PostHogEvent } from "#/posthog/events"
import { setStatus, setTxHash } from "#/store/action-flow"
import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants"
import { PROCESS_STATUSES } from "#/types"
import { eip1193, logPromiseFailure } from "#/utils"
import { useTimeout } from "@chakra-ui/react"
import { useMutation } from "@tanstack/react-query"
import WalletInteractionModal from "../WalletInteractionModal"
Expand All @@ -28,6 +30,7 @@ export default function DepositBTCModal() {
const handleBitcoinBalanceInvalidation = useInvalidateQueries({
queryKey: userKeys.balance(),
})
const { handleCapture, handleCaptureWithCause } = usePostHogCapture()

const sessionId = useRef(Math.random())
const { cancel, resolve, sessionIdToPromise } = useCancelPromise(
Expand Down Expand Up @@ -59,8 +62,11 @@ export default function DepositBTCModal() {
(transactionHash: string) => {
dispatch(setTxHash(transactionHash))
handleStake()
handleCapture(PostHogEvent.DepositSuccess, {
transactionHash,
})
},
[dispatch, handleStake],
[dispatch, handleStake, handleCapture],
)

const onDepositBTCError = useCallback(
Expand All @@ -72,8 +78,10 @@ export default function DepositBTCModal() {
} else {
onError(error)
}

handleCaptureWithCause(error, PostHogEvent.DepositFailure)
},
[sessionIdToPromise, handlePause, onError],
[sessionIdToPromise, handlePause, onError, handleCaptureWithCause],
)

const { mutate: sendBitcoinTransaction, status } = useDepositBTCTransaction({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { useInitializeWithdraw } from "#/acre-react/hooks"
import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants"
import { activityInitialized } from "#/store/wallet"
import { useMutation } from "@tanstack/react-query"
import { PostHogEvent } from "#/posthog/events"
import { usePostHogCapture } from "#/hooks/posthog/usePostHogCapture"
import BuildTransactionModal from "./BuildTransactionModal"
import WalletInteractionModal from "../WalletInteractionModal"

Expand Down Expand Up @@ -44,6 +46,7 @@ export default function SignMessageModal() {
amount,
ACTION_FLOW_TYPES.UNSTAKE,
)
const { handleCapture, handleCaptureWithCause } = usePostHogCapture()

const dataBuiltStepCallback = useCallback(() => {
setWaitingStatus("built-data")
Expand All @@ -58,7 +61,8 @@ export default function SignMessageModal() {
const onSignMessageSuccess = useCallback(() => {
handleBitcoinPositionInvalidation()
dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED))
}, [dispatch, handleBitcoinPositionInvalidation])
handleCapture(PostHogEvent.WithdrawalSuccess)
}, [dispatch, handleBitcoinPositionInvalidation, handleCapture])

const onSignMessageError = useCallback(
(error: unknown) => {
Expand All @@ -77,8 +81,15 @@ export default function SignMessageModal() {
} else {
onSignMessageError(error)
}

handleCaptureWithCause(error, PostHogEvent.WithdrawalFailure)
},
[sessionIdToPromise, handlePause, onSignMessageError],
[
sessionIdToPromise,
handlePause,
onSignMessageError,
handleCaptureWithCause,
],
)

const { mutate: handleSignMessage } = useMutation({
Expand Down
6 changes: 6 additions & 0 deletions dapp/src/constants/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const LATEST_COMMIT_HASH = import.meta.env.VITE_LATEST_COMMIT_HASH

const ACRE_API_ENDPOINT = import.meta.env.VITE_ACRE_API_ENDPOINT

const POSTHOG_API_HOST = import.meta.env.VITE_POSTHOG_API_HOST

const POSTHOG_API_KEY = import.meta.env.VITE_POSTHOG_API_KEY

export default {
PROD,
USE_TESTNET,
Expand All @@ -35,4 +39,6 @@ export default {
NETWORK_TYPE,
LATEST_COMMIT_HASH,
ACRE_API_ENDPOINT,
POSTHOG_API_HOST,
POSTHOG_API_KEY,
}
3 changes: 3 additions & 0 deletions dapp/src/constants/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const TVL_ENABLED = import.meta.env.VITE_FEATURE_FLAG_TVL_ENABLED === "true"
const GATING_DAPP_ENABLED =
import.meta.env.VITE_FEATURE_GATING_DAPP_ENABLED === "true"

const POSTHOG_ENABLED = import.meta.env.VITE_FEATURE_POSTHOG_ENABLED === "true"

const MOBILE_MODE_ENABLED =
import.meta.env.VITE_FEATURE_MOBILE_MODE_ENABLED === "true"

Expand All @@ -25,6 +27,7 @@ const featureFlags = {
ACRE_POINTS_ENABLED,
TVL_ENABLED,
GATING_DAPP_ENABLED,
POSTHOG_ENABLED,
MOBILE_MODE_ENABLED,
}

Expand Down
3 changes: 3 additions & 0 deletions dapp/src/hooks/posthog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./usePostHogIdentity"
export * from "./usePostHogCapture"
export * from "./usePostHogPageViewCapture"
40 changes: 40 additions & 0 deletions dapp/src/hooks/posthog/usePostHogCapture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { PostHogEvent } from "#/posthog/events"
import { PostHog, usePostHog } from "posthog-js/react"
import { useCallback } from "react"

type CaptureArgs = [
eventName: PostHogEvent,
...rest: Parameters<PostHog["capture"]> extends [unknown, ...infer R]
? R
: never,
]

export const usePostHogCapture = () => {
const posthog = usePostHog()

const handleCapture = useCallback(
(...captureArgs: CaptureArgs) => {
posthog.capture(...captureArgs)
},
[posthog],
)

const handleCaptureWithCause = useCallback(
(error: unknown, ...captureArgs: CaptureArgs) => {
const [eventName, parameters, ...rest] = captureArgs

const captureParameters =
error instanceof Error
? {
...parameters,
cause: error.message,
}
: undefined

handleCapture(eventName, captureParameters, ...rest)
},
[handleCapture],
)

return { handleCapture, handleCaptureWithCause }
}
27 changes: 27 additions & 0 deletions dapp/src/hooks/posthog/usePostHogIdentity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PostHog, usePostHog } from "posthog-js/react"
import { useCallback } from "react"
import { sha256, toUtf8Bytes } from "ethers"

type IdentifyArgs = Parameters<PostHog["identify"]>

export const usePostHogIdentity = () => {
const posthog = usePostHog()

const handleIdentification = useCallback(
(...identifyArgs: IdentifyArgs) => {
const [id, ...rest] = identifyArgs
if (!id) return

const hashedId = sha256(toUtf8Bytes(id.toLowerCase())).slice(2, 12)

posthog.identify(hashedId, ...rest)
},
[posthog],
)

const resetIdentity = useCallback(() => {
posthog.reset()
}, [posthog])

return { handleIdentification, resetIdentity }
}
15 changes: 15 additions & 0 deletions dapp/src/hooks/posthog/usePostHogPageViewCapture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PostHogEvent } from "#/posthog/events"
import { useEffect } from "react"
import { useLocation } from "react-router-dom"
import { usePostHogCapture } from "./usePostHogCapture"

export const usePostHogPageViewCapture = () => {
const { handleCapture } = usePostHogCapture()
const location = useLocation()

useEffect(() => {
handleCapture(PostHogEvent.PageView)
}, [location, handleCapture])

return handleCapture
}
13 changes: 11 additions & 2 deletions dapp/src/hooks/useAcrePoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { useMutation, useQuery } from "@tanstack/react-query"
import { acreApi } from "#/utils"
import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants"
import { MODAL_TYPES } from "#/types"
import { PostHogEvent } from "#/posthog/events"
import { useWallet } from "./useWallet"
import { useModal } from "./useModal"
import { usePostHogCapture } from "./posthog/usePostHogCapture"

const { userKeys, acreKeys } = queryKeysFactory

Expand All @@ -21,6 +23,7 @@ type UseAcrePointsReturnType = {
export default function useAcrePoints(): UseAcrePointsReturnType {
const { ethAddress = "" } = useWallet()
const { openModal } = useModal()
const { handleCapture, handleCaptureWithCause } = usePostHogCapture()

const userPointsDataQuery = useQuery({
queryKey: [...userKeys.pointsData(), ethAddress],
Expand All @@ -47,9 +50,15 @@ export default function useAcrePoints(): UseAcrePointsReturnType {
claimedAmount,
totalAmount,
})

handleCapture(PostHogEvent.PointsClaimSuccess, {
claimedAmount,
totalAmount,
})
},
onError: (error) => {
handleCaptureWithCause(error, PostHogEvent.PointsClaimFailure)
},
// TODO: Add the case when something goes wrong
// onError: (error) => {},
})

return {
Expand Down
Loading

0 comments on commit a39e8e9

Please sign in to comment.