Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

useContractSchemaRpc: Parse schema based on module version #45

Merged
merged 2 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/wallet-connectors/src/WalletConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ function serializeUpdateContractMessage(
}

/**
* Convert schema into the object format expected by the Mobile crypto library.
* Convert schema into the object format expected by the Mobile crypto library (function 'parameter_to_json')
* which decodes the parameter before presenting it to the user for approval.
* @param schema The schema object.
*/
function convertSchemaFormat(schema: Schema | undefined) {
Expand Down
48 changes: 35 additions & 13 deletions samples/contractupdate/src/useContractSchemaRpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,31 @@ export interface SchemaRpcResult {
schema: Schema;
}

function findCustomSections(m: WebAssembly.Module) {
function findCustomSections(m: WebAssembly.Module, moduleVersion: number) {
function getCustomSections(sectionName: string, schemaVersion: SchemaVersion | undefined) {
const s = WebAssembly.Module.customSections(m, sectionName);
return s.length === 0 ? undefined : { sectionName, schemaVersion, contents: s };
}
// First look for embedded version, then v1, then v0. The "v"s being off by 1 is not an error.
return (
getCustomSections('concordium-schema', undefined) ||
getCustomSections('concordium-schema-v2', SchemaVersion.V1) ||
getCustomSections('concordium-schema-v1', SchemaVersion.V0)
);

// First look for section containing schema with embedded version, then "-v1" or "-v2" depending on the module version.
// See also comment in 'useContractSchemaRpc'.
switch (moduleVersion) {
case 0:
return (
getCustomSections('concordium-schema', undefined) || // always v0
getCustomSections('concordium-schema-v1', SchemaVersion.V0) // v0 (not a typo)
);
case 1:
return (
getCustomSections('concordium-schema', undefined) || // v1, v2, or v3
getCustomSections('concordium-schema-v2', SchemaVersion.V1) // v1 (not a typo)
);
}
return getCustomSections('concordium-schema', undefined); // expecting to find this section in future module versions
}

function findSchema(m: WebAssembly.Module): Result<SchemaRpcResult | undefined, string> {
const sections = findCustomSections(m);
function findSchema(m: WebAssembly.Module, moduleVersion: 0 | 1): Result<SchemaRpcResult | undefined, string> {
const sections = findCustomSections(m, moduleVersion);
if (!sections) {
return ok(undefined);
}
Expand All @@ -39,13 +49,25 @@ export function useContractSchemaRpc(rpc: ConcordiumGRPCClient, contract: Info)
const [result, setResult] = useState<Result<SchemaRpcResult | undefined, string>>();
useEffect(() => {
ResultAsync.fromPromise(rpc.getModuleSource(new ModuleReference(contract.moduleRef)), errorString)
.andThen((r) => {
if (!r) {
.andThen(({ version, source }) => {
if (source.length === 0) {
return err('module source is empty');
}
return ResultAsync.fromPromise(WebAssembly.compile(r.source), errorString);
// The module can contain a schema in one of two different custom sections.
// The supported sections depend on the module version.
// The schema version can be either defined by the section name or embedded into the actual schema:
// - Both v0 and v1 modules support the section 'concordium-schema' where the schema includes the version.
// - For v0 modules this is always a v0 schema.
// - For v1 modules this can be a v1, v2, or v3 schema.
// - V0 modules additionally support section 'concordium-schema-v1' which always contain a v0 schema (not a typo).
// - V1 modules additionally support section 'concordium-schema-v2' which always contain a v1 schema (not a typo).
// The section 'concordium-schema' is the most common and is what the current tooling produces.
return ResultAsync.fromPromise(
WebAssembly.compile(source).then((module) => ({ module, version })),
errorString
);
})
.andThen(findSchema)
.andThen(({ module, version }) => findSchema(module, version))
.then(setResult);
}, [contract, rpc]);
return result;
Expand Down