Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

chore: reorganize frame metadata #480

Merged
merged 15 commits into from
Dec 22, 2022
Merged
32 changes: 27 additions & 5 deletions _tasks/download_frame_metadata.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
import * as fs from "../deps/std/fs.ts"
import * as path from "../deps/std/path.ts"
import * as Z from "../deps/zones.ts"
import * as C from "../mod.ts"
import * as U from "../util/mod.ts"

const outDir = path.join(Deno.cwd(), "frame_metadata", "_downloaded")
await fs.emptyDir(outDir)
const names = Object.keys(C.knownClients)
const outDir = new URL("../frame_metadata/_downloaded", import.meta.url)
try {
Deno.removeSync(outDir, { recursive: true })
} catch (_e) {}
Deno.mkdirSync(outDir)

const modFilePath = new URL("_downloaded/mod.ts", outDir)
const modFileContents = `// This file was generated by \`_tasks/download_frame_metadata.ts\`
import * as U from "../../util/mod.ts"
import { $metadata } from "../mod.ts"

export const [
${names.join(",\n ")},
] = await Promise.all([
${names.map((name) => `download("${name}")`).join(",\n ")},
])

async function download(name: string) {
return $metadata.decode(
U.hex.decodeBuf((await Deno.readFile(new URL(\`./$\{name}.scale\`, import.meta.url))).slice(2)),
)
}
`
Deno.writeTextFileSync(modFilePath, modFileContents, { create: true })

U.throwIfError(await Z.ls(...Object.entries(C.knownClients).map(download)).run())

