Skip to content

Commit

Permalink
Merge pull request #402 from privacy-scaling-explorations/feat/eas-at…
Browse files Browse the repository at this point in the history
…testations-options

Add options to `EAS_ATTESTATIONS` credential validator
  • Loading branch information
vplasencia authored Feb 20, 2024
2 parents b8ac449 + d09b6b8 commit 9269128
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 31 deletions.
3 changes: 3 additions & 0 deletions libs/credentials/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export type EASContext = {
queryGraph: (query: string) => Promise<any>
attester?: BigNumberish
schemaId?: BigNumberish
revocable?: boolean
revoked?: boolean
isOffchain?: boolean
}

export type Context = Web2Context | BlockchainContext | EASContext
Expand Down
193 changes: 168 additions & 25 deletions libs/credentials/src/validators/easAttestations/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,205 @@ describe("EASAttestations", () => {
queryGraph: jest.fn()
}

queryGraphMocked.queryGraph.mockReturnValue([
{
id: "0x52561c95029d9f2335839ddc96a69ee9737a18e2a781e64659b7bd645ccb8efc",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
revocable: true,
revoked: false,
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
isOffchain: false
},
{
id: "0xee06a022c7d55f67bac213d6b2cd384a899ef79a57f1f5f148e45c313b4fdebe",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
revocable: true,
revoked: false,
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
isOffchain: false
},
{
id: "0xfbc0f1aac4379c18fa9a5b6493825234a8ca82a2a296148465d150c2e64c6202",
recipient: "0x0000000000000000000000000000000000000000",
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
revocable: true,
revoked: false,
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
isOffchain: false
},
{
id: "0x227510204bcfe7b543388b82c6e02aafe7b0d0a20e4f159794e8121611aa601b",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
revocable: true,
revoked: false,
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
isOffchain: false
}
])

it("Should return true if an account has greater than or equal to 3 attestations", async () => {
queryGraphMocked.queryGraph.mockReturnValue([
const result = await validateCredentials(
{
id: "0x52561c95029d9f2335839ddc96a69ee9737a18e2a781e64659b7bd645ccb8efc",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8"
id: easAttestations.id,
criteria: {
minAttestations: 3
}
},
{
id: "0xee06a022c7d55f67bac213d6b2cd384a899ef79a57f1f5f148e45c313b4fdebe",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph
}
)

expect(result).toBeTruthy()
})

it("Should return true if the given optional criterias are satisfied", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 1
}
},
{
id: "0xfbc0f1aac4379c18fa9a5b6493825234a8ca82a2a296148465d150c2e64c6202",
recipient: "0x0000000000000000000000000000000000000000"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
revocable: true,
revoked: false,
isOffchain: false
}
)

expect(result).toBeTruthy()
})

it("Should return false if the attester optional criteria doesn't match", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 1
}
},
{
id: "0x227510204bcfe7b543388b82c6e02aafe7b0d0a20e4f159794e8121611aa601b",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d4",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
revocable: true,
revoked: false,
isOffchain: false
}
])
)

expect(result).toBeFalsy()
})

it("Should return false if the schemaId optional criteria doesn't match", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 3
minAttestations: 1
}
},
{
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5d",
revocable: true,
revoked: false,
isOffchain: false
}
)

expect(result).toBeTruthy()
expect(result).toBeFalsy()
})

it("Should return false if an account has less than 3 attestations", async () => {
queryGraphMocked.queryGraph.mockReturnValue([
it("Should return false if the revocable optional criteria doesn't match", async () => {
const result = await validateCredentials(
{
id: "0x52561c95029d9f2335839ddc96a69ee9737a18e2a781e64659b7bd645ccb8efc",
recipient: "0x0000000000000000000000000000000000000000"
id: easAttestations.id,
criteria: {
minAttestations: 1
}
},
{
id: "0xee06a022c7d55f67bac213d6b2cd384a899ef79a57f1f5f148e45c313b4fdebe",
recipient: "0x0000000000000000000000000000000000000000"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
revocable: false,
revoked: false,
isOffchain: false
}
)

expect(result).toBeFalsy()
})

it("Should return false if the revoked optional criteria doesn't match", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 1
}
},
{
id: "0xfbc0f1aac4379c18fa9a5b6493825234a8ca82a2a296148465d150c2e64c6202",
recipient: "0x0000000000000000000000000000000000000000"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
revocable: true,
revoked: true,
isOffchain: false
}
)

expect(result).toBeFalsy()
})

it("Should return false if the isOffchain optional criteria doesn't match", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
criteria: {
minAttestations: 1
}
},
{
id: "0x227510204bcfe7b543388b82c6e02aafe7b0d0a20e4f159794e8121611aa601b",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8"
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
queryGraph: queryGraphMocked.queryGraph,
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
schemaId:
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
revocable: true,
revoked: false,
isOffchain: true
}
])
)

expect(result).toBeFalsy()
})

it("Should return false if an account has less than 3 attestations", async () => {
const result = await validateCredentials(
{
id: easAttestations.id,
Expand All @@ -70,7 +213,7 @@ describe("EASAttestations", () => {
}
},
{
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
queryGraph: queryGraphMocked.queryGraph
}
)
Expand Down
54 changes: 48 additions & 6 deletions libs/credentials/src/validators/easAttestations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,66 @@ const validator: Validator = {
*/
async validate(criteria: Criteria, context: Context) {
if ("recipient" in context) {
const { recipient } = context as EASContext

const {
recipient,
attester,
schemaId,
revocable,
revoked,
isOffchain
} = context as EASContext
const getAttestations = (context as EASContext).queryGraph

const attestations = await getAttestations(`
query {
attestations {
id
recipient
attester
revocable
revoked
schemaId
isOffchain
}
}
`)

const recipientAttestations = attestations.filter(
(attestation: any) => attestation.recipient === recipient
const filteredAttestations = attestations.filter(
(attestation: any) => {
// Mandatory recipient check.
if (attestation.recipient !== recipient) return false

// Optional criteria checks.
if (
attester !== undefined &&
attestation.attester !== attester
)
return false
if (
schemaId !== undefined &&
attestation.schemaId !== schemaId
)
return false
if (
revocable !== undefined &&
attestation.revocable !== revocable
)
return false
if (
revoked !== undefined &&
attestation.revoked !== revoked
)
return false
if (
isOffchain !== undefined &&
attestation.isOffchain !== isOffchain
)
return false

return true
}
)

return recipientAttestations.length >= criteria.minAttestations
return filteredAttestations.length >= criteria.minAttestations
}

throw new Error("No recipient value found")
Expand Down

0 comments on commit 9269128

Please sign in to comment.