Skip to content

Commit

Permalink
🔥 Refactor: Cleaning up
Browse files Browse the repository at this point in the history
  • Loading branch information
PsicoThePato committed Oct 7, 2024
1 parent d92410a commit 4adf940
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 153 deletions.
15 changes: 1 addition & 14 deletions apps/commune-worker/src/workers/module-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,7 @@ export async function moduleFetcherWorker(props: WorkerProps) {
// TODO: do this in a better way
const modules = await queryRegisteredModulesInfo(
props.lastBlock.apiAtBlock,
[
"name",
// "keys"
"address",
"registrationBlock",
"metadata",
"lastUpdate",
"emission",
"incentive",
"dividends",
// "delegationFee",
// "stakeFrom",
],
[NETUID_ZERO],
NETUID_ZERO,
);
const modulesData = modules.map((module) =>
SubspaceModuleToDatabase(module, props.lastBlock.blockNumber),
Expand Down
73 changes: 27 additions & 46 deletions packages/subspace/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { encodeAddress } from "@polkadot/util-crypto";
import type {
Api,
LastBlock,
OptionalProperties,
SS58Address,
StakeOutData,
SubspaceModule,
Expand All @@ -25,7 +24,6 @@ import {
ChainEntry,
handleDaos,
handleProposals,
StorageEntry,
getPropsToMap,
standardizeUidToSS58address,
SubspacePalletName,
Expand Down Expand Up @@ -479,15 +477,6 @@ export async function queryUserTotalStaked(
* @param netuidWhitelist if empty, modules from all subnets are returned
*/

export async function queryRegisteredSubnetsInfo(api: Api) {
console.log("Fetching subnet keys from the chain...");
const netuids = (await api.query.subspaceModule!.subnetNames!.entries()).map(
(entry) => new StorageEntry(entry).netuid,
);

console.log(netuids);
}


export async function querySubnetParams(api: Api): Promise<Array<NetworkSubnetConfig>> {
const subnetProps: Array<SubspaceStorageName> = [
Expand All @@ -505,7 +494,7 @@ export async function querySubnetParams(api: Api): Promise<Array<NetworkSubnetCo
subnetEmissionModule: ["subnetEmission"],
governanceModule: ["subnetGovernanceConfig"]
} as Record<SubspacePalletName, SubspaceStorageName[]>;
const subnetInfo = await queryChain(api, props, [0]);
const subnetInfo = await queryChain(api, props);
const subnetNames = subnetInfo["subnetNames"];


Expand Down Expand Up @@ -539,23 +528,27 @@ export async function querySubnetParams(api: Api): Promise<Array<NetworkSubnetCo
}


export async function queryRegisteredModulesInfo<
P extends OptionalProperties<SubspaceModule> & SubspaceStorageName,
>(
export async function queryRegisteredModulesInfo(
api: Api,
extraProps: P[] = [],
netuidWhitelist?: number[],
netuid: number,
): Promise<SubspaceModule[]> {
netuidWhitelist = netuidWhitelist?.length
? Array.from(new Set(netuidWhitelist))
: undefined;
console.log("Fetching module keys from the chain...");
const keyQuery: Record<SubspacePalletName, SubspaceStorageName[]> = { subspaceModule: ["keys"] }
const uidToSS58Query = await queryChain(api, keyQuery, netuidWhitelist);
const keyQuery: { subspaceModule: SubspaceStorageName[] } = { subspaceModule: ["keys"] }
const uidToSS58Query = await queryChain(api, keyQuery, netuid);
const uidToSS58 = uidToSS58Query['keys'] as Record<string, SS58Address>;
const extraPropsQuery: Record<SubspacePalletName, P[]> = { subspaceModule: extraProps }
const modulesInfo = await queryChain(api, extraPropsQuery, netuidWhitelist);
//eslint-disable-next-line
const moduleProps: Array<SubspaceStorageName> = [
"name",
"address",
"registrationBlock",
"metadata",
"lastUpdate",
"emission",
"incentive",
"dividends",

]
const extraPropsQuery: { subspaceModule: SubspaceStorageName[] } = { subspaceModule: moduleProps }
const modulesInfo = await queryChain(api, extraPropsQuery, netuid);
const processedModules = standardizeUidToSS58address(modulesInfo, uidToSS58);
const moduleMap: SubspaceModule[] = [];

Expand All @@ -565,31 +558,19 @@ export async function queryRegisteredModulesInfo<
console.error(`Module key not found for uid ${uid}`);
continue;
}
// TODO: remove ts-igore
// @ts-ignore
const emission = processedModules["emission"][moduleKey];
// @ts-ignore
const incentive = processedModules["incentive"][moduleKey];
// @ts-ignore
const dividends = processedModules["dividends"][moduleKey];
const module = SUBSPACE_MODULE_SCHEMA.parse({
uid: parseInt(uid),
uid: uid,
key: moduleKey,
netuid: 0,
// @ts-ignore
netuid: netuid,
name: processedModules["name"][moduleKey],
// @ts-ignore
address: processedModules["address"][moduleKey],
// @ts-ignore
registrationBlock: processedModules["registrationBlock"][moduleKey],
// @ts-ignore
metadata: processedModules["metadata"][moduleKey],
// @ts-ignore
lastUpdate: processedModules["lastUpdate"][moduleKey],
atBlock: 0,
emission: emission ? BigInt(emission) : -1n,
incentive: incentive ? BigInt(incentive) : -1n,
dividends: dividends ? BigInt(dividends) : -1n,
emission: processedModules["emission"][moduleKey],
incentive: processedModules["incentive"][moduleKey],
dividends: processedModules["dividends"][moduleKey],
delegationFee: 0,
stakeFrom: 0n,

Expand All @@ -608,18 +589,18 @@ async function queryChain<
T extends SubspaceStorageName,
>(
api: Api,
props: Record<SubspacePalletName, T[]>,
netuidWhitelist?: number[],
props: Partial<Record<SubspacePalletName, T[]>>,
netuidWhitelist?: number,
): Promise<Record<T, Record<string, string | Record<string, any>>>> {
if (Object.keys(props).length === 0) {
return {} as Record<T, Record<string, string>>;
}
// TODO: accept multiple netuids
const modulePropMap: Record<T, Record<string, string>> = {} as Record<T, Record<string, string>>;
const moduletas = await getPropsToMap(props, api, 0);
const moduletas = await getPropsToMap(props, api, netuidWhitelist);
const entries = Object.entries(moduletas) as [T, ChainEntry][];
entries.map(([prop, entry]) => {
modulePropMap[prop] = entry.getMapModules(0);
modulePropMap[prop] = entry.getMapModules(netuidWhitelist);
});
return modulePropMap;
}
45 changes: 9 additions & 36 deletions packages/types/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,53 +135,26 @@ assert<Extends<z.infer<typeof PROPOSAL_SCHEMA>, Proposal>>();

export const SUBSPACE_MODULE_NAME_SCHEMA = z.string();
export const SUBSPACE_MODULE_ADDRESS_SCHEMA = z.string();
export const NUMBER_SCHEMA = z.number();
export const SUBSPACE_MODULE_REGISTRATION_BLOCK_SCHEMA = z.number();
export const NUMBER_SCHEMA = z.coerce.number();
export const SUBSPACE_MODULE_REGISTRATION_BLOCK_SCHEMA = z.coerce.number();
export const SUBSPACE_MODULE_METADATA_SCHEMA = z.string(); // TODO: validate it's a valid ipfs hash or something (?)
export const SUBSPACE_MODULE_LAST_UPDATE_SCHEMA = z.any();

export const SUBSPACE_MODULE_SCHEMA = z.object({
netuid: z.number(),
netuid: z.coerce.number(),
key: ADDRESS_SCHEMA,
uid: z.number(),
uid: z.coerce.number().int(),
name: SUBSPACE_MODULE_NAME_SCHEMA.optional(),
address: SUBSPACE_MODULE_ADDRESS_SCHEMA.optional(),
registrationBlock: SUBSPACE_MODULE_REGISTRATION_BLOCK_SCHEMA.optional(),
metadata: SUBSPACE_MODULE_METADATA_SCHEMA.optional(),
lastUpdate: SUBSPACE_MODULE_LAST_UPDATE_SCHEMA.optional(),
atBlock: z.number().optional(),
atBlock: z.coerce.number().optional(),

emission: z.bigint().optional(),
incentive: z.bigint().optional(),
dividends: z.bigint().optional(),
delegationFee: z.number().optional(),
emission: z.coerce.bigint().optional(),
incentive: z.coerce.bigint().optional(),
dividends: z.coerce.bigint().optional(),
delegationFee: z.coerce.number().optional(),

stakeFrom: z.bigint().optional(),
});

export const modulePropResolvers: {
[P in OptionalProperties<SubspaceModule>]: (
value: Codec,
) => z.SafeParseReturnType<unknown, SubspaceModule[P]>;
} = {
name: (value: Codec) =>
SUBSPACE_MODULE_NAME_SCHEMA.safeParse(value.toPrimitive()),
address: (value: Codec) =>
SUBSPACE_MODULE_ADDRESS_SCHEMA.safeParse(value.toPrimitive()),
registrationBlock: (value: Codec) =>
SUBSPACE_MODULE_REGISTRATION_BLOCK_SCHEMA.safeParse(value.toPrimitive()),
lastUpdate: (value: Codec) =>
SUBSPACE_MODULE_LAST_UPDATE_SCHEMA.safeParse(value.toPrimitive()), // not really working right now (Cannot read properties of undefined (reading 'toPrimitive'))
metadata: (value: Codec) =>
SUBSPACE_MODULE_METADATA_SCHEMA.safeParse(value.toPrimitive()),
atBlock: (value: Codec) => NUMBER_SCHEMA.safeParse(value.toPrimitive()),
emission: (value: Codec) =>
TOKEN_AMOUNT_SCHEMA.safeParse(value.toPrimitive()),
incentive: (value: Codec) =>
TOKEN_AMOUNT_SCHEMA.safeParse(value.toPrimitive()),
dividends: (value: Codec) =>
TOKEN_AMOUNT_SCHEMA.safeParse(value.toPrimitive()),
delegationFee: (value: Codec) => NUMBER_SCHEMA.safeParse(value.toPrimitive()),
stakeFrom: (value: Codec) =>
TOKEN_AMOUNT_SCHEMA.safeParse(value.toPrimitive()),
};
66 changes: 9 additions & 57 deletions packages/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ import type {
import {
CUSTOM_METADATA_SCHEMA,
DAO_APPLICATIONS_SCHEMA,
isSS58,
modulePropResolvers,
PROPOSAL_SCHEMA,
SUBSPACE_MODULE_SCHEMA,
URL_SCHEMA
} from "@commune-ts/types";

Expand Down Expand Up @@ -267,7 +264,7 @@ export function getExpirationTime(

export interface ChainEntry {

getMapModules(netuid: number): Record<string, string>;
getMapModules(netuid?: number): Record<string, string>;
}


Expand All @@ -288,12 +285,12 @@ export type SubspaceStorageName =
// TODO: add MinimumAllowedStake, stakeFrom

export function standardizeUidToSS58address<T extends SubspaceStorageName>(
outerRecord: Record<T, Record<string, string | number>>,
outerRecord: Record<T, Record<string, any>>,
uidToKey: Record<string, SS58Address>,
): Record<T, Record<string, string | number>> {
const processedRecord: Record<T, Record<string, string | number>> = {} as Record<T, Record<string, string | number>>;

const entries = Object.entries(outerRecord) as [T, Record<string, string | number>][];
const entries = Object.entries(outerRecord) as [T, Record<string, any>][];
for (const [outerKey, innerRecord] of entries) {
const processedInnerRecord: Record<string, string | number> = {};

Expand Down Expand Up @@ -346,9 +343,9 @@ export function getSubspaceStorageMappingKind(
}

export async function getPropsToMap(
props: Record<SubspacePalletName, SubspaceStorageName[]>,
props: Partial<Record<SubspacePalletName, SubspaceStorageName[]>>,
api: Api,
netuid: number,
netuid?: number,
): Promise<Record<SubspaceStorageName, ChainEntry>> {
const mapped_prop_entries: Record<SubspaceStorageName, ChainEntry> = {} as Record<SubspaceStorageName, ChainEntry>

Expand Down Expand Up @@ -396,6 +393,9 @@ export class StorageVecMap implements ChainEntry {
constructor(private readonly entry: [StorageKey<AnyTuple>, Codec][]) { }

getMapModules(netuid: number) {
if (netuid === undefined) {
throw new Error("netuid is required for StorageVecMap");
}
const subnet_values = this.entry[netuid];
if (subnet_values != undefined) {
const values = subnet_values[1].toPrimitive() as string[];
Expand All @@ -411,7 +411,7 @@ export class StorageVecMap implements ChainEntry {
export class SimpleMap implements ChainEntry {
constructor(private readonly entry: [StorageKey<AnyTuple>, Codec][]) { }

getMapModules(netuid: number) {
getMapModules() {
const modules_map = Object.fromEntries(
this.entry.map((value, index) => [index, value[1].toPrimitive()]),
);
Expand All @@ -434,54 +434,6 @@ export class DoubleMapEntries implements ChainEntry {
}


export class StorageEntry {
constructor(private readonly entry: [StorageKey<AnyTuple>, unknown]) { }
get netuid(): number {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.entry[0].args[0]!.toPrimitive() as number;
}

get uidOrKey(): string | number {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.entry[0].args[1]!.toPrimitive() as string | number;
}

get value(): Codec {
return this.entry[1] as Codec;
}
/**
* as the module identifier can be a uid or a key, this function resolves it to a key
*/
resolveKey(uidKeyMap: Map<number, Map<number, SS58Address>>): SS58Address {
const isUid = typeof this.uidOrKey === "number";

const key = isUid
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
uidKeyMap.get(this.netuid)!.get(this.uidOrKey)!
: this.uidOrKey;

assertOrThrow(isSS58(key), `key ${this.netuid}::${key} is an SS58Address`);

return key;
}

parse<P extends OptionalProperties<SubspaceModule>>(prop: P) {
const parsedValue = modulePropResolvers[prop](this.value);
return parsedValue;
}
}

// the value of a "keys" entry is a codec that holds a ss58 address
export function newSubstrateModule(keyEntry: StorageEntry): SubspaceModule {
const key = keyEntry.value.toPrimitive() as SS58Address;

return SUBSPACE_MODULE_SCHEMA.parse({
uid: keyEntry.uidOrKey as number,
netuid: keyEntry.netuid,
key,
});
}

export function parseAddress(valueRaw: Codec): DaoApplications | null {
const value = valueRaw.toPrimitive();
const validated = DAO_APPLICATIONS_SCHEMA.safeParse(value);
Expand Down

0 comments on commit 4adf940

Please sign in to comment.