function download<Name extends Z.$<string>, Client extends Z.$<C.rpc.Client>>(
Expand All @@ -14,7 +36,7 @@ function download<Name extends Z.$<string>, Client extends Z.$<C.rpc.Client>>(
return Z.ls(...entry).next(async ([name, client]) => {
try {
const metadataHex = U.throwIfError(await C.state.getMetadata(client)().run())
const outPath = path.join(outDir, `${name}.scale`)
const outPath = new URL(`_downloaded/${name}.scale`, outDir)
console.log(`Downloading ${name} metadata to "${outPath}".`)
await Deno.writeTextFile(outPath, metadataHex)
return
Expand Down
4 changes: 2 additions & 2 deletions codegen/codecs.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Codec } from "../deps/scale.ts"
import { assertEquals } from "../deps/std/testing/asserts.ts"
import * as M from "../frame_metadata/mod.ts"
import { DeriveCodec } from "../scale_info/mod.ts"
import * as testClients from "../test_util/clients/mod.ts"
import { InMemoryCache } from "./server/cache.ts"
import { LocalCapiCodegenServer } from "./server/local.ts"
Expand All @@ -21,7 +21,7 @@ for (const runtime of Object.keys(testClients)) {
`http://localhost:${port!}/@local/proxy/${chainUrl}/@${version}/codecs.ts`
)
server.abortController.abort()
const deriveCodec = M.DeriveCodec(metadata.tys)
const deriveCodec = DeriveCodec(metadata.tys)
const derivedCodecs = metadata.tys.map(deriveCodec)
const codegenCodecs = codegened._all
const origInspect = Codec.prototype["_inspect"]!
Expand Down
8 changes: 4 additions & 4 deletions codegen/genCodecs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as M from "../frame_metadata/mod.ts"
import { Ty, TyVisitor } from "../scale_info/mod.ts"
import { normalizeCase } from "../util/case.ts"
import { CodegenProps } from "./mod.ts"
import { S } from "./utils.ts"

export function genCodecs(props: CodegenProps, typeVisitor: M.TyVisitor<string>) {
export function genCodecs(props: CodegenProps, typeVisitor: TyVisitor<string>) {
const { tys } = props.metadata
const namespaceImports = new Set<string>()

Expand All @@ -13,7 +13,7 @@ import type * as types from "./types/mod.ts"

`

const visitor = new M.TyVisitor<string>(tys, {
const visitor = new TyVisitor<string>(tys, {
unitStruct(ty) {
return addCodecDecl(ty, "C.$null")
},
Expand Down Expand Up @@ -141,7 +141,7 @@ import type * as types from "./types/mod.ts"

return file

function addCodecDecl(ty: M.Ty, value: string) {
function addCodecDecl(ty: Ty, value: string) {
if (ty.path.length > 1) {
namespaceImports.add(ty.path[0]!)
}
Expand Down
13 changes: 7 additions & 6 deletions codegen/genMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import * as M from "../frame_metadata/mod.ts"
import { Metadata } from "../frame_metadata/mod.ts"
import { hex } from "../mod.ts"
import { Ty, TyVisitor, UnionTyDef } from "../scale_info/mod.ts"
import { normalizeCase } from "../util/case.ts"
import { Files } from "./Files.ts"
import { getRawCodecPath, makeDocComment, S } from "./utils.ts"

export function genMetadata(
metadata: M.Metadata,
typeVisitor: M.TyVisitor<string>,
metadata: Metadata,
typeVisitor: TyVisitor<string>,
files: Files,
) {
const { tys, extrinsic, pallets } = metadata

const isUnitVisitor = new M.TyVisitor<boolean>(tys, {
const isUnitVisitor = new TyVisitor<boolean>(tys, {
unitStruct: () => true,
wrapperStruct(_, inner) {
return this.visit(inner)
Expand Down Expand Up @@ -68,7 +69,7 @@ import { $, C, client } from "../capi.ts"
)
}
if (pallet.calls) {
const ty = pallet.calls as M.Ty & M.UnionTyDef
const ty = pallet.calls as Ty & UnionTyDef
const isStringUnion = ty.members.every((x) => !x.fields.length)
for (const call of ty.members) {
const type = normalizeCase(call.name)
Expand Down Expand Up @@ -130,7 +131,7 @@ const _extrinsic = ${
export const extrinsic = C.extrinsic<typeof client, ${typeVisitor.visit(callTy!)}>(client);
`)

function getExtrasCodec(xs: [string, M.Ty][]) {
function getExtrasCodec(xs: [string, Ty][]) {
return S.array(
xs.filter((x) => !isUnitVisitor.visit(x[1])).map((x) => getRawCodecPath(x[1])),
)
Expand Down
4 changes: 2 additions & 2 deletions codegen/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export abstract class CodegenServer {
))
}

filesMemo = new Map<C.M.Metadata, Files>()
filesMemo = new Map<C.frame.Metadata, Files>()
async files(chainUrl: string, version: string, chainVersion: string) {
const metadata = await this.metadata(chainUrl, chainVersion)
return U.getOrInit(this.filesMemo, metadata, () => {
Expand Down Expand Up @@ -415,7 +415,7 @@ export const client = C.rpcClient(C.rpc.proxyProvider, ${JSON.stringify(chainUrl
}

metadata(chainUrl: string, version: string) {
return this.cache.get(`metadata/${chainUrl}/${version}`, C.M.$metadata, async () => {
return this.cache.get(`metadata/${chainUrl}/${version}`, C.frame.$metadata, async () => {
const client = this.client(chainUrl)
const [chainVersion, metadata] = U.throwIfError(
await C.Z.ls(
Expand Down
22 changes: 11 additions & 11 deletions codegen/typeVisitor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { posix as pathPosix } from "../deps/std/path.ts"
import * as M from "../frame_metadata/mod.ts"
import { Ty, TyVisitor, TyVisitorMethods } from "../scale_info/mod.ts"
import { normalizeCase } from "../util/case.ts"
import { getOrInit } from "../util/mod.ts"
import { Files } from "./Files.ts"
Expand All @@ -8,19 +8,19 @@ import { makeDocComment, S } from "./utils.ts"

class TypeFile {
reexports = new Set<string>()
types = new Map<string, M.Ty>()
types = new Map<string, Ty>()
get ext() {
return this.reexports.size ? "/mod.ts" : ".ts"
}
}

export function createTypeVisitor(props: CodegenProps, files: Files) {
const { tys } = props.metadata
const paths = new Map<M.Ty, string | null>()
const paths = new Map<Ty, string | null>()
const typeFiles = new Map<string, TypeFile>()
addPath("types.Compact", { type: "Compact" } as M.Ty)
addPath("types.Compact", { type: "Compact" } as Ty)

const visitor = new M.TyVisitor<string>(tys, {
const visitor = new TyVisitor<string>(tys, {
unitStruct(_ty) {
return "null"
},
Expand Down Expand Up @@ -127,7 +127,7 @@ export function createTypeVisitor(props: CodegenProps, files: Files) {

return visitor

function getPath(ty: M.Ty): string | null {
function getPath(ty: Ty): string | null {
return getOrInit(paths, ty, () => {
if (
ty.type === "Struct" && ty.fields.length === 1 && ty.params.some((x) => x.ty !== undefined)
Expand All @@ -142,7 +142,7 @@ export function createTypeVisitor(props: CodegenProps, files: Files) {
return path
})

function _getPath(ty: M.Ty): string | null {
function _getPath(ty: Ty): string | null {
if (ty.type === "Primitive") {
return (ty.kind === "bool" || ty.kind === "str" ? null : ty.kind)
}
Expand Down Expand Up @@ -182,7 +182,7 @@ export function createTypeVisitor(props: CodegenProps, files: Files) {
}
}

function addPath(path: string, ty: M.Ty) {
function addPath(path: string, ty: Ty) {
let pair = split(path.replace(/\./g, "/"))
if (!pair) throw new Error("addPath called with orphan")
getOrInit(typeFiles, pair[0], () => new TypeFile()).types.set(path, ty)
Expand All @@ -197,11 +197,11 @@ export function createTypeVisitor(props: CodegenProps, files: Files) {
}
}

function createTypeDecl(path: string, ty: M.Ty) {
function createTypeDecl(path: string, ty: Ty) {
const name = path.slice(path.lastIndexOf(".") + 1)
const docs = makeDocComment(ty.docs)

const fallback = (key: keyof M.TyVisitorMethods<string>) => (...args: any) => {
const fallback = (key: keyof TyVisitorMethods<string>) => (...args: any) => {
return `\
${docs}
export type ${name} = ${(visitor[key] as any)!(...args)}
Expand All @@ -214,7 +214,7 @@ export const $${name[0]!.toLowerCase()}${name.slice(1)}: $.Codec<${
}> = codecs.$${ty.id}
`

return codec + new M.TyVisitor<string>(tys, {
return codec + new TyVisitor<string>(tys, {
unitStruct() {
return `\
${docs}
Expand Down
4 changes: 2 additions & 2 deletions codegen/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as M from "../frame_metadata/mod.ts"
import { Ty } from "../scale_info/mod.ts"

export namespace S {
export function array(items: string[]): string {
Expand All @@ -22,6 +22,6 @@ export function makeDocComment(docs: string[] = []) {
return `/**\n * ${docs.join("\n * ")}\n */\n`
}

export function getRawCodecPath(ty: M.Ty) {
export function getRawCodecPath(ty: Ty) {
return `codecs.$${ty.id}`
}
38 changes: 16 additions & 22 deletions effects/contracts/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import * as Z from "../../deps/zones.ts"
import {
$contractsApiCallArgs,
$contractsApiCallResult,
ContractMetadata,
} from "../../frame_metadata/Contract.ts"
import { DeriveCodec, MultiAddress } from "../../frame_metadata/mod.ts"
Message as InkMessage,
Metadata as InkMetadata,
} from "../../ink_metadata/mod.ts"
import { MultiAddress } from "../../primitives/mod.ts"
import { Client } from "../../rpc/mod.ts"
import { DeriveCodec } from "../../scale_info/mod.ts"
import * as U from "../../util/mod.ts"
import { extrinsic } from "../extrinsic.ts"
import { state } from "../rpc_known_methods.ts"

export interface CallProps {
sender: MultiAddress
contractAddress: Uint8Array
contractMetadata: ContractMetadata
message: ContractMetadata.Message
inkMetadata: InkMetadata
message: InkMessage
args: any[]
}

Expand All @@ -24,11 +26,11 @@ export function call<Client_ extends Z.Effect<Client>>(client: Client_) {
const {
sender,
contractAddress,
contractMetadata,
inkMetadata,
message,
args,
} = _props as Z.Rec$Access<Props>
const $message_ = $message(contractMetadata, message)
const $message_ = $message(inkMetadata, message)
const data = Z.ls($message_, message, args).next(([{ $args }, { selector }, args]) =>
$args.encode([U.hex.decode(selector), ...args])
)
Expand All @@ -48,22 +50,17 @@ export interface CallTxProps {
sender: MultiAddress
contractAddress: Uint8Array
value?: bigint
contractMetadata: ContractMetadata
message: ContractMetadata.Message
inkMetadata: InkMetadata
message: InkMessage
args: any[]
}

export function callTx<Client_ extends Z.Effect<Client>>(client: Client_) {
return <Props extends Z.Rec$<CallTxProps>>(_props: Props) => {
const {
sender,
contractAddress,
value,
contractMetadata,
message,
args,
} = _props as Z.Rec$Access<Props>
const $message_ = $message(contractMetadata, message)
const { sender, contractAddress, value, inkMetadata, message, args } = _props as Z.Rec$Access<
Props
>
const $message_ = $message(inkMetadata, message)
const data = Z.ls($message_, message, args).next(([{ $args }, { selector }, args]) =>
$args.encode([U.hex.decode(selector), ...args])
)
Expand Down Expand Up @@ -128,10 +125,7 @@ interface MessageCodecs {
$result: $.Codec<any>
}

function $message(
metadata: Z.$<ContractMetadata>,
message: Z.$<ContractMetadata.Message>,
): Z.$<MessageCodecs> {
function $message(metadata: Z.$<InkMetadata>, message: Z.$<InkMessage>): Z.$<MessageCodecs> {
return Z.ls(metadata, message).next(([metadata, message]) => {
const deriveCodec = DeriveCodec(metadata.V3.types)
return {
Expand Down
40 changes: 20 additions & 20 deletions effects/contracts/events.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import * as $ from "../../deps/scale.ts"
import * as Z from "../../deps/zones.ts"
import { ContractMetadata, DeriveCodec } from "../../frame_metadata/mod.ts"
import { Metadata as InkMetadata } from "../../ink_metadata/mod.ts"
import { DeriveCodec } from "../../scale_info/mod.ts"
import { ExtrinsicEvent } from "../events.ts"

export function events(
contractMetadata: Z.$<ContractMetadata>,
events: Z.$<ExtrinsicEvent[]>,
) {
const $events = Z.ls(contractMetadata).next(([contractMetadata]) => {
return $.taggedUnion(
"type",
contractMetadata.V3.spec.events
.map((e) => [
e.label,
[
"value",
$.tuple(...e.args.map((a) => DeriveCodec(contractMetadata.V3.types)(a.type.type))),
],
]),
export function events(inkMetadata: Z.$<InkMetadata>, events: Z.$<ExtrinsicEvent[]>) {
const $events = Z
.ls(inkMetadata)
.next(([inkMetadata]) =>
$.taggedUnion(
"type",
inkMetadata.V3.spec.events
.map((e) => [
e.label,
[
"value",
$.tuple(...e.args.map((a) => DeriveCodec(inkMetadata.V3.types)(a.type.type))),
],
]),
)
)
})
return Z.ls(events, $events).next(([events, $events]) => {
return events
return Z.ls(events, $events).next(([events, $events]) =>
events
.filter((e) => e.event?.type === "Contracts" && e.event?.value?.type === "ContractEmitted")
.map((e) => $events.decode(e.event?.value.data))
})
)
}
Loading