Skip to content

Commit

Permalink
feat(examples): fetch data from mimir
Browse files Browse the repository at this point in the history
  • Loading branch information
moreal committed May 15, 2024
1 parent c9ae21a commit 9e9f3ec
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 40 deletions.
60 changes: 22 additions & 38 deletions examples/daily-reward-dapp/src/Agent.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Buffer } from "buffer";
import { BencodexDictionary } from "@planetarium/bencodex";
import { useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import {
useGetAvatarsWithTipQuery,
useStageTransactionMutation,
} from "./generated/graphql";
import { getChronoSdk } from "@planetarium/chrono-sdk";
import { Address } from "@planetarium/account";
import { GetAvatarsResponse, getAvatars, getTip } from "./mimir-client";

interface RefillButtonProps {
signer: Address;
Expand Down Expand Up @@ -106,62 +106,46 @@ function RefillButton({ signer, avatarAddress }: RefillButtonProps) {
}

interface AgentProps {
network: "odin" | "heimdall";
agentAddress: Address;
}

function Agent({ agentAddress }: AgentProps) {
const { data, loading, error } = useGetAvatarsWithTipQuery({
variables: {
agentAddress: agentAddress.toString(),
},
pollInterval: 500,
});
function Agent({ network, agentAddress }: AgentProps) {
const [agent, setAgent] = useState<GetAvatarsResponse>();
const [tip, setTip] = useState<number>();

if (loading) {
return <p className="mt-8 text-white">Loading</p>;
}

if (error) {
return (
<p className="mt-8 text-white">Failed to fetch agent-related states.</p>
);
}

if (data === undefined) {
return (
<p className="mt-8 text-white">Unexpected failure while fetching data.</p>
);
}
useEffect(() => {
setInterval(() => {
getAvatars(network, agentAddress.toString()).then(setAgent);
getTip(network).then(setTip);
}, 500);
}, [network, agentAddress]);

if (data.stateQuery.agent === null || data.stateQuery.agent === undefined) {
if (agent === undefined || tip === undefined) {
return (
<p className="mt-8 text-white">
There is no such agent. (address: {agentAddress.toString()})
</p>
<p className="mt-8 text-white">Loading or unexpected failure while fetching data.</p>
);
}
const agent = data.stateQuery.agent;

if (agent.avatarStates === null || agent.avatarStates === undefined) {
if (agent.avatars.length < 1) {
return (
<p className="mt-8 text-white">The agent may not have avatar states.</p>
<p className="mt-8 text-white">The agent may not have any avatars.</p>
);
}
const avatarStates = agent.avatarStates;
const tipIndex = data.nodeStatus.tip.index;
const avatars = agent.avatars;

return (
<div className="flex flex-col mt-8 min-w-full min-h-full justify-center items-center">
{avatarStates.map((avatar) => (
<div className="p-8 shadow-lg w-4/12 bg-slate-100" key={avatar.address}>
{avatars.map(({ avatarAddress, avatarName, actionPoint, dailyRewardReceivedIndex }) => (
<div className="p-8 shadow-lg w-4/12 bg-slate-100" key={avatarAddress}>
<div className="flex flex-row justify-center items-center gap-4">
<span className="font-bold">
{avatar.name} ({avatar.actionPoint} / 120)
{avatarName} ({actionPoint} / 120)
</span>
{tipIndex - avatar.dailyRewardReceivedIndex > 2550 ? (
{tip - dailyRewardReceivedIndex > 2550 ? (
<RefillButton
signer={agentAddress}
avatarAddress={Address.fromHex(avatar.address)}
avatarAddress={Address.fromHex(avatarAddress)}
/>
) : (
<></>
Expand Down
18 changes: 16 additions & 2 deletions examples/daily-reward-dapp/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import Agent from "./Agent";
import { getChronoSdk } from "@planetarium/chrono-sdk";
import { Address } from "@planetarium/account";
Expand All @@ -14,8 +14,18 @@ function App() {
const [isConnected, setConnected] = useState<boolean>(false);
const [currentNetwork, setCurrentNetwork] = useState<{
gqlEndpoint: string,
genesisHash: string,
id: string,
} | null>(null);
const guessedNetworkName = useMemo<"odin" | "heimdall" | "unknown">(() => {
if (currentNetwork?.genesisHash?.toLowerCase() === "4582250d0da33b06779a8475d283d5dd210c683b9b999d74d03fac4f58fa6bce") {
return "odin";
} else if (currentNetwork?.genesisHash?.toLowerCase() === "729fa26958648a35b53e8e3905d11ec53b1b4929bf5f499884aed7df616f5913") {
return "heimdall";
} else {
return "unknown";
}
}, [currentNetwork]);

const chronoWallet = getChronoSdk();

Expand Down Expand Up @@ -88,6 +98,10 @@ function App() {
return <>Loading... (network)</>
}

if (guessedNetworkName === "unknown") {
return <>Unknown network (genesis hash: {currentNetwork.genesisHash})</>
}

const client = new ApolloClient({
uri: currentNetwork.gqlEndpoint,
cache: new InMemoryCache(),
Expand All @@ -107,7 +121,7 @@ function App() {
</option>
))}
</select>
<Agent agentAddress={accounts[currentAccount].address} />
<Agent network={guessedNetworkName} agentAddress={accounts[currentAccount].address} />
</div>
</ApolloProvider>
);
Expand Down
83 changes: 83 additions & 0 deletions examples/daily-reward-dapp/src/mimir-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
export const BASE_URL = "https://mimir.nine-chronicles.dev/";

const defaultHeaders: HeadersInit = {
"Content-Type": "application/json",
};

interface FetchOptions<TBody = undefined> {
method?: "GET" | "POST";
body?: TBody;
headers?: HeadersInit;
}

async function fetchAPI<TResponse, TBody = undefined>(
endpoint: string,
options: FetchOptions<TBody> = {}
): Promise<TResponse> {
try {
const { method = "GET", body, headers } = options;

const config: RequestInit = {
method,
headers: { ...defaultHeaders, ...headers },
body: body ? JSON.stringify(body) : null,
};

const url = `${BASE_URL}${endpoint}`;

const response = await fetch(url, config);

if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}

const contentType = response.headers.get("Content-Type") || "";
if (contentType.includes("application/json")) {
return (await response.json()) as TResponse;
} else if (contentType.includes("text/csv")) {
return (await response.text()) as unknown as TResponse;
} else {
throw new Error(`Unsupported response format: ${contentType}`);
}
} catch (error) {
console.error("Error fetching data:", error);
throw error;
}
}

export async function getSheetNames(network: string): Promise<string[]> {
return await fetchAPI<string[]>(`${network}/sheets/names`);
}

export async function getSheet(network: string, name: string): Promise<string> {
return await fetchAPI<string>(`${network}/sheets/${name}`, {
headers: { accept: "text/csv" },
});
}

interface Avatar {
avatarAddress: string;
avatarName: string;
level: number;
actionPoint: number;
dailyRewardReceivedIndex: number;
}

export interface GetAvatarsResponse {
avatars: Avatar[];
}

export async function getAvatars(network: string, agentAddress: string): Promise<GetAvatarsResponse> {
return await fetchAPI<GetAvatarsResponse>(`${network}/agent/${agentAddress}/avatars`, {
headers: { accept: "application/json" },
});
}

export async function getTip(network: string): Promise<number> {
const resp = await fetchAPI<{
index: number;
}>(`${network}/tip`, {
headers: { accept: "application/json" },
});
return resp.index;
}

0 comments on commit 9e9f3ec

Please sign in to comment.