Skip to content

Commit

Permalink
Add code for merkle root
Browse files Browse the repository at this point in the history
  • Loading branch information
motechFR committed Nov 1, 2024
1 parent 5a934c9 commit dafdc50
Show file tree
Hide file tree
Showing 10 changed files with 933 additions and 60 deletions.
3 changes: 2 additions & 1 deletion .ebstalk.apps.env/scoutgameadmin.env
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ AIRSTACK_API_KEY="{{pull:secretsmanager:/io.cv.app/prd/farcaster:SecretString:ai

REACT_APP_BUILDER_NFT_CONTRACT_ADDRESS="{{pull:secretsmanager:/io.cv.app/prd/buildernft:SecretString:builder_smart_contract_address}}"

REACT_APP_SCOUTPROTOCOL_CONTRACT_ADDRESS="{{pull:secretsmanager:/io.cv.app/prd/buildernft:SecretString:builder_smart_contract_address}}"
REACT_APP_SCOUTPROTOCOL_CONTRACT_ADDRESS="{{pull:secretsmanager:/io.cv.app/prd/buildernft:SecretString:scoutprotocol_contract_address}}"
SCOUTPROTOCOL_CLAIMS_MANAGER_KEY="{{pull:secretsmanager:/io.cv.app/prd/buildernft:SecretString:scoutprotocol_claims_manager_key}}"
6 changes: 4 additions & 2 deletions apps/scoutgameadmin/app/(general)/contract/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ContractHome } from 'components/contract/ContractsHome';
import { aggregateProtocolData } from 'lib/contract/aggregateProtocolData';
import { getContractData } from 'lib/contract/getContractData';

export const dynamic = 'force-dynamic';

export default async function Dashboard() {
const data = await getContractData();
return <ContractHome seasonOne={data} />;
const seasonOneData = await getContractData();
const protocolData = await aggregateProtocolData();
return <ContractHome seasonOne={seasonOneData} protocol={protocolData} />;
}
5 changes: 3 additions & 2 deletions apps/scoutgameadmin/components/contract/ContractsHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { Tabs, Tab, Box } from '@mui/material';
import { useState } from 'react';

import type { ProtocolData } from 'lib/contract/aggregateProtocolData';
import type { BuilderNFTContractData } from 'lib/contract/getContractData';

import { ProtocolContractDashboard } from './ProtocolContractDashboard';
import { SeasonOneDashboard } from './SeasonOneDashboard';

