@cubist-labs/cubesigner-sdk 0.1.26 → 0.1.77
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/README.md +94 -33
- package/dist/src/ethers/index.d.ts +25 -5
- package/dist/src/ethers/index.js +58 -16
- package/dist/src/fido.d.ts +76 -0
- package/dist/src/fido.js +148 -0
- package/dist/src/index.d.ts +148 -35
- package/dist/src/index.js +320 -53
- package/dist/src/key.d.ts +64 -8
- package/dist/src/key.js +91 -19
- package/dist/src/org.d.ts +98 -9
- package/dist/src/org.js +144 -29
- package/dist/src/paginator.d.ts +76 -0
- package/dist/src/paginator.js +99 -0
- package/dist/src/role.d.ts +20 -8
- package/dist/src/role.js +7 -5
- package/dist/src/schema.d.ts +2395 -393
- package/dist/src/schema.js +1 -1
- package/dist/src/session/cognito_manager.d.ts +59 -0
- package/dist/src/session/cognito_manager.js +111 -0
- package/dist/src/session/session_manager.d.ts +15 -0
- package/dist/src/session/session_manager.js +21 -2
- package/dist/src/session/session_storage.js +1 -1
- package/dist/src/session/signer_session_manager.d.ts +24 -12
- package/dist/src/session/signer_session_manager.js +45 -20
- package/dist/src/signer_session.d.ts +136 -38
- package/dist/src/signer_session.js +187 -80
- package/dist/src/util.d.ts +20 -0
- package/dist/src/util.js +31 -2
- package/package.json +12 -7
- package/src/ethers/index.ts +88 -16
- package/src/fido.ts +166 -0
- package/src/index.ts +366 -77
- package/src/key.ts +112 -16
- package/src/org.ts +200 -37
- package/src/paginator.ts +122 -0
- package/src/role.ts +24 -11
- package/src/schema.ts +2458 -449
- package/src/session/{management_session_manager.ts → cognito_manager.ts} +13 -15
- package/src/session/session_manager.ts +25 -1
- package/src/session/session_storage.ts +1 -1
- package/src/session/signer_session_manager.ts +57 -27
- package/src/signer_session.ts +266 -89
- package/src/util.ts +41 -0
- package/src/session/oidc_session_manager.ts +0 -193
package/src/signer_session.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CubeSigner,
|
|
4
|
+
Key,
|
|
5
|
+
toKeyInfo,
|
|
6
|
+
Org,
|
|
7
|
+
KeyInfo,
|
|
8
|
+
MfaReceipt,
|
|
9
|
+
IdentityProof,
|
|
10
|
+
MfaFidoChallenge,
|
|
11
|
+
} from ".";
|
|
3
12
|
import { components, paths } from "./client";
|
|
4
|
-
import { assertOk } from "./util";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
13
|
+
import { JsonMap, assertOk } from "./util";
|
|
14
|
+
import { PublicKeyCredential } from "./fido";
|
|
15
|
+
import {
|
|
16
|
+
NewSessionResponse,
|
|
17
|
+
SignerSessionManager,
|
|
18
|
+
SignerSessionStorage,
|
|
19
|
+
} from "./session/signer_session_manager";
|
|
8
20
|
|
|
9
21
|
/* eslint-disable */
|
|
10
22
|
export type EvmSignRequest =
|
|
@@ -20,7 +32,9 @@ export type BlobSignRequest =
|
|
|
20
32
|
export type BtcSignRequest =
|
|
21
33
|
paths["/v0/org/{org_id}/btc/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
|
|
22
34
|
export type SolanaSignRequest =
|
|
23
|
-
paths["/
|
|
35
|
+
paths["/v0/org/{org_id}/solana/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
|
|
36
|
+
export type AvaSignRequest =
|
|
37
|
+
paths["/v0/org/{org_id}/ava/sign/{pubkey}"]["post"]["requestBody"]["content"]["application/json"];
|
|
24
38
|
|
|
25
39
|
export type EvmSignResponse =
|
|
26
40
|
components["responses"]["Eth1SignResponse"]["content"]["application/json"];
|
|
@@ -38,6 +52,8 @@ export type SolanaSignResponse =
|
|
|
38
52
|
components["responses"]["SolanaSignResponse"]["content"]["application/json"];
|
|
39
53
|
export type MfaRequestInfo =
|
|
40
54
|
components["responses"]["MfaRequestInfo"]["content"]["application/json"];
|
|
55
|
+
export type AvaSignResponse =
|
|
56
|
+
components["responses"]["AvaSignResponse"]["content"]["application/json"];
|
|
41
57
|
|
|
42
58
|
export type AcceptedResponse = components["schemas"]["AcceptedResponse"];
|
|
43
59
|
export type ErrorResponse = components["schemas"]["ErrorResponse"];
|
|
@@ -47,20 +63,61 @@ export type BtcSignatureKind = components["schemas"]["BtcSignatureKind"];
|
|
|
47
63
|
/** MFA request kind */
|
|
48
64
|
export type MfaType = components["schemas"]["MfaType"];
|
|
49
65
|
|
|
66
|
+
/** Ava P- or X-chain transaction */
|
|
67
|
+
export type AvaTx = { P: AvaPChainTx } | { X: AvaXChainTx };
|
|
68
|
+
|
|
69
|
+
/** Ava P-chain transaction */
|
|
70
|
+
export type AvaPChainTx =
|
|
71
|
+
| { AddPermissionlessValidator: JsonMap }
|
|
72
|
+
| { AddSubnetValidator: JsonMap }
|
|
73
|
+
| { AddValidator: JsonMap }
|
|
74
|
+
| { CreateChain: JsonMap }
|
|
75
|
+
| { CreateSubnet: JsonMap }
|
|
76
|
+
| { Export: JsonMap }
|
|
77
|
+
| { Import: JsonMap };
|
|
78
|
+
|
|
79
|
+
/** Ava X-chain transaction */
|
|
80
|
+
export type AvaXChainTx = { Base: JsonMap } | { Export: JsonMap } | { Import: JsonMap };
|
|
81
|
+
|
|
50
82
|
type SignFn<U> = (headers?: HeadersInit) => Promise<U | AcceptedResponse>;
|
|
51
83
|
|
|
84
|
+
export interface MfaRequired {
|
|
85
|
+
/** Org id */
|
|
86
|
+
org_id: string;
|
|
87
|
+
/** MFA request id */
|
|
88
|
+
id: string;
|
|
89
|
+
/** Optional MFA session */
|
|
90
|
+
session?: NewSessionResponse | null;
|
|
91
|
+
}
|
|
92
|
+
|
|
52
93
|
/**
|
|
53
|
-
* A response of a
|
|
94
|
+
* A response of a CubeSigner request.
|
|
54
95
|
*/
|
|
55
96
|
export class SignResponse<U> {
|
|
56
|
-
readonly #cs: CubeSigner;
|
|
57
|
-
readonly #orgId: string;
|
|
58
97
|
readonly #signFn: SignFn<U>;
|
|
59
98
|
readonly #resp: U | AcceptedResponse;
|
|
99
|
+
/**
|
|
100
|
+
* Optional MFA id. Only set if there is an MFA request associated with the
|
|
101
|
+
* signing request
|
|
102
|
+
*/
|
|
103
|
+
readonly #mfaRequired?: MfaRequired;
|
|
104
|
+
|
|
105
|
+
/** @return {string} The MFA id associated with this request */
|
|
106
|
+
mfaId(): string {
|
|
107
|
+
return this.#mfaRequired!.id;
|
|
108
|
+
}
|
|
60
109
|
|
|
61
|
-
/** @return {boolean} True if this
|
|
110
|
+
/** @return {boolean} True if this request requires an MFA approval */
|
|
62
111
|
requiresMfa(): boolean {
|
|
63
|
-
return
|
|
112
|
+
return this.#mfaRequired !== undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Returns session information to use for any MFA approval requests (if any was included in the response).
|
|
117
|
+
* @return {ClientSessionInfo | undefined}
|
|
118
|
+
*/
|
|
119
|
+
mfaSessionInfo(): NewSessionResponse | undefined {
|
|
120
|
+
return (this.#resp as AcceptedResponse).accepted?.MfaRequired?.session ?? undefined;
|
|
64
121
|
}
|
|
65
122
|
|
|
66
123
|
/** @return {U} The signed data */
|
|
@@ -69,47 +126,56 @@ export class SignResponse<U> {
|
|
|
69
126
|
}
|
|
70
127
|
|
|
71
128
|
/**
|
|
72
|
-
* Approves the MFA request using a given
|
|
73
|
-
*
|
|
74
|
-
* Note: This only works for MFA requests that require a single approval.
|
|
129
|
+
* Approves the MFA request using a given session and a TOTP code.
|
|
75
130
|
*
|
|
76
131
|
* @param {SignerSession} session Signer session to use
|
|
77
132
|
* @param {string} code 6-digit TOTP code
|
|
78
133
|
* @return {SignResponse<U>} The result of signing with the approval
|
|
79
134
|
*/
|
|
80
135
|
async approveTotp(session: SignerSession, code: string): Promise<SignResponse<U>> {
|
|
81
|
-
|
|
82
|
-
|
|
136
|
+
assert(this.requiresMfa());
|
|
137
|
+
const mfaId = this.mfaId();
|
|
138
|
+
const mfaOrgId = this.#mfaRequired!.org_id;
|
|
83
139
|
const mfaApproval = await session.totpApprove(mfaId, code);
|
|
84
140
|
assert(mfaApproval.id === mfaId);
|
|
85
141
|
const mfaConf = mfaApproval.receipt?.confirmation;
|
|
86
142
|
|
|
87
143
|
if (!mfaConf) {
|
|
88
|
-
|
|
144
|
+
return this;
|
|
89
145
|
}
|
|
90
146
|
|
|
91
|
-
return await this
|
|
147
|
+
return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
|
|
92
148
|
}
|
|
93
149
|
|
|
94
150
|
/**
|
|
95
|
-
* Approves the MFA request using CubeSigner
|
|
96
|
-
*
|
|
97
|
-
* Note: This only works for MFA requests that require a single approval.
|
|
151
|
+
* Approves the MFA request using a given `CubeSigner` instance (i.e., its management session).
|
|
98
152
|
*
|
|
153
|
+
* @param {CubeSigner} cs CubeSigner whose session to use
|
|
99
154
|
* @return {SignResponse<U>} The result of signing with the approval
|
|
100
155
|
*/
|
|
101
|
-
async approve(): Promise<SignResponse<U>> {
|
|
102
|
-
|
|
156
|
+
async approve(cs: CubeSigner): Promise<SignResponse<U>> {
|
|
157
|
+
assert(this.requiresMfa());
|
|
158
|
+
const mfaId = this.#mfaRequired!.id;
|
|
159
|
+
const mfaOrgId = this.#mfaRequired!.org_id;
|
|
103
160
|
|
|
104
|
-
const mfaApproval = await Org.mfaApprove(
|
|
161
|
+
const mfaApproval = await Org.mfaApprove(cs, mfaOrgId, mfaId);
|
|
105
162
|
assert(mfaApproval.id === mfaId);
|
|
106
163
|
const mfaConf = mfaApproval.receipt?.confirmation;
|
|
107
164
|
|
|
108
165
|
if (!mfaConf) {
|
|
109
|
-
|
|
166
|
+
return this;
|
|
110
167
|
}
|
|
111
168
|
|
|
112
|
-
return await this
|
|
169
|
+
return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {MfaReceipt} mfaReceipt The MFA receipt
|
|
174
|
+
* @return {Promise<SignResponse<U>>} The result of signing after MFA approval
|
|
175
|
+
*/
|
|
176
|
+
async signWithMfaApproval(mfaReceipt: MfaReceipt): Promise<SignResponse<U>> {
|
|
177
|
+
const headers = SignResponse.getMfaHeaders(mfaReceipt);
|
|
178
|
+
return new SignResponse(this.#signFn, await this.#signFn(headers));
|
|
113
179
|
}
|
|
114
180
|
|
|
115
181
|
// --------------------------------------------------------------------------
|
|
@@ -119,44 +185,45 @@ export class SignResponse<U> {
|
|
|
119
185
|
/**
|
|
120
186
|
* Constructor.
|
|
121
187
|
*
|
|
122
|
-
* @param {CubeSigner} cs The CubeSigner instance to use for requests
|
|
123
|
-
* @param {string} orgId The org id of the corresponding signing request
|
|
124
188
|
* @param {SignFn} signFn The signing function that this response is from.
|
|
125
189
|
* This argument is used to resend requests with
|
|
126
190
|
* different headers if needed.
|
|
127
191
|
* @param {U | AcceptedResponse} resp The response as returned by the OpenAPI
|
|
128
192
|
* client.
|
|
129
193
|
*/
|
|
130
|
-
constructor(
|
|
131
|
-
this.#cs = cs;
|
|
132
|
-
this.#orgId = orgId;
|
|
194
|
+
constructor(signFn: SignFn<U>, resp: U | AcceptedResponse) {
|
|
133
195
|
this.#signFn = signFn;
|
|
134
196
|
this.#resp = resp;
|
|
197
|
+
this.#mfaRequired = (this.#resp as AcceptedResponse).accepted?.MfaRequired;
|
|
135
198
|
}
|
|
136
199
|
|
|
137
200
|
/**
|
|
138
|
-
*
|
|
139
|
-
* @
|
|
201
|
+
* Static constructor.
|
|
202
|
+
* @param {SignFn} signFn The signing function that this response is from.
|
|
203
|
+
* This argument is used to resend requests with
|
|
204
|
+
* different headers if needed.
|
|
205
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
206
|
+
* @return {Promise<SignResponse<U>>} New instance of this class.
|
|
140
207
|
*/
|
|
141
|
-
async
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
const headers = {
|
|
145
|
-
"x-cubist-mfa-id": mfaId,
|
|
146
|
-
"x-cubist-mfa-confirmation": mfaConf,
|
|
147
|
-
};
|
|
148
|
-
return new SignResponse(this.#cs, this.#orgId, this.#signFn, await this.#signFn(headers));
|
|
208
|
+
static async create<U>(signFn: SignFn<U>, mfaReceipt?: MfaReceipt): Promise<SignResponse<U>> {
|
|
209
|
+
const seed = await signFn(this.getMfaHeaders(mfaReceipt));
|
|
210
|
+
return new SignResponse(signFn, seed);
|
|
149
211
|
}
|
|
150
212
|
|
|
151
213
|
/**
|
|
152
|
-
*
|
|
214
|
+
* Returns HTTP headers containing a given MFA receipt.
|
|
215
|
+
*
|
|
216
|
+
* @param {MfaReceipt} mfaReceipt MFA receipt
|
|
217
|
+
* @return {HeadersInit} Headers including that receipt
|
|
153
218
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
219
|
+
static getMfaHeaders(mfaReceipt?: MfaReceipt): HeadersInit | undefined {
|
|
220
|
+
return mfaReceipt
|
|
221
|
+
? {
|
|
222
|
+
"x-cubist-mfa-id": mfaReceipt.mfaId,
|
|
223
|
+
"x-cubist-mfa-org-id": mfaReceipt.mfaOrgId,
|
|
224
|
+
"x-cubist-mfa-confirmation": mfaReceipt.mfaConf,
|
|
225
|
+
}
|
|
226
|
+
: undefined;
|
|
160
227
|
}
|
|
161
228
|
}
|
|
162
229
|
|
|
@@ -197,15 +264,19 @@ export class SignerSessionInfo {
|
|
|
197
264
|
|
|
198
265
|
/** Signer session. */
|
|
199
266
|
export class SignerSession {
|
|
200
|
-
|
|
201
|
-
sessionMgr: OidcSessionManager | SignerSessionManager;
|
|
267
|
+
sessionMgr: SignerSessionManager;
|
|
202
268
|
readonly #orgId: string;
|
|
203
269
|
|
|
270
|
+
/** Org id */
|
|
271
|
+
get orgId() {
|
|
272
|
+
return this.#orgId;
|
|
273
|
+
}
|
|
274
|
+
|
|
204
275
|
/**
|
|
205
276
|
* Returns the list of keys that this token grants access to.
|
|
206
277
|
* @return {Key[]} The list of keys.
|
|
207
278
|
*/
|
|
208
|
-
async keys(): Promise<
|
|
279
|
+
async keys(): Promise<KeyInfo[]> {
|
|
209
280
|
const resp = await (
|
|
210
281
|
await this.sessionMgr.client()
|
|
211
282
|
).get("/v0/org/{org_id}/token/keys", {
|
|
@@ -213,7 +284,7 @@ export class SignerSession {
|
|
|
213
284
|
parseAs: "json",
|
|
214
285
|
});
|
|
215
286
|
const data = assertOk(resp);
|
|
216
|
-
return data.keys.map((k
|
|
287
|
+
return data.keys.map((k) => toKeyInfo(k));
|
|
217
288
|
}
|
|
218
289
|
|
|
219
290
|
/**
|
|
@@ -234,13 +305,72 @@ export class SignerSession {
|
|
|
234
305
|
return assertOk(resp);
|
|
235
306
|
}
|
|
236
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Initiate approval of an existing MFA request using FIDO.
|
|
310
|
+
* @param {string} mfaId The MFA request ID.
|
|
311
|
+
* @return {Promise<MfaFidoChallenge>} A challenge that needs to be answered to complete the approval.
|
|
312
|
+
*/
|
|
313
|
+
async fidoApproveStart(mfaId: string): Promise<MfaFidoChallenge> {
|
|
314
|
+
const client = await this.sessionMgr.client();
|
|
315
|
+
const resp = await client.post("/v0/org/{org_id}/mfa/{mfa_id}/fido", {
|
|
316
|
+
params: { path: { org_id: this.#orgId, mfa_id: mfaId } },
|
|
317
|
+
parseAs: "json",
|
|
318
|
+
});
|
|
319
|
+
const challenge = assertOk(resp);
|
|
320
|
+
return new MfaFidoChallenge(this, mfaId, challenge);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Complete a previously initiated MFA request approval using FIDO.
|
|
325
|
+
* @param {string} mfaId The MFA request ID
|
|
326
|
+
* @param {string} challengeId The challenge ID
|
|
327
|
+
* @param {PublicKeyCredential} credential The answer to the challenge
|
|
328
|
+
* @return {Promise<MfaRequestInfo>} The current status of the MFA request.
|
|
329
|
+
*/
|
|
330
|
+
async fidoApproveComplete(
|
|
331
|
+
mfaId: string,
|
|
332
|
+
challengeId: string,
|
|
333
|
+
credential: PublicKeyCredential,
|
|
334
|
+
): Promise<MfaRequestInfo> {
|
|
335
|
+
const client = await this.sessionMgr.client();
|
|
336
|
+
const resp = await client.patch("/v0/org/{org_id}/mfa/{mfa_id}/fido", {
|
|
337
|
+
params: { path: { org_id: this.#orgId, mfa_id: mfaId } },
|
|
338
|
+
body: {
|
|
339
|
+
challenge_id: challengeId,
|
|
340
|
+
credential,
|
|
341
|
+
},
|
|
342
|
+
parseAs: "json",
|
|
343
|
+
});
|
|
344
|
+
return assertOk(resp);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Get a pending MFA request by its id.
|
|
349
|
+
* @param {CubeSigner} cs Management session to use (this argument will be removed in future versions)
|
|
350
|
+
* @param {string} mfaId The id of the MFA request.
|
|
351
|
+
* @return {Promise<MfaRequestInfo>} The MFA request.
|
|
352
|
+
*/
|
|
353
|
+
async getMfaInfo(cs: CubeSigner, mfaId: string): Promise<MfaRequestInfo> {
|
|
354
|
+
const resp = await (
|
|
355
|
+
await cs.management()
|
|
356
|
+
).get("/v0/org/{org_id}/mfa/{mfa_id}", {
|
|
357
|
+
params: { path: { org_id: this.#orgId, mfa_id: mfaId } },
|
|
358
|
+
});
|
|
359
|
+
return assertOk(resp);
|
|
360
|
+
}
|
|
361
|
+
|
|
237
362
|
/**
|
|
238
363
|
* Submit an EVM sign request.
|
|
239
364
|
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
240
365
|
* @param {EvmSignRequest} req What to sign.
|
|
366
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt.
|
|
241
367
|
* @return {Promise<EvmSignResponse | AcceptedResponse>} Signature
|
|
242
368
|
*/
|
|
243
|
-
async signEvm(
|
|
369
|
+
async signEvm(
|
|
370
|
+
key: Key | string,
|
|
371
|
+
req: EvmSignRequest,
|
|
372
|
+
mfaReceipt?: MfaReceipt,
|
|
373
|
+
): Promise<SignResponse<EvmSignResponse>> {
|
|
244
374
|
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
245
375
|
const sign = async (headers?: HeadersInit) => {
|
|
246
376
|
const resp = await (
|
|
@@ -253,16 +383,21 @@ export class SignerSession {
|
|
|
253
383
|
});
|
|
254
384
|
return assertOk(resp);
|
|
255
385
|
};
|
|
256
|
-
return
|
|
386
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
257
387
|
}
|
|
258
388
|
|
|
259
389
|
/**
|
|
260
390
|
* Submit an 'eth2' sign request.
|
|
261
391
|
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
262
392
|
* @param {Eth2SignRequest} req What to sign.
|
|
393
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
263
394
|
* @return {Promise<Eth2SignResponse | AcceptedResponse>} Signature
|
|
264
395
|
*/
|
|
265
|
-
async signEth2(
|
|
396
|
+
async signEth2(
|
|
397
|
+
key: Key | string,
|
|
398
|
+
req: Eth2SignRequest,
|
|
399
|
+
mfaReceipt?: MfaReceipt,
|
|
400
|
+
): Promise<SignResponse<Eth2SignResponse>> {
|
|
266
401
|
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
267
402
|
const sign = async (headers?: HeadersInit) => {
|
|
268
403
|
const resp = await (
|
|
@@ -275,15 +410,19 @@ export class SignerSession {
|
|
|
275
410
|
});
|
|
276
411
|
return assertOk(resp);
|
|
277
412
|
};
|
|
278
|
-
return
|
|
413
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
279
414
|
}
|
|
280
415
|
|
|
281
416
|
/**
|
|
282
417
|
* Sign a stake request.
|
|
283
418
|
* @param {Eth2StakeRequest} req The request to sign.
|
|
419
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
284
420
|
* @return {Promise<Eth2StakeResponse | AcceptedResponse>} The response.
|
|
285
421
|
*/
|
|
286
|
-
async stake(
|
|
422
|
+
async stake(
|
|
423
|
+
req: Eth2StakeRequest,
|
|
424
|
+
mfaReceipt?: MfaReceipt,
|
|
425
|
+
): Promise<SignResponse<Eth2StakeResponse>> {
|
|
287
426
|
const sign = async (headers?: HeadersInit) => {
|
|
288
427
|
const resp = await (
|
|
289
428
|
await this.sessionMgr.client()
|
|
@@ -295,18 +434,20 @@ export class SignerSession {
|
|
|
295
434
|
});
|
|
296
435
|
return assertOk(resp);
|
|
297
436
|
};
|
|
298
|
-
return
|
|
437
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
299
438
|
}
|
|
300
439
|
|
|
301
440
|
/**
|
|
302
441
|
* Sign an unstake request.
|
|
303
442
|
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
304
443
|
* @param {Eth2UnstakeRequest} req The request to sign.
|
|
444
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
305
445
|
* @return {Promise<Eth2UnstakeResponse | AcceptedResponse>} The response.
|
|
306
446
|
*/
|
|
307
447
|
async unstake(
|
|
308
448
|
key: Key | string,
|
|
309
449
|
req: Eth2UnstakeRequest,
|
|
450
|
+
mfaReceipt?: MfaReceipt,
|
|
310
451
|
): Promise<SignResponse<Eth2UnstakeResponse>> {
|
|
311
452
|
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
312
453
|
const sign = async (headers?: HeadersInit) => {
|
|
@@ -320,16 +461,21 @@ export class SignerSession {
|
|
|
320
461
|
});
|
|
321
462
|
return assertOk(resp);
|
|
322
463
|
};
|
|
323
|
-
return
|
|
464
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
324
465
|
}
|
|
325
466
|
|
|
326
467
|
/**
|
|
327
468
|
* Sign a raw blob.
|
|
328
469
|
* @param {Key | string} key The key to sign with (either {@link Key} or its ID).
|
|
329
470
|
* @param {BlobSignRequest} req What to sign
|
|
471
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
330
472
|
* @return {Promise<BlobSignResponse | AcceptedResponse>} The response.
|
|
331
473
|
*/
|
|
332
|
-
async signBlob(
|
|
474
|
+
async signBlob(
|
|
475
|
+
key: Key | string,
|
|
476
|
+
req: BlobSignRequest,
|
|
477
|
+
mfaReceipt?: MfaReceipt,
|
|
478
|
+
): Promise<SignResponse<BlobSignResponse>> {
|
|
333
479
|
const key_id = typeof key === "string" ? (key as string) : key.id;
|
|
334
480
|
const sign = async (headers?: HeadersInit) => {
|
|
335
481
|
const resp = await (
|
|
@@ -344,16 +490,21 @@ export class SignerSession {
|
|
|
344
490
|
});
|
|
345
491
|
return assertOk(resp);
|
|
346
492
|
};
|
|
347
|
-
return
|
|
493
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
348
494
|
}
|
|
349
495
|
|
|
350
496
|
/**
|
|
351
497
|
* Sign a bitcoin message.
|
|
352
498
|
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
353
499
|
* @param {BtcSignRequest} req What to sign
|
|
500
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
354
501
|
* @return {Promise<BtcSignResponse | AcceptedResponse>} The response.
|
|
355
502
|
*/
|
|
356
|
-
async signBtc(
|
|
503
|
+
async signBtc(
|
|
504
|
+
key: Key | string,
|
|
505
|
+
req: BtcSignRequest,
|
|
506
|
+
mfaReceipt?: MfaReceipt,
|
|
507
|
+
): Promise<SignResponse<BtcSignResponse>> {
|
|
357
508
|
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
358
509
|
const sign = async (headers?: HeadersInit) => {
|
|
359
510
|
const resp = await (
|
|
@@ -368,24 +519,26 @@ export class SignerSession {
|
|
|
368
519
|
});
|
|
369
520
|
return assertOk(resp);
|
|
370
521
|
};
|
|
371
|
-
return
|
|
522
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
372
523
|
}
|
|
373
524
|
|
|
374
525
|
/**
|
|
375
526
|
* Sign a solana message.
|
|
376
527
|
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
377
528
|
* @param {SolanaSignRequest} req What to sign
|
|
529
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
378
530
|
* @return {Promise<SolanaSignResponse | AcceptedResponse>} The response.
|
|
379
531
|
*/
|
|
380
532
|
async signSolana(
|
|
381
533
|
key: Key | string,
|
|
382
534
|
req: SolanaSignRequest,
|
|
535
|
+
mfaReceipt?: MfaReceipt,
|
|
383
536
|
): Promise<SignResponse<SolanaSignResponse>> {
|
|
384
537
|
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
385
538
|
const sign = async (headers?: HeadersInit) => {
|
|
386
539
|
const resp = await (
|
|
387
540
|
await this.sessionMgr.client()
|
|
388
|
-
).post("/
|
|
541
|
+
).post("/v0/org/{org_id}/solana/sign/{pubkey}", {
|
|
389
542
|
params: { path: { org_id: this.#orgId, pubkey } },
|
|
390
543
|
body: req,
|
|
391
544
|
headers,
|
|
@@ -393,45 +546,69 @@ export class SignerSession {
|
|
|
393
546
|
});
|
|
394
547
|
return assertOk(resp);
|
|
395
548
|
};
|
|
396
|
-
return
|
|
549
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
397
550
|
}
|
|
398
551
|
|
|
399
552
|
/**
|
|
400
|
-
*
|
|
401
|
-
* @param {
|
|
402
|
-
* @param {
|
|
403
|
-
* @
|
|
553
|
+
* Sign an Avalanche P- or X-chain message.
|
|
554
|
+
* @param {Key | string} key The key to sign with (either {@link Key} or its material ID).
|
|
555
|
+
* @param {AvaTx} tx Avalanche message (transaction) to sign
|
|
556
|
+
* @param {MfaReceipt} mfaReceipt Optional MFA receipt
|
|
557
|
+
* @return {Promise<AvaSignResponse | AcceptedResponse>} The response.
|
|
558
|
+
*/
|
|
559
|
+
async signAva(
|
|
560
|
+
key: Key | string,
|
|
561
|
+
tx: AvaTx,
|
|
562
|
+
mfaReceipt?: MfaReceipt,
|
|
563
|
+
): Promise<SignResponse<AvaSignResponse>> {
|
|
564
|
+
const pubkey = typeof key === "string" ? (key as string) : key.materialId;
|
|
565
|
+
const sign = async (headers?: HeadersInit) => {
|
|
566
|
+
const req = <AvaSignRequest>{
|
|
567
|
+
tx: tx as unknown,
|
|
568
|
+
};
|
|
569
|
+
const resp = await (
|
|
570
|
+
await this.sessionMgr.client()
|
|
571
|
+
).post("/v0/org/{org_id}/ava/sign/{pubkey}", {
|
|
572
|
+
params: { path: { org_id: this.#orgId, pubkey } },
|
|
573
|
+
body: req,
|
|
574
|
+
headers,
|
|
575
|
+
parseAs: "json",
|
|
576
|
+
});
|
|
577
|
+
return assertOk(resp);
|
|
578
|
+
};
|
|
579
|
+
return await SignResponse.create(sign, mfaReceipt);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Obtain a proof of authentication.
|
|
584
|
+
*
|
|
585
|
+
* @return {Promise<IdentityProof>} Proof of authentication
|
|
404
586
|
*/
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
587
|
+
async proveIdentity(): Promise<IdentityProof> {
|
|
588
|
+
const client = await this.sessionMgr.client();
|
|
589
|
+
const resp = await client.post("/v0/org/{org_id}/identity/prove", {
|
|
590
|
+
params: { path: { org_id: this.#orgId } },
|
|
591
|
+
parseAs: "json",
|
|
592
|
+
});
|
|
593
|
+
return assertOk(resp);
|
|
411
594
|
}
|
|
412
595
|
|
|
413
596
|
/**
|
|
414
|
-
* Loads an existing
|
|
415
|
-
* @param {
|
|
416
|
-
* @
|
|
417
|
-
* @return {Promise<SignerSession>} New signer session
|
|
597
|
+
* Loads an existing signer session from storage.
|
|
598
|
+
* @param {SignerSessionStorage} storage The session storage to use
|
|
599
|
+
* @return {Promise<SingerSession>} New signer session
|
|
418
600
|
*/
|
|
419
|
-
static async
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
): Promise<SignerSession> {
|
|
423
|
-
const manager = await OidcSessionManager.loadFromStorage(storage);
|
|
424
|
-
return new SignerSession(cs, manager);
|
|
601
|
+
static async loadSignerSession(storage: SignerSessionStorage): Promise<SignerSession> {
|
|
602
|
+
const manager = await SignerSessionManager.loadFromStorage(storage);
|
|
603
|
+
return new SignerSession(manager);
|
|
425
604
|
}
|
|
426
605
|
|
|
427
606
|
/**
|
|
428
607
|
* Constructor.
|
|
429
|
-
* @param {
|
|
430
|
-
* @param {OidcSessionManager | SignerSessionManager} sessionMgr The session manager to use
|
|
608
|
+
* @param {SignerSessionManager} sessionMgr The session manager to use
|
|
431
609
|
* @internal
|
|
432
610
|
*/
|
|
433
|
-
constructor(
|
|
434
|
-
this.cs = cs;
|
|
611
|
+
constructor(sessionMgr: SignerSessionManager) {
|
|
435
612
|
this.sessionMgr = sessionMgr;
|
|
436
613
|
this.#orgId = sessionMgr.orgId;
|
|
437
614
|
}
|
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
|
+
}
|