Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update PAPI and improve fellows-action #20

Merged
merged 2 commits into from
Apr 2, 2024
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
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
"@actions/core": "^1.10.1",
"@actions/github": "^5.1.1",
"@octokit/webhooks-types": "^7.3.1",
"@polkadot-api/cli": "^0.0.1-b0f30456ec8e18fce96b1a2a2a9f7418a4f5b837.1.0",
"@polkadot-api/client": "^0.0.1-b0f30456ec8e18fce96b1a2a2a9f7418a4f5b837.1.0",
"@polkadot-api/node-polkadot-provider": "^0.0.1-b0f30456ec8e18fce96b1a2a2a9f7418a4f5b837.1.0",
"@polkadot-api/sm-provider": "^0.0.1-b0f30456ec8e18fce96b1a2a2a9f7418a4f5b837.1.0",
"@polkadot-api/cli": "0.0.1-28172e65e6c4fb53198b9932ff624f8eef05fe68.1.0",
"@polkadot-api/client": "0.0.1-28172e65e6c4fb53198b9932ff624f8eef05fe68.1.0",
"@polkadot-api/node-polkadot-provider": "0.0.1-28172e65e6c4fb53198b9932ff624f8eef05fe68.1.0",
"@polkadot-api/sm-provider": "0.0.1-28172e65e6c4fb53198b9932ff624f8eef05fe68.1.0",
"@substrate/connect-known-chains": "^1.1.2",
"smoldot": "^2.0.22"
"smoldot": "2.0.22"
},
"devDependencies": {
"@eng-automation/js-style": "^2.3.0",
Expand Down
12 changes: 6 additions & 6 deletions polkadot-api.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"relay": {
"outputFolder": "src/codegen",
"chain": "polkadot",
"metadata": "relay.scale"
},
"collectives": {
"outputFolder": "src/codegen",
"wsUrl": "wss://polkadot-collectives-rpc.polkadot.io",
"metadata": "collectives.scale"
},
"relay": {
"outputFolder": "src/codegen",
"wsUrl": "wss://rpc.polkadot.io",
"metadata": "relay.scale"
}
}
}
160 changes: 57 additions & 103 deletions src/fellows.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createClient, PolkadotClient } from "@polkadot-api/client";
import { createClient, SS58String } from "@polkadot-api/client";
import { getChain } from "@polkadot-api/node-polkadot-provider";
import { getSmProvider } from "@polkadot-api/sm-provider";
import {
Expand All @@ -25,132 +25,86 @@ export const fetchAllFellows = async (
logger.info("Initializing smoldot");
const smoldot = start();

let polkadotClient: PolkadotClient | null = null;

try {
const relayChain = await smoldot.addChain({
chainSpec: polkadot,
});
logger.debug("Connecting to collective parachain");
await smoldot.addChain({
chainSpec: polkadot_collectives,
potentialRelayChains: [relayChain],
disableJsonRpc: true,
});

const SmProviderCollectives = getSmProvider(smoldot, {
potentialRelayChains: [relayChain],
chainSpec: polkadot_collectives,
});
logger.info("Initializing PAPI");
polkadotClient = createClient(
logger.info("Initializing the relay client");
const relayClient = createClient(
getChain({
provider: getSmProvider(smoldot, polkadot),
keyring: [],
}),
);
const relayApi = relayClient.getTypedApi(relayDescriptor);

const getGhHandle = async (
address: SS58String,
): Promise<string | undefined> => {
const identity =
await relayApi.query.Identity.IdentityOf.getValue(address);

if (identity)
return identity.info.additional
.find(([key]) => key.value?.asText() === "github")?.[1]
.value?.asText()
.replace("@", "");

const superIdentityAddress = (
await relayApi.query.Identity.SuperOf.getValue(address)
)?.[0];
return await (superIdentityAddress && getGhHandle(superIdentityAddress));
};

logger.info("Initializing the collectives client");
const collectivesClient = createClient(
getChain({
provider: SmProviderCollectives,
provider: getSmProvider(smoldot, {
potentialRelayChains: [relayChain],
chainSpec: polkadot_collectives,
}),
keyring: [],
}),
);
const collectivesApi = collectivesClient.getTypedApi(collectiveDescriptor);

// We fetch all the members from the collective
const collectivesApi = polkadotClient.getTypedApi(collectiveDescriptor);
// Pull the members of the FellowshipCollective
const memberEntries =
await collectivesApi.query.FellowshipCollective.Members.getEntries();

// We iterate over the fellow data and convert them into usable values
const fellows: FellowData[] = [];
for (const member of memberEntries) {
// We filter candidates (who are rank 0)
if (member.value > 0) {
const [address] = member.keyArgs;
fellows.push({ address, rank: member.value });
}
}
// Build the Array of FellowData and filter out candidates (zero rank members)
const fellows: FellowData[] = memberEntries
.map(({ keyArgs: [address], value: rank }) => {
return { address, rank };
})
.filter(({ rank }) => rank > 0);
logger.debug(JSON.stringify(fellows));

// Once we obtained this information, we disconnect this api.
polkadotClient.destroy();

logger.debug("Connecting to relay parachain.");

// We move into the relay chain
const SmProviderRelay = getSmProvider(smoldot, {
potentialRelayChains: [relayChain],
chainSpec: polkadot,
});
polkadotClient = createClient(
getChain({
provider: SmProviderRelay,
keyring: [],
// We no longer need the collectives client, so let's destroy it
collectivesClient.destroy();

// Let's now pull the GH handles of the fellows
const users: FellowObject[] = await Promise.all(
fellows.map(async ({ address, rank }) => {
return {
address,
rank,
githubHandle: await getGhHandle(address),
};
}),
);
const relayApi = polkadotClient.getTypedApi(relayDescriptor);

const users: FellowObject[] = [];

// We iterate over the different members and extract their data
for (const fellow of fellows) {
logger.debug(
`Fetching identity of '${fellow.address}', rank: ${fellow.rank}`,
);

const fellowData = await relayApi.query.Identity.IdentityOf.getValue(
fellow.address,
);

let data: FellowObject = { address: fellow.address, rank: fellow.rank };

// If the identity is null, we check if there is a super identity.
if (!fellowData) {
logger.debug("Identity is null. Checking for super identity");
const superIdentity = await relayApi.query.Identity.SuperOf.getValue(
fellow.address,
);
if (superIdentity) {
const [address] = superIdentity;
logger.debug(
`${fellow.address} has a super identity: ${address}. Adding it to the array`,
);

fellows.push({ address, rank: fellow.rank });
} else {
logger.debug("No super identity found. Skipping");
}

continue;
}

const additional = fellowData.info.additional;

// If it does not have additional data (GitHub handle goes here) we ignore it
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (!additional || additional.length < 1) {
logger.debug("Additional data is null. Skipping");
continue;
}

for (const additionalData of additional) {
const [key, value] = additionalData;
// We verify that they have an additional data of the key "github"
// If it has a handle defined, we push it into the array
const fieldName = key.value?.asText();
logger.debug(`Analyzing: ${fieldName ?? "unknown field"}`);
const fieldValue = value.value?.asText();
if (fieldName === "github" && fieldValue && fieldValue.length > 0) {
logger.debug(`Found handles: '${fieldValue}`);
// We add it to the array and remove the @ if they add it to the handle
data = { ...data, githubHandle: fieldValue.replace("@", "") };
}
users.push(data);
}
}
logger.info(`Found users: ${JSON.stringify(Array.from(users.entries()))}`);

// We are now done with the relay client
relayClient.destroy();

return users;
} catch (error) {
logger.error(error as Error);
throw error;
} finally {
if (polkadotClient) {
polkadotClient.destroy();
}
await smoldot.terminate();
}
};
23 changes: 11 additions & 12 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true
},
"exclude": [
"node_modules",
]
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"resolveJsonModule": true,
"esModuleInterop": true
},
"exclude": ["node_modules"]
}
Loading
Loading