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

Add EAS Attestations credentials to API and Dashboard #570

Closed
wants to merge 7 commits into from
60 changes: 42 additions & 18 deletions apps/api/src/app/credentials/credentials.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
Web2Provider,
providers,
Web2Context,
BlockchainContext
BlockchainContext,
EASContext,
EASNetworks
} from "@bandada/credentials"
import { blockchainCredentialSupportedNetworks } from "@bandada/utils"
import { id } from "@ethersproject/hash"
Expand Down Expand Up @@ -139,7 +141,7 @@ export class CredentialsService {
} = this.oAuthState.get(credentialOAuthState))
const provider = getProvider(providerName)

let context: Web2Context | BlockchainContext
let context: Web2Context | BlockchainContext | EASContext

if (address && credentialProvider === "blockchain") {
const { network } = credentials.credentials[i].criteria
Expand Down Expand Up @@ -171,6 +173,14 @@ export class CredentialsService {
jsonRpcProvider
}

// Check if the same account has already joined the group.
accountHash = id(address + groupId)
} else if (address && credentialProvider === "eas") {
context = {
network: EASNetworks.ETHEREUM_SEPOLIA,
address: address[0]
}

// Check if the same account has already joined the group.
accountHash = id(address + groupId)
} else {
Expand Down Expand Up @@ -259,30 +269,44 @@ export class CredentialsService {

let accountHash: string

let context: Web2Context | BlockchainContext
let context: Web2Context | BlockchainContext | EASContext

if (address) {
const { network } = JSON.parse(group.credentials).criteria
const { network, recipient } = JSON.parse(
group.credentials
).criteria

if (network) {
const supportedNetwork =
blockchainCredentialSupportedNetworks.find(
(n) => n.name.toLowerCase() === network.toLowerCase()
)

const supportedNetwork = blockchainCredentialSupportedNetworks.find(
(n) => n.name.toLowerCase() === network.toLowerCase()
)
if (supportedNetwork === undefined)
throw new BadRequestException(
`The network is not supported`
)

if (supportedNetwork === undefined)
throw new BadRequestException(`The network is not supported`)
const networkEnvVariableName = supportedNetwork.id.toUpperCase()

const networkEnvVariableName = supportedNetwork.id.toUpperCase()
const web3providerRpcURL =
process.env[`${networkEnvVariableName}_RPC_URL`]

const web3providerRpcURL =
process.env[`${networkEnvVariableName}_RPC_URL`]
const jsonRpcProvider = await (
provider as BlockchainProvider
).getJsonRpcProvider(web3providerRpcURL)

const jsonRpcProvider = await (
provider as BlockchainProvider
).getJsonRpcProvider(web3providerRpcURL)
context = {
address: address[0],
jsonRpcProvider
}
}

context = {
address: address[0],
jsonRpcProvider
if (recipient) {
context = {
network: EASNetworks.ETHEREUM_SEPOLIA,
address: address[0]
}
}

// Check if the same account has already joined the group.
Expand Down
54 changes: 53 additions & 1 deletion apps/dashboard/src/pages/credentials.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
blockchain,
Web2Provider,
twitter,
github
github,
eas
} from "@bandada/credentials"
import { Flex, Text, Button } from "@chakra-ui/react"
import { useEffect, useState, useCallback, useContext } from "react"
Expand Down Expand Up @@ -227,6 +228,57 @@ export default function CredentialsPage() {
}
}

// If the credential is EAS
if (
providerName === eas.name &&
isLoggedInAdmin() &&
state &&
admin
) {
if (groupType) {
const bandadaCredentials =
localStorage.getItem(LOCAL_STORAGE)
if (!bandadaCredentials) return null
const providers = JSON.parse(bandadaCredentials)
providers[providerName] = [
state,
undefined,
admin.address
]
localStorage.setItem(
LOCAL_STORAGE,
JSON.stringify(providers)
)
if (!groupId || !memberId) return
const url = getUrlNextEmpty(groupId, memberId)

if (url === null) {
const clientRedirectUrl =
await validateCredentials()
if (clientRedirectUrl) {
window.location.replace(clientRedirectUrl)
} else {
setMessage("You have joined the group!")
}
return
}

window.location.replace(url)
}

const redirectUrl = await addMemberByCredentials(
[state],
undefined,
[admin.address]
)

if (redirectUrl) {
window.location.replace(redirectUrl)
} else {
setMessage("You have joined the group!")
}
}

// If it is a web2 credential. This is the first request for web2 credentials
if (
(providerName === twitter.name ||
Expand Down
36 changes: 36 additions & 0 deletions libs/credentials/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,42 @@ validateCredentials(
}
}
)

// Validate blockchain credentials
validateCredentials(
{
id: blockchainBalance.id,
criteria: {
minBalance: "10",
network: "sepolia",
blockNumber: 4749638
}
},
{
address: "0x",
jsonRpcProvider
}
)

// Validate EAS attestations credentials
validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 1,
recipient: "0x0",
attester: "0x1",
schemaId: "0x2",
revocable: true,
revoked: false,
isOffchain: false
}
},
{
network: EASNetworks.ETHEREUM,
address: "0x1"
}
)
```

## Validate many credentials
Expand Down
12 changes: 8 additions & 4 deletions libs/credentials/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,16 @@ describe("Credentials library", () => {
})

describe("# queryGraph", () => {
it("Should return a function that can be used to query graphs data using GraphQL", () => {
const query = queryGraph(
it("Should return a function that can be used to query graphs data using GraphQL", async () => {
const query = await queryGraph(
"https://easscan.org/graphql",
`
query {
attestations {
attestations(where: {
recipient: {
equals: "0x"
}
}) {
recipient
attester
revocable
Expand All @@ -164,7 +168,7 @@ describe("Credentials library", () => {
`
)

expect(query).toBeUndefined()
expect(query).toEqual({})
})
})

Expand Down
2 changes: 1 addition & 1 deletion libs/credentials/src/queryGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { request } from "@bandada/utils"
* @returns The function to query the graph.
*/
export default function queryGraph(endpoint: string, query: string) {
request(endpoint, {
return request(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
data: JSON.stringify({
Expand Down
3 changes: 2 additions & 1 deletion libs/credentials/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export type BlockchainContext = {
}

export type EASContext = {
queryGraph: (query: string) => Promise<any>
network: EASNetworks
address: BigNumberish
}

export type Context = Web2Context | BlockchainContext | EASContext
Expand Down
Loading
Loading