@cubist-labs/cubesigner-sdk 0.1.50 → 0.2.2

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.
Files changed (47) hide show
  1. package/README.md +66 -13
  2. package/dist/src/client.d.ts +434 -7
  3. package/dist/src/client.js +1022 -18
  4. package/dist/src/ethers/index.d.ts +2 -4
  5. package/dist/src/ethers/index.js +11 -9
  6. package/dist/src/fido.d.ts +76 -0
  7. package/dist/src/fido.js +148 -0
  8. package/dist/src/index.d.ts +102 -30
  9. package/dist/src/index.js +126 -72
  10. package/dist/src/key.d.ts +15 -45
  11. package/dist/src/key.js +31 -93
  12. package/dist/src/mfa.d.ts +85 -14
  13. package/dist/src/mfa.js +158 -40
  14. package/dist/src/org.d.ts +237 -123
  15. package/dist/src/org.js +108 -213
  16. package/dist/src/paginator.d.ts +76 -0
  17. package/dist/src/paginator.js +99 -0
  18. package/dist/src/role.d.ts +76 -74
  19. package/dist/src/role.js +79 -136
  20. package/dist/src/schema.d.ts +1672 -520
  21. package/dist/src/schema.js +1 -1
  22. package/dist/src/schema_types.d.ts +103 -0
  23. package/dist/src/schema_types.js +3 -0
  24. package/dist/src/session/session_manager.js +2 -2
  25. package/dist/src/session/session_storage.js +1 -1
  26. package/dist/src/session/signer_session_manager.d.ts +16 -29
  27. package/dist/src/session/signer_session_manager.js +27 -78
  28. package/dist/src/signer_session.d.ts +232 -125
  29. package/dist/src/signer_session.js +149 -250
  30. package/dist/src/util.d.ts +20 -0
  31. package/dist/src/util.js +31 -2
  32. package/package.json +13 -11
  33. package/src/client.ts +1217 -7
  34. package/src/ethers/index.ts +11 -18
  35. package/src/index.ts +149 -101
  36. package/src/key.ts +28 -121
  37. package/src/mfa.ts +202 -0
  38. package/src/org.ts +126 -275
  39. package/src/paginator.ts +122 -0
  40. package/src/role.ts +108 -181
  41. package/src/schema.ts +1673 -520
  42. package/src/schema_types.ts +103 -0
  43. package/src/session/session_manager.ts +2 -2
  44. package/src/session/session_storage.ts +1 -1
  45. package/src/session/signer_session_manager.ts +38 -108
  46. package/src/signer_session.ts +164 -323
  47. package/src/util.ts +41 -0
@@ -1,77 +1,58 @@
1
1
  import assert from "assert";
