Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 65 additions & 54 deletions apps/server/npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dependencies": {
"@hono/node-server": "1.14.2",
"@hono/node-ws": "1.1.4",
"@keetanetwork/anchor": "0.0.20",
"@keetanetwork/anchor": "0.0.67",
"@keetanetwork/asn1-napi-rs": "1.2.0",
"@keetanetwork/web-ui-utils": "1.3.10",
"hono": "4.7.10",
Expand Down
9 changes: 7 additions & 2 deletions apps/server/src/api/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { Hono } from "hono";
import { NotFoundError } from "./errors";
import { KeetaNet } from "@keetanetwork/anchor";
import { getManyTokens } from "./token";
import type { ToJSONSerializable } from "@keetanetwork/anchor/lib/utils/json";

type UserClientState = Awaited<ReturnType<KeetaNet.UserClient['state']>>

const storage = new Hono<WorkerEnv>()
/**
Expand All @@ -22,7 +25,7 @@ const storage = new Hono<WorkerEnv>()
throw new NotFoundError('Invalid public key');
}

const state = await userClient.state()
const state: UserClientState = await userClient.state()

const balances = state.balances.map(function(balance) {
return({
Expand All @@ -36,10 +39,12 @@ const storage = new Hono<WorkerEnv>()
});
const tokens = await getManyTokens(client, tokensPublicKey, explorer.keetaNet.network.getBaseToken());

const info: ToJSONSerializable<UserClientState['info']> = KeetaNet.lib.Utils.Conversion.toJSONSerializable(state.info);

const account = {
publicKey: accountPublicKey,
headBlock: state.currentHeadBlock,
info: KeetaNet.lib.Utils.Conversion.toJSONSerializable(state.info),
info: info,
tokens: balances.map(function({ balance, publicKey }) {
return({
...tokens[publicKey],
Expand Down
26 changes: 20 additions & 6 deletions apps/server/src/api/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { validator } from "hono/validator";
import * as v from "valibot";
import { splitEvenly } from "@/utils/array";
import { Numeric } from "@keetanetwork/web-ui-utils/helpers/Numeric";
import type { GenericAccount } from "@keetanetwork/web-ui-utils/helpers/keetanet-operations";
import type { GenericAccount } from "@keetanetwork/keetanet-client/lib/account";

/**
* Types
Expand All @@ -25,7 +25,11 @@ export type TokenDetails = {
type: "BASE" | "TRUSTABLE" | "RISKY" | "UNKNOWN";
};

type AccountInfo = Awaited<ReturnType<typeof KeetaNetLib.UserClient.prototype.client.getAccountsInfo>>[number];
type KeetaNetLibType = typeof KeetaNetLib;
type AccountKeyAlgorithm = KeetaNetLibType['lib']['Account']['AccountKeyAlgorithm'][keyof KeetaNetLibType['lib']['Account']['AccountKeyAlgorithm']];

type AccountInfo<AccountType extends AccountKeyAlgorithm> = Awaited<ReturnType<typeof KeetaNetLib.UserClient.prototype.client.getAccountInfo<AccountType>>>
type TokenAccountInfo = AccountInfo<KeetaNetLibType['lib']['Account']['AccountKeyAlgorithm']['TOKEN']>

/**
* Schema to validate query parameters for /token endpoint
Expand Down Expand Up @@ -67,7 +71,7 @@ function parseTokenMetadata(metadata: string | undefined): { decimalPlaces: numb
return({ decimalPlaces: 0 });
}

export function parseTokenDetails(token: AccountInfo, baseToken: GenericAccount): TokenDetails {
export function parseTokenDetails(token: TokenAccountInfo, baseToken: GenericAccount): TokenDetails {
const metadata = parseTokenMetadata(token.info.metadata);

return({
Expand Down Expand Up @@ -122,7 +126,15 @@ export async function getManyTokens(client: InstanceType<typeof KeetaNetLib.Clie
const filteredInfos = Object.entries(infos).filter(([, data]) => data && data.account.isToken())

// Parse details for each token account
return Object.fromEntries(filteredInfos.map(([key, data]) => ([key, parseTokenDetails(data, baseToken)])))
return Object.fromEntries(filteredInfos.map(function([key, data]) {
// XXX: TypeScript isn't narrowing the type based on this, sadly
if (!data.account.isToken()) {
throw(new Error('Expected token account'));
}

// @ts-ignore
return([key, parseTokenDetails(data, baseToken)]);
}));
}


Expand Down Expand Up @@ -152,10 +164,12 @@ const token = new Hono<WorkerEnv>()
throw new NotFoundError('Invalid public key');
}

const info = await client.getAccountInfo(tokenPublicKey);
const tokenPublicKeyTyped = KeetaNetLib.lib.Account.fromPublicKeyString(tokenPublicKey).assertKeyType(KeetaNetLib.lib.Account.AccountKeyAlgorithm.TOKEN);

const info = await client.getAccountInfo(tokenPublicKeyTyped);
const token = parseTokenDetails(info, c.get('explorer').keetaNet.network.getBaseToken());

return jsonResponse(c, { token })
})

export default token
export default token
Loading
Loading