-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
idl.ts
156 lines (152 loc) · 4.5 KB
/
idl.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import camelCase from "camelcase";
import { Layout } from "buffer-layout";
import * as borsh from "@project-serum/borsh";
import { IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../../idl.js";
import { IdlError } from "../../error.js";
export class IdlCoder {
public static fieldLayout(
field: { name?: string } & Pick<IdlField, "type">,
types?: IdlTypeDef[]
): Layout {
const fieldName =
field.name !== undefined ? camelCase(field.name) : undefined;
switch (field.type) {
case "bool": {
return borsh.bool(fieldName);
}
case "u8": {
return borsh.u8(fieldName);
}
case "i8": {
return borsh.i8(fieldName);
}
case "u16": {
return borsh.u16(fieldName);
}
case "i16": {
return borsh.i16(fieldName);
}
case "u32": {
return borsh.u32(fieldName);
}
case "i32": {
return borsh.i32(fieldName);
}
case "f32": {
return borsh.f32(fieldName);
}
case "u64": {
return borsh.u64(fieldName);
}
case "i64": {
return borsh.i64(fieldName);
}
case "f64": {
return borsh.f64(fieldName);
}
case "u128": {
return borsh.u128(fieldName);
}
case "i128": {
return borsh.i128(fieldName);
}
case "bytes": {
return borsh.vecU8(fieldName);
}
case "string": {
return borsh.str(fieldName);
}
case "publicKey": {
return borsh.publicKey(fieldName);
}
default: {
if ("vec" in field.type) {
return borsh.vec(
IdlCoder.fieldLayout(
{
name: undefined,
type: field.type.vec,
},
types
),
fieldName
);
} else if ("option" in field.type) {
return borsh.option(
IdlCoder.fieldLayout(
{
name: undefined,
type: field.type.option,
},
types
),
fieldName
);
} else if ("defined" in field.type) {
const defined = field.type.defined;
// User defined type.
if (types === undefined) {
throw new IdlError("User defined types not provided");
}
const filtered = types.filter((t) => t.name === defined);
if (filtered.length !== 1) {
throw new IdlError(`Type not found: ${JSON.stringify(field)}`);
}
return IdlCoder.typeDefLayout(filtered[0], types, fieldName);
} else if ("array" in field.type) {
let arrayTy = field.type.array[0];
let arrayLen = field.type.array[1];
let innerLayout = IdlCoder.fieldLayout(
{
name: undefined,
type: arrayTy,
},
types
);
return borsh.array(innerLayout, arrayLen, fieldName);
} else {
throw new Error(`Not yet implemented: ${field}`);
}
}
}
}
public static typeDefLayout(
typeDef: IdlTypeDef,
types: IdlTypeDef[] = [],
name?: string
): Layout {
if (typeDef.type.kind === "struct") {
const fieldLayouts = typeDef.type.fields.map((field) => {
const x = IdlCoder.fieldLayout(field, types);
return x;
});
return borsh.struct(fieldLayouts, name);
} else if (typeDef.type.kind === "enum") {
let variants = typeDef.type.variants.map((variant: IdlEnumVariant) => {
const name = camelCase(variant.name);
if (variant.fields === undefined) {
return borsh.struct([], name);
}
const fieldLayouts = variant.fields.map((f: IdlField | IdlType) => {
if (!f.hasOwnProperty("name")) {
throw new Error("Tuple enum variants not yet implemented.");
}
// this typescript conversion is ok
// because if f were of type IdlType
// (that does not have a name property)
// the check before would've errored
return IdlCoder.fieldLayout(f as IdlField, types);
});
return borsh.struct(fieldLayouts, name);
});
if (name !== undefined) {
// Buffer-layout lib requires the name to be null (on construction)
// when used as a field.
return borsh.rustEnum(variants).replicate(name);
}
return borsh.rustEnum(variants, name);
} else {
throw new Error(`Unknown type kint: ${typeDef}`);
}
}
}