2
- import { CubeSigner, Key, toKeyInfo, Org, KeyInfo } from ".";
3
- import { components, paths } from "./client";
4
- import { assertOk } from "./util";
5
- import {
6
- NewSessionResponse,
7
- SignerSessionManager,
8
- SignerSessionStorage,
9
- } from "./session/signer_session_manager";
10
-
11
- /* eslint-disable */
12
- export type EvmSignRequest =
13
- paths["/v1/org/{org_id}/eth1/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
14
- export type Eth2SignRequest =
15
- paths["/v1/org/{org_id}/eth2/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
16
- export type Eth2StakeRequest =
17
- paths["/v1/org/{org_id}/eth2/stake"]["post"]["requestBody"]["content"]["application/json"];
18
- export type Eth2UnstakeRequest =
19
- paths["/v1/org/{org_id}/eth2/unstake/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
20
- export type BlobSignRequest =
21
- paths["/v1/org/{org_id}/blob/sign/{key_id}"]["post"]["requestBody"]["content"]["application/json"];
22
- export type BtcSignRequest =
23
- paths["/v0/org/{org_id}/btc/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
24
- export type SolanaSignRequest =
25
- paths["/v1/org/{org_id}/solana/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
26
-
27
- export type EvmSignResponse =
28
- components["responses"]["Eth1SignResponse"]["content"]["application/json"];
29
- export type Eth2SignResponse =
30
- components["responses"]["Eth2SignResponse"]["content"]["application/json"];
31
- export type Eth2StakeResponse =
32
- components["responses"]["StakeResponse"]["content"]["application/json"];
33
- export type Eth2UnstakeResponse =
34
- components["responses"]["UnstakeResponse"]["content"]["application/json"];
35
- export type BlobSignResponse =
36
- components["responses"]["BlobSignResponse"]["content"]["application/json"];
37
- export type BtcSignResponse =
38
- components["responses"]["BtcSignResponse"]["content"]["application/json"];
39
- export type SolanaSignResponse =
40
- components["responses"]["SolanaSignResponse"]["content"]["application/json"];
41
- export type MfaRequestInfo =
42
- components["responses"]["MfaRequestInfo"]["content"]["application/json"];
43
-
44
- export type AcceptedResponse = components["schemas"]["AcceptedResponse"];
45
- export type ErrorResponse = components["schemas"]["ErrorResponse"];
46
- export type BtcSignatureKind = components["schemas"]["BtcSignatureKind"];
47
- /* eslint-enable */
48
-
49
- /** MFA request kind */
50
- export type MfaType = components["schemas"]["MfaType"];
51
-
52
- type SignFn<U> = (headers?: HeadersInit) => Promise<U | AcceptedResponse>;
2
+ import { CubeSigner, toKeyInfo, MfaReceipt, KeyInfo } from ".";
3
+ import { CubeSignerClient } from "./client";
4
+ import { AcceptedResponse, NewSessionResponse } from "./schema_types";
5
+ import { SignerSessionManager, SignerSessionStorage } from "./session/signer_session_manager";
6
+
7
+ type Response<U> = U | AcceptedResponse;
8
+ type RequestFn<U> = (headers?: HeadersInit) => Promise<Response<U>>;
9
+ type MapFn<U, V> = (u: U) => V;
10
+
11
+ /**
12
+ * Takes a {@link Response<U>} and a {@link MapFn<U, V>} function and returns
13
+ * a {@link Response<V>} that maps the value of the original response when its status code is 200.
14
+ *
15
+ * @param {Response<U>} resp Original response
16
+ * @param {Map<U, V>} mapFn Map to apply to the response value when its status code is 200.
17
+ * @return {Response<V>} Response whose value for status code 200 is mapped from U to V
18
+ */
19
+ export function mapResponse<U, V>(resp: Response<U>, mapFn: MapFn<U, V>): Response<V> {
20
+ if ((resp as AcceptedResponse).accepted?.MfaRequired) {
21
+ return resp as AcceptedResponse;
22
+ } else {
23
+ return mapFn(resp as U);
24
+ }
25
+ }
26
+
27
+ export interface MfaRequired {
28
+ /** Org id */
29
+ org_id: string;
30
+ /** MFA request id */
31
+ id: string;
32
+ /** Optional MFA session */
33
+ session?: NewSessionResponse | null;
34
+ }
53
35
 
54
36
  /**
55
37
  * A response of a CubeSigner request.
56
38
  */
57
- export class SignResponse<U> {
58
- readonly #orgId: string;
59
- readonly #signFn: SignFn<U>;
39
+ export class CubeSignerResponse<U> {
40
+ readonly #requestFn: RequestFn<U>;
60
41
  readonly #resp: U | AcceptedResponse;
61
42
  /**
62
43
  * Optional MFA id. Only set if there is an MFA request associated with the
63
44
  * signing request
64
45
  */
65
- #mfaId?: string;
46
+ readonly #mfaRequired?: MfaRequired;
66
47
 
67
48
  /** @return {string} The MFA id associated with this request */
68
49
  mfaId(): string {
69
- return this.#mfaId!;
50
+ return this.#mfaRequired!.id;
70
51
  }
71
52
 
72
53
  /** @return {boolean} True if this request requires an MFA approval */
73
54
  requiresMfa(): boolean {
74
- return this.#mfaId !== undefined;
55
+ return this.#mfaRequired !== undefined;
75
56
  }
76
57
 
77
58
  /**
@@ -82,8 +63,11 @@ export class SignResponse<U> {
82
63
  return (this.#resp as AcceptedResponse).accepted?.MfaRequired?.session ?? undefined;
83
64
  }
84
65
 
85
- /** @return {U} The signed data */
66
+ /** @return {U} The response data, if no MFA is required */
86
67
  data(): U {
68
+ if (this.requiresMfa()) {
69
+ throw new Error("Cannot call `data()` while MFA is required");
70
+ }
87
71
  return this.#resp as U;
88
72
  }
89
73
 
@@ -92,10 +76,12 @@ export class SignResponse<U> {
92
76
  *
93
77
  * @param {SignerSession} session Signer session to use
94
78
  * @param {string} code 6-digit TOTP code
95
- * @return {SignResponse<U>} The result of signing with the approval
79
+ * @return {CubeSignerResponse<U>} The result of signing with the approval
96
80
  */
97
- async approveTotp(session: SignerSession, code: string): Promise<SignResponse<U>> {
81
+ async approveTotp(session: SignerSession, code: string): Promise<CubeSignerResponse<U>> {
82
+ assert(this.requiresMfa());
98
83
  const mfaId = this.mfaId();
84
+ const mfaOrgId = this.#mfaRequired!.org_id;
99
85
  const mfaApproval = await session.totpApprove(mfaId, code);
100
86
  assert(mfaApproval.id === mfaId);
101
87
  const mfaConf = mfaApproval.receipt?.confirmation;
@@ -104,18 +90,21 @@ export class SignResponse<U> {
104
90
  return this;
105
91
  }
106
92
 
107
- return await this.signWithMfaApproval(mfaApproval);
93
+ return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
108
94
  }
109
95
 
110
96
  /**
111
- * Approves the MFA request using a given `CubeSigner` instance (i.e., its management session).
97
+ * Approves the MFA request using a given `CubeSignerClient` instance (i.e., its session).
112
98
  *
113
99
  * @param {CubeSigner} cs CubeSigner whose session to use
114
- * @return {SignResponse<U>} The result of signing with the approval
100
+ * @return {CubeSignerResponse<U>} The result of signing with the approval
115
101
  */
116
- async approve(cs: CubeSigner): Promise<SignResponse<U>> {
117
- const mfaId = this.mfaId();
118
- const mfaApproval = await Org.mfaApprove(cs, this.#orgId, mfaId);
102
+ async approve(cs: CubeSigner): Promise<CubeSignerResponse<U>> {
103
+ assert(this.requiresMfa());
104
+ const mfaId = this.#mfaRequired!.id;
105
+ const mfaOrgId = this.#mfaRequired!.org_id;
106
+
107
+ const mfaApproval = await cs.mfaApprove(mfaOrgId, mfaId);
119
108
  assert(mfaApproval.id === mfaId);
120
109
  const mfaConf = mfaApproval.receipt?.confirmation;
121
110
 
@@ -123,16 +112,16 @@ export class SignResponse<U> {
123
112
  return this;
124
113
  }
125
114
 
126
- return await this.signWithMfaApproval(mfaApproval);
115
+ return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
127
116
  }
128
117
 
129
118
  /**
130
- * @param {MfaRequestInfo} mfaInfo The MFA request info with the approval
131
- * @return {Promise<SignResponse<U>>} The result of signing after MFA approval
119
+ * @param {MfaReceipt} mfaReceipt The MFA receipt
120
+ * @return {Promise<CubeSignerResponse<U>>} The result of signing after MFA approval
132
121
  */
133
- async signWithMfaApproval(mfaInfo: MfaRequestInfo): Promise<SignResponse<U>> {
134
- const headers = SignResponse.getMfaHeaders(this.mfaId(), mfaInfo.receipt!.confirmation);
135
- return new SignResponse(this.#orgId, this.#signFn, await this.#signFn(headers));
122
+ async signWithMfaApproval(mfaReceipt: MfaReceipt): Promise<CubeSignerResponse<U>> {
123
+ const headers = CubeSignerResponse.getMfaHeaders(mfaReceipt);
124
+ return new CubeSignerResponse(this.#requestFn, await this.#requestFn(headers));
136
125
  }
137
126
 
138
127
  // --------------------------------------------------------------------------
@@ -142,50 +131,59 @@ export class SignResponse<U> {
142
131
  /**
143
132
  * Constructor.
144
133
  *
145
- * @param {string} orgId The org id of the corresponding signing request
146
- * @param {SignFn} signFn The signing function that this response is from.
147
- * This argument is used to resend requests with
148
- * different headers if needed.
149
- * @param {U | AcceptedResponse} resp The response as returned by the OpenAPI
150
- * client.
134
+ * @param {RequestFn} requestFn
135
+ * The signing function that this response is from.
136
+ * This argument is used to resend requests with different headers if needed.
137
+ * @param {U | AcceptedResponse} resp The response as returned by the OpenAPI client.
151
138
  */
152
- constructor(orgId: string, signFn: SignFn<U>, resp: U | AcceptedResponse) {
153
- this.#orgId = orgId;
154
- this.#signFn = signFn;
139
+ constructor(requestFn: RequestFn<U>, resp: U | AcceptedResponse) {
140
+ this.#requestFn = requestFn;
155
141
  this.#resp = resp;
142
+ this.#mfaRequired = (this.#resp as AcceptedResponse).accepted?.MfaRequired;
143
+ }
156
144
 
157
- const mfaRequired = (this.#resp as AcceptedResponse).accepted?.MfaRequired;
158
- if (mfaRequired) {
159
- this.#mfaId = mfaRequired.id;
160
- }
145
+ /**
146
+ * Static constructor.
147
+ * @param {RequestFn} requestFn
148
+ * The request function that this response is from.
149
+ * This argument is used to resend requests with different headers if needed.
150
+ * @param {MfaReceipt} mfaReceipt Optional MFA receipt
151
+ * @return {Promise<CubeSignerResponse<U>>} New instance of this class.
152
+ */
153
+ static async create<U>(
154
+ requestFn: RequestFn<U>,
155
+ mfaReceipt?: MfaReceipt,
156
+ ): Promise<CubeSignerResponse<U>> {
157
+ const seed = await requestFn(this.getMfaHeaders(mfaReceipt));
158
+ return new CubeSignerResponse(requestFn, seed);
161
159
  }
162
160
 
163
161
  /**
164
- * MFA receipt to attach.
162
+ * Returns HTTP headers containing a given MFA receipt.
165
163
  *
166
- * @param {string} mfaId MFA request id
167
- * @param {string} mfaConf MFA receipt confirmation code
168
- * @return {HeadersInit} Headers
164
+ * @param {MfaReceipt} mfaReceipt MFA receipt
165
+ * @return {HeadersInit} Headers including that receipt
169
166
  */
170
- static getMfaHeaders(mfaId: string, mfaConf: string): HeadersInit {
171
- return {
172
- "x-cubist-mfa-id": mfaId,
173
- "x-cubist-mfa-confirmation": mfaConf,
174
- };
167
+ static getMfaHeaders(mfaReceipt?: MfaReceipt): HeadersInit | undefined {
168
+ return mfaReceipt
169
+ ? {
170
+ "x-cubist-mfa-id": mfaReceipt.mfaId,
171
+ "x-cubist-mfa-org-id": mfaReceipt.mfaOrgId,
172
+ "x-cubist-mfa-confirmation": mfaReceipt.mfaConf,
173
+ }
174
+ : undefined;
175
175
  }
176
176
  }
177
177
 
178
178
  /** Signer session info. Can only be used to revoke a token, but not for authentication. */
179
179
  export class SignerSessionInfo {
180
- readonly #cs: CubeSigner;
181
- readonly #orgId: string;
182
- readonly #roleId: string;
180
+ readonly #csc: CubeSignerClient;
183
181
  readonly #sessionId: string;
184
182
  public readonly purpose: string;
185
183
 
186
- /** Revoke this token */
184
+ /** Revoke this session */
187
185
  async revoke() {
188
- await SignerSession.revoke(this.#cs, this.#orgId, this.#roleId, this.#sessionId);
186
+ await this.#csc.sessionRevoke(this.#sessionId);
189
187
  }
190
188
 
191
189
  // --------------------------------------------------------------------------
@@ -194,235 +192,105 @@ export class SignerSessionInfo {
194
192
 
195
193
  /**
196
194
  * Internal constructor.
197
- * @param {CubeSigner} cs CubeSigner instance to use when calling `revoke`
198
- * @param {string} orgId Organization ID
199
- * @param {string} roleId Role ID
200
- * @param {string} hash The hash of the token; can be used for revocation but not for auth
195
+ * @param {CubeSignerClient} cs CubeSigner instance to use when calling `revoke`
196
+ * @param {string} sessionId The ID of the session; can be used for revocation but not for auth
201
197
  * @param {string} purpose Session purpose
202
198
  * @internal
203
199
  */
204
- constructor(cs: CubeSigner, orgId: string, roleId: string, hash: string, purpose: string) {
205
- this.#cs = cs;
206
- this.#orgId = orgId;
207
- this.#roleId = roleId;
208
- this.#sessionId = hash;
200
+ constructor(cs: CubeSignerClient, sessionId: string, purpose: string) {
201
+ this.#csc = cs;
202
+ this.#sessionId = sessionId;
209
203
  this.purpose = purpose;
210
204
  }
211
205
  }
212
206
 
213
- /** Signer session. */
207
+ /**
208
+ * Signer session.
209
+ *
210
+ * @deprecated Use {@link CubeSignerClient} instead.
211
+ */
214
212
  export class SignerSession {
215
- sessionMgr: SignerSessionManager;
216
- readonly #orgId: string;
213
+ readonly #csc: CubeSignerClient;
214
+
215
+ /** Deprecated */
216
+ get sessionMgr() {
217
+ return this.#csc.sessionMgr;
218
+ }
219
+
220
+ /** Org id */
221
+ get orgId() {
222
+ return this.#csc.orgId;
223
+ }
217
224
 
218
225
  /**
219
226
  * Returns the list of keys that this token grants access to.
220
- * @return {Key[]} The list of keys.
227
+ * @return {KeyInfo[]} The list of keys.
221
228
  */
222
229
  async keys(): Promise<KeyInfo[]> {
223
- const resp = await (
224
- await this.sessionMgr.client()
225
- ).get("/v0/org/{org_id}/token/keys", {
226
- params: { path: { org_id: this.#orgId } },
227
- parseAs: "json",
228
- });
229
- const data = assertOk(resp);
230
- return data.keys.map((k) => toKeyInfo(k));
230
+ const keys = await this.#csc.sessionKeysList();
231
+ return keys.map((k) => toKeyInfo(k));
231
232
  }
232
233
 
233
- /**
234
- * Approve a pending MFA request using TOTP.
235
- *
236
- * @param {string} mfaId The MFA request to approve
237
- * @param {string} code The TOTP code
238
- * @return {Promise<MfaRequestInfo>} The current status of the MFA request
239
- */
240
- async totpApprove(mfaId: string, code: string): Promise<MfaRequestInfo> {
241
- const resp = await (
242
- await this.sessionMgr.client()
243
- ).patch("/v0/org/{org_id}/mfa/{mfa_id}/totp", {
244
- params: { path: { org_id: this.#orgId, mfa_id: mfaId } },
245
- body: { code },
246
- parseAs: "json",
247
- });
248
- return assertOk(resp);
234
+ /** Approve a pending MFA request using TOTP. */
235
+ get totpApprove() {
236
+ return this.#csc.mfaApproveTotp.bind(this.#csc);
249
237
  }
250
238
 
251
- /**
252
- * Get a pending MFA request by its id.
253
- * @param {CubeSigner} cs Management session to use (this argument will be removed in future versions)
254
- * @param {string} mfaId The id of the MFA request.
255
- * @return {Promise<MfaRequestInfo>} The MFA request.
256
- */
257
- async getMfaInfo(cs: CubeSigner, mfaId: string): Promise<MfaRequestInfo> {
258
- const resp = await (
259
- await cs.management()
260
- ).get("/v0/org/{org_id}/mfa/{mfa_id}", {
261
- params: { path: { org_id: this.#orgId, mfa_id: mfaId } },
262
- });
263
- return assertOk(resp);
239
+ /** Initiate approval of an existing MFA request using FIDO. */
240
+ get fidoApproveStart() {
241
+ return this.#csc.mfaApproveFidoInit.bind(this.#csc);
264
242
  }
265
243
 
266
- /**
267
- * Submit an EVM sign request.
268
- * @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
269
- * @param {EvmSignRequest} req What to sign.
270
- * @return {Promise<EvmSignResponse | AcceptedResponse>} Signature
271
- */
272
- async signEvm(key: Key | string, req: EvmSignRequest): Promise<SignResponse<EvmSignResponse>> {
273
- const pubkey = typeof key === "string" ? (key as string) : key.materialId;
274
- const sign = async (headers?: HeadersInit) => {
275
- const resp = await (
276
- await this.sessionMgr.client()
277
- ).post("/v1/org/{org_id}/eth1/sign/{pubkey}", {
278
- params: { path: { org_id: this.#orgId, pubkey } },
279
- body: req,
280
- headers,
281
- parseAs: "json",
282
- });
283
- return assertOk(resp);
284
- };
285
- return new SignResponse(this.#orgId, sign, await sign());
244
+ /** Get a pending MFA request by its id. */
245
+ get getMfaInfo() {
246
+ return this.#csc.mfaGet.bind(this.#csc);
286
247
  }
287
248
 
288
- /**
289
- * Submit an 'eth2' sign request.
290
- * @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
291
- * @param {Eth2SignRequest} req What to sign.
292
- * @return {Promise<Eth2SignResponse | AcceptedResponse>} Signature
293
- */
294
- async signEth2(key: Key | string, req: Eth2SignRequest): Promise<SignResponse<Eth2SignResponse>> {
295
- const pubkey = typeof key === "string" ? (key as string) : key.materialId;
296
- const sign = async (headers?: HeadersInit) => {
297
- const resp = await (
298
- await this.sessionMgr.client()
299
- ).post("/v1/org/{org_id}/eth2/sign/{pubkey}", {
300
- params: { path: { org_id: this.#orgId, pubkey } },
301
- body: req,
302
- headers,
303
- parseAs: "json",
304
- });
305
- return assertOk(resp);
306
- };
307
- return new SignResponse(this.#orgId, sign, await sign());
249
+ /** Submit an EVM sign request. */
250
+ get signEvm() {
251
+ return this.#csc.signEvm.bind(this.#csc);
308
252
  }
309
253
 
310
- /**
311
- * Sign a stake request.
312
- * @param {Eth2StakeRequest} req The request to sign.
313
- * @return {Promise<Eth2StakeResponse | AcceptedResponse>} The response.
314
- */
315
- async stake(req: Eth2StakeRequest): Promise<SignResponse<Eth2StakeResponse>> {
316
- const sign = async (headers?: HeadersInit) => {
317
- const resp = await (
318
- await this.sessionMgr.client()
319
- ).post("/v1/org/{org_id}/eth2/stake", {
320
- params: { path: { org_id: this.#orgId } },
321
- body: req,
322
- headers,
323
- parseAs: "json",
324
- });
325
- return assertOk(resp);
326
- };
327
- return new SignResponse(this.#orgId, sign, await sign());
254
+ /** Submit an 'eth2' sign request. */
255
+ get signEth2() {
256
+ return this.#csc.signEth2.bind(this.#csc);
328
257
  }
329
258
 
330
- /**
331
- * Sign an unstake request.
332
- * @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
333
- * @param {Eth2UnstakeRequest} req The request to sign.
334
- * @return {Promise<Eth2UnstakeResponse | AcceptedResponse>} The response.
335
- */
336
- async unstake(
337
- key: Key | string,
338
- req: Eth2UnstakeRequest,
339
- ): Promise<SignResponse<Eth2UnstakeResponse>> {
340
- const pubkey = typeof key === "string" ? (key as string) : key.materialId;
341
- const sign = async (headers?: HeadersInit) => {
342
- const resp = await (
343
- await this.sessionMgr.client()
344
- ).post("/v1/org/{org_id}/eth2/unstake/{pubkey}", {
345
- params: { path: { org_id: this.#orgId, pubkey } },
346
- body: req,
347
- headers,
348
- parseAs: "json",
349
- });
350
- return assertOk(resp);
351
- };
352
- return new SignResponse(this.#orgId, sign, await sign());
259
+ /** Sign a stake request. */
260
+ get stake() {
261
+ return this.#csc.signStake.bind(this.#csc);
353
262
  }
354
263
 
355
- /**
356
- * Sign a raw blob.
357
- * @param {Key | string} key The key to sign with (either {@link Key} or its ID).
358
- * @param {BlobSignRequest} req What to sign
359
- * @return {Promise<BlobSignResponse | AcceptedResponse>} The response.
360
- */
361
- async signBlob(key: Key | string, req: BlobSignRequest): Promise<SignResponse<BlobSignResponse>> {
362
- const key_id = typeof key === "string" ? (key as string) : key.id;
363
- const sign = async (headers?: HeadersInit) => {
364
- const resp = await (
365
- await this.sessionMgr.client()
366
- ).post("/v1/org/{org_id}/blob/sign/{key_id}", {
367
- params: {
368
- path: { org_id: this.#orgId, key_id },
369
- },
370
- body: req,
371
- headers,
372
- parseAs: "json",
373
- });
374
- return assertOk(resp);
375
- };
376
- return new SignResponse(this.#orgId, sign, await sign());
264
+ /** Sign an unstake request. */
265
+ get unstake() {
266
+ return this.#csc.signUnstake.bind(this.#csc);
377
267
  }
378
268
 
379
- /**
380
- * Sign a bitcoin message.
381
- * @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
382
- * @param {BtcSignRequest} req What to sign
383
- * @return {Promise<BtcSignResponse | AcceptedResponse>} The response.
384
- */
385
- async signBtc(key: Key | string, req: BtcSignRequest): Promise<SignResponse<BtcSignResponse>> {
386
- const pubkey = typeof key === "string" ? (key as string) : key.materialId;
387
- const sign = async (headers?: HeadersInit) => {
388
- const resp = await (
389
- await this.sessionMgr.client()
390
- ).post("/v0/org/{org_id}/btc/sign/{pubkey}", {
391
- params: {
392
- path: { org_id: this.#orgId, pubkey },
393
- },
394
- body: req,
395
- headers: headers,
396
- parseAs: "json",
397
- });
398
- return assertOk(resp);
399
- };
400
- return new SignResponse(this.#orgId, sign, await sign());
269
+ /** Sign a raw blob.*/
270
+ get signBlob() {
271
+ return this.#csc.signBlob.bind(this.#csc);
272
+ }
273
+
274
+ /** Sign a bitcoin message. */
275
+ get signBtc() {
276
+ return this.#csc.signBtc.bind(this.#csc);
277
+ }
278
+
279
+ /** Sign a solana message. */
280
+ get signSolana() {
281
+ return this.#csc.signSolana.bind(this.#csc);
282
+ }
283
+
284
+ /** Sign an Avalanche P- or X-chain message. */
285
+ get signAva() {
286
+ return this.#csc.signAva.bind(this.#csc);
401
287
  }
402
288
 
403
289
  /**
404
- * Sign a solana message.
405
- * @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
406
- * @param {SolanaSignRequest} req What to sign
407
- * @return {Promise<SolanaSignResponse | AcceptedResponse>} The response.
290
+ * Obtain a proof of authentication.
408
291
  */
409
- async signSolana(
410
- key: Key | string,
411
- req: SolanaSignRequest,
412
- ): Promise<SignResponse<SolanaSignResponse>> {
413
- const pubkey = typeof key === "string" ? (key as string) : key.materialId;
414
- const sign = async (headers?: HeadersInit) => {
415
- const resp = await (
416
- await this.sessionMgr.client()
417
- ).post("/v1/org/{org_id}/solana/sign/{pubkey}", {
418
- params: { path: { org_id: this.#orgId, pubkey } },
419
- body: req,
420
- headers,
421
- parseAs: "json",
422
- });
423
- return assertOk(resp);
424
- };
425
- return new SignResponse(this.#orgId, sign, await sign());
292
+ get proveIdentity() {
293
+ return this.#csc.identityProve.bind(this.#csc);
426
294
  }
427
295
 
428
296
  /**
@@ -441,33 +309,6 @@ export class SignerSession {
441
309
  * @internal
442
310
  */
443
311
  constructor(sessionMgr: SignerSessionManager) {
444
- this.sessionMgr = sessionMgr;
445
- this.#orgId = sessionMgr.orgId;
446
- }
447
-
448
- // --------------------------------------------------------------------------
449
- // -- INTERNAL --------------------------------------------------------------
450
- // --------------------------------------------------------------------------
451
-
452
- /* eslint-disable require-jsdoc */
453
-
454
- /**
455
- * Static method for revoking a token (used both from {SignerSession} and {SignerSessionInfo}).
456
- * @param {CubeSigner} cs CubeSigner instance
457
- * @param {string} orgId Organization ID
458
- * @param {string} roleId Role ID
459
- * @param {string} sessionId Signer session ID
460
- * @internal
461
- */
462
- static async revoke(cs: CubeSigner, orgId: string, roleId: string, sessionId: string) {
463
- const resp = await (
464
- await cs.management()
465
- ).del("/v0/org/{org_id}/roles/{role_id}/tokens/{session_id}", {
466
- params: {
467
- path: { org_id: orgId, role_id: roleId, session_id: sessionId },
468
- },
469
- parseAs: "json",
470
- });
471
- assertOk(resp);
312
+ this.#csc = new CubeSignerClient(sessionMgr);
472
313
  }
473
314
  }
package/src/util.ts CHANGED
@@ -1,5 +1,13 @@
1
1
  import * as path from "path";
2
2
 
3
+ /** JSON map type */
4
+ export interface JsonMap {
5
+ [member: string]: string | number | boolean | null | JsonArray | JsonMap;
6
+ }
7
+
8
+ /** JSON array type */
9
+ export type JsonArray = Array<string | number | boolean | null | JsonArray | JsonMap>;
10
+
3
11
  /**
4
12
  * Directory where CubeSigner stores config files.
5
13
  * @return {string} Config dir
@@ -56,3 +64,36 @@ export function assertOk<D, T>(resp: ResponseType<D, T>, description?: string):
56
64
  }
57
65
  return resp.data;
58
66
  }
67
+
68
+ /**
69
+ * Browser-friendly helper for decoding a 'base64url'-encoded string into a byte array.
70
+ *
71
+ * @param {string} b64url The 'base64url'-encoded string to decode
72
+ * @return {Uint8Array} Decoded byte array
73
+ */
74
+ export function decodeBase64Url(b64url: string): Uint8Array {
75
+ const b64 = b64url.replace(/-/g, "+").replace(/_/g, "/").replace(/=*$/g, "");
76
+
77
+ // NOTE: there is no "base64url" encoding in the "buffer" module for the browser (unlike in node.js)
78
+ return typeof Buffer === "function"
79
+ ? Buffer.from(b64, "base64")
80
+ : Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
81
+ }
82
+
83
+ /**
84
+ * Browser-friendly helper for encoding a byte array into a 'base64url`-encoded string.
85
+ *
86
+ * @param {Iterable<number>} buffer The byte array to encode
87
+ * @return {string} The 'base64url' encoding of the byte array.
88
+ */
89
+ export function encodeToBase64Url(buffer: Iterable<number>): string {
90
+ const bytes = new Uint8Array(buffer);
91
+
92
+ // NOTE: there is no "base64url" encoding in the "buffer" module for the browser (unlike in node.js)
93
+ const b64 =
94
+ typeof Buffer === "function"
95
+ ? Buffer.from(bytes).toString("base64")
96
+ : btoa(bytes.reduce((s, b) => s + String.fromCharCode(b), ""));
97
+
98
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=*$/g, "");
99
+ }