Skip to content

Commit

Permalink
Query xcRegions (#28)
Browse files Browse the repository at this point in the history
* Query xcRegions

* working

* cleanup

* make linter happy
  • Loading branch information
Szegoo authored Jan 7, 2024
1 parent 1c6069b commit 492a6f0
Show file tree
Hide file tree
Showing 7 changed files with 2,115 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
WS_CORETIME_CHAIN="WSS endpoint of the coretime chain"
WS_RELAY_CHAIN="WSS endpoint of the coretime relay chain"
WS_CONTRACTS_CHAIN="WSS endpoint of the contracts chain"
WS_CONTRACTS_CHAIN="WSS endpoint of the contracts chain"
CONTRACT_XC_REGIONS="AddressOfXcRegionsContract"
1 change: 1 addition & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const nextConfig = {
WS_CORETIME_CHAIN: process.env.WS_CORETIME_CHAIN,
WS_RELAY_CHAIN: process.env.WS_RELAY_CHAIN,
WS_CONTRACTS_CHAIN: process.env.WS_CONTRACTS_CHAIN,
CONTRACT_XC_REGIONS: process.env.CONTRACT_XC_REGIONS,
},
};

Expand Down
1 change: 1 addition & 0 deletions src/contexts/apis/consts.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const WS_RELAY_CHAIN = process.env.WS_RELAY_CHAIN ?? '';
export const WS_CORETIME_CHAIN = process.env.WS_CORETIME_CHAIN ?? '';
export const WS_CONTRACTS_CHAIN = process.env.WS_CONTRACTS_CHAIN ?? '';
export const CONTRACT_XC_REGIONS = process.env.CONTRACT_XC_REGIONS ?? '';
132 changes: 123 additions & 9 deletions src/contexts/regions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useInkathon } from '@scio-labs/use-inkathon';
import { contractQuery, decodeOutput, useContract, useInkathon } from '@scio-labs/use-inkathon';
import React, { createContext, useContext, useEffect, useState } from 'react';

import {
countOne,
getBlockTimestamp,
parseHNString,
parseHNStringToString,
stringifyOnChainId as stringifyOnChainRegionId,
} from '@/utils/functions';

Expand All @@ -19,7 +20,9 @@ import {
} from '@/models';

import { useCoretimeApi, useRelayApi } from '../apis';
import { CONTRACT_XC_REGIONS } from '../apis/consts';
import { ApiState } from '../apis/types';
import XcRegionsMetadata from "../../contracts/xc_regions.json";

