Last active
August 22, 2024 22:28
-
-
Save agustif/3de891bd71470eedfb7a56901d104b30 to your computer and use it in GitHub Desktop.
find-user-airstack.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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