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

IPFS metadata storage #86

Merged
merged 7 commits into from
Aug 19, 2021
Merged

IPFS metadata storage #86

merged 7 commits into from
Aug 19, 2021

Conversation

wildmolasses
Copy link
Contributor

@wildmolasses wildmolasses commented Aug 4, 2021

This PR resolves #67

Important note: This PR uses a trick to accomplish the metaPtr resolution. Instead of resolving the metaPtr directly, it splits the URL, takes the CID, and resolves that with our fleek ipfs connection instance. Even if a metaPtr specified the cloudflare gateway, it would still use fleek to resolve. If a metaPtr did not have a CID in the last position of the URL, the fetch would completely fail.

The metadata fetching isn't robust. If the fetch fails, the metadata status will be 'error' and it will not reattempt a fetch.

There are no UI states yet corresponding to the metadata fetch status states of "pending", "resolved", "error"

@wildmolasses wildmolasses force-pushed the ipfs-poc branch 2 times, most recently from fd048be to 76262b4 Compare August 4, 2021 20:27
@apbendi
Copy link
Collaborator

apbendi commented Aug 5, 2021

Great start @wildmolasses! Before making any changes to the frontend, be sure to rebase to main

@apbendi apbendi mentioned this pull request Aug 10, 2021
17 tasks
@wildmolasses wildmolasses force-pushed the ipfs-poc branch 3 times, most recently from cbb988c to 1e8218d Compare August 14, 2021 03:07
@wildmolasses wildmolasses marked this pull request as ready for review August 14, 2021 03:44
@wildmolasses wildmolasses force-pushed the ipfs-poc branch 2 times, most recently from b174305 to bdd8f0d Compare August 16, 2021 15:30
@mds1 mds1 mentioned this pull request Aug 16, 2021
Copy link
Collaborator

@thelostone-mc thelostone-mc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left a couple of comments

app/index.html Outdated Show resolved Hide resolved
app/src/shims.d.ts Outdated Show resolved Hide resolved
return ipfsFetch({
cid: url.split('/').reverse()[0],
});
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ would it be worth adding comments to the functions on

  • what it does
  • what are the arguments

It would be useful if we decide to add in auto doc generation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, more comments would be useful!

Re docgen, personally I have not been using NatSpec everywhere, so we'll need some comments cleanup before we do docgen, but you're right that is probably best practice going forward

app/src/config.ts Outdated Show resolved Hide resolved
@@ -159,6 +161,28 @@ export default function useDataStore() {
lastBlockTimestamp.value = (timestamp as BigNumber).toNumber();
grants.value = grantsList as Grant[];
grantRounds.value = grantRoundsList as GrantRound[];
const metaPtrs = grants.value.map((grant) => grant.metaPtr);
const newMetadata = metaPtrs
.filter((metaPtr) => !grantMetadata.value[metaPtr]) // only want new metaPtrs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checking -> it looks like a grant can have multiple metadata but we want only the which as status as pending ?
not super clear on what we are doing here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'll try to add some comments!

@@ -28,6 +28,10 @@ export function isValidAddress(val: string | undefined) {
return val && isAddress(val);
}

export function isDefined(val: unknown) {
return !!val;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend moving this to utils package

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should hold off on this for now per #114.

Though it also feels like this function is simple enough that it can be removed which might even be more readable (e.g. people know what Boolean() or !! does, but would have to look up what isDefined does

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm using it for form validation; would Boolean() work just as well? I like how "isDefined" makes things a little more explicit but could defer to you guys!

app/src/store/data.ts Outdated Show resolved Hide resolved
app/src/utils/ipfs.ts Outdated Show resolved Hide resolved
Comment on lines +89 to +93
const form = ref<{ owner: string; payee: string; name: string; description: string }>({
owner: '',
payee: '',
metaPtr: '',
name: '',
description: '',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we define a local Form type, since I imagine we'll be adding more fields later too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's only used once I don't think it's necessary, but would defer to you guys

Comment on lines 110 to 112
const metaPtr = await ipfs
.createGrant({ name, description })
.then((cid) => ipfs.createMetaPtr({ cid: cid.toString() }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why you use a .then instead of

Suggested change
const metaPtr = await ipfs
.createGrant({ name, description })
.then((cid) => ipfs.createMetaPtr({ cid: cid.toString() }));
const cid = await ipfs.createGrant({ name, description })
const metaPtr = await ipfs.createMetaPtr({ cid: cid.toString() }));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my general rule is that if something is used once there's no reason to declare it, i.e. since we don't use cid elsewhere there's no reason to declare it. i break this sometimes for readability's sake, but then clauses are pretty readable to me. Thoughts?

Copy link
Collaborator

@apbendi apbendi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking and working great, @wildmolasses. Nice job getting this going.

My only comment is on the way we're processing the metaPtr URI. Instead of hacking off the CID from the end— and assuming it's there in the first place— I think we should just have a whitelisted set of endpoints from which the app will fetch content from. This should be separate from the concern of whether the endpoint is an IPFS gateway or not.

In other words, we should have a hardcoded list of valid endpoints, which can include just https://ipfs-api.dev.fleek.cool for now (or also https://cloudflare-ipfs.com if we want) and when the metaPtr has a url at one of those endpoints, we should fetch the contents. If it doesn't, it shouldn't fetch, and should probably have an error message like "Unsupported source for grant metadata" or something like that.

Curious to hear what others think of this approach cc @thelostone-mc @mds1 @gdixon

@wildmolasses
Copy link
Contributor Author

wildmolasses commented Aug 18, 2021

Overall looking and working great, @wildmolasses. Nice job getting this going.

My only comment is on the way we're processing the metaPtr URI. Instead of hacking off the CID from the end— and assuming it's there in the first place— I think we should just have a whitelisted set of endpoints from which the app will fetch content from. This should be separate from the concern of whether the endpoint is an IPFS gateway or not.

In other words, we should have a hardcoded list of valid endpoints, which can include just https://ipfs-api.dev.fleek.cool for now (or also https://cloudflare-ipfs.com if we want) and when the metaPtr has a url at one of those endpoints, we should fetch the contents. If it doesn't, it shouldn't fetch, and should probably have an error message like "Unsupported source for grant metadata" or something like that.

Curious to hear what others think of this approach cc @thelostone-mc @mds1 @gdixon

In principle I know that's correct, however different endpoints have different auth models -- well, really, fleek is the one where we need an api key in order to fetch. So if we're going to use the fleek endpoint as our metaPtr, do we want to write conditional logic where if the metaPtr is fleek (which is currently the case for any grant created by this app) then use an api key, and otherwise proceed without auth token? it starts to feel a little weird, but maybe this is acceptable.

@apbendi
Copy link
Collaborator

apbendi commented Aug 18, 2021

In principle I know that's correct, however different endpoints have different auth models -- well, really, fleek is the one where we need an api key in order to fetch. So if we're going to use the fleek endpoint as our metaPtr, do we want to write conditional logic where if the metaPtr is fleek (which is currently the case for any grant created by this app) then use an api key, and otherwise proceed without auth token? it starts to feel a little weird, but maybe this is acceptable.

Per our discussion offline, I think the right approach here is to use keep metaptr fetching dumb, so an http endpoint that requires an API key should not be used. For the immediate term, we can use a whitelisted cloudflare (or another open IPFS gateway) as the metaPtr URL, therefore allowing us to fetch without any authentication.

@mds1 mds1 merged commit 422e669 into main Aug 19, 2021
This was referenced Aug 20, 2021
@thelostone-mc thelostone-mc deleted the ipfs-poc branch September 6, 2021 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IPFS Grant Metadata Storage Proof-of-Concept
4 participants