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

chore: cleanup to metadata and extrinsic effect apis #312

Merged
merged 4 commits into from
Oct 22, 2022
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
6 changes: 3 additions & 3 deletions effect/EntryRead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { codec } from "./core/codec.ts";
import { decoded } from "./core/decoded.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import { storageKey } from "./core/storageKey.ts";
import { entryMetadata, Metadata, palletMetadata } from "./Metadata.ts";
import { Metadata } from "./Metadata.ts";
import { RpcCall } from "./RpcCall.ts";

export class EntryRead<
Expand All @@ -27,8 +27,8 @@ export class EntryRead<
super();
const metadata_ = new Metadata(config, blockHash);
const deriveCodec_ = deriveCodec(metadata_);
const palletMetadata_ = palletMetadata(metadata_, palletName);
const entryMetadata_ = entryMetadata(palletMetadata_, entryName);
const palletMetadata_ = metadata_.pallet(palletName);
const entryMetadata_ = palletMetadata_.entry(entryName);
const $storageKey_ = $storageKey(deriveCodec_, palletMetadata_, entryMetadata_);
const storageKey_ = storageKey($storageKey_, ...keys);
const storageCall = new RpcCall(config, "state_getStorage", [storageKey_, blockHash]);
Expand Down
6 changes: 3 additions & 3 deletions effect/EntryWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { $storageKey } from "./core/$storageKey.ts";
import { codec } from "./core/codec.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import { storageKey } from "./core/storageKey.ts";
import { entryMetadata, Metadata, palletMetadata } from "./Metadata.ts";
import { Metadata } from "./Metadata.ts";
import { RpcCall } from "./RpcCall.ts";
import { RpcSubscription } from "./RpcSubscription.ts";

Expand All @@ -29,8 +29,8 @@ export class EntryWatch<
super();
const metadata_ = new Metadata(config);
const deriveCodec_ = deriveCodec(metadata_);
const palletMetadata_ = palletMetadata(metadata_, palletName);
const entryMetadata_ = entryMetadata(palletMetadata_, entryName);
const palletMetadata_ = metadata_.pallet(palletName);
const entryMetadata_ = palletMetadata_.entry(entryName);
const $storageKey_ = $storageKey(deriveCodec_, palletMetadata_, entryMetadata_);
const entryValueTypeI = Z.sel(entryMetadata_, "value");
const $entry = codec(deriveCodec_, entryValueTypeI);
Expand Down
74 changes: 64 additions & 10 deletions effect/ExtrinsicSentWatch.ts → effect/Extrinsic.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { unimplemented } from "../deps/std/testing/asserts.ts";
import * as Z from "../deps/zones.ts";
import * as M from "../frame_metadata/mod.ts";
import * as author from "../known/rpc/author.ts";
import { Config } from "../mod.ts";
import * as rpc from "../rpc/mod.ts";
import { NotifMessage } from "../rpc/mod.ts";
import * as ss58 from "../ss58/mod.ts";
import * as U from "../util/mod.ts";
import { $extrinsic } from "./core/$extrinsic.ts";
Expand All @@ -12,7 +13,7 @@ import { Metadata } from "./Metadata.ts";
import { RpcCall } from "./RpcCall.ts";
import { RpcSubscription } from "./RpcSubscription.ts";

export interface SendAndWatchExtrinsicProps {
export interface ExtrinsicProps {
sender: M.MultiAddress;
palletName: string;
methodName: string;
Expand All @@ -21,22 +22,35 @@ export interface SendAndWatchExtrinsicProps {
mortality?: [period: bigint, phase: bigint];
nonce?: string;
tip?: bigint;
sign: M.SignExtrinsic;
createWatchHandler: U.CreateWatchHandler<rpc.NotifMessage>;
}

export class ExtrinsicSentWatch<Props extends Z.Rec$<SendAndWatchExtrinsicProps>> extends Z.Name {
export class Extrinsic<Props extends Z.Rec$<ExtrinsicProps>> {
constructor(
readonly config: Config,
readonly props: Props,
) {}

signed<Sign extends Z.$<M.SignExtrinsic>>(sign: Sign): SignedExtrinsic<Props, Sign> {
return new SignedExtrinsic(this.config, this.props, sign);
}
}

export class SignedExtrinsic<
Props extends Z.Rec$<ExtrinsicProps>,
Sign extends Z.$<M.SignExtrinsic>,
> extends Z.Name {
root;

constructor(
readonly config: Config,
readonly props_: Props,
readonly sign: Sign,
) {
super();
const props = props_ as Z.Rec$Access<Props>;
const metadata_ = new Metadata(config);
const deriveCodec_ = deriveCodec(metadata_);
const $extrinsic_ = $extrinsic(deriveCodec_, metadata_, props.sign, config.addressPrefix);
const $extrinsic_ = $extrinsic(deriveCodec_, metadata_, this.sign, config.addressPrefix);
const runtimeVersion = new RpcCall(config, "state_getRuntimeVersion", []);
const senderSs58 = Z.call(props.sender, function senderSs58(sender) {
return ((): string => {
Expand All @@ -52,13 +66,15 @@ export class ExtrinsicSentWatch<Props extends Z.Rec$<SendAndWatchExtrinsicProps>
})();
});
const accountNextIndex = new RpcCall(config, "system_accountNextIndex", [senderSs58]);
const genesisHash = hexDecode(Z.sel(new RpcCall(config, "chain_getBlockHash", [0]), "result"));
const genesisHash = hexDecode(
Z.sel(new RpcCall(config, "chain_getBlockHash", [0]), "result"),
);
const checkpointHash = props.checkpoint
? Z.call(props.checkpoint, function checkpointOrUndef(v) {
return v ? U.hex.decode(v) : v;
})
: genesisHash;
const extrinsicHex = Z.call(
this.root = Z.call(
Z.ls(
$extrinsic_,
props.sender,
Expand Down Expand Up @@ -108,13 +124,51 @@ export class ExtrinsicSentWatch<Props extends Z.Rec$<SendAndWatchExtrinsicProps>
return U.hex.encode(extrinsicBytes);
},
);
}

watch<
WatchHandler extends U.CreateWatchHandler<NotifMessage<author.TransactionStatus>>,
>(watchHandler: WatchHandler): SignedExtrinsicWatch<this, WatchHandler> {
return new SignedExtrinsicWatch(this.config, this, watchHandler);
}

get sent(): SignedExtrinsicSent<this> {
return new SignedExtrinsicSent(this.config, this);
}
}

// TODO: is this really required? Why not use the RPC call effect directly?
export class SignedExtrinsicWatch<
SignedExtrinsic extends Z.$<U.Hex>,
WatchHandler extends U.CreateWatchHandler<NotifMessage<author.TransactionStatus>>,
> extends Z.Name {
root;

constructor(
readonly config: Config,
readonly signedExtrinsic: SignedExtrinsic,
readonly watchHandler: WatchHandler,
) {
super();
this.root = new RpcSubscription(
config,
"author_submitAndWatchExtrinsic",
[extrinsicHex],
props.createWatchHandler,
[signedExtrinsic],
watchHandler,
// TODO: use effect system for cbs such as this
(ok) => new RpcCall(config, "author_unwatchExtrinsic", [ok.result]),
);
}
}

export class SignedExtrinsicSent<SignedExtrinsic extends Z.$<U.Hex>> extends Z.Name {
root;

constructor(
readonly config: Config,
readonly signedExtrinsic: SignedExtrinsic,
) {
super();
this.root = new RpcCall(config, "author_submitExtrinsic", [signedExtrinsic]);
}
}
6 changes: 3 additions & 3 deletions effect/KeyPageRead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { $key } from "./core/$key.ts";
import { $storageKey } from "./core/$storageKey.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import { storageKey } from "./core/storageKey.ts";
import { entryMetadata, Metadata, palletMetadata } from "./Metadata.ts";
import { Metadata } from "./Metadata.ts";
import { RpcCall } from "./RpcCall.ts";

export class KeyPageRead<
Expand All @@ -26,9 +26,9 @@ export class KeyPageRead<
super();
const metadata_ = new Metadata(config, blockHash as Rest[1]);
const deriveCodec_ = deriveCodec(metadata_);
const palletMetadata_ = palletMetadata(metadata_, palletName);
const palletMetadata_ = metadata_.pallet(palletName);
const entryMetadata_ = Z.call(
entryMetadata(palletMetadata_, entryName),
palletMetadata_.entry(entryName),
function assertIsMap(entryMetadata) {
if (entryMetadata.type !== "Map") {
return new ReadingKeysOfNonMapError();
Expand Down
49 changes: 43 additions & 6 deletions effect/Metadata.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as $ from "../deps/scale.ts";
import * as Z from "../deps/zones.ts";
import * as M from "../frame_metadata/mod.ts";
import { Config } from "../mod.ts";
Expand All @@ -15,19 +16,55 @@ export class Metadata<Rest extends [blockHash?: Z.$<U.HexHash | undefined>]> ext
try {
return M.fromPrefixedHex(call.result);
} catch (e) {
return new MetadataDecodeError(e);
return e as $.CodecError;
}
},
);
}

pallet = <PalletName extends Z.$<string>>(palletName: PalletName) => {
return new PalletMetadata(this, palletName);
};
}

export const palletMetadata = Z.call.fac(M.getPallet);
export const entryMetadata = Z.call.fac(M.getEntry);
export class PalletMetadata<Metadata extends Z.$<M.Metadata>, PalletName extends Z.$<string>>
extends Z.Name
{
root;

export class MetadataDecodeError extends U.ErrorCtor("MetadataDecode") {
// TODO: replace with internal scale error & ensure appropriate trace info
constructor(readonly scaleError: unknown) {
constructor(
readonly metadata: Metadata,
readonly palletName: PalletName,
) {
super();
this.root = Z.call(
Z.ls(metadata, palletName),
function palletMetadataImpl([metadata, palletName]) {
return M.getPallet(metadata, palletName);
},
);
}

entry = <EntryName extends Z.$<string>>(entryName: EntryName) => {
return new EntryMetadata(this, entryName);
};
}

export class EntryMetadata<PalletMetadata extends Z.$<M.Pallet>, EntryName extends Z.$<string>>
extends Z.Name
{
root;

constructor(
readonly palletMetadata: PalletMetadata,
readonly entryName: EntryName,
) {
super();
this.root = Z.call(
Z.ls(palletMetadata, entryName),
function entryMetadataImpl([palletMetadata, entryName]) {
return M.getEntry(palletMetadata, entryName);
},
);
}
}
23 changes: 9 additions & 14 deletions effect/extrinsic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,29 +87,25 @@ Deno.test({

async function collectExtrinsicEvents(
config: C.Config,
{ palletName, methodName, args }: Pick<
C.SendAndWatchExtrinsicProps,
"palletName" | "methodName" | "args"
>,
{ palletName, methodName, args }: Omit<C.ExtrinsicProps, "sender">,
sender: KeyringPair,
): Promise<string[]> {
const extrinsicEvents: string[] = [];
// TODO: get rid of this `any`
const root = new C.ExtrinsicSentWatch(config as any, {
const root = new C.Extrinsic(config as any, {
sender: {
type: "Id",
value: sender.publicKey,
},
palletName,
methodName,
args,
sign(message) {
return {
type: "Sr25519",
value: sender.sign(message),
};
},
createWatchHandler(stop) {
})
.signed((message) => ({
type: "Sr25519",
value: sender.sign(message),
}))
.watch((stop) => {
return (event) => {
if (typeof event.params.result === "string") {
extrinsicEvents.push(event.params.result);
Expand All @@ -124,8 +120,7 @@ async function collectExtrinsicEvents(
}
}
};
},
});
});
U.throwIfError(await run(root));
return extrinsicEvents;
}
2 changes: 1 addition & 1 deletion effect/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export * from "./BlockRead.ts";
export * from "./BlockWatch.ts";
export * from "./EntryRead.ts";
export * from "./EntryWatch.ts";
export * from "./ExtrinsicSentWatch.ts";
export * from "./Extrinsic.ts";
export * from "./KeyPageRead.ts";
export * from "./Metadata.ts";
export * from "./RpcCall.ts";
Expand Down
12 changes: 6 additions & 6 deletions examples/polkadot_js_signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as C from "../mod.ts";
import * as T from "../test_util/mod.ts";
import * as U from "../util/mod.ts";

const root = new C.ExtrinsicSentWatch(T.westend, {
const root = new C.Extrinsic(T.westend, {
sender: {
type: "Id",
value: T.alice.publicKey,
Expand All @@ -17,7 +17,8 @@ const root = new C.ExtrinsicSentWatch(T.westend, {
value: T.bob.publicKey,
},
},
sign: {
})
.signed({
signPayload(payload) {
const tr = new TypeRegistry();
tr.setSignedExtensions(payload.signedExtensions);
Expand All @@ -27,8 +28,8 @@ const root = new C.ExtrinsicSentWatch(T.westend, {
.sign(T.alice),
);
},
},
createWatchHandler(stop) {
})
.watch((stop) => {
return (event) => {
if (typeof event.params.result === "string") {
console.log("Extrinsic", event.params.result);
Expand All @@ -44,7 +45,6 @@ const root = new C.ExtrinsicSentWatch(T.westend, {
}
}
};
},
});
});

U.throwIfError(await C.run(root));
18 changes: 8 additions & 10 deletions examples/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as C from "../mod.ts";
import * as T from "../test_util/mod.ts";
import * as U from "../util/mod.ts";

const root = new C.ExtrinsicSentWatch(T.westend, {
const root = new C.Extrinsic(T.westend, {
sender: {
type: "Id",
value: T.alice.publicKey,
Expand All @@ -16,13 +16,12 @@ const root = new C.ExtrinsicSentWatch(T.westend, {
value: T.bob.publicKey,
},
},
sign(message) {
return {
type: "Sr25519",
value: T.alice.sign(message),
};
},
createWatchHandler(stop) {
})
.signed((message) => ({
type: "Sr25519",
value: T.alice.sign(message),
}))
.watch((stop) => {
return (event) => {
if (typeof event.params.result === "string") {
console.log("Extrinsic", event.params.result);
Expand All @@ -38,7 +37,6 @@ const root = new C.ExtrinsicSentWatch(T.westend, {
}
}
};
},
});
});

U.throwIfError(await C.run(root));
Loading