interface RegionsData {
regions: Array<RegionMetadata>;
Expand Down Expand Up @@ -57,7 +60,9 @@ const RegionDataProvider = ({ children }: Props) => {
const {
state: { api: relayApi, apiState: relayApiState },
} = useRelayApi();
const { activeAccount } = useInkathon();
const { api: contractsApi, isConnected: contractsReady, activeAccount } = useInkathon();

const { contract } = useContract(XcRegionsMetadata, CONTRACT_XC_REGIONS);

const [regions, setRegions] = useState<Array<RegionMetadata>>([]);
const [timeslicePeriod, setTimeslicePeriod] = useState<number>(0);
Expand All @@ -67,7 +72,9 @@ const RegionDataProvider = ({ children }: Props) => {
coretimeApi &&
coretimeApiState === ApiState.READY &&
relayApi &&
relayApiState === ApiState.READY;
relayApiState === ApiState.READY &&
contractsApi &&
contractsReady;

const fetchTasks = async () => {
if (!coretimeApi || coretimeApiState !== ApiState.READY) return {};
Expand Down Expand Up @@ -105,14 +112,19 @@ const RegionDataProvider = ({ children }: Props) => {

const tasks = await fetchTasks();

const rawXcRegionIds = await getOwnedRawXcRegionIds();
const xcRegions = await getOwnedXcRegions(rawXcRegionIds);

const brokerRegions = await getBrokerRegions();

const _regions: Array<RegionMetadata> = [];
const res = await coretimeApi.query.broker.regions.entries();
for await (const [key, value] of res) {
const [regionId] = key.toHuman() as [HumanRegionId];
const regionData = value.toHuman() as HumanRegionRecord;

for await (const region of [...brokerRegions, ...xcRegions]) {
const regionId = region[0];
const regionData = region[1];

const { begin, core, mask } = regionId;
const { end, owner, paid } = regionData;
const { end, owner, paid, origin } = regionData;

const beginBlockHeight = timeslicePeriod * parseHNString(begin);
const beginTimestamp = await getBlockTimestamp(relayApi, beginBlockHeight); // begin block timestamp
Expand Down Expand Up @@ -149,7 +161,7 @@ const RegionDataProvider = ({ children }: Props) => {
end: endTimestamp,
owner,
paid: nPaid,
origin: RegionOrigin.CORETIME_CHAIN,
origin: origin ? origin : RegionOrigin.CORETIME_CHAIN,
rawId,
consumed,
name: name ?? `Region #${_regions.length + 1}`,
Expand Down Expand Up @@ -189,6 +201,108 @@ const RegionDataProvider = ({ children }: Props) => {
);
};

const getBrokerRegions = async (): Promise<Array<[HumanRegionId, HumanRegionRecord]>> => {
if (!coretimeApi) {
return [];
}
const brokerEntries = await coretimeApi.query.broker.regions.entries();

const brokerRegions: Array<[HumanRegionId, HumanRegionRecord]> = brokerEntries
.map(([key, value]) => {
const keyTuple = key.toHuman();

// This is defensive.
if (keyTuple && Array.isArray(keyTuple) && keyTuple[0] !== undefined) {
return [keyTuple[0] as HumanRegionId, value.toHuman() as HumanRegionRecord];
}
return null;
})
.filter(entry => entry !== null) as Array<[HumanRegionId, HumanRegionRecord]>;

return brokerRegions;
}

const getOwnedRawXcRegionIds = async (): Promise<Array<string>> => {
if (!contractsApi || !contract || !activeAccount) {
return [];
}

const rawRegionIds = [];
let isError = false;
let index = 0;

while (!isError) {
const result = await contractQuery(
contractsApi,
"",
contract,
"PSP34Enumerable::owners_token_by_index",
{},
[activeAccount.address, index],
);

const { output, isError: queryError, decodedOutput } = decodeOutput(
result,
contract,
"PSP34Enumerable::owners_token_by_index",
);

if (queryError || decodedOutput === "TokenNotExists") {
isError = true;
} else {
rawRegionIds.push(parseHNStringToString(output.Ok.U128));
index++;
}
}

return rawRegionIds;
};

const getOwnedXcRegions = async (rawRegionIds: Array<string>): Promise<Array<[HumanRegionId, HumanRegionRecord]>> => {
if (!contractsApi || !contract || !activeAccount) {
return [];
}

const regions: Array<[HumanRegionId, HumanRegionRecord]> = [];

for await (const regionId of rawRegionIds) {
const result = await contractQuery(
contractsApi,
"",
contract,
"RegionMetadata::get_metadata",
{},
[regionId],
);

const { output, isError: queryError } = decodeOutput(
result,
contract,
"RegionMetadata::get_metadata",
);

if (!queryError) {
const versionedRegion = output.Ok;

// TODO: Once cross-chain region transfers are enabled from the broker pallet ensure
// metadata is correct.

regions.push([{
begin: versionedRegion.region.begin,
core: versionedRegion.region.core,
mask: versionedRegion.region.mask,
}, {
end: versionedRegion.region.end,
owner: activeAccount.address,
origin: RegionOrigin.CONTRACTS_CHAIN,
paid: undefined
}]);
}
}

return regions;
}

return (
<RegionDataContext.Provider
value={{
Expand Down
Loading

0 comments on commit 492a6f0

Please sign in to comment.