I currently rely on u256
types on most of my models, and since Dojo js stack is not really supporting it yet, I am duplicating a lot of code on my projects, but it is a pain to maintain.
Yesterday I discovered that some of my contribution to that direction does not work anymore, so better formally issue it.
Probably everyone agrees that the best thing is to update the packages and actually support it, right?
I'm willing to do it.
Here's how I see it.
Just don't want to break anything else...
@latticexyz/recs
vs. @dojoengine/recs
Is there anything really necessary in Dojo's fork of mud recs?
Can't we just use Lattice's instead?
Talking to @ponderingdemocritus a while back, I got the notion that there isn't really.
Since I needed mud 2.0 for u256
, I replaced all my recs imports to mud, while Dojo was on mud 1.0.
But now that Dojo is broadly using mud 2.0, can't we just switch to @latticexyz/recs
?
Everything was working fine.
Now I tried replacing my imports to dojo's fork and started getting all sorts of obscure problems, so got back to mud recs.
Recs version with BigInt support
Because of mud 2.0 recs, I added this to generateComponents.cjs
// Extract recs package version
const { dependencies } = require(path.resolve("./package.json"));
const recsVersion = dependencies?.["@dojoengine/recs"] ?? "";
const isRecsVersion2 = /^[\^\~]?2./g.exec(recsVersion) != null;
console.log(
`...generating for @dojoengine/recs version ${
isRecsVersion2
? "2 (bigint support, Entity as string)"
: "1 (no bigint, EntityIndex as number)"
}`
)
This is now broken because the version check is looking in dojo's recs, not lattice's...
So I propose to remove the recs version check and just use mud 2.0 as default, with BigInt support.
OK?
Recs types
Just saying that a u256
is a RecsType.BigInt
is not enough.
One u256
is actually two u128
in cairo, using two slots of event data.
Because of that... I added the types
field on the generated metadata, so I can type check when parsing event data.
My models are looking like this on contractComponents.ts:
return defineComponent(
world,
{
seed: RecsType.BigInt,
minter: RecsType.BigInt,
domain_id: RecsType.Number,
token_id: RecsType.Number,
yonder: RecsType.Number,
},
{
metadata: {
name: name,
types: ["u256","ContractAddress","u16","u16","u16"],
},
}
);
But I just dicovered that my types
were hijacked!
It is not storing cairo types anymore, instead, only custom types.
@kariy, is that the purpose or you just adapted to the new parser?
Adding all primitive tyes as well will fix this for me.
Event data to components...
Now that I know which model fields are u256
, decodeComponent() has to be updated to consume two values from the event data when a u256
pops up...
export function decodeComponent(
schema: any,
values: string[],
valuesIndex: number
): any {
// Iterate through the keys of the schema and reduce them to build the decoded component.
return Object.keys(schema).reduce((acc: any, key) => {
// If the current schema key points to an object and doesn't have a 'type' property,
// it means it's a nested component. Therefore, we recursively decode it.
if (typeof schema[key] === "object" && !schema[key].type) {
acc[key] = decodeComponent(schema[key], values, valuesIndex);
} else {
// If the schema key points directly to a type or is not an object,
// we parse its value using the provided parseComponentValue function
// and move to the next index in the values array.
acc[key] = parseComponentValue(values[valuesIndex], schema[key]);
valuesIndex++;
}
return acc;
}, {});
}
npx core
Makes no sense to me that we use this command to generate the components file:
npx @dojoengine/core xxx/manifest.json yyy/contractComponents.ts
EDIT: nevermind, now that I understand better how it works, I see it is correct.
Unit tests
I have NO idea on how to add unit tests to keep these things working forever.
I'll leave that to someone else to do the base implementation.
Just an idea...