@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.
- package/README.md +66 -13
- package/dist/src/client.d.ts +434 -7
- package/dist/src/client.js +1022 -18
- package/dist/src/ethers/index.d.ts +2 -4
- package/dist/src/ethers/index.js +11 -9
- package/dist/src/fido.d.ts +76 -0
- package/dist/src/fido.js +148 -0
- package/dist/src/index.d.ts +102 -30
- package/dist/src/index.js +126 -72
- package/dist/src/key.d.ts +15 -45
- package/dist/src/key.js +31 -93
- package/dist/src/mfa.d.ts +85 -14
- package/dist/src/mfa.js +158 -40
- package/dist/src/org.d.ts +237 -123
- package/dist/src/org.js +108 -213
- package/dist/src/paginator.d.ts +76 -0
- package/dist/src/paginator.js +99 -0
- package/dist/src/role.d.ts +76 -74
- package/dist/src/role.js +79 -136
- package/dist/src/schema.d.ts +1672 -520
- package/dist/src/schema.js +1 -1
- package/dist/src/schema_types.d.ts +103 -0
- package/dist/src/schema_types.js +3 -0
- package/dist/src/session/session_manager.js +2 -2
- package/dist/src/session/session_storage.js +1 -1
- package/dist/src/session/signer_session_manager.d.ts +16 -29
- package/dist/src/session/signer_session_manager.js +27 -78
- package/dist/src/signer_session.d.ts +232 -125
- package/dist/src/signer_session.js +149 -250
- package/dist/src/util.d.ts +20 -0
- package/dist/src/util.js +31 -2
- package/package.json +13 -11
- package/src/client.ts +1217 -7
- package/src/ethers/index.ts +11 -18
- package/src/index.ts +149 -101
- package/src/key.ts +28 -121
- package/src/mfa.ts +202 -0
- package/src/org.ts +126 -275
- package/src/paginator.ts +122 -0
- package/src/role.ts +108 -181
- package/src/schema.ts +1673 -520
- package/src/schema_types.ts +103 -0
- package/src/session/session_manager.ts +2 -2
- package/src/session/session_storage.ts +1 -1
- package/src/session/signer_session_manager.ts +38 -108
- package/src/signer_session.ts +164 -323
- package/src/util.ts +41 -0
package/src/signer_session.ts
CHANGED
|
@@ -1,77 +1,58 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import { CubeSigner,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
58
|
-
readonly #
|
|
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
|
-
#
|
|
46
|
+
readonly #mfaRequired?: MfaRequired;
|
|
66
47
|
|
|
67
48
|
/** @return {string} The MFA id associated with this request */
|
|
68
49
|
mfaId(): string {
|
|
69
|
-
return this.#
|
|
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.#
|
|
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
|
|
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 {
|
|
79
|
+
* @return {CubeSignerResponse<U>} The result of signing with the approval
|
|
96
80
|
*/
|
|
97
|
-
async approveTotp(session: SignerSession, code: string): Promise<
|
|
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(
|
|
93
|
+
return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
|
|
108
94
|
}
|
|
109
95
|
|
|
110
96
|
/**
|
|
111
|
-
* Approves the MFA request using a given `
|
|
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 {
|
|
100
|
+
* @return {CubeSignerResponse<U>} The result of signing with the approval
|
|
115
101
|
*/
|
|
116
|
-
async approve(cs: CubeSigner): Promise<
|
|
117
|
-
|
|
118
|
-
const
|
|
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(
|
|
115
|
+
return await this.signWithMfaApproval({ mfaId, mfaOrgId, mfaConf });
|
|
127
116
|
}
|
|
128
117
|
|
|
129
118
|
/**
|
|
130
|
-
* @param {
|
|
131
|
-
* @return {Promise<
|
|
119
|
+
* @param {MfaReceipt} mfaReceipt The MFA receipt
|
|
120
|
+
* @return {Promise<CubeSignerResponse<U>>} The result of signing after MFA approval
|
|
132
121
|
*/
|
|
133
|
-
async signWithMfaApproval(
|
|
134
|
-
const headers =
|
|
135
|
-
return new
|
|
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 {
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
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(
|
|
153
|
-
this.#
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
|
162
|
+
* Returns HTTP headers containing a given MFA receipt.
|
|
165
163
|
*
|
|
166
|
-
* @param {
|
|
167
|
-
* @
|
|
168
|
-
* @return {HeadersInit} Headers
|
|
164
|
+
* @param {MfaReceipt} mfaReceipt MFA receipt
|
|
165
|
+
* @return {HeadersInit} Headers including that receipt
|
|
169
166
|
*/
|
|
170
|
-
static getMfaHeaders(
|
|
171
|
-
return
|
|
172
|
-
|
|
173
|
-
|
|
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 #
|
|
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
|
|
184
|
+
/** Revoke this session */
|
|
187
185
|
async revoke() {
|
|
188
|
-
await
|
|
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 {
|
|
198
|
-
* @param {string}
|
|
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:
|
|
205
|
-
this.#
|
|
206
|
-
this.#
|
|
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
|
-
/**
|
|
207
|
+
/**
|
|
208
|
+
* Signer session.
|
|
209
|
+
*
|
|
210
|
+
* @deprecated Use {@link CubeSignerClient} instead.
|
|
211
|
+
*/
|
|
214
212
|
export class SignerSession {
|
|
215
|
-
|
|
216
|
-
|
|
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 {
|
|
227
|
+
* @return {KeyInfo[]} The list of keys.
|
|
221
228
|
*/
|
|
222
229
|
async keys(): Promise<KeyInfo[]> {
|
|
223
|
-
const
|
|
224
|
-
|
|
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
|
-
|
|
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
|
-
|
|
253
|
-
|
|
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
|
-
|
|
268
|
-
|
|
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
|
-
|
|
290
|
-
|
|
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
|
-
|
|
312
|
-
|
|
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
|
-
|
|
332
|
-
|
|
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
|
-
|
|
357
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
410
|
-
|
|
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
|
|
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
|
+
}
|