Skip to content

Commit

Permalink
Merge pull request #49 from orcaprotocol/willkim/fetch-supers
Browse files Browse the repository at this point in the history
feat: add get super pod/proposal
  • Loading branch information
Will Kim authored May 16, 2022
2 parents d1260a8 + 0858ae4 commit af7d512
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 161 deletions.
53 changes: 37 additions & 16 deletions src/Pod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ethers } from 'ethers';
import axios from 'axios';
import ENS from '@ensdomains/ensjs';
import { getControllerByAddress, getDeployment } from '@orcaprotocol/contracts';
import { config } from './config';
Expand All @@ -23,6 +22,7 @@ import {
} from './lib/services/create-safe-transaction';
import Proposal from './Proposal';
import type { ProposalStatus } from './Proposal';
import { fetchPodUsers, fetchUserPodIds } from './lib/services/subgraph';

/**
* The `Pod` object is the interface for fetching pod data.
Expand Down Expand Up @@ -169,6 +169,13 @@ export default class Pod {
*/
memberPods?: Pod[];

/**
* @ignore
* @property Array of Pod objects for any super pods
* Do not call this property directly, use `Pod.getSuperPods()`
*/
superPods?: Pod[];

/**
* Returns an array of Proposal objects in reverse chronological order. Defaults to returning 5,
* which can be overridden by passing { limit: 10 } for example in the options.
Expand Down Expand Up @@ -281,28 +288,42 @@ export default class Pod {
.slice(0, limit); // Slice to return the requested limited Proposals.
};

/**
* Returns an array of this pod's super pods, i.e., pods that this pod is a member of
*/
getSuperPods = async (): Promise<Pod[]> => {
if (this.superPods) return this.superPods;
const userPodIds = await fetchUserPodIds(this.safe);
this.superPods = await Promise.all(userPodIds.map(async podId => new Pod(podId)));
return this.superPods;
};

/**
* Returns an array of all active super proposals, i.e., active proposals of any super pods
*/
getSuperProposals = async (): Promise<Proposal[]> => {
const superPods = await this.getSuperPods();
if (superPods.length === 0) return [];
const superProposals = (
await Promise.all(
superPods.map(async pod => {
const [activeProposal] = await pod.getProposals({ status: 'active' });
return activeProposal;
}),
)
).filter(x => x); // Filter all null values, i.e., super pods that have no active proposals
return superProposals;
};

/**
* Returns of list of all member addresses.
* Members include member pods and member EOAs
*/
getMembers = async (): Promise<string[]> => {
const { subgraphUrl } = config;
if (this.members) return this.members;
const { data } = await axios.post(subgraphUrl, {
query: `query GetPodUsers($id: ID!) {
pod(id: $id) {
users {
user {
id
}
}
}
}`,
variables: { id: this.id },
});
const { users } = data.data.pod || { users: [] };
const users = await fetchPodUsers(this.id);
// Checksum all addresses.
this.members = users.length > 0 ? users.map(user => ethers.utils.getAddress(user.user.id)) : [];
this.members = users.length > 0 ? users.map(user => ethers.utils.getAddress(user)) : [];
return this.members;
};

Expand Down
33 changes: 5 additions & 28 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Pod from './Pod';
import { Pod as PodType, Proposal as ProposalType, ProposalStatus } from './types';
import { init, config } from './config';
import { checkAddress } from './lib/utils';
import { fetchUserPodIds, fetchAdminPodIds } from './lib/services/subgraph';

/**
* Gets a pod object.
Expand All @@ -25,23 +26,8 @@ async function getUserPods(address: string): Promise<Pod[]> {
} catch {
throw new TypeError(`Invalid address provided to getUserPods: ${address}`);
}
const { data } = await axios.post(config.subgraphUrl, {
query: `query GetUserPods($id: ID!) {
user(id: $id) {
pods {
id
pod {
id
}
}
}
}`,
variables: { id: address.toLowerCase() },
});
const { pods } = data?.data?.user || { pods: [] };
// Remove GraphQL nested layer for UserPod
const unsortedPods = pods.map(({ pod }) => parseInt(pod.id, 10));
return Promise.all(unsortedPods.map(async pod => new Pod(pod)));
const userPodIds = await fetchUserPodIds(address);
return Promise.all(userPodIds.map(async pod => new Pod(pod)));
}

/**
Expand All @@ -50,17 +36,8 @@ async function getUserPods(address: string): Promise<Pod[]> {
*/
async function getAdminPods(address: string): Promise<Pod[]> {
checkAddress(address);

const { data } = await axios.post(config.subgraphUrl, {
query: `query GetUserPods($id: ID!) {
user(id: $id) {
adminPods
}
}`,
variables: { id: address.toLowerCase() },
});
const { adminPods } = data.data.user || { adminPods: [] };
return Promise.all(adminPods.map(async pod => new Pod(parseInt(pod, 10))));
const adminPodIds = await fetchAdminPodIds(address);
return Promise.all(adminPodIds.map(async pod => new Pod(pod)));
}

export {
Expand Down
65 changes: 65 additions & 0 deletions src/lib/services/subgraph.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import axios from 'axios';
import { config } from '../../config';

/**
* Returns an array of addresses of all pod members.
* @param id
*/
export async function fetchPodUsers(id: number): Promise<string[]> {
const { data } = await axios.post(config.subgraphUrl, {
query: `query GetPodUsers($id: ID!) {
pod(id: $id) {
users {
user {
id
}
}
}
}`,
variables: { id },
});
const { users } = data.data.pod || { users: [] };
return users.map(user => user.user.id);
}

/**
* Returns a list of Pod IDs from subgraph that user is a member of.
* @param address
*/
export async function fetchUserPodIds(address: string): Promise<number[]> {
const { data } = await axios.post(config.subgraphUrl, {
query: `query GetUserPods($id: ID!) {
user(id: $id) {
pods {
id
pod {
id
}
}
}
}`,
variables: { id: address.toLowerCase() },
});
const { pods } = data?.data?.user || { pods: [] };
// Remove GraphQL nested layer for UserPod
const podIds = pods.map(({ pod }) => parseInt(pod.id, 10));
return podIds;
}

/**
* Returns an array of Pod IDs from sub graph that an address is the admin of
* @param address
*/
export async function fetchAdminPodIds(address: string): Promise<number[]> {
const { data } = await axios.post(config.subgraphUrl, {
query: `query GetUserPods($id: ID!) {
user(id: $id) {
adminPods
}
}`,
variables: { id: address.toLowerCase() },
});
const { adminPods } = data.data.user || { adminPods: [] };
const podIds = adminPods.map(pod => parseInt(pod, 10));
return podIds;
}
Loading

0 comments on commit af7d512

Please sign in to comment.