Reputation: 11
I'm setting up a Nuxt.js app with @polkadot-js. When I do request to custom substrate runtime module with my @polkadot/types - I'm getting this error Class constructor Struct cannot be invoked without 'new'
.
This is for a Nuxt.js app with official setup of typescript. In the past, I've tried to setup it with clean Nuxt.js and Vue but always the same error. Only if I setup clean NodeJS (with or without typescript) or with @polkadot react apps - it works well.
I've created a repository to try some other ways.
API call:
class VecU32 extends Vector.with(u32) {}
class Kind extends Struct {
constructor(value) {
super({
stuff: VecU32
}, value);
}
}
const Alice = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
const provider = new WsProvider("ws://127.0.0.1:9944");
const typeRegistry = getTypeRegistry();
typeRegistry.register({ Kind });
const api = await ApiPromise.create(provider);
// With types providede in create function - works well
// types: {
// Kind: {
// stuff: "Vec<u32>"
// }
// }
const res = await api.query.template.kinds(Alice);
console.log(res);
I expect empty (or some values, depending on what is in the blockchain) result output, but the actual output is the error, Class constructor Struct cannot be invoked without 'new'
.
Upvotes: 1
Views: 652
Reputation: 63
Short answer:
Instead of this const typeRegistry = getTypeRegistry();
, do:
const typeRegistry.register({
Kind: {
'stuff': 'Vec<u32>'
}
});
Longer answer
When you're calling typeRegistry.register({ Kind });
you're trying to register the Typescript class as a custom type in the registry, but the types you need to pass to the type registry of the API have nothing to do with your Typescript types, these two are not directly associated to each other.
Event if you'd be writing plain Javascript you would need to register your custom Substrate Types in the Polkadot-JS API.
The types passed to the API are used to decode and encode the data you're sending and receiving to/from your substrate node. They are compliant with the SCALE codec which is also implemented in the Substrate core Rust code. Using these types makes sure that the data can be correctly de- and encoded in different environments and by different languages.
You can read more about it here: https://substrate.dev/docs/en/overview/low-level-data-format
The Javascript representation of these types are what's listed as "Codec types" in the Polkadot-JS docs: https://polkadot.js.org/api/types/#codec-types
All the other types you find in the Polkadot-JS docs are extensions of these low-level codec types.
What you need to pass to the JS-API are all custom types of all your custom substrate modules so that the API knows how to de- and encode your data, so in your case what you declared here in Rust:
pub struct Kind {
stuff: Vec<u32>,
}
needs to be registered like this in Javascript:
const typeRegistry.register({
Kind: {
'stuff': 'Vec<u32>'
}
});
Your Typescript types on the other hand are there to make sure that the data your handling client side in your frontend written in typescript has the correct types.
They're only needed by Typescript and they're adding an extra layer of security, but the types itself are not needed to communicate with the API. Your data definitely needs to have the correct format to prevent errors, though.
You can think of https://www.npmjs.com/package/@polkadot/types as a Substrate/ Polkadot specific version of https://github.com/DefinitelyTyped/DefinitelyTyped
But even if you're not using Typescript https://polkadot.js.org/api/types/ is still 100% your go-to reference.
Upvotes: 2