Skip to content

Instantly share code, notes, and snippets.

@agustif
Last active August 22, 2024 22:28
Show Gist options
  • Save agustif/3de891bd71470eedfb7a56901d104b30 to your computer and use it in GitHub Desktop.
Save agustif/3de891bd71470eedfb7a56901d104b30 to your computer and use it in GitHub Desktop.
find-user-airstack.ts
export enum SocialDappName {
Farcaster = "farcaster",
Lens = "lens",
}
type User = {
connectedAddresses: any[];
userAddress: string;
userId?: string;
profileName?: string;
};
type FindUserParams = {
ensNames: string[]; // Modified to accept an array of ENS names
dappName: SocialDappName;
};
type FindUserResult = {
users: User[]; // Modified to return an array of users
errors: string[]; // Modified to return an array of errors
};
export const findUsersByEnsNames = async ({
ensNames,
dappName = SocialDappName.Farcaster,
}: FindUserParams): Promise<FindUserResult> => {
if (!ensNames || ensNames.length === 0) {
return { users: [], errors: ["ENS names are required"] };
}
const results: User[] = [];
const errors: string[] = [];
for (const ensName of ensNames) {
const query = `
query FindUserByEnsName($ensName: Identity!) {
Socials(
input: {
filter: {identity: {_eq: $ensName}, dappName: {_eq: ${dappName}}},
blockchain: ethereum
}
) {
Social {
dappName
profileName
userId
userAddress
connectedAddresses {
address
chainId
blockchain
timestamp
}
}
}
}
`;
const variables = { ensName };
try {
const response = await fetch("https://api.airstack.xyz/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.AIRSTACK_API_KEY ?? ""}`,
},
body: JSON.stringify({
query,
variables,
}),
});
const result = await response.json();
if (result.errors) {
console.error("GraphQL errors:", result.errors);
errors.push(`GraphQL error for ${ensName}: ${result.errors[0].message}`);
continue;
}
const user = result.data?.Socials?.Social[0] ?? null;
if (user) {
results.push(user);
} else {
errors.push(`User not found for ENS name: ${ensName}`);
}
} catch (error:any) {
console.error("Error fetching user data:", error);
errors.push(`Error fetching user data for ${ensName}: ${error.message}`);
}
}
return { users: results, errors };
};
export const findUserFidByEnsName = async (
ensName: string,
dappName: SocialDappName = SocialDappName.Farcaster
): Promise<number | null> => {
if (!ensName) {
throw new Error("ENS name is required");
}
// Ensure the ENS name is in lower case and trimmed
const sanitizedEnsName = ensName.toLowerCase();
const query = `
query FindUserByEnsName($ensName: Identity!) {
Socials(
input: {
filter: {identity: {_eq: $ensName}, dappName: {_eq: ${dappName}}},
blockchain: ethereum
}
) {
Social {
userId
}
}
}
`;
const variables = { ensName: sanitizedEnsName };
try {
const response = await fetch("https://api.airstack.xyz/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.AIRSTACK_API_KEY ?? ""}`,
},
body: JSON.stringify({
query,
variables,
}),
});
const result = await response.json();
if (result.errors) {
console.error("GraphQL errors:", result.errors);
return null;
}
const userFid = result.data?.Socials?.Social[0]?.userId ?? null;
return userFid ? Number(userFid) : null;
} catch (error: any) {
console.error("Error fetching user data:", error);
return null;
}
};
export const findUserFidByIdentity = async (
identity: string,
dappName: SocialDappName = SocialDappName.Farcaster
): Promise<number | null> => {
if (!identity) {
throw new Error("Identity is required");
}
// Ensure no trimming or unnecessary modifications to the input
const query = `
query FindUserByIdentity($identity: Identity!) {
Socials(
input: {
filter: {identity: {_eq: $identity}, dappName: {_eq: ${dappName}}},
blockchain: ethereum
}
) {
Social {
userId
}
}
}
`;
const variables = { identity };
try {
const response = await fetch("https://api.airstack.xyz/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.AIRSTACK_API_KEY ?? ""}`,
},
body: JSON.stringify({
query,
variables,
}),
});
const result = await response.json();
if (result.errors) {
console.error("GraphQL errors:", result.errors);
return null;
}
const userFid = result.data?.Socials?.Social[0]?.userId ?? null;
return userFid ? Number(userFid) : null;
} catch (error: any) {
console.error("Error fetching user data:", error);
return null;
}
};
export const findUserFid = async (
input: string
): Promise<number | null> => {
let fid = await findUserFidByIdentity(input);
if (fid === null) {
// Try with Farcaster FID format
if (/^\d+$/.test(input)) {
fid = await findUserFidByIdentity(`fc_fid:${input}`);
}
// If FID is not found, try with Farcaster username format
if (fid === null) {
fid = await findUserFidByIdentity(`fc_fname:${input}`);
}
}
return fid;
};
export const findUserWalletsByFid = async (
fid: number,
dappName: SocialDappName = SocialDappName.Farcaster
): Promise<string[] | null> => {
// if (!fid) {
// throw new Error("FID is required");
// }
const query = `
query FindUserWalletsByFid($ensName: Identity!) {
Socials(
input: {
filter: {identity: {_eq: $ensName}, dappName: {_eq: ${dappName}}},
blockchain: ethereum
}
) {
Social {
userId
connectedAddresses {
address
}
}
}
}
`;
const variables = { ensName: `fc_fid:${fid}` };
try {
const response = await fetch("https://api.airstack.xyz/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.AIRSTACK_API_KEY ?? ""}`,
},
body: JSON.stringify({
query,
variables,
}),
});
const result = await response.json();
if (result.errors) {
console.error("GraphQL errors:", result.errors);
return null;
}
// console.log(result.data.Socials.Social)
// convert to simple array reading .address from object
// remove non evm based addys like solan'as
// filter out nulls
const user = result.data?.Socials?.Social[0]?.connectedAddresses.map((address: { address: any; }) => address.address.startsWith('0x') ?
address.address : null).filter((address: any) => address !== null) ?? null;
return user;
} catch (error: any) {
console.error("Error fetching user data:", error);
return null;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment