-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathregistration.ts
64 lines (50 loc) · 2.58 KB
/
registration.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import type { Layout } from "@wormhole-foundation/sdk-base";
import type { WormholeRegistry } from "../registry.js";
import type { ProtocolName } from "../protocol.js";
// //LayoutLiteralToLayoutMapping is the compile-time analog/complement to the runtime
// // payload factory. It uses TypeScript's interface merging mechanic to "dynamically" extend known
// // payload types that are declared in different protocols. This allows us to have full type safety
// // when constructing payloads via the factory without having to ever declare the mapping of all
// // payloads and their respective layouts in a single place (which, besides being a terrible code
// // smell, would also prevent users of the SDK from registering their own payload types!)
// export namespace WormholeRegistry {
// //effective type: Record<string, Layout>
// export interface PayloadLiteralToLayoutMapping {}
// }
export type LayoutLiteral = keyof WormholeRegistry.PayloadLiteralToLayoutMapping & string;
export type PayloadLiteral = LayoutLiteral | "Uint8Array";
export type LayoutOf<LL extends LayoutLiteral> = LL extends infer V extends LayoutLiteral
? WormholeRegistry.PayloadLiteralToLayoutMapping[V]
: never;
type ToLiteralFormat<PN extends ProtocolName, PayloadName extends string> = PN extends null
? PayloadName
: `${PN}:${PayloadName}`;
export type ComposeLiteral<
ProtocolN extends ProtocolName,
PayloadN extends string,
Literal,
> = ToLiteralFormat<ProtocolN, PayloadN> extends infer L extends Literal ? L : never;
export const composeLiteral = <ProtocolN extends ProtocolName, PayloadN extends string>(
protocol: ProtocolN,
payloadName: PayloadN,
) =>
(protocol ? `${protocol}:${payloadName}` : payloadName) as ComposeLiteral<
ProtocolN,
PayloadN,
PayloadLiteral
>;
export const payloadFactory = new Map<LayoutLiteral, Layout>();
export function registerPayloadType(protocol: ProtocolName, name: string, layout: Layout) {
const payloadLiteral = composeLiteral(protocol, name);
if (payloadFactory.has(payloadLiteral))
throw new Error(`Payload type ${payloadLiteral} already registered`);
payloadFactory.set(payloadLiteral, layout);
}
type AtLeast1<T> = readonly [T, ...T[]];
export type NamedPayloads = AtLeast1<readonly [string, Layout]>;
export type RegisterPayloadTypes<ProtocolN extends ProtocolName, NP extends NamedPayloads> = {
readonly [E in NP[number] as ToLiteralFormat<ProtocolN, E[0]>]: E[1];
};
export function registerPayloadTypes(protocol: ProtocolName, payloads: NamedPayloads) {
for (const [name, layout] of payloads) registerPayloadType(protocol, name, layout);
}