Skip to content

Commit

Permalink
manage: on chain data
Browse files Browse the repository at this point in the history
  • Loading branch information
0x0ece committed Apr 6, 2024
1 parent aaaf958 commit d1da0e5
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 84 deletions.
36 changes: 19 additions & 17 deletions anchor/tests/devnet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ describe("glam_devnet", () => {
extension: "",
launchDate: "2024-04-01",
lifecycle: "active",
uri: "",
imageUri: "",
};

const [fundPDA, fundBump] = PublicKey.findProgramAddressSync(
Expand Down Expand Up @@ -195,6 +197,7 @@ describe("glam_devnet", () => {

beforeAll(async () => {}, 15_000);

/*
// Subscribe to the fund
it("Manager tests subscribe USDC to fund", async () => {
console.log("managerUsdcAta", managerUsdcAta);
Expand Down Expand Up @@ -239,6 +242,7 @@ describe("glam_devnet", () => {
);
// expect(managerShares.amount).toEqual(shares.supply);
});
*/

/*
it("Manager redeems 100% of fund", async () => {
Expand Down Expand Up @@ -496,8 +500,22 @@ describe("glam_devnet", () => {
TESTS TO CREATE - do NOT rerun
*/

/*
it("Close fund", async () => {
await program.methods
.close()
.accounts({
fund: 'CrtYP7DWrUGzLfNBWEvnYoBVuGni2pPpiAzYa2ZesJnm',
manager: manager.publicKey
})
.rpc();
// The account should no longer exist, returning null.
const closedAccount = await program.account.fund.fetchNullable(fundPDA);
expect(closedAccount).toBeNull();
});
*/

/*
// This is the test used to initialize the 1st devnet fund, do NOT rerun
it("Initialize fund", async () => {
try {
Expand Down Expand Up @@ -539,7 +557,6 @@ describe("glam_devnet", () => {
expect(fund.symbol).toEqual(fundSymbol);
expect(fund.isActive).toEqual(true);
});
*/

/*
it("Update fund", async () => {
Expand Down Expand Up @@ -691,19 +708,4 @@ describe("glam_devnet", () => {
}, 10_000);
*/

/*
it("Close fund", async () => {
await program.methods
.close()
.accounts({
fund: '2exrMpmVboCb57t94KHZWKEv7nrcoa5rQSawE19atsrt',
manager: manager.publicKey
})
.rpc();
// The account should no longer exist, returning null.
const closedAccount = await program.account.fund.fetchNullable(fundPDA);
expect(closedAccount).toBeNull();
});
*/
});
124 changes: 70 additions & 54 deletions web/src/app/manage/Manage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,69 @@ import { Add } from "@carbon/icons-react";
import { Link } from "react-router-dom";
import { formatNumber } from "../utils/format-number";
import { relative } from "path";

/*
GLAMsYF1Uo1LG855FVGHS853FyJ4aYkWf6B4E1sVzprc
GLaMc99QpnP1VKNwwFjNgUk4vhrGKu2JanCKzYRmKAgY
GLam9tx5LoYZHWEb2kKz3GqJW8TJJ4Vd2Q5vp1T2vo1c
GLAM7aqKnLbo65cRvyBk7WGuh9WTzWAxJZ7sUXdaf8rx
fAbioarvxMkYAsBAwg5Tmd5cipU8ZHxdmK47jqZWtpv
2X24TzxetDQcKob24wTEBq7gk7Q2KsfWQCvSyf1EfbhD
*/
import { useGlamProgram } from "../glam/glam-data-access";
import { useWallet } from "@solana/wallet-adapter-react";

export const Manage = () => {
const mockApiData = [
{
id: "AdXkDnJpFKqZeoUygLvm5dp2b5JGVPz3rEWfGCtB5Kc2",
symbol: "iBTC",
name: "iShares Bitcoin Trust",
aum: 15941890385,
nav: 39.72,
backgroundImage:
'url("https://api.glam.systems/image/EMAbk6kYhQbvtpqWyfvDPVJBvD5isMZvQT5aM4TyCAeG.png")'
},
{
id: "AdXkDnJpFKqZeoUygLvm5dp2b5JGVPz3rEWfGCtB5Kc2",
symbol: "iETH",
name: "iShares Ethereum Trust",
aum: 15941890385,
nav: 39.72,
backgroundImage:
'url("https://api.glam.systems/image/yurUzfjdrUH2ujsWwQkFsv8eQJiJwgbHQFUZtf5yqoV.png")'
},
{
id: "AdXkDnJpFKqZeoUygLvm5dp2b5JGVPz3rEWfGCtB5Kc2",
symbol: "iSOL",
name: "iShares Solana Trust",
aum: 15941890385,
nav: 39.72,
backgroundImage:
'url("https://api.glam.systems/image/fAbioarvxMkYAsBAwg5Tmd5cipU8ZHxdmK47jqZWtpv.png")'
},
{
id: "AdXkDnJpFKqZeoUygLvm5dp2b5JGVPz3rEWfGCtB5Kc2",
symbol: "iBONK",
name: "iShares Bonk Trust",
aum: 15941890385,
nav: 39.72,
backgroundImage:
'url("https://api.glam.systems/image/GLam9tx5LoYZHWEb2kKz3GqJW8TJJ4Vd2Q5vp1T2vo1c.png")'
}
];
// const mockApiData = [
// {
// id: "CWb949XA3vrdiEp2BFtjr9MbUonHke8CVdTb8Cr7Hctd",
// symbol: "RHW",
// name: "Renaissance Hackathon Winners",
// aum: 75_000,
// nav: 175.75,
// backgroundImage:
// 'url("https://api.glam.systems/image/4hDzLKRYr8zAnmXLLsmmazkp3Hg8AvHFSiqUTHFktNoF.png")'
// },
// {
// id: "6ZBb3LRddLtBq6DeNtSaUrMipieaFJgTETgTBoiAGBCC",
// symbol: "CAF",
// name: "Colosseum Accelerator Fund",
// aum: 600_000_000,
// nav: 600.00,
// backgroundImage:
// 'url("https://api.glam.systems/image/5NsVEVGdYqNSneWBhogA7yLDB9dYTAEyERnSj6wK68V3.png")'
// },
// {
// id: "6a2Jb6fQoH8TZF1qTawrriMoEiqQf2w6KMyj4pPFA3ju",
// symbol: "OMMG",
// name: "Orca Market Making Group",
// aum: 15_941_890,
// nav: 139.72,
// backgroundImage:
// 'url("https://api.glam.systems/image/3qs8hDSDKDAPuQfJrXnv9DDdGm4Ki3E1kTETAQRJR4dJ.png")'
// },
// {
// id: "Asytc9KxdgWVQJAp4KrYzu1B21R7AdQfhXx6bBHHnSm4",
// symbol: "PDA",
// name: "Pyth DAO Treasury",
// aum: 101_118_482,
// nav: 182.3,
// backgroundImage:
// 'url("https://api.glam.systems/image/3hTZD8KfhTKY18C64tYAbjvTYQXHtggEXGNrFFTmDbgA.png")'
// }
// ];

const { accounts } = useGlamProgram();
const { publicKey } = useWallet();
let data = (accounts.data || [])
.filter((d) => (d.account.manager.toString() == (publicKey || "").toString()))
.map((d) => {
const fund = d.account;
const id = d.publicKey.toString();
return {
id,
symbol: fund.symbol,
name: fund.name,
aum: 0,
nav: 0,
backgroundImage:
`url("https://api.glam.systems/image/${fund.shareClasses[0]}.png")`
};
});
// if (!data.length) {
// data = mockApiData;
// }

// when clicking on a tile, navigate to the relevant product page
return (
Expand All @@ -65,7 +77,7 @@ export const Manage = () => {
narrow
className="w-[80vw] h-full mt-[100px] max-h-[67vh] items-center overflow-y-auto hide-scrollbar"
>
{mockApiData.map((position) => (
{data.map((position) => (
<Column key={position.id} lg={4} md={4} sm={2} className="my-[6px]">
<Link to={`/products/${position.id}`}>
<ClickableTile
Expand All @@ -78,14 +90,18 @@ export const Manage = () => {
<p className="gray">{position.symbol}</p>
<strong>{position.name}</strong>
</div>
{ position.aum && (
<div className="flex flex-col">
<p className="gray">AUM</p>
<strong>{formatNumber(position.aum)}</strong>
</div>
<div className="flex flex-col">
<p className="gray">NAV</p>
<strong>{formatNumber(position.nav)}</strong>
</div>
) || ""}
{ position.nav && (
<div className="flex flex-col">
<p className="gray">NAV</p>
<strong>{formatNumber(position.nav)}</strong>
</div>
) || ""}
<div
className="w-[32px] h-[32px] md:w-[64px] md:h-[64px]"
style={{
Expand Down
3 changes: 1 addition & 2 deletions web/src/app/products/product-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,10 @@ export default function ProductPage() {
imgURL: `https://api.glam.systems/image/${imageURL}.png`,
manager: data?.manager,
treasury: data?.treasury,
// managerName: "ema1.sol",
shareClass0: data?.shareClasses[0],
investmentObjective:
"The Glam Investment Fund seeks to reflect generally the performance of the price of Bitcoin and Solana.",
nav: totalShares ? aum / totalShares : 10,
nav: totalShares ? aum / totalShares : 100,
// dailyNavChange: 2,
dailyNavChange: fundPerfChartData[fundPerfChartData.length - 2].value,
// daily: 0.29,
Expand Down
43 changes: 32 additions & 11 deletions web/src/app/products/products-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@ import { formatDateFromTimestamp } from "../utils/format-number";
import { useGlamProgram } from "../glam/glam-data-access";
import { useNavigate } from "react-router-dom";

const capitalize = (s: string) => (
s.charAt(0).toUpperCase() + s.slice(1)
);

/* Sort funds by inception data (last created first)
and by symbol if funds have the same inception date */
const sortFunds = (a: any, b: any) => {
if (a.inception == b.inception) {
return (a.symbol <= b.symbol) ? -1 : 1;
}
return (a.inception < b.inception) ? 1 : -1;
}

export default function ProductsOverview() {
const { accounts } = useGlamProgram();
const navigate = useNavigate();

let rows: any[] = [];
if (accounts.data) {
rows = accounts.data.map((account) => {
let rows = (accounts.data || []).map((account) => {
const fund = account.account;
const imageKey =
fund.shareClasses[0].toBase58() || "1111111111111111111111111111111111";
Expand All @@ -37,13 +48,14 @@ export default function ProductsOverview() {
fees_management: fund.shareClassesMetadata[0].feeManagement / 10_000.0,
fees_performance:
fund.shareClassesMetadata[0].feePerformance / 10_000.0,
inception: (
inception: new Date(Date.parse(
fund.shareClassesMetadata[0].launchDate
),
status: fund.shareClassesMetadata[0].lifecycle.toUpperCase()
)),
status: capitalize(fund.shareClassesMetadata[0].lifecycle),
shareClassAsset: fund.shareClassesMetadata[0].shareClassAsset,
policyDistribution: capitalize(fund.shareClassesMetadata[0].policyDistribution),
};
});
}
}).sort(sortFunds);

const headers = [
{
Expand All @@ -66,13 +78,21 @@ export default function ProductsOverview() {
key: "aum",
header: "AUM"
},*/
{
/*{
key: "share_classes_len",
header: "Share Classes"
},
{
key: "assets_len",
header: "Assets"
},*/
{
key: "shareClassAsset",
header: "Share Class Asset"
},
{
key: "policyDistribution",
header: "Policy Distribution"
},
{
key: "fees_management",
Expand Down Expand Up @@ -133,7 +153,7 @@ export default function ProductsOverview() {
if (cell.info.header === "inception") {
return (
<TableCell key={cell.id}>
{(cell.value)}
{cell.value.toISOString().split("T")[0]}
</TableCell>
);
} else if (cell.info.header === "aum") {
Expand Down Expand Up @@ -163,14 +183,15 @@ export default function ProductsOverview() {
))}
</TableBody>
</Table>
{/*
<Pagination
page={1}
pageSize={10}
pageSizes={[10, 20, 30, 40, 50]}
totalItems={rows.length}
onChange={() => console.log("change")}
itemsPerPageText={null}
/>
/>*/}
</TableContainer>
)}
</DataTable>
Expand Down

0 comments on commit d1da0e5

Please sign in to comment.