export function ContractHome({ seasonOne }: { seasonOne: BuilderNFTContractData }) {
export function ContractHome({ seasonOne, protocol }: { seasonOne: BuilderNFTContractData; protocol: ProtocolData }) {
const [selectedTab, setSelectedTab] = useState(0);

const handleChange = (event: React.SyntheticEvent, newValue: number) => {
Expand All @@ -23,7 +24,7 @@ export function ContractHome({ seasonOne }: { seasonOne: BuilderNFTContractData
</Tabs>
<Box mt={2}>
{selectedTab === 0 && <SeasonOneDashboard {...seasonOne} />}
{selectedTab === 1 && <ProtocolContractDashboard {...seasonOne} />}
{selectedTab === 1 && <ProtocolContractDashboard {...protocol} />}
</Box>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Box, Divider, Grid2, IconButton, Typography } from '@mui/material';
import Link from 'next/link';
import { MdLaunch } from 'react-icons/md';

import type { ProtocolData } from 'lib/contract/aggregateProtocolData';
import type { BuilderNFTContractData } from 'lib/contract/getContractData';

function ContractLink({
Expand Down Expand Up @@ -45,7 +46,7 @@ function GridDivider() {
);
}

export function ProtocolContractDashboard(data: BuilderNFTContractData) {
export function ProtocolContractDashboard(data: ProtocolData) {
const itemSizeTwoColumnMd = { xs: 12, md: 6 };
const itemSizeThreeColumnMd = { xs: 12, md: 4 };

Expand All @@ -56,15 +57,15 @@ export function ProtocolContractDashboard(data: BuilderNFTContractData) {
</Grid2>
<Grid2 size={itemSizeTwoColumnMd}>
<ContractLink
address={data.contractAddress}
address={data.proxy}
title='Proxy address'
linkType='token'
subtitle='Long term contract for interacting with the protocol'
/>
</Grid2>
<Grid2 size={itemSizeTwoColumnMd}>
<ContractLink
address={data.currentImplementation}
address={data.implementation}
title='Current Implementation'
subtitle='This contract is called by the proxy and contains the main protocol logic'
/>
Expand All @@ -73,70 +74,28 @@ export function ProtocolContractDashboard(data: BuilderNFTContractData) {
<Grid2 size={12}>
<SectionTitle title='Data' />
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
<Typography variant='h6'>Registered builder NFTs</Typography>
<Typography variant='body1' fontWeight='bold'>
{data.totalSupply.toString()}
</Typography>
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
{/* Currently, this is the balance of the proceeds receiver wallet. Once we start moving funds, we should look at logs instead */}
<Typography variant='h6'>Sales</Typography>
<Typography variant='body1' fontWeight='bold'>
{Number(data.receiverUsdcBalance).toLocaleString('en-US')} USD
</Typography>
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
{/* Currently, this is the balance of the proceeds receiver wallet. Once we start moving funds, we should look at logs instead */}
<Typography variant='h6'>Unique NFT holders</Typography>
<Typography variant='body1' fontWeight='bold'>
{Number(data.nftSalesData.uniqueHolders).toLocaleString('en-US')}
</Typography>
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
{/* Currently, this is the balance of the proceeds receiver wallet. Once we start moving funds, we should look at logs instead */}
<Typography variant='h6'>Total NFTs minted</Typography>
<Typography variant='body1' fontWeight='bold'>
{Number(data.nftSalesData.totalNftsSold).toLocaleString('en-US')}
</Typography>
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
{/* Currently, this is the balance of the proceeds receiver wallet. Once we start moving funds, we should look at logs instead */}
<Typography variant='h6'>NFTs paid with points</Typography>
<Typography variant='body1' fontWeight='bold'>
{Number(data.nftSalesData.nftsPaidWithPoints).toLocaleString('en-US')}
</Typography>
</Grid2>
<Grid2 size={itemSizeThreeColumnMd}>
{/* Currently, this is the balance of the proceeds receiver wallet. Once we start moving funds, we should look at logs instead */}
<Typography variant='h6'>NFTs paid with crypto</Typography>
<Typography variant='body1' fontWeight='bold'>
{Number(data.nftSalesData.nftsPaidWithCrypto).toLocaleString('en-US')}
</Typography>
</Grid2>
{data.merkleRoots.map((root) => (
<Grid2 size={itemSizeThreeColumnMd} key={root.week}>
<Typography variant='h6'>Merkle Root for week {root.week}</Typography>
<Typography variant='body1'>{root.root}</Typography>
</Grid2>
))}
<GridDivider />
<Grid2 size={12}>
<SectionTitle title='Roles & Permissions' />
</Grid2>
<Grid2 size={itemSizeTwoColumnMd}>
<ContractLink
address={data.currentAdmin}
address={data.admin}
title='Admin'
subtitle='Admin wallet can upgrade the contract, update the wallet that receives proceeds from NFT sales, modify pricing, register builders and mint tokens.'
/>
</Grid2>
<Grid2 size={itemSizeTwoColumnMd}>
<ContractLink
address={data.currentMinter}
title='Minter'
subtitle='Minter wallet can register new builder nfts and mint tokens to any address.'
/>
</Grid2>
<Grid2 size={itemSizeTwoColumnMd}>
<ContractLink
address={data.proceedsReceiver}
title='Proceeds Receiver'
subtitle='This is the wallet address that receives funds paid to mint builder NFTs.'
address={data.claimsManager}
title='Claims Manager'
subtitle='The wallet that can register weekly merkle roots'
/>
</Grid2>
</Grid2>
Expand Down
49 changes: 49 additions & 0 deletions apps/scoutgameadmin/lib/contract/aggregateProtocolData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { getAllISOWeeksFromSeasonStart } from '@packages/scoutgame/dates';
import {
protocolImplementationReadonlyApiClient,
protocolProxyReadonlyApiClient
} from '@packages/scoutgame/protocol/clients/protocolReadClients';
import { getScoutProtocolAddress } from '@packages/scoutgame/protocol/constants';
import type { Address } from 'viem';

type MerkleRoot = {
week: string;
root: string;
};

export type ProtocolData = {
admin: Address;
proxy: Address;
implementation: Address;
claimsManager: Address;
merkleRoots: MerkleRoot[];
};

export async function aggregateProtocolData(): Promise<ProtocolData> {
const [implementation, admin, claimsManager] = await Promise.all([
protocolProxyReadonlyApiClient.implementation(),
protocolProxyReadonlyApiClient.admin(),
protocolProxyReadonlyApiClient.claimsManager()
]);

const weeks = getAllISOWeeksFromSeasonStart();

const merkleRoots = await Promise.all(
weeks.map((week) =>
protocolImplementationReadonlyApiClient
.getMerkleRoot({ args: { week } })
.then((root) => ({ week, root }))
.catch(() => {
return { week, root: 'No root found' };
})
)
);

return {
merkleRoots,
admin: admin as Address,
proxy: getScoutProtocolAddress(),
implementation: implementation as Address,
claimsManager: claimsManager as Address
};
}
Loading

0 comments on commit dafdc50

Please sign in to comment.