-
Notifications
You must be signed in to change notification settings - Fork 192
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
feat: add hasVerifiedAttestations and getVerifiedAttestations #95
Conversation
|
`; | ||
|
||
/** | ||
* Retrieves attestations for a given address and chain, optionally filtered by schemas. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the context of Coinbase Verifications. Do we want to be more specific here in that case?
e.g. getCoinbaseVerifications
Same with below, should we name it hasCoinbaseVerifications
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bringing this up in case we extend Onchain Kit to support all attestations in general -- which IMO, we should!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the path to support all attestations in general?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we ever settled on a clear path for this.
But absent any decisions, I think we should be more opinionated with the naming to leave room for more general EAS support in the near future. Committing to something abstract like getAttestation
which really only targets CB Verifications would preclude us from that option.
cc: @Zizzamia
src/core/getAttestation.ts
Outdated
* @returns A promise that resolves to an array of Attestations. | ||
* @throws Will throw an error if the request to the GraphQL API fails. | ||
*/ | ||
export async function getAttestation( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we set this up manually?
I was thinking longer term we could just use https://the-guild.dev/graphql/codegen
Allows us to appropriately keep up with EAS' GraphQL specs, and also more easily add new helpers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we want to codegen? I am generally against codegen as they are the eveil of good developer experience for OSS libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically this.
If you look at the link I shared, you can arguably get the same experience, without having to manually plumb the queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In another scenario I'd agree with you if we're actually adding significantly more value / logic over what codegen already provides.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of codegen we want? Like one for each Attestation? help me understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends. In this context, we are asking GraphQL for "attestations that are not expired or revoked for a specific address, a specific attester and possibly a set of schema IDs". There's an additional dimension here which is the network.
I'd personally codegen what we already have:
query findActiveAttestations(...) {
// ... current fields, but broken out as a fragment ...
}
Then this current function or if we rename it to findCoinbaseVerifications
/ getCoinbaseVerifications
will just be a light wrapper around the generated code. But this ensures strong consistency with the actual EAS GraphQL schema, and we're not writing our types ourselves making it easier to maintain longer term. Our focus will simply be providing a better experience over someone writing their own queries or generating their own GraphQL client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then for the other use-case in this context, we have hasVerifiedAttestations
which can simply be another codegen query because there's actually a specific GraphQL resolver for that! That is, findFirstAttestation
in EAS' GraphQL. This way, we are letting the GraphQL API handle most of the filtering for us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I'm not strongly holding this opinion. It's something we can do later. I rather we don't block this PR from going out. But it would address your other comment:
Would love we have strong types on what's returing and what each of them means.
In the sense that we would have the types auto-gen.
src/core/getAttestation.ts
Outdated
* @returns A promise that resolves to an array of Attestations. | ||
* @throws Will throw an error if the request to the GraphQL API fails. | ||
*/ | ||
export async function getAttestation( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This implicitly filters out revoked or expired attestations. We may want a different name for it to reflect that. Similar to comment further up.
src/core/hasVerifiedAttestations.ts
Outdated
const schemaUids = getChainSchemasUids(expectedSchemas, chain.id); | ||
const attestations = await getAttestation(chain, address, { schemas: expectedSchemas }); | ||
const schemasFound = attestations.map((attestation) => attestation.schemaId); | ||
|
||
return schemaUids.every((schemaUid) => schemasFound.includes(schemaUid)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no change needed, but a more optimal solution would be to let the GraphQL server handle all this.
package.json
Outdated
@@ -18,6 +18,8 @@ | |||
"release:version": "changeset version && yarn install --immutable" | |||
}, | |||
"peerDependencies": { | |||
"graphql": "^16.8.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this clash with any other GraphQL dependcy in the industry? I am a bit ingronant here, but those work this well with Relay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering if we can say
"graphql": "*",
or choose a minium version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not an expert here, who should we loop in on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
graphql
is the base dependency which Relay relies on too. But as we are setting this as a peer dependency, we're less likely to have clashes.
schemaId: string; | ||
timeCreated: number; | ||
txid: string; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a line of comment for each property, so we know what they are used for.
export async function hasVerifiedAttestations( | ||
chain: Chain, | ||
address: Address, | ||
expectedSchemas: AttestationSchema[] = [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expectedSchemas
sounds odd. What exactly are we passing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see we have those 'VERIFIED ACCOUNT' | 'VERIFIED COUNTRY'
, not sure I follow.
Step 1, tell me the chain
Step 2, tell me an address, ok but who address? Customer address? unclear.
Step 3, tell me a schema, ok what schema? how do I know where those schemas are?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to be more opinionated on naming address? what if it is not a customer, it is something else to me. Might name like 'walletAddress'. But I assume that address in onchain app is clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
address
is probably fine, but we need good example in the docs on how this works and how and when should be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think address
is fine. Otherwise it would be target
/ recipient
/ subject
, all of which may not convey the desired meaning.
export async function getAttestation<TChain extends Chain>( | ||
address: Address, | ||
chain: TChain, | ||
filters?: { schemas?: AttestationSchema[] }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cbfyi curios, what other kind of filters we imagine to have later on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess GraphQL filters maybe
where: { AND: [conditions] },
orderBy: [{ timeCreated: 'desc' }],
distinct: ['schemaId', 'attester'],
take: 10,
mmmm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah perhaps we can drive this with use-cases:
- Gating: I want to know if someone has X, Y, Z attestation
- Display / Visual: I want to get all latest attestations to display, by attester and/or schema
- Additional Logic: I want to get a specific attestation to check its payload / contents
And for both (1), and (2), we would want to filter by only active by default. (3) doesn't even have to hit GraphQL, but if we want the payload / contents to be unpacked, it's more convenient if we do.
That should cover 70% of apps leveraging attestations IMO.
closing as going to break down in smaller PRs. |
What changed? Why?
Introduce new functionalities that make easier verify addresses in the Ethereum Attestation Service (EAS).
hasVerifiedAttestations
getAttestation
Notes to reviewers
How has it been tested?
Local build and consuming in a playground