Skip to content

Commit

Permalink
Merge pull request #46 from Topledger/wallet-and-token-analytics
Browse files Browse the repository at this point in the history
update analytics url
  • Loading branch information
urluckyturtle01 authored Dec 7, 2023
2 parents 8e03631 + 945f0bc commit 405a8aa
Show file tree
Hide file tree
Showing 7 changed files with 3,137 additions and 60 deletions.
2 changes: 1 addition & 1 deletion pages/home/components/SearchDashboards/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function SearchDashboards() {
router.push("/programs?p_Program+Address=JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB");
}}
ref={searchRef}
placeholder="Enter a program"
placeholder="Program or Token"
/>
<Transition in={searchActive} nodeRef={dashboardListRef}>
{(state) => (
Expand Down
54 changes: 46 additions & 8 deletions pages/programs/components/ProgramAddressInput/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/router";
import cx from "classnames";
import { usePopper } from "react-popper";
import { Transition } from "react-transition-group";
Expand All @@ -10,14 +9,19 @@ import DashboardList, { Arrow } from "pages/home/components/DashboardList";
import searchStyles from "../../../home/components/SearchDashboards/index.module.scss";
import styles from "./ProgramAddressInput.module.scss";
import Portal from "@/components/Portal";
import { PARAMETER_NAMES } from "pages/programs/constants";
import { useSearchObject } from "pages/programs/utils";
import { useRouter } from "next/router";

function ProgramAdressInput({ isDashboard, onApply, programs }) {
function ProgramAdressInput({ isDashboard, parameterName, onApply, programs }) {
const [filterText, setFilterText] = useState("");
const [portalContainer, setPortalContainer] = useState();
const searchRef = useRef();
const router = useRouter();
const query = useSearchObject();
const suggestionListRef = useRef();
const { ["p_Program Address"]: address } = router.query;
const { [`p_${parameterName}`]: address } = query;
console.log("address", address, query);
const { styles: popperStyles } = usePopper(
searchRef.current,
suggestionListRef.current
Expand All @@ -30,16 +34,50 @@ function ProgramAdressInput({ isDashboard, onApply, programs }) {
const handleArrowClick = (value) => {
if (filterText) {
const queryParams = new URLSearchParams(location.search);
queryParams.set("p_Program Address", value ?? filterText);
PARAMETER_NAMES.forEach((name) => queryParams.delete(`p_${name}`));
queryParams.set(`p_${parameterName}`, value ?? filterText);
const newURL = new URL(location.href);
newURL.search = queryParams.toString();
router.push(newURL.href);
// router.push(newURL.href);
window.location.href = newURL.href;
// onApply(value ?? filterText)
}
};

useEffect(() => {
if (!address) {
const queryParams = new URLSearchParams(location.search);
PARAMETER_NAMES.forEach((name) => queryParams.delete(`p_${name}`));
queryParams.set(
`p_${parameterName}`,
"JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB"
);
const newURL = new URL(location.href);
newURL.search = queryParams.toString();
// router.push(newURL.href);
window.location.href = newURL.href;
}
}, []);

useEffect(() => {
if (parameterName) {
const queryParams = new URLSearchParams(location.search);
const currentParamName = PARAMETER_NAMES.find((name) =>
queryParams.has(`p_${name}`)
);
if (currentParamName) {
const address = queryParams.get(`p_${currentParamName}`);
queryParams.delete(`p_${currentParamName}`);
queryParams.set(`p_${parameterName}`, address);

const newURL = new URL(location.href);
newURL.search = queryParams.toString();
router.push(newURL.href);
}
}
}, [parameterName]);

const handleSelect = (program) => {
console.log("program", program);
if (program.id) {
setFilterText(program.id);
handleArrowClick(program.id);
Expand Down Expand Up @@ -76,11 +114,11 @@ function ProgramAdressInput({ isDashboard, onApply, programs }) {
className={cx(searchStyles.search, styles.search, {
dashboardInput: isDashboard,
})}
onStateChange={() => {}}
onStateChange={() => { }}
onChange={handleInputChange}
ref={searchRef}
defaultFocused
placeholder="Enter a program address"
placeholder="Enter a Program or Token Address"
onEnter={handleArrowClick}
value={filterText}
/>
Expand Down
32 changes: 32 additions & 0 deletions pages/programs/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const DASHBOARDS = {
programs: {
client: "tl",
token: "oIEupNW8g4Ua9C64JvUsYRLNlOZej940x341KaAH",
adddressParamName: "Program Address",
title: "Solana Program",
},
wallet: {
client: "tl",
token: "T36Gx8PC8nZtot8jqIbM8yMU1l2ZjvCltXs2MLY5",
adddressParamName: "wallet address",
title: "Solana Wallet",
},
token: {
client: "tl",
token: "NECxpxtYkwl4p3AnXN8pUEZpdy57h8jO0xADB3PZ",
adddressParamName: "token mint",
title: "Solana Token",
},
};

export const DASHBOARD_PARAM_MAPPING = Object.keys(DASHBOARDS).reduce(
(obj, type) => ({
...obj,
[DASHBOARDS[type].adddressParamName]: DASHBOARDS[type],
}),
{}
);

export const PARAMETER_NAMES = Object.keys(DASHBOARDS).map(
(type) => DASHBOARDS[type].adddressParamName
);
93 changes: 70 additions & 23 deletions pages/programs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,27 @@ import { useCallback, useEffect, useRef, useState } from "react";
import cx from "classnames";
import dynamic from "next/dynamic";
import Head from "next/head";
import { useRouter } from "next/router";
import { useQuery } from "react-query";

import { sendEvent } from "helpers/gaHelper";
import { fetchProgramList } from "queries";
import { fetchAddressInfo, fetchProgramList } from "queries";
import Loader from "./components/Loader";
import ProgramAdressInput from "./components/ProgramAddressInput";
import styles from "./programs.module.scss";
import {
DASHBOARDS,
DASHBOARD_PARAM_MAPPING,
PARAMETER_NAMES,
} from "./constants";
import { useSearchObject } from "./utils";

const FeedbackForm = dynamic(() => import(/** webackChunkName: "FeedbackForm" */"@/components/FeedbackForm"), {
ssr: false
});
const FeedbackForm = dynamic(
() =>
import(/** webackChunkName: "FeedbackForm" */ "@/components/FeedbackForm"),
{
ssr: false,
}
);

const DashboardHead = ({ programName }) => (
<Head>
Expand Down Expand Up @@ -44,12 +53,21 @@ const TLDashboards = dynamic(
);

function Programs() {
const router = useRouter();
const query = useSearchObject();
const dashboardRef = useRef();
const { ["p_Program Address"]: address } = router.query;
const [dashboardLoading, setDashboardLoading] = useState(true);
const parametersRef = useRef();

const [parameterName, setParameterName] = useState(
PARAMETER_NAMES.find((name) => query[`p_${name}`]) ??
DASHBOARDS.programs.adddressParamName
);

const [dashboard, setDashboard] = useState(
DASHBOARD_PARAM_MAPPING[parameterName]
);
const address = query[`p_${parameterName}`];

const { data: programList = {}, isLoading } = useQuery(
"PROGRAM_LIST",
() =>
Expand All @@ -58,10 +76,21 @@ function Programs() {
),
{
cacheTime: 3600,
refetchOnWindowFocus: false,
}
);

const title = programList[address]?.program_name ?? "Solana Program";
const { data: addressInfo, isLoading: isAddressLoading } = useQuery(
["ADDRESS_INFO", address],
() => fetchAddressInfo({ address }),
{
cacheTime: 3600,
refetchOnWindowFocus: false,
enabled: !!address,
}
);

const title = programList[address]?.program_name ?? dashboard?.title;
const subTitle = address;

const handleDashboardLoad = useCallback(
Expand All @@ -80,7 +109,7 @@ function Programs() {
let updated = false;
parameters.forEach((parameter) => {
if (
parameter.name === "Program Address" &&
parameter.name === dashboard.adddressParamName &&
parameter.getExecutionValue() !== address
) {
parameter.setValue(address);
Expand All @@ -92,12 +121,12 @@ function Programs() {
}
}
},
[programList]
[programList, dashboard]
);

useEffect(() => {
updateParameterAddress(address);
}, [address]);
}, [dashboard, address]);

useEffect(() => {
if (address) {
Expand All @@ -106,13 +135,27 @@ function Programs() {
// pageView({ path: window.location.pathname, title });
}, [address]);

useEffect(() => {
if (addressInfo) {
console.log("addressInfo", addressInfo);
const dashboard = addressInfo.isProgram
? DASHBOARDS.programs
: addressInfo.isToken
? DASHBOARDS.token
: DASHBOARDS.wallet;
setDashboard(dashboard);
setParameterName(dashboard.adddressParamName);
}
}, [addressInfo]);

return (
<>
<DashboardHead programName={title} />
<div className={styles.programContainer}>
<div className="dashboard">
<ProgramAdressInput
isDashboard
parameterName={parameterName}
onApply={() => {}}
programs={programList}
/>
Expand All @@ -122,20 +165,22 @@ function Programs() {
<span className="title-text">{title}</span>
<span className="title-subtext">{subTitle}</span>
</div>
{isLoading && <Loader />}
{isLoading && isAddressLoading && <Loader />}
<div
className={cx(styles.dashboardContainer, { dashboardLoading })}
>
<TLDashboards
key={address}
client="tl"
token="oIEupNW8g4Ua9C64JvUsYRLNlOZej940x341KaAH"
className={styles.dashboard}
loader={<Loader />}
onDashboardLoad={handleDashboardLoad}
parameters={parametersRef.current}
dashboardRef={dashboardRef}
/>
{address && dashboard.token && dashboard.client && (
<TLDashboards
key={address}
client={dashboard.client}
token={dashboard.token}
className={styles.dashboard}
loader={<Loader />}
onDashboardLoad={handleDashboardLoad}
parameters={parametersRef.current}
dashboardRef={dashboardRef}
/>
)}
</div>
{!isLoading && !dashboardLoading && <FeedbackForm />}
</div>
Expand All @@ -146,4 +191,6 @@ function Programs() {
);
}

export default Programs;
export default dynamic(() => Promise.resolve(Programs), {
ssr: false,
});
32 changes: 32 additions & 0 deletions pages/programs/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react";

export function useSearchParams() {
const router = useRouter();
const [params, setParams] = useState(
new URLSearchParams(window?.location?.search)
);
console.log("router.asPath", router.asPath);

useEffect(() => {
const handleRouteChange = (url) => {
setParams(new URLSearchParams(url.split("?")[1]));
};

router.events.on("routeChangeComplete", handleRouteChange);

return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}, []);

return params;
}

export function useSearchObject() {
const params = useSearchParams();

return useMemo(() => {
return Object.fromEntries(params.entries());
}, [params]);
}
34 changes: 34 additions & 0 deletions queries/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,37 @@ export const postFeedback = async (formData) => {
);
console.log("form response", response.data);
};

export const fetchAddressInfo = async ({ address }) => {
const data = {
jsonrpc: "2.0",
id: 1,
method: "getAccountInfo",
params: [
address,
{
encoding: "jsonParsed",
},
],
};
const response = await axios.post(
"https://external-api.topledger.xyz/",
data,
{
headers: {
"Content-Type": "application/json",
},
withCredentials: false,
}
);
const result = response?.data?.result || {};
const type = result?.value?.data?.parsed?.type;
const info = result?.value?.data?.parsed?.info;
return {
isProgram: type === "program",
isToken: type === "mint" || (type === "account" && info?.mint),
isWallet:
result?.value?.data?.parsed?.info?.owner ===
"11111111111111111111111111111111",
};
};
Loading

0 comments on commit 405a8aa

Please sign in to comment.