Closed connormcmk closed 1 year ago
After further inspection, it seems the issue might be coming from the data structures being different in the responses from v1 and v2 farcaster
You can see that for the v1 farcaster endpoint (of which all-casts-in-thread
is a member) it returns:
"reactions": {
"likes": [
{ "fid": 474 },
...
],
"recasts": [
{"fid": 454}
]
},
Whereas for v2 endpoint it returns:
"reactions": {
"count": 5,
"fids": [
124,
...
]
},
It would probably be ideal to map these two return types to the same datastructure. I recommend using the v2 data structure for now:
type Cast = {
hash: Hash;
thread_hash: Hash | null;
parent_hash: Hash | null;
parent_url: string | null;
parent_author: {
fid: number | null;
};
author: {
fid: number;
username: string;
display_name: string;
pfp_url: string;
profile: {
bio: {
text: string;
};
};
follower_count: number;
following_count: number;
verifications: Hash[];
active_status: 'active';
};
text: string;
timestamp: string;
embeds: Embed[];
reactions: {
likes: Like[];
recasts: Recast[];
};
replies: {
count: number;
};
}
this is my oversight - forgot to implement a separate v1 Cast type. will get a fix out later today.
I think we should map it all to the v2 Cast type, handling multiple different types is annoying
Or have a v1 Cast type and a utility function that maps it to v2 / generic, but I think it's best to just have 1, what do you think?
yep that makes sense, it looks like the types are the same besides the key casing. will use the existing type!
the types actually don't match perfectly, the V1 casts have a different format for recasters (fname in a separate array vs with the FID). current thinking is to just omit the names from the returned type, but want to think it through a bit more and test as well so will not be able to get a release out today.
if you want to try to use the version I have going that's not fully finished, you can use the casts-in-thread-type
branch!
@alex-grover Have you had a chance to look at this since then? Picking this back up now.
I think we should just map it from:
{
"recasts": {
"count": 5,
"fids": [
129,
13978,
14392,
10311,
880
]
},
"recasters": [
"phil",
"forogh",
"shahroozraeisi",
"aeon",
"accountless.eth"
]
}
to:
{
"recasts": [
{
"fid": 129,
"fname": "phil"
},
{
"fid": 13978,
"fname": "forogh"
},
{
"fid": 14392,
"fname": "shahroozraeisi"
},
{
"fid": 10311,
"fname": "aeon"
},
{
"fid": 880,
"fname": "accountless.eth"
}
]
}
Right?
Should be as simple as:
recasts.fids.forEach((fid, index) => {
const fname = recasters[index];
obj.recasts.push({ fid, fname });
});
The only perhaps dangerous assumption we really have to make is that the fnamse of recasters
is always in the same order as the fids in recasts.fids
.
Asked Manan in Neynar channel: https://warpcast.com/nor/0xa53f6d10
P.S. it also looks like parentHash
in v1 should be mapped to parent_hash
in the v2 Cast object, guessing there are a handful of more mappings to make so would be worth checking
Confirmed that they will be in the correct order:
great, thanks for looking into that. have not picked back up yet but can have this released in a couple hours
P.S. it also looks like
parentHash
in v1 should be mapped toparent_hash
in the v2 Cast object, guessing there are a handful of more mappings to make so would be worth checking
Can you elaborate what you mean here? Is this sufficient or is there something else I've missed? https://github.com/alex-grover/neynar-next/commit/ee8bdcfd28822eee4dde1d9a4b149c845dcd9903#diff-1113f47917f0bc0f7f54e7f179e6120af0ce81ecfb6e3d1d0942c65f69628ff3R120
can you try v0.2.8?
thanks again for the details here!
Can you elaborate what you mean here? Is this sufficient or is there something else I've missed? https://github.com/alex-grover/neynar-next/commit/ee8bdcfd28822eee4dde1d9a4b149c845dcd9903#diff-1113f47917f0bc0f7f54e7f179e6120af0ce81ecfb6e3d1d0942c65f69628ff3R120
Yeah, that looks perfect!
can you try v0.2.8?
thanks again for the details here!
Thank you! Will test and follow up this afternoon
Yep, it's working. The only issue is that it seems like Cast.author should be of type User, right now it has a bespoke definition, so the response from the getUser endpoint returns a different User than the author field in the getCast endpoint
I.e. switch from:
export type Cast = {
hash: Hash
thread_hash: Hash | null
parent_hash: Hash | null
parent_url: string | null
parent_author: {
fid: number | null
}
author: {
fid: number
username: string
display_name: string
pfp_url: string
profile: {
bio: {
text: string
}
}
follower_count: number
following_count: number
verifications: Address[]
active_status: 'active' | 'inactive'
}
text: string
timestamp: string
embeds: Embed[]
reactions: {
likes: Like[]
recasts: Recast[]
}
replies: {
count: number
}
}
To
export type Cast = {
hash: Hash
thread_hash: Hash | null
parent_hash: Hash | null
parent_url: string | null
parent_author: {
fid: number | null
}
author: User
text: string
timestamp: string
embeds: Embed[]
reactions: {
likes: Like[]
recasts: Recast[]
}
replies: {
count: number
}
}
If you'd like, let's open it as a new issue. Is this something that changed with this commit or did it already exist?
That already existed - same distinction of v1 vs v2 endpoints, the user endpoints are from v1. A guiding principle I had when writing this originally was to stick to exactly what the Neynar docs + APIs were returning to make it easy to match this library with what you see when running a test query.
I agree that having 2 separate types is annoying to deal with. Now that we've stepped away from that, I'm wondering if the best approach here is to just map the UserV1 types to the V2 types, or to return the V1 type to match the APIs and export a utility function for ease of use.
My worry with converting everything is that we'll run into more places where the data doesn't match - the APIs seem to have some bugs and design quirks so this seems pretty likely to me if we cover every single endpoint.
Thinking for now we can convert and just keep an eye out for mismatches down the line, what do you think? Hopefully this is somewhat solved with the upcoming OpenAPI spec. Either way, if you could open another issue that would be great ππ½
Cool, created a new one. https://github.com/alex-grover/neynar-next/issues/36
I agree that having 2 separate types is annoying to deal with. Now that we've stepped away from that, I'm wondering if the best approach here is to just map the UserV1 types to the V2 types, or to return the V1 type to match the APIs and export a utility function for ease of use.
Yeah I think this is exactly the right approach. The whole reason I picked up the package in the first place was because I assumed we'd all swarm on a single place to handle the subtleties of neynar's somewhat wonky api spec, and push updates in a single place as the API evolves.
Obviously, any api user can read the docs themselves if they want the direct api experience, so the real value here is mapping the complexities of the neynar api to a consistent set of types and having knowledge of edge cases so the user doesn't have to worry about them.
just my 2c wdyt?
yep that makes sense to me. will work on it today :)
Describe the bug The return type of getCastsInThread is:
However, the actual internal values of
result.casts
isWhat's expected instead is a structure matching the Cast type, like this: