@cubist-labs/cubesigner-sdk 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE +177 -0
- package/LICENSE-MIT +25 -0
- package/NOTICE +13 -0
- package/README.md +470 -0
- package/dist/examples/ethers.d.ts +1 -0
- package/dist/examples/ethers.js +142 -0
- package/dist/spec/env/beta.json +9 -0
- package/dist/spec/env/gamma.json +9 -0
- package/dist/spec/env/prod.json +9 -0
- package/dist/src/client.d.ts +10 -0
- package/dist/src/client.js +21 -0
- package/dist/src/env.d.ts +15 -0
- package/dist/src/env.js +35 -0
- package/dist/src/ethers/index.d.ts +50 -0
- package/dist/src/ethers/index.js +122 -0
- package/dist/src/index.d.ts +114 -0
- package/dist/src/index.js +205 -0
- package/dist/src/key.d.ts +114 -0
- package/dist/src/key.js +201 -0
- package/dist/src/mfa.d.ts +23 -0
- package/dist/src/mfa.js +63 -0
- package/dist/src/org.d.ts +161 -0
- package/dist/src/org.js +264 -0
- package/dist/src/role.d.ts +224 -0
- package/dist/src/role.js +256 -0
- package/dist/src/schema.d.ts +3049 -0
- package/dist/src/schema.js +7 -0
- package/dist/src/session/generic.d.ts +47 -0
- package/dist/src/session/generic.js +3 -0
- package/dist/src/session/management_session_manager.d.ts +59 -0
- package/dist/src/session/management_session_manager.js +111 -0
- package/dist/src/session/oidc_session_manager.d.ts +78 -0
- package/dist/src/session/oidc_session_manager.js +142 -0
- package/dist/src/session/session_manager.d.ts +74 -0
- package/dist/src/session/session_manager.js +79 -0
- package/dist/src/session/session_storage.d.ts +47 -0
- package/dist/src/session/session_storage.js +76 -0
- package/dist/src/session/signer_session_manager.d.ts +88 -0
- package/dist/src/session/signer_session_manager.js +159 -0
- package/dist/src/sign.d.ts +114 -0
- package/dist/src/sign.js +248 -0
- package/dist/src/signer_session.d.ts +180 -0
- package/dist/src/signer_session.js +369 -0
- package/dist/src/util.d.ts +35 -0
- package/dist/src/util.js +75 -0
- package/dist/test/sessions.d.ts +35 -0
- package/dist/test/sessions.js +56 -0
- package/package.json +61 -0
- package/src/client.ts +12 -0
- package/src/env.ts +25 -0
- package/src/ethers/index.ts +131 -0
- package/src/index.ts +220 -0
- package/src/key.ts +249 -0
- package/src/org.ts +333 -0
- package/src/role.ts +385 -0
- package/src/schema.ts +3054 -0
- package/src/session/management_session_manager.ts +136 -0
- package/src/session/oidc_session_manager.ts +193 -0
- package/src/session/session_manager.ts +114 -0
- package/src/session/session_storage.ts +73 -0
- package/src/session/signer_session_manager.ts +211 -0
- package/src/signer_session.ts +464 -0
- package/src/util.ts +58 -0
- package/tsconfig.json +32 -0
package/src/role.ts
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CubeSigner,
|
|
3
|
+
Key,
|
|
4
|
+
MfaType,
|
|
5
|
+
SignerSession,
|
|
6
|
+
SignerSessionInfo,
|
|
7
|
+
SignerSessionLifetime,
|
|
8
|
+
SignerSessionManager,
|
|
9
|
+
SignerSessionStorage,
|
|
10
|
+
} from ".";
|
|
11
|
+
import { components, paths } from "./client";
|
|
12
|
+
import { assertOk } from "./util";
|
|
13
|
+
|
|
14
|
+
type UpdateRoleRequest =
|
|
15
|
+
paths["/v0/org/{org_id}/keys/{key_id}"]["patch"]["requestBody"]["content"]["application/json"];
|
|
16
|
+
type KeyWithPoliciesInfo = components["schemas"]["KeyWithPolicies"];
|
|
17
|
+
export type RoleInfo = components["schemas"]["RoleInfo"];
|
|
18
|
+
|
|
19
|
+
/** Restrict transaction receiver.
|
|
20
|
+
* @example { TxReceiver: "0x8c594691c0e592ffa21f153a16ae41db5befcaaa" }
|
|
21
|
+
* */
|
|
22
|
+
export type TxReceiver = { TxReceiver: string };
|
|
23
|
+
|
|
24
|
+
/** The kind of deposit contracts. */
|
|
25
|
+
export enum DepositContract {
|
|
26
|
+
/** Canonical deposit contract */
|
|
27
|
+
Canonical, // eslint-disable-line no-unused-vars
|
|
28
|
+
/** Wrapper deposit contract */
|
|
29
|
+
Wrapper, // eslint-disable-line no-unused-vars
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Restrict transactions to calls to deposit contract. */
|
|
33
|
+
export type TxDeposit = TxDepositBase | TxDepositPubkey | TxDepositRole;
|
|
34
|
+
|
|
35
|
+
/** Restrict transactions to calls to deposit contract*/
|
|
36
|
+
export type TxDepositBase = { TxDeposit: { kind: DepositContract } };
|
|
37
|
+
|
|
38
|
+
/** Restrict transactions to calls to deposit contract with fixed validator (pubkey):
|
|
39
|
+
* @example { TxDeposit: { kind: DespositContract.Canonical, validator: { pubkey: "8879...8"} }}
|
|
40
|
+
* */
|
|
41
|
+
export type TxDepositPubkey = { TxDeposit: { kind: DepositContract; pubkey: string } };
|
|
42
|
+
|
|
43
|
+
/** Restrict transactions to calls to deposit contract with any validator key in a role:
|
|
44
|
+
* @example { TxDeposit: { kind: DespositContract.Canonical, validator: { role_id: "Role#c63...af"} }}
|
|
45
|
+
* */
|
|
46
|
+
export type TxDepositRole = { TxDeposit: { kind: DepositContract; role_id: string } };
|
|
47
|
+
|
|
48
|
+
/** All different kinds of sensitive operations. */
|
|
49
|
+
export enum OperationKind {
|
|
50
|
+
BlobSign = "BlobSign", // eslint-disable-line no-unused-vars
|
|
51
|
+
EvmSign = "Eth1Sign", // eslint-disable-line no-unused-vars
|
|
52
|
+
Eth2Sign = "Eth2Sign", // eslint-disable-line no-unused-vars
|
|
53
|
+
Eth2Stake = "Eth2Stake", // eslint-disable-line no-unused-vars
|
|
54
|
+
Eth2Unstake = "Eth2Unstake", // eslint-disable-line no-unused-vars
|
|
55
|
+
SolanaSign = "SolanaSign", // eslint-disable-line no-unused-vars
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Require MFA for transactions.
|
|
59
|
+
* @example {
|
|
60
|
+
* RequireMfa: {
|
|
61
|
+
* count: 1,
|
|
62
|
+
* allowed_mfa_types: [ "Totp" ],
|
|
63
|
+
* allowed_approvers: [ "User#123" ],
|
|
64
|
+
* restricted_operations: [
|
|
65
|
+
* "Eth1Sign",
|
|
66
|
+
* "BlobSign"
|
|
67
|
+
* ]
|
|
68
|
+
* }
|
|
69
|
+
* }
|
|
70
|
+
* */
|
|
71
|
+
export type RequireMfa = {
|
|
72
|
+
RequireMfa: {
|
|
73
|
+
count?: number;
|
|
74
|
+
restricted_operations?: OperationKind[];
|
|
75
|
+
allowed_approvers?: string[];
|
|
76
|
+
allowed_mfa_types?: MfaType[];
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/** Allow raw blob signing */
|
|
81
|
+
export type AllowRawBlobSigning = "AllowRawBlobSigning";
|
|
82
|
+
|
|
83
|
+
/** Key policy
|
|
84
|
+
* @example [
|
|
85
|
+
* {
|
|
86
|
+
* "TxReceiver": "0x8c594691c0e592ffa21f153a16ae41db5befcaaa"
|
|
87
|
+
* },
|
|
88
|
+
* {
|
|
89
|
+
* "TxDeposit": {
|
|
90
|
+
* "kind": "Canonical"
|
|
91
|
+
* }
|
|
92
|
+
* },
|
|
93
|
+
* {
|
|
94
|
+
* "RequireMfa": {
|
|
95
|
+
* "count": 1,
|
|
96
|
+
* "allowed_mfa_types": ["CubeSigner"],
|
|
97
|
+
* "restricted_operations": [
|
|
98
|
+
* "Eth1Sign",
|
|
99
|
+
* "BlobSign"
|
|
100
|
+
* ]
|
|
101
|
+
* }
|
|
102
|
+
* }
|
|
103
|
+
* ]
|
|
104
|
+
* */
|
|
105
|
+
export type KeyPolicy = (TxReceiver | TxDeposit | RequireMfa | AllowRawBlobSigning)[];
|
|
106
|
+
|
|
107
|
+
/** A key guarded by a policy. */
|
|
108
|
+
export class KeyWithPolicies {
|
|
109
|
+
readonly #cs: CubeSigner;
|
|
110
|
+
readonly #orgId: string;
|
|
111
|
+
readonly keyId: string;
|
|
112
|
+
readonly policy?: KeyPolicy;
|
|
113
|
+
|
|
114
|
+
/** @return {Promise<Key>} The key */
|
|
115
|
+
async getKey(): Promise<Key> {
|
|
116
|
+
return await Key.getKey(this.#cs, this.#orgId, this.keyId);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Constructor.
|
|
120
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
121
|
+
* @param {string} orgId The id of the organization to which the key belongs.
|
|
122
|
+
* @param {KeyWithPoliciesInfo} keyWithPolicies The key and its policies
|
|
123
|
+
* @internal
|
|
124
|
+
* */
|
|
125
|
+
constructor(cs: CubeSigner, orgId: string, keyWithPolicies: KeyWithPoliciesInfo) {
|
|
126
|
+
this.#cs = cs;
|
|
127
|
+
this.#orgId = orgId;
|
|
128
|
+
this.keyId = keyWithPolicies.key_id;
|
|
129
|
+
this.policy = keyWithPolicies.policy as unknown as KeyPolicy;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Roles. */
|
|
134
|
+
export class Role {
|
|
135
|
+
readonly #cs: CubeSigner;
|
|
136
|
+
readonly #orgId: string;
|
|
137
|
+
/** Human-readable name for the role */
|
|
138
|
+
public readonly name?: string;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The ID of the role.
|
|
142
|
+
* @example Role#bfe3eccb-731e-430d-b1e5-ac1363e6b06b
|
|
143
|
+
* */
|
|
144
|
+
readonly id: string;
|
|
145
|
+
|
|
146
|
+
/** Delete the role. */
|
|
147
|
+
async delete(): Promise<void> {
|
|
148
|
+
await Role.deleteRole(this.#cs, this.#orgId, this.id);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Is the role enabled? */
|
|
152
|
+
async enabled(): Promise<boolean> {
|
|
153
|
+
const data = await this.fetch();
|
|
154
|
+
return data.enabled;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Enable the role. */
|
|
158
|
+
async enable() {
|
|
159
|
+
await this.update({ enabled: true });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Disable the role. */
|
|
163
|
+
async disable() {
|
|
164
|
+
await this.update({ enabled: false });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** The list of users with access to the role.
|
|
168
|
+
* @example [
|
|
169
|
+
* "User#c3b9379c-4e8c-4216-bd0a-65ace53cf98f",
|
|
170
|
+
* "User#5593c25b-52e2-4fb5-b39b-96d41d681d82"
|
|
171
|
+
* ]
|
|
172
|
+
* */
|
|
173
|
+
async users(): Promise<string[]> {
|
|
174
|
+
const data = await this.fetch();
|
|
175
|
+
return data.users;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Add a user to the role.
|
|
179
|
+
* Adds an existing user to an existing role.
|
|
180
|
+
* @param {string} userId The user-id of the user to add to the role.
|
|
181
|
+
* */
|
|
182
|
+
async addUser(userId: string) {
|
|
183
|
+
const resp = await (
|
|
184
|
+
await this.#cs.management()
|
|
185
|
+
).put("/v0/org/{org_id}/roles/{role_id}/add_user/{user_id}", {
|
|
186
|
+
params: { path: { org_id: this.#orgId, role_id: this.id, user_id: userId } },
|
|
187
|
+
parseAs: "json",
|
|
188
|
+
});
|
|
189
|
+
assertOk(resp, "Failed to add user to role");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The list of keys in the role.
|
|
193
|
+
* @example [
|
|
194
|
+
* {
|
|
195
|
+
* id: "Key#bfe3eccb-731e-430d-b1e5-ac1363e6b06b",
|
|
196
|
+
* policy: { TxReceiver: "0x8c594691c0e592ffa21f153a16ae41db5befcaaa" }
|
|
197
|
+
* },
|
|
198
|
+
* ]
|
|
199
|
+
* */
|
|
200
|
+
async keys(): Promise<KeyWithPolicies[]> {
|
|
201
|
+
const data = await this.fetch();
|
|
202
|
+
return data.keys.map((k) => new KeyWithPolicies(this.#cs, this.#orgId, k));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Add keys to the role.
|
|
206
|
+
* Adds a list of existing keys to an existing role.
|
|
207
|
+
* @param {Key[]} keys The list of keys to add to the role.
|
|
208
|
+
* @param {KeyPolicy?} policy The optional policy to apply to each key.
|
|
209
|
+
* */
|
|
210
|
+
async addKeys(keys: Key[], policy?: KeyPolicy) {
|
|
211
|
+
const resp = await (
|
|
212
|
+
await this.#cs.management()
|
|
213
|
+
).put("/v0/org/{org_id}/roles/{role_id}/add_keys", {
|
|
214
|
+
params: { path: { org_id: this.#orgId, role_id: this.id } },
|
|
215
|
+
body: {
|
|
216
|
+
key_ids: keys.map((k) => k.id),
|
|
217
|
+
policy: (policy ?? null) as Record<string, never>[] | null,
|
|
218
|
+
},
|
|
219
|
+
parseAs: "json",
|
|
220
|
+
});
|
|
221
|
+
assertOk(resp, "Failed to add keys to role");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Add a key to the role.
|
|
225
|
+
* Adds an existing key to an existing role.
|
|
226
|
+
* @param {Key} key The key to add to the role.
|
|
227
|
+
* @param {KeyPolicy?} policy The optional policy to apply to the key.
|
|
228
|
+
* */
|
|
229
|
+
async addKey(key: Key, policy?: KeyPolicy) {
|
|
230
|
+
return await this.addKeys([key], policy);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Remove key from the role.
|
|
234
|
+
* Removes an existing key from an existing role.
|
|
235
|
+
* @param {Key} key The key to remove from the role.
|
|
236
|
+
* */
|
|
237
|
+
async removeKey(key: Key) {
|
|
238
|
+
const resp = await (
|
|
239
|
+
await this.#cs.management()
|
|
240
|
+
).del("/v0/org/{org_id}/roles/{role_id}/keys/{key_id}", {
|
|
241
|
+
params: { path: { org_id: this.#orgId, role_id: this.id, key_id: key.id } },
|
|
242
|
+
parseAs: "json",
|
|
243
|
+
});
|
|
244
|
+
assertOk(resp, "Failed to remove key from role");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Create a new session for this role.
|
|
249
|
+
* @param {SignerSessionStorage} storage The session storage to use
|
|
250
|
+
* @param {string} purpose Descriptive purpose.
|
|
251
|
+
* @param {SignerSessionLifetime} ttl Optional session lifetimes.
|
|
252
|
+
* @return {Promise<SignerSession>} New signer session.
|
|
253
|
+
*/
|
|
254
|
+
async createSession(
|
|
255
|
+
storage: SignerSessionStorage,
|
|
256
|
+
purpose: string,
|
|
257
|
+
ttl?: SignerSessionLifetime,
|
|
258
|
+
): Promise<SignerSession> {
|
|
259
|
+
const manager = await SignerSessionManager.create(
|
|
260
|
+
this.#cs,
|
|
261
|
+
storage,
|
|
262
|
+
this.#orgId,
|
|
263
|
+
this.id,
|
|
264
|
+
purpose,
|
|
265
|
+
ttl,
|
|
266
|
+
);
|
|
267
|
+
return new SignerSession(this.#cs, manager);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* List all signer sessions for this role. Returned objects can be used to
|
|
272
|
+
* revoke individual sessions, but they cannot be used for authentication.
|
|
273
|
+
* @return {Promise<SignerSessionInfo[]>} Signer sessions for this role.
|
|
274
|
+
*/
|
|
275
|
+
async sessions(): Promise<SignerSessionInfo[]> {
|
|
276
|
+
const resp = await (
|
|
277
|
+
await this.#cs.management()
|
|
278
|
+
).get("/v0/org/{org_id}/roles/{role_id}/tokens", {
|
|
279
|
+
params: { path: { org_id: this.#orgId, role_id: this.id } },
|
|
280
|
+
});
|
|
281
|
+
const data = assertOk(resp);
|
|
282
|
+
return data.tokens.map(
|
|
283
|
+
(t) => new SignerSessionInfo(this.#cs, this.#orgId, this.id, t.hash, t.purpose),
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// --------------------------------------------------------------------------
|
|
288
|
+
// -- INTERNAL --------------------------------------------------------------
|
|
289
|
+
// --------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
/** Create a new role.
|
|
292
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
293
|
+
* @param {string} orgId The id of the organization to which the role belongs.
|
|
294
|
+
* @param {RoleInfo} data The JSON response from the API server.
|
|
295
|
+
* @internal
|
|
296
|
+
* */
|
|
297
|
+
constructor(cs: CubeSigner, orgId: string, data: RoleInfo) {
|
|
298
|
+
this.#cs = cs;
|
|
299
|
+
this.#orgId = orgId;
|
|
300
|
+
this.id = data.role_id;
|
|
301
|
+
this.name = data.name ?? undefined;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Update the role.
|
|
305
|
+
* @param {UpdateRoleRequest} request The JSON request to send to the API server.
|
|
306
|
+
* */
|
|
307
|
+
private async update(request: UpdateRoleRequest): Promise<void> {
|
|
308
|
+
const resp = await (
|
|
309
|
+
await this.#cs.management()
|
|
310
|
+
).patch("/v0/org/{org_id}/roles/{role_id}", {
|
|
311
|
+
params: { path: { org_id: this.#orgId, role_id: this.id } },
|
|
312
|
+
body: request,
|
|
313
|
+
parseAs: "json",
|
|
314
|
+
});
|
|
315
|
+
assertOk(resp);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/** Create new role.
|
|
319
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
320
|
+
* @param {string} orgId The id of the organization to which the role belongs.
|
|
321
|
+
* @param {string?} name The optional name of the role.
|
|
322
|
+
* @return {Role} The new role.
|
|
323
|
+
* @internal
|
|
324
|
+
* */
|
|
325
|
+
static async createRole(cs: CubeSigner, orgId: string, name?: string): Promise<Role> {
|
|
326
|
+
const resp = await (
|
|
327
|
+
await cs.management()
|
|
328
|
+
).post("/v0/org/{org_id}/roles", {
|
|
329
|
+
params: { path: { org_id: orgId } },
|
|
330
|
+
body: name ? { name } : undefined,
|
|
331
|
+
parseAs: "json",
|
|
332
|
+
});
|
|
333
|
+
const data = assertOk(resp);
|
|
334
|
+
return await Role.getRole(cs, orgId, data.role_id);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Get a role by id.
|
|
338
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
339
|
+
* @param {string} orgId The id of the organization to which the role belongs.
|
|
340
|
+
* @param {string} roleId The id of the role to get.
|
|
341
|
+
* @return {Role} The role.
|
|
342
|
+
* @internal
|
|
343
|
+
* */
|
|
344
|
+
static async getRole(cs: CubeSigner, orgId: string, roleId: string): Promise<Role> {
|
|
345
|
+
const resp = await (
|
|
346
|
+
await cs.management()
|
|
347
|
+
).get("/v0/org/{org_id}/roles/{role_id}", {
|
|
348
|
+
params: { path: { org_id: orgId, role_id: roleId } },
|
|
349
|
+
parseAs: "json",
|
|
350
|
+
});
|
|
351
|
+
const data = assertOk(resp);
|
|
352
|
+
return new Role(cs, orgId, data);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Fetches the role information.
|
|
356
|
+
* @return {RoleInfo} The role information.
|
|
357
|
+
* @internal
|
|
358
|
+
* */
|
|
359
|
+
private async fetch(): Promise<RoleInfo> {
|
|
360
|
+
const resp = await (
|
|
361
|
+
await this.#cs.management()
|
|
362
|
+
).get("/v0/org/{org_id}/roles/{role_id}", {
|
|
363
|
+
params: { path: { org_id: this.#orgId, role_id: this.id } },
|
|
364
|
+
parseAs: "json",
|
|
365
|
+
});
|
|
366
|
+
const data = assertOk(resp);
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Delete role.
|
|
371
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
372
|
+
* @param {string} orgId The id of the organization to which the role belongs.
|
|
373
|
+
* @param {string} roleId The id of the role to delete.
|
|
374
|
+
* @internal
|
|
375
|
+
* */
|
|
376
|
+
private static async deleteRole(cs: CubeSigner, orgId: string, roleId: string): Promise<void> {
|
|
377
|
+
const resp = await (
|
|
378
|
+
await cs.management()
|
|
379
|
+
).del("/v0/org/{org_id}/roles/{role_id}", {
|
|
380
|
+
params: { path: { org_id: orgId, role_id: roleId } },
|
|
381
|
+
parseAs: "json",
|
|
382
|
+
});
|
|
383
|
+
assertOk(resp);
|
|
384
|
+
}
|
|
385
|
+
}
|