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

chore: misc effect cleanup #366

Merged
merged 4 commits into from
Nov 8, 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
4 changes: 2 additions & 2 deletions effects/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as Z from "../deps/zones.ts";
import * as rpc from "../rpc/mod.ts";
import * as U from "../util/mod.ts";
import { codec } from "./core/codec.ts";
import { decoded } from "./core/decoded.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import * as e$ from "./core/scale.ts";
import { constMetadata, metadata, palletMetadata } from "./metadata.ts";

export function const_<Client extends Z.$<rpc.Client>>(client: Client) {
Expand All @@ -23,7 +23,7 @@ export function const_<Client extends Z.$<rpc.Client>>(client: Client) {
const entryValueTypeI = constMetadata_.access("ty").access("id");
const constValue = constMetadata_.access("value");
const $const = codec(deriveCodec_, entryValueTypeI);
return decoded($const, constValue, "value").zoned("Const");
return e$.decoded($const, constValue, "value").zoned("Const");
};
}
Object.defineProperty(const_, "name", {
Expand Down
14 changes: 0 additions & 14 deletions effects/core/$key.ts

This file was deleted.

19 changes: 0 additions & 19 deletions effects/core/decoded.ts

This file was deleted.

5 changes: 0 additions & 5 deletions effects/core/hex.ts

This file was deleted.

11 changes: 11 additions & 0 deletions effects/core/option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as Z from "../../deps/zones.ts";

// TODO: move this into zones
export function option<Target, UseResult>(
target: Target,
use: (resolved: NonNullable<Z.T<Target>>) => UseResult,
): Z.Effect<undefined | Exclude<UseResult, Error>, Z.E<Target> | Extract<UseResult, Error>> {
return Z.call(target, (resolved) => {
return resolved ? use(resolved) : undefined;
});
}
35 changes: 35 additions & 0 deletions effects/core/scale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as $ from "../../deps/scale.ts";
import * as Z from "../../deps/zones.ts";

export function decoded<
Codec extends Z.$<$.Codec<unknown>>,
Encoded extends Z.$<Uint8Array>,
Key extends Z.$<PropertyKey>,
>(
codec: Codec,
encoded: Encoded,
key: Key,
) {
return Z.call(
Z.ls(codec, encoded, key),
function decodedImpl([codec, encoded, key]): Record<Z.T<Key>, any> {
return { [key]: codec.decode(encoded) } as any;
},
);
}

// TODO: eventually, utilize `V` to toggle runtime validation
export function encoded<Codec extends Z.$<$.Codec<any>>, Decoded>(
codec: Codec,
decoded: Decoded,
isAsync?: boolean,
) {
return Z.call(Z.ls(codec, decoded, isAsync), function encodedImpl([codec, decoded]) {
try {
$.assert(codec, decoded);
} catch (e) {
return e as $.ScaleAssertError;
}
return codec[isAsync ? "encodeAsync" : "encode"](decoded);
});
}
10 changes: 0 additions & 10 deletions effects/core/storageKey.ts

This file was deleted.

11 changes: 5 additions & 6 deletions effects/entryRead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import * as rpc from "../rpc/mod.ts";
import * as U from "../util/mod.ts";
import { $storageKey } from "./core/$storageKey.ts";
import { codec } from "./core/codec.ts";
import { decoded } from "./core/decoded.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import { hexDecode } from "./core/hex.ts";
import { storageKey } from "./core/storageKey.ts";
import * as e$ from "./core/scale.ts";
import { entryMetadata, metadata, palletMetadata } from "./metadata.ts";
import { state } from "./rpc/known.ts";

Expand All @@ -27,10 +25,11 @@ export function entryRead<Client extends Z.$<rpc.Client>>(client: Client) {
const palletMetadata_ = palletMetadata(metadata_, palletName);
const entryMetadata_ = entryMetadata(palletMetadata_, entryName);
const $storageKey_ = $storageKey(deriveCodec_, palletMetadata_, entryMetadata_);
const storageKey_ = storageKey($storageKey_, ...keys);
const storageValueHex = state.getStorage(client)(storageKey_, blockHash);
const storageKey = Z.call(e$.encoded($storageKey_, Z.ls(...keys)), U.hex.encode);
const storageBytesHex = state.getStorage(client)(storageKey, blockHash);
const storageBytes = Z.call(storageBytesHex, U.hex.decode);
const entryValueTypeI = entryMetadata_.access("value");
const $entry = codec(deriveCodec_, entryValueTypeI);
return decoded($entry, hexDecode(storageValueHex), "value").zoned("EntryRead");
return e$.decoded($entry, storageBytes, "value").zoned("EntryRead");
};
}
17 changes: 11 additions & 6 deletions effects/entryWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import * as U from "../util/mod.ts";
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 * as e$ from "./core/scale.ts";
import { entryMetadata, metadata, palletMetadata } from "./metadata.ts";
import { state } from "./rpc/known.ts";

export type WatchEntryEvent = [key?: U.Hex, value?: unknown];
export type WatchEntryEvent = [key?: unknown, value?: unknown];

export function entryWatch<Client extends Z.$<rpc.Client>>(client: Client) {
return <
Expand All @@ -30,18 +30,23 @@ export function entryWatch<Client extends Z.$<rpc.Client>>(client: Client) {
const entryValueTypeI = entryMetadata_.access("value");
const $entry = codec(deriveCodec_, entryValueTypeI);
const storageKeys = Z.call(
storageKey($storageKey_, ...keys.length ? [keys] : []),
function wrapWithList(v) {
return [v];
e$.encoded($storageKey_, keys.length ? [keys] : []),
function hexEncodeAndWrapWithList(v) {
return [U.hex.encode(v)];
},
);
const listenerMapped = Z.call(Z.ls($entry, listener), ([$entry, listener]) => {
return function listenerMapped(
this: rpc.ClientSubscribeContext,
changeset: known.StorageChangeSet,
) {
// TODO: in some cases there might be keys to decode
// key ? $storageKey.decode(U.hex.decode(key)) : undefined
const getKey = (key: known.Hex) => {
return key;
};
const changes: WatchEntryEvent[] = changeset.changes.map(([key, val]) => {
return [key, val ? $entry.decode(U.hex.decode(val)) : undefined];
return [getKey(key), val ? $entry.decode(U.hex.decode(val)) : undefined];
});
listener.apply(this, [changes]);
};
Expand Down
110 changes: 40 additions & 70 deletions effects/extrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import * as U from "../util/mod.ts";
import { const as const_ } from "./const.ts";
import { $extrinsic } from "./core/$extrinsic.ts";
import { deriveCodec } from "./core/deriveCodec.ts";
import { hexDecode } from "./core/hex.ts";
import { option } from "./core/option.ts";
import * as e$ from "./core/scale.ts";
import { metadata } from "./metadata.ts";
import { author, chain, system } from "./rpc/known.ts";

Expand Down Expand Up @@ -43,19 +44,22 @@ export class SignedExtrinsic<
Props extends Z.Rec$<ExtrinsicProps>,
Sign extends Z.$<M.SignExtrinsic>,
> {
props;
extrinsic;

constructor(readonly props_: Props, readonly sign: Sign) {
const props = props_ as Z.Rec$Access<Props>;
const metadata_ = metadata(props.client)();
constructor(props_: Props, readonly sign: Sign) {
this.props = props_ as Z.Rec$Access<Props>;
const metadata_ = metadata(this.props.client)();
const deriveCodec_ = deriveCodec(metadata_);
const addrPrefix = const_(props.client)("System", "SS58Prefix").access("value").as<number>();
const addrPrefix = const_(this.props.client)("System", "SS58Prefix")
.access("value").as<number>();
const $extrinsic_ = $extrinsic(deriveCodec_, metadata_, this.sign, addrPrefix);
const versions = const_(props.client)("System", "Version").access("value");
const versions = const_(this.props.client)("System", "Version").access("value");
const specVersion = versions.access("spec_version").as<number>();
const transactionVersion = versions.access("transaction_version").as<number>();
// TODO: create match effect in zones and use here
const senderSs58 = Z.call(
Z.ls(addrPrefix, props.sender),
Z.ls(addrPrefix, this.props.sender),
function senderSs58([addrPrefix, sender]) {
switch (sender.type) {
case "Id": {
Expand All @@ -68,79 +72,45 @@ export class SignedExtrinsic<
}
},
);
const nonce = system.accountNextIndex(props.client)(senderSs58);
const genesisHash = hexDecode(chain.getBlockHash(props.client)(0));
const checkpointHash = props.checkpoint
? Z.call(props.checkpoint, function checkpointOrUndef(v) {
return v ? U.hex.decode(v) : v;
})
const nonce = system.accountNextIndex(this.props.client)(senderSs58);
const genesisHashBytes = chain.getBlockHash(this.props.client)(0);
const genesisHash = Z.call(genesisHashBytes, U.hex.decode);
const checkpointHash = this.props.checkpoint
? option(this.props.checkpoint, U.hex.decode)
: genesisHash;
this.extrinsic = Z.call(
Z.ls(
$extrinsic_,
props.sender,
props.methodName,
props.palletName,
specVersion,
transactionVersion,
nonce,
genesisHash,
props.args,
checkpointHash,
props.tip,
props.mortality,
),
async function formExtrinsicHex([
$extrinsic,
sender,
methodName,
palletName,
specVersion,
transactionVersion,
nonce,
genesisHash,
args,
checkpoint,
tip,
mortality,
]) {
const extrinsicBytes = await $extrinsic.encodeAsync({
protocolVersion: 4, // TODO: grab this from elsewhere
palletName,
methodName,
args,
signature: {
address: sender,
extra: [
mortality
? {
type: "Mortal",
value: mortality,
}
: { type: "Immortal" },
nonce,
tip || 0,
],
additional: [specVersion, transactionVersion, checkpoint, genesisHash],
},
});
return U.hex.encode(extrinsicBytes);
},
);
const $extrinsicProps = Z.rec({
protocolVersion: 4,
palletName: this.props.palletName,
methodName: this.props.methodName,
args: this.props.args,
signature: Z.rec({
address: this.props.sender,
extra: Z.ls(
this.props.mortality
? Z.rec({ type: "Mortal", value: this.props.mortality })
: { type: "Immortal" },
nonce,
this.props.tip || 0,
),
additional: Z.ls(specVersion, transactionVersion, checkpointHash, genesisHash),
}),
});
this.extrinsic = Z.call(e$.encoded($extrinsic_, $extrinsicProps, true), U.hex.encode);
}

watch<Listener extends Z.$<U.Listener<known.TransactionStatus, rpc.ClientSubscribeContext>>>(
listener: Listener,
) {
const subscriptionId = author.submitAndWatchExtrinsic(
this.props_.client as Props["client"],
)([this.extrinsic], listener);
return author.unwatchExtrinsic(this.props_.client as Props["client"])(subscriptionId)
const subscriptionId = author.submitAndWatchExtrinsic(this.props.client)(
[this.extrinsic],
listener,
);
return author.unwatchExtrinsic(this.props.client)(subscriptionId)
.zoned("ExtrinsicWatch");
}

get sent() {
return author.submitExtrinsic(this.props_.client as Props["client"])(this.extrinsic)
return author.submitExtrinsic(this.props.client)(this.extrinsic)
.zoned("ExtrinsicSent");
}
}
19 changes: 8 additions & 11 deletions effects/keyPageRead.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as Z from "../deps/zones.ts";
import * as rpc from "../rpc/mod.ts";
import * as U from "../util/mod.ts";
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 * as e$ from "./core/scale.ts";
import { mapMetadata, metadata, palletMetadata } from "./metadata.ts";
import { state } from "./rpc/known.ts";

Expand All @@ -25,22 +24,20 @@ export function keyPageRead<Client extends Z.$<rpc.Client>>(client: Client) {
const palletMetadata_ = palletMetadata(metadata_, palletName);
const entryMetadata_ = mapMetadata(palletMetadata_, entryName);
const $storageKey_ = $storageKey(deriveCodec_, palletMetadata_, entryMetadata_);
const startKey = start ? storageKey($storageKey_, start) : undefined;
const storageKey_ = storageKey($storageKey_);
const storageKey = Z.call(e$.encoded($storageKey_, []), U.hex.encode);
const startKey = start ? Z.call(e$.encoded($storageKey_, []), U.hex.encode) : undefined;
const keysEncoded = state.getKeysPaged(client)(
storageKey_,
storageKey,
count,
startKey,
blockHash as Rest[1],
);
const $key_ = $key(deriveCodec_, palletMetadata_, entryMetadata_);
return Z.call(
Z.ls($key_, keysEncoded),
function keysDecodedImpl([$key, keysEncoded]) {
return Z
.call(Z.ls($storageKey_, keysEncoded), function keysDecodedImpl([$key, keysEncoded]) {
return keysEncoded.map((keyEncoded: U.Hex) => {
return $key.decode(U.hex.decode(keyEncoded));
});
},
).zoned("KeyPageRead");
})
.zoned("KeyPageRead");
};
}
1 change: 1 addition & 0 deletions effects/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as rpc from "../rpc/mod.ts";
import * as U from "../util/mod.ts";
import { state } from "./rpc/known.ts";

// TODO: callable object so that one doesn't need the extra parens when not specifying block hash?
export function metadata<Client extends Z.$<rpc.Client>>(client: Client) {
return <Rest extends [blockHash?: Z.$<U.HexHash | undefined>]>(...[blockHash]: [...Rest]) => {
return Z.call(
Expand Down