mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-15 11:20:36 +08:00
Use subgraph for Gnosis Safe information
Signed-off-by: Sebastian Martinez <sebastinez@me.com>
This commit is contained in:
+38
-14
@@ -31,17 +31,42 @@ const GetOrgs = `
|
||||
}
|
||||
`;
|
||||
|
||||
const GetOrgsByOwner = `
|
||||
query GetOrgsByOwner($owners: [String!]!) {
|
||||
const GetSafesByOwners = `
|
||||
query GetSafesByOwner($owners: [String!]!) {
|
||||
safes(where: { owners_contains: $owners }) {
|
||||
id
|
||||
owners
|
||||
threshold
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const GetOrgsByOwners = `
|
||||
query GetOrgsByOwners($owners: [String!]!) {
|
||||
orgs(where: { owner_in: $owners }) {
|
||||
id
|
||||
owner
|
||||
safe {
|
||||
id
|
||||
owners
|
||||
threshold
|
||||
}
|
||||
creator
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GetSafe = `
|
||||
query GetSafe($addr: ID!) {
|
||||
safe(id: $addr) {
|
||||
id
|
||||
owners
|
||||
threshold
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export class Org {
|
||||
address: string;
|
||||
owner: string;
|
||||
@@ -259,20 +284,19 @@ export class Org {
|
||||
return profile;
|
||||
}
|
||||
|
||||
// Return only Orgs that have a specific user as owner
|
||||
static async getOrgsByOwner(owner: string, config: Config): Promise<Org[]> {
|
||||
const orgsResult = await utils.querySubgraph(config.orgs.subgraph, GetOrgsByOwner, { owners: [owner] });
|
||||
return orgsResult.orgs.map((o: { id: string; owner: string }) => {
|
||||
return new Org(o.id, o.owner);
|
||||
});
|
||||
}
|
||||
static async getOrgsByMember(owner: string, config: Config): Promise<Org[]> {
|
||||
type Safe = { id: string; owners: string[]; threshold: number };
|
||||
|
||||
static async getOrgsByMember(memberAddr: string, config: Config): Promise<Org[]> {
|
||||
const wallets = await utils.getOwnerSafes(memberAddr, config);
|
||||
const owners = wallets?.concat([memberAddr]);
|
||||
const orgsResult = await utils.querySubgraph(config.orgs.subgraph, GetOrgsByOwner, { owners });
|
||||
// TODO: We use two subgraph queries since we can't do a filter query yet in the subgraph
|
||||
// https://github.com/graphprotocol/graph-node/issues/2539#issuecomment-855979841
|
||||
const safesByOwner = await utils.querySubgraph(config.orgs.subgraph, GetSafesByOwners, { owners: [owner] });
|
||||
const safes = safesByOwner.safes.reduce(
|
||||
(prev: any, curr: Safe) => prev.concat(curr.id), []);
|
||||
const orgsByOwner = await utils.querySubgraph(config.orgs.subgraph, GetOrgsByOwners, { owners: [...safes, owner] });
|
||||
|
||||
return orgsResult.orgs.map((o: { id: string; owner: string }) => {
|
||||
const orgs: any[] = [...orgsByOwner.orgs];
|
||||
|
||||
return orgs.map((o: { id: string; owner: string }) => {
|
||||
return new Org(o.id, o.owner);
|
||||
});
|
||||
}
|
||||
|
||||
+10
-37
@@ -11,6 +11,7 @@ import { getAvatar, getSeedHost, getSeedId, getAnchorsAccount, getRegistration }
|
||||
import type { BasicProfile } from '@datamodels/identity-profile-basic';
|
||||
import { ProfileType } from '@app/profile';
|
||||
import { parseUnits } from "@ethersproject/units";
|
||||
import { GetSafe } from "@app/base/orgs/Org";
|
||||
|
||||
export enum AddressType {
|
||||
Contract,
|
||||
@@ -354,56 +355,28 @@ export async function resolveEnsProfile(addressOrName: string, profileType: Prof
|
||||
|
||||
// Check whether a Gnosis Safe exists at an address.
|
||||
export async function isSafe(address: string, config: Config): Promise<boolean> {
|
||||
if (! config.safe.api) return false;
|
||||
// For the subgraph we need to pass a lowercase address
|
||||
const query = await querySubgraph(config.orgs.subgraph, GetSafe, { addr: address.toLowerCase() });
|
||||
|
||||
const addr = ethers.utils.getAddress(address);
|
||||
const response = await fetch(`${config.safe.api}/api/v1/safes/${addr}/`, { method: 'HEAD' });
|
||||
|
||||
return response.ok;
|
||||
return query.safe !== null ? true : false;
|
||||
}
|
||||
|
||||
// Get a Gnosis Safe at an address.
|
||||
export async function getSafe(address: string, config: Config): Promise<Safe | null> {
|
||||
if (! config.safe.api) return null;
|
||||
// For the subgraph we need to pass a lowercase address
|
||||
const query = await querySubgraph(config.orgs.subgraph, GetSafe, { addr: address.toLowerCase() });
|
||||
|
||||
const addr = ethers.utils.getAddress(address);
|
||||
const response = await fetch(`${config.safe.api}/api/v1/safes/${addr}/`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
if (! response.ok) {
|
||||
if (! query.safe) {
|
||||
return null;
|
||||
}
|
||||
const json = await response.json();
|
||||
|
||||
return {
|
||||
address: json.address,
|
||||
owners: json.owners,
|
||||
threshold: json.threshold
|
||||
address: query.safe.id,
|
||||
owners: query.safe.owners,
|
||||
threshold: query.safe.threshold
|
||||
};
|
||||
}
|
||||
|
||||
// Get the Gnosis Safe addresses owned by the given address.
|
||||
export async function getOwnerSafes(owner: string, config: Config): Promise<string[] | null> {
|
||||
if (! config.safe.api) return null;
|
||||
|
||||
const addr = ethers.utils.getAddress(owner);
|
||||
const response = await fetch(`${config.safe.api}/api/v1/owners/${addr}/safes/`, {
|
||||
method: 'GET',
|
||||
headers: { 'Accept': 'application/json' }
|
||||
});
|
||||
|
||||
if (! response.ok) {
|
||||
return null;
|
||||
}
|
||||
const json = await response.json();
|
||||
|
||||
return json.safes;
|
||||
}
|
||||
|
||||
// Get token balances for an address.
|
||||
export async function getTokens(address: string, config: Config): Promise<Array<Token>> {
|
||||
const userBalances = await config.provider.send("alchemy_getTokenBalances", [address, "DEFAULT_TOKENS"]);
|
||||
|
||||
Reference in New Issue
Block a user