Skip to content

Commit

Permalink
Implement PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
cprussin committed Jun 24, 2024
1 parent 2dceecb commit c73baf3
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 52 deletions.
22 changes: 14 additions & 8 deletions apps/api-reference/src/apis/evm/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,27 @@ export const ETHUSD =
const HERMES_URL = "https://hermes.pyth.network";

export const getLatestPriceFeed = async (feedId: string) => {
const url = new URL("/api/latest_price_feeds", HERMES_URL);
const url = new URL("/v2/updates/price/latest", HERMES_URL);
url.searchParams.set("ids[]", feedId);
url.searchParams.set("target_chain", "evm");
url.searchParams.set("binary", "true");
return safeFetch(priceFeedSchema, url);
};

const priceFeedSchema = singletonArray(
z.object({
vaa: z.string().transform((value) => toZeroXPrefixedHex(value)),
price: z.object({
publish_time: z.number(),
}),
const priceFeedSchema = z.object({
binary: z.object({
data: singletonArray(z.string()).transform((value) =>
toZeroXPrefixedHex(value),
),
}),
);
parsed: singletonArray(
z.object({
price: z.object({
publish_time: z.number(),
}),
}),
),
});

const toZeroXPrefixedHex = (value: string) =>
`0x${Buffer.from(value, "base64").toString("hex")}`;
Expand Down
2 changes: 1 addition & 1 deletion apps/api-reference/src/apis/evm/get-update-fee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ const [feeAmount] = await contract.getUpdateFee(updateData);

const getParams = async (feedId: string) => {
const feed = await getLatestPriceFeed(feedId);
return { updateData: feed.vaa };
return { updateData: feed.binary.data };
};
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ const getParams = async (
},
) => {
const feed = await getLatestPriceFeed(priceId);
const fee = await ctx.readContract("getUpdateFee", [[feed.vaa]]);
const fee = await ctx.readContract("getUpdateFee", [[feed.binary.data]]);
if (typeof fee !== "bigint") {
throw new TypeError("Invalid fee");
}
return {
updateData: feed.vaa,
updateData: feed.binary.data,
priceId,
minPublishTime: (feed.price.publish_time - 5).toString(),
maxPublishTime: (feed.price.publish_time + 5).toString(),
minPublishTime: (feed.parsed.price.publish_time - 5).toString(),
maxPublishTime: (feed.parsed.price.publish_time + 5).toString(),
fee: fee.toString(),
};
};
8 changes: 4 additions & 4 deletions apps/api-reference/src/apis/evm/parse-price-feed-updates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ const getParams = async (
},
) => {
const feed = await getLatestPriceFeed(priceId);
const fee = await ctx.readContract("getUpdateFee", [[feed.vaa]]);
const fee = await ctx.readContract("getUpdateFee", [[feed.binary.data]]);
if (typeof fee !== "bigint") {
throw new TypeError("Invalid fee");
}
return {
updateData: feed.vaa,
updateData: feed.binary.data,
priceId,
minPublishTime: (feed.price.publish_time - 5).toString(),
maxPublishTime: (feed.price.publish_time + 5).toString(),
minPublishTime: (feed.parsed.price.publish_time - 5).toString(),
maxPublishTime: (feed.parsed.price.publish_time + 5).toString(),
fee: fee.toString(),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ const getParams = async (
},
) => {
const feed = await getLatestPriceFeed(priceId);
const fee = await ctx.readContract("getUpdateFee", [[feed.vaa]]);
const fee = await ctx.readContract("getUpdateFee", [[feed.binary.data]]);
if (typeof fee !== "bigint") {
throw new TypeError("Invalid fee");
}
return {
updateData: feed.vaa,
updateData: feed.binary.data,
priceId,
publishTime: feed.price.publish_time.toString(),
publishTime: feed.parsed.price.publish_time.toString(),
fee: fee.toString(),
};
};
4 changes: 2 additions & 2 deletions apps/api-reference/src/apis/evm/update-price-feeds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ const getParams = async (
},
) => {
const feed = await getLatestPriceFeed(feedId);
const fee = await ctx.readContract("getUpdateFee", [[feed.vaa]]);
const fee = await ctx.readContract("getUpdateFee", [[feed.binary.data]]);
if (typeof fee !== "bigint") {
throw new TypeError("Invalid fee");
}
return {
updateData: feed.vaa,
updateData: feed.binary.data,
fee: fee.toString(),
};
};
45 changes: 38 additions & 7 deletions apps/api-reference/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,65 @@
"use client";

import clsx from "clsx";
import type { ComponentProps, ElementType } from "react";
import {
type ComponentProps,
type ElementType,
type MouseEvent,
useState,
useCallback,
type CSSProperties,
} from "react";

type ButtonProps<T extends ElementType> = Omit<ComponentProps<T>, "as"> & {
as?: T;
loading?: boolean | undefined;
gradient?: boolean | undefined;
};

export const Button = <T extends ElementType>({
as,
className,
loading,
disabled,
gradient,
...props
}: ButtonProps<T>) => {
const Component = as ?? "button";
const [mouse, setMouse] = useState({ x: 0, y: 0 });

const updateMouse = useCallback((e: MouseEvent<HTMLButtonElement>) => {
setMouse({
x: e.pageX - e.currentTarget.offsetLeft,
y: e.pageY - e.currentTarget.offsetTop,
});
}, []);

return (
<Component
disabled={loading === true || disabled === true}
onMouseMove={updateMouse}
style={
gradient
? ({
"--gradient-left": `${mouse.x.toString()}px`,
"--gradient-top": `${mouse.y.toString()}px`,
} as CSSProperties)
: {}
}
className={clsx(
"rounded-lg border text-sm font-medium transition-all duration-300",
"relative overflow-hidden rounded-lg border text-sm font-medium transition-all duration-300",
{
"border-neutral-400 bg-pythpurple-600/5 hover:border-pythpurple-600 hover:bg-pythpurple-600/15 hover:shadow-md dark:border-neutral-600 dark:bg-pythpurple-400/5 dark:hover:border-pythpurple-400 dark:hover:bg-pythpurple-400/15 dark:hover:shadow-white/20":
"border-neutral-400 hover:border-pythpurple-600 hover:shadow-md dark:border-neutral-600 dark:hover:border-pythpurple-400 dark:hover:shadow-white/20":
!loading && !disabled,
},
{
"before:absolute before:left-[var(--gradient-left)] before:top-[var(--gradient-top)] before:-ml-[20rem] before:-mt-[20rem] before:block before:size-[40rem] before:scale-0 before:bg-gradient-radial before:from-pythpurple-400/30 before:to-70% before:opacity-50 before:transition before:duration-500 hover:before:scale-100 hover:before:opacity-100 dark:before:from-pythpurple-600/30":
gradient && !loading && !disabled,
"bg-pythpurple-600/5 hover:bg-pythpurple-600/15 dark:bg-pythpurple-400/5 dark:hover:bg-pythpurple-400/15":
!gradient && !loading && !disabled,
"border-neutral-200 bg-neutral-100 text-neutral-400 dark:border-neutral-800 dark:bg-neutral-900 dark:text-neutral-500":
loading === true || disabled === true,
"cursor-not-allowed": disabled === true && loading !== true,
"cursor-wait": loading === true,
},
{ "cursor-not-allowed": disabled === true && loading !== true },
{ "cursor-wait": loading === true },
className,
)}
{...props}
Expand Down
23 changes: 23 additions & 0 deletions apps/api-reference/src/components/ErrorTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ExclamationCircleIcon } from "@heroicons/react/24/solid";
import clsx from "clsx";
import type { ReactNode } from "react";

import { Tooltip } from "../Tooltip";

type Props = {
children: ReactNode;
className?: string | undefined;
};

export const ErrorTooltip = ({ className, children }: Props) => (
<Tooltip arrow={{ width: 6, height: 10 }} gap={0} placement="top-end">
<Tooltip.Trigger
as={ExclamationCircleIcon}
className={clsx("text-red-500 dark:text-red-700", className)}
/>
<Tooltip.Content className="z-50 whitespace-pre-line rounded-md border border-red-500 bg-red-50 px-3 py-2 text-red-800 shadow-md dark:border-red-900 dark:bg-red-950 dark:text-red-200 dark:shadow-white/5">
<Tooltip.Arrow className="fill-red-500 dark:fill-red-700" />
<div className="max-w-40 text-xs">{children}</div>
</Tooltip.Content>
</Tooltip>
);
33 changes: 24 additions & 9 deletions apps/api-reference/src/components/EvmApi/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Field,
Label,
} from "@headlessui/react";
import { ArrowPathIcon } from "@heroicons/react/24/outline";
import PythAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
import PythErrorsAbi from "@pythnetwork/pyth-sdk-solidity/abis/PythErrors.json";
import { ChainIcon } from "connectkit";
Expand All @@ -32,6 +33,7 @@ import { ParameterInput } from "./parameter-input";
import { type EvmApiType, RunButton } from "./run-button";
import { useIsMounted } from "../../use-is-mounted";
import { type SupportedLanguage, Code } from "../Code";
import { ErrorTooltip } from "../ErrorTooltip";
import { InlineLink } from "../InlineLink";
import { Select } from "../Select";

Expand Down Expand Up @@ -258,9 +260,12 @@ const Example = <ParameterName extends string>({
setParamValues,
}: ExampleProps<ParameterName>) => {
const config = useConfig();
const [error, setError] = useState<string | undefined>(undefined);
const [loading, setLoading] = useState(false);

const updateValues = useCallback(() => {
if (typeof example.parameters === "function") {
setError(undefined);
const address = getContractAddress(config.state.chainId);
if (!address) {
throw new Error(
Expand All @@ -272,12 +277,18 @@ const Example = <ParameterName extends string>({
readContract(config, { abi, address, functionName, args }),
});
if (params instanceof Promise) {
setLoading(true);
params
.then((paramsResolved) => {
setParamValues(paramsResolved);
})
.catch(() => {
/* TODO add some UI when this errors */
setError(
"An error occurred while fetching data for this example, please try again",
);
})
.finally(() => {
setLoading(false);
});
} else {
setParamValues(params);
Expand All @@ -289,13 +300,17 @@ const Example = <ParameterName extends string>({
const Icon = example.icon;

return (
<InlineLink
as="button"
onClick={updateValues}
className="flex flex-row items-center gap-2"
>
{Icon && <Icon className="h-4" />}
<span>{example.name}</span>
</InlineLink>
<div className="flex flex-row items-center gap-2">
<InlineLink
as="button"
onClick={updateValues}
className="flex flex-row items-center gap-2"
>
{Icon && <Icon className="h-4" />}
<span>{example.name}</span>
</InlineLink>
{error && <ErrorTooltip className="size-4">{error}</ErrorTooltip>}
{loading && <ArrowPathIcon className="size-4 animate-spin" />}
</div>
);
};
5 changes: 3 additions & 2 deletions apps/api-reference/src/components/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { MaxWidth } from "../MaxWidth";

export const Home = () => (
<main className="grid size-full place-content-center py-16 text-center">
<h1 className="mb-24 text-6xl font-semibold text-pythpurple-600 dark:text-pythpurple-400">
<h1 className="mb-16 text-4xl font-semibold text-pythpurple-600 dark:text-pythpurple-400">
Pyth Network API Reference
</h1>
<MaxWidth>
Expand Down Expand Up @@ -62,7 +62,8 @@ const ProductLink = ({
<Button
as={Link}
href={href}
className="flex flex-col items-center gap-6 p-6 text-left sm:flex-row"
gradient
className="flex flex-col items-center gap-2 p-6 text-center sm:flex-row sm:gap-6 sm:pr-12 sm:text-left"
>
<Icon className="h-24 p-3 text-pythpurple-600 dark:text-pythpurple-400" />
<div className="flex flex-col gap-2">
Expand Down
16 changes: 4 additions & 12 deletions apps/api-reference/src/components/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import {
Input as HeadlessUiInput,
type InputProps,
} from "@headlessui/react";
import { ExclamationCircleIcon } from "@heroicons/react/24/solid";
import clsx from "clsx";
import type { ReactNode } from "react";

import { Tooltip } from "../Tooltip";
import { ErrorTooltip } from "../ErrorTooltip";

type Props = InputProps & {
label: ReactNode;
Expand Down Expand Up @@ -44,16 +43,9 @@ export const Input = ({
{...props}
/>
{validationError && (
<Tooltip arrow={{ width: 6, height: 10 }} gap={0} placement="top-end">
<Tooltip.Trigger
as={ExclamationCircleIcon}
className="absolute right-3 top-3 h-6 text-red-500 dark:text-red-700"
/>
<Tooltip.Content className="z-50 whitespace-pre-line rounded-md border border-red-500 bg-red-50 px-3 py-2 text-red-800 shadow-md dark:border-red-900 dark:bg-red-950 dark:text-red-200 dark:shadow-white/5">
<Tooltip.Arrow className="fill-red-500 dark:fill-red-700" />
<div className="max-w-40 text-xs">{validationError}</div>
</Tooltip.Content>
</Tooltip>
<ErrorTooltip className="absolute right-3 top-3 h-6">
{validationError}
</ErrorTooltip>
)}
</div>
<Description className="mx-3 text-xs font-light text-neutral-600 dark:text-neutral-400">
Expand Down
3 changes: 3 additions & 0 deletions apps/api-reference/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const tailwindConfig = {
plugins: [forms],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
},
fontFamily: {
sans: ["var(--font-sans)"],
mono: ["var(--font-mono)"],
Expand Down

0 comments on commit c73baf3

Please sign in to comment.