@tomo-inc/cubist-wallet-sdk 0.0.4
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/CHANGELOG.md +11 -0
- package/README.md +14 -0
- package/RN.md +54 -0
- package/package.json +40 -0
- package/project.json +59 -0
- package/src/__tests__/cube-mfa.test.ts +64 -0
- package/src/api.ts +64 -0
- package/src/const.ts +96 -0
- package/src/cube-account.ts +324 -0
- package/src/cube-connect.ts +22 -0
- package/src/cube-export.ts +125 -0
- package/src/cube-libs.ts +29 -0
- package/src/cube-mfa.ts +494 -0
- package/src/cube-sign.ts +210 -0
- package/src/export-key.ts +150 -0
- package/src/index.ts +15 -0
- package/src/passkey.ts +221 -0
- package/src/signature.ts +23 -0
- package/src/types.ts +269 -0
- package/src/utils.ts +71 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +23 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { userExportKeygen } from "./cube-libs";
|
|
2
|
+
|
|
3
|
+
const EXPORT_KEY_STORAGE_KEY = "cubist_export_key";
|
|
4
|
+
|
|
5
|
+
interface StoredKeyPair {
|
|
6
|
+
publicKey: JsonWebKey;
|
|
7
|
+
privateKey: JsonWebKey;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class CubeExportKeyService {
|
|
11
|
+
private static instance: CubeExportKeyService;
|
|
12
|
+
public exportKey: CryptoKeyPair | null = null;
|
|
13
|
+
|
|
14
|
+
public constructor() {
|
|
15
|
+
if (!window?.localStorage) {
|
|
16
|
+
throw new Error("localStorage is not available");
|
|
17
|
+
}
|
|
18
|
+
this.ensureExportKey();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public static getInstance() {
|
|
22
|
+
if (!CubeExportKeyService.instance) {
|
|
23
|
+
CubeExportKeyService.instance = new CubeExportKeyService();
|
|
24
|
+
}
|
|
25
|
+
return CubeExportKeyService.instance;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Recover exportKey from localStorage
|
|
30
|
+
*/
|
|
31
|
+
private async recoverExportKey(): Promise<void> {
|
|
32
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const storedKey = window.localStorage.getItem(EXPORT_KEY_STORAGE_KEY);
|
|
38
|
+
if (storedKey) {
|
|
39
|
+
const keyData: StoredKeyPair = JSON.parse(storedKey);
|
|
40
|
+
|
|
41
|
+
// Import public key from JWK
|
|
42
|
+
const publicKey = await crypto.subtle.importKey(
|
|
43
|
+
"jwk",
|
|
44
|
+
keyData.publicKey,
|
|
45
|
+
{
|
|
46
|
+
name: "ECDH",
|
|
47
|
+
namedCurve: "P-256",
|
|
48
|
+
},
|
|
49
|
+
true,
|
|
50
|
+
[],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Import private key from JWK
|
|
54
|
+
const privateKey = await crypto.subtle.importKey(
|
|
55
|
+
"jwk",
|
|
56
|
+
keyData.privateKey,
|
|
57
|
+
{
|
|
58
|
+
name: "ECDH",
|
|
59
|
+
namedCurve: "P-256",
|
|
60
|
+
},
|
|
61
|
+
true,
|
|
62
|
+
["deriveKey", "deriveBits"],
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
this.exportKey = { publicKey, privateKey };
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error("Failed to recover exportKey from localStorage:", error);
|
|
69
|
+
// If recovery fails, clear corrupted data
|
|
70
|
+
this.clearStoredExportKey();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generate new exportKey and store it in localStorage
|
|
76
|
+
*/
|
|
77
|
+
private async generateAndStoreExportKey(): Promise<void> {
|
|
78
|
+
try {
|
|
79
|
+
const key = await userExportKeygen();
|
|
80
|
+
this.exportKey = key;
|
|
81
|
+
await this.storeExportKey(key);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error("Failed to generate exportKey:", error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Store exportKey in localStorage by exporting to JWK format
|
|
89
|
+
*/
|
|
90
|
+
private async storeExportKey(keyPair: CryptoKeyPair): Promise<void> {
|
|
91
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
// Export public key to JWK format
|
|
97
|
+
const publicKeyJwk = await crypto.subtle.exportKey("jwk", keyPair.publicKey);
|
|
98
|
+
|
|
99
|
+
// Export private key to JWK format
|
|
100
|
+
const privateKeyJwk = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
|
|
101
|
+
|
|
102
|
+
// Store as JSON
|
|
103
|
+
const keyData: StoredKeyPair = {
|
|
104
|
+
publicKey: publicKeyJwk,
|
|
105
|
+
privateKey: privateKeyJwk,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
window.localStorage.setItem(EXPORT_KEY_STORAGE_KEY, JSON.stringify(keyData));
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error("Failed to store exportKey in localStorage:", error);
|
|
111
|
+
// Handle quota exceeded error
|
|
112
|
+
if (error instanceof DOMException && error.name === "QuotaExceededError") {
|
|
113
|
+
console.warn("localStorage quota exceeded, clearing old data");
|
|
114
|
+
// Optionally clear old data or handle gracefully
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Clear stored exportKey from localStorage
|
|
121
|
+
*/
|
|
122
|
+
private clearStoredExportKey(): void {
|
|
123
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
window.localStorage.removeItem(EXPORT_KEY_STORAGE_KEY);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error("Failed to clear exportKey from localStorage:", error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Ensure exportKey is ready before use
|
|
136
|
+
*/
|
|
137
|
+
private async ensureExportKey(): Promise<void> {
|
|
138
|
+
if (this.exportKey) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Try to recover from localStorage
|
|
143
|
+
await this.recoverExportKey();
|
|
144
|
+
|
|
145
|
+
// If still not available, generate a new one
|
|
146
|
+
if (!this.exportKey) {
|
|
147
|
+
await this.generateAndStoreExportKey();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CubeConnect } from "./cube-connect";
|
|
2
|
+
import { CubeExportService } from "./cube-export";
|
|
3
|
+
import { CubeAccountService } from "./cube-account";
|
|
4
|
+
import { CubeMfaService } from "./cube-mfa";
|
|
5
|
+
import { CubeSignService } from "./cube-sign";
|
|
6
|
+
|
|
7
|
+
export * from "./const";
|
|
8
|
+
|
|
9
|
+
export { CubeConnect, CubeExportService, CubeAccountService, CubeMfaService, CubeSignService };
|
|
10
|
+
|
|
11
|
+
export * from "./types";
|
|
12
|
+
|
|
13
|
+
export type { SessionData } from "./cube-libs";
|
|
14
|
+
import { CubeConfig } from "./types";
|
|
15
|
+
export type { CubeConfig };
|
package/src/passkey.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { cache, CubeStage, RelayOrigins, TomoStage } from "@tomo-inc/wallet-utils";
|
|
2
|
+
import { UserToken } from "./types";
|
|
3
|
+
|
|
4
|
+
const RELAY_NAME = "passkey-relay";
|
|
5
|
+
const SENDER_NAME = "cubist-sdk";
|
|
6
|
+
|
|
7
|
+
let passkeyRelayWindow: any = null;
|
|
8
|
+
let windowCloseInterval: NodeJS.Timeout | null = null;
|
|
9
|
+
|
|
10
|
+
export interface CubeRelayConfig {
|
|
11
|
+
rpId: string;
|
|
12
|
+
tomoStage: TomoStage;
|
|
13
|
+
cubeStage?: CubeStage;
|
|
14
|
+
tomoClientId: string;
|
|
15
|
+
oidcToken?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const openWindow = ({ url, name, width, height }: any): Window | null => {
|
|
19
|
+
const RN = (window as any).ReactNativeWebView;
|
|
20
|
+
if (RN) {
|
|
21
|
+
const message = {
|
|
22
|
+
url,
|
|
23
|
+
name,
|
|
24
|
+
};
|
|
25
|
+
RN.postMessage(
|
|
26
|
+
JSON.stringify({
|
|
27
|
+
type: "OPEN_PASSKEY_RELAY",
|
|
28
|
+
message,
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
closed: false,
|
|
34
|
+
postMessage: (message: any) => {
|
|
35
|
+
RN.postMessage(
|
|
36
|
+
JSON.stringify({
|
|
37
|
+
type: "PASSKEY_RELAY_MESSAGE",
|
|
38
|
+
message,
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
},
|
|
42
|
+
} as any;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const top = (window.innerHeight - (height || 400)) / 2 + window.screenY;
|
|
46
|
+
const left = (window.innerWidth - (width || 400)) / 2 + window.screenX;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const relyWindow = window.open(
|
|
50
|
+
url,
|
|
51
|
+
name,
|
|
52
|
+
`dialog=yes,top=${top}px,left=${left},width=${width !== undefined ? width : 400}px,height=${height !== undefined ? height : 600}px`,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Fallback to iframe modal if:
|
|
56
|
+
// 1. window.open is blocked by browser
|
|
57
|
+
// 2. iOS Safari requires user interaction for window.open
|
|
58
|
+
if (!relyWindow) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return relyWindow;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("Failed to open window:", error);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const closeWindow = () => {
|
|
70
|
+
try {
|
|
71
|
+
if (passkeyRelayWindow && !passkeyRelayWindow.closed) {
|
|
72
|
+
passkeyRelayWindow.close();
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error("Failed to close window:", error);
|
|
76
|
+
} finally {
|
|
77
|
+
passkeyRelayWindow = null;
|
|
78
|
+
if (windowCloseInterval) {
|
|
79
|
+
clearInterval(windowCloseInterval);
|
|
80
|
+
windowCloseInterval = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// const addWindowCloseListener = (onClose: () => void) => {
|
|
86
|
+
// if (windowCloseInterval) {
|
|
87
|
+
// clearInterval(windowCloseInterval);
|
|
88
|
+
// }
|
|
89
|
+
|
|
90
|
+
// windowCloseInterval = setInterval(() => {
|
|
91
|
+
// if (passkeyRelayWindow && passkeyRelayWindow.closed) {
|
|
92
|
+
// console.log("Passkey window was closed by user");
|
|
93
|
+
// onClose();
|
|
94
|
+
// if (windowCloseInterval) {
|
|
95
|
+
// clearInterval(windowCloseInterval);
|
|
96
|
+
// windowCloseInterval = null;
|
|
97
|
+
// }
|
|
98
|
+
// passkeyRelayWindow = null;
|
|
99
|
+
// }
|
|
100
|
+
// }, 1000);
|
|
101
|
+
// };
|
|
102
|
+
|
|
103
|
+
// const removeWindowCloseListener = () => {
|
|
104
|
+
// if (windowCloseInterval) {
|
|
105
|
+
// clearInterval(windowCloseInterval);
|
|
106
|
+
// windowCloseInterval = null;
|
|
107
|
+
// }
|
|
108
|
+
// };
|
|
109
|
+
|
|
110
|
+
export const sendPasskeyMessage = async (message: any, tomoStage: TomoStage) => {
|
|
111
|
+
if (passkeyRelayWindow === null) {
|
|
112
|
+
throw new Error("Failed to open relay window");
|
|
113
|
+
}
|
|
114
|
+
const origin = RelayOrigins[tomoStage] || RelayOrigins["dev"];
|
|
115
|
+
passkeyRelayWindow.postMessage({ ...message, from: SENDER_NAME }, origin);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const initPasskeyPage = async (config: CubeRelayConfig): Promise<UserToken> => {
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
config = (config || cache.get("cubeConfig")) as CubeRelayConfig;
|
|
121
|
+
if (!config.oidcToken || !config.tomoClientId) {
|
|
122
|
+
reject({ message: "oidcToken/tomoClientId is required" });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const PASSKEY_ORIGIN = RelayOrigins[config.tomoStage];
|
|
127
|
+
if (!PASSKEY_ORIGIN) {
|
|
128
|
+
reject({ message: "tomoStage must be dev/pre/prod." });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
passkeyRelayWindow = openWindow({
|
|
133
|
+
url: `${PASSKEY_ORIGIN}/passkey?origin=${window.location.origin}`,
|
|
134
|
+
name: "relay-passkey",
|
|
135
|
+
width: 400,
|
|
136
|
+
height: 600,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const handleMessage = (event: MessageEvent) => {
|
|
140
|
+
const { type, data, from, error } = event.data;
|
|
141
|
+
|
|
142
|
+
if (type === "passkey-relay-loaded" && from === RELAY_NAME) {
|
|
143
|
+
sendPasskeyMessage({ type: "init", params: config }, config.tomoStage);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (type === "passkey-relay-init" && from === RELAY_NAME) {
|
|
147
|
+
window.removeEventListener("message", handleMessage);
|
|
148
|
+
resolve(data);
|
|
149
|
+
}
|
|
150
|
+
// else if (type === "error" || type === "cancel") {
|
|
151
|
+
// window.removeEventListener("message", handleMessage);
|
|
152
|
+
// reject(new Error(error || "Passkey initialization cancelled"));
|
|
153
|
+
// }
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// addWindowCloseListener(() => {
|
|
157
|
+
// window.removeEventListener("message", handleMessage);
|
|
158
|
+
// reject(new Error("Passkey window was closed by user"));
|
|
159
|
+
// });
|
|
160
|
+
|
|
161
|
+
window.addEventListener("message", handleMessage);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const addPasskey = async (
|
|
166
|
+
params: { fidoName: string; receipt?: any },
|
|
167
|
+
config: CubeRelayConfig,
|
|
168
|
+
): Promise<any> => {
|
|
169
|
+
if (!passkeyRelayWindow) {
|
|
170
|
+
await initPasskeyPage(config);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
const handleMessage = (event: MessageEvent) => {
|
|
175
|
+
const { type, data, from, error } = event.data;
|
|
176
|
+
|
|
177
|
+
if (type === "passkey-relay-addFido" && from === RELAY_NAME) {
|
|
178
|
+
window.removeEventListener("message", handleMessage);
|
|
179
|
+
// removeWindowCloseListener();
|
|
180
|
+
resolve(data);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// addWindowCloseListener(() => {
|
|
185
|
+
// window.removeEventListener("message", handleMessage);
|
|
186
|
+
// reject(new Error("Add passkey window was closed by user"));
|
|
187
|
+
// });
|
|
188
|
+
|
|
189
|
+
window.addEventListener("message", handleMessage);
|
|
190
|
+
sendPasskeyMessage({ type: "addFido", params }, config.tomoStage);
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const verifyPasskey = async (params: { mfaId: string }, config: CubeRelayConfig): Promise<any> => {
|
|
195
|
+
if (!passkeyRelayWindow) {
|
|
196
|
+
await initPasskeyPage(config);
|
|
197
|
+
}
|
|
198
|
+
return new Promise((resolve, reject) => {
|
|
199
|
+
const handleMessage = (event: MessageEvent) => {
|
|
200
|
+
const { type, data: receipt, from, error } = event.data;
|
|
201
|
+
|
|
202
|
+
if (type === "passkey-relay-verify" && from === RELAY_NAME) {
|
|
203
|
+
window.removeEventListener("message", handleMessage);
|
|
204
|
+
// removeWindowCloseListener();
|
|
205
|
+
resolve(receipt);
|
|
206
|
+
}
|
|
207
|
+
// else if (type === "error" || type === "cancel") {
|
|
208
|
+
// window.removeEventListener("message", handleMessage);
|
|
209
|
+
// reject(new Error(error || "Passkey verification cancelled"));
|
|
210
|
+
// }
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// addWindowCloseListener(() => {
|
|
214
|
+
// window.removeEventListener("message", handleMessage);
|
|
215
|
+
// reject(new Error("Verify passkey window was closed by user"));
|
|
216
|
+
// });
|
|
217
|
+
|
|
218
|
+
window.addEventListener("message", handleMessage);
|
|
219
|
+
sendPasskeyMessage({ type: "verify", params }, config.tomoStage);
|
|
220
|
+
});
|
|
221
|
+
};
|
package/src/signature.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import CryptoJS from "crypto-js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cube signature generation function
|
|
5
|
+
* @param cubeToken - Cube token
|
|
6
|
+
* @param salt - salt, default is "dev@tomo"
|
|
7
|
+
* @returns signed request object
|
|
8
|
+
*/
|
|
9
|
+
export const generateCubeSignature = async (data: any, salt: string) => {
|
|
10
|
+
if (!salt) {
|
|
11
|
+
throw new Error("salt is required");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const timestamp = Date.now().toString();
|
|
15
|
+
const req = {
|
|
16
|
+
...data,
|
|
17
|
+
timestamp,
|
|
18
|
+
};
|
|
19
|
+
const reqString = JSON.stringify(req);
|
|
20
|
+
const signature = CryptoJS.SHA256(reqString + salt).toString();
|
|
21
|
+
|
|
22
|
+
return { timestamp, signature };
|
|
23
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { CubeStage, TomoStage } from "@tomo-inc/wallet-utils";
|
|
2
|
+
|
|
3
|
+
export type MfaType = "fido" | "emailOtp" | "totp";
|
|
4
|
+
|
|
5
|
+
export type SeedPhrase = any;
|
|
6
|
+
|
|
7
|
+
export interface MfaInfo {
|
|
8
|
+
success?: boolean;
|
|
9
|
+
message?: string;
|
|
10
|
+
data?: any;
|
|
11
|
+
error?: string;
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
type: MfaType;
|
|
15
|
+
status: {
|
|
16
|
+
allowed_approvers: string[];
|
|
17
|
+
allowed_mfa_types: string[];
|
|
18
|
+
approved_by: any;
|
|
19
|
+
count: number;
|
|
20
|
+
num_auth_factors: 1;
|
|
21
|
+
};
|
|
22
|
+
created_at: number;
|
|
23
|
+
created_by: string;
|
|
24
|
+
expires_at: number;
|
|
25
|
+
provenance: string;
|
|
26
|
+
receipt: any;
|
|
27
|
+
related_ids: string[];
|
|
28
|
+
request: {
|
|
29
|
+
body: any;
|
|
30
|
+
method: "DELETE" | "POST" | "PUT" | "DELETE" | "GET";
|
|
31
|
+
path: string;
|
|
32
|
+
};
|
|
33
|
+
verifyStatus?: "pending" | "approved" | "rejected";
|
|
34
|
+
mfaRequired?: {
|
|
35
|
+
fido: boolean;
|
|
36
|
+
totp: boolean;
|
|
37
|
+
emailOtp: boolean | number; //seconds
|
|
38
|
+
emailOtpRemainTime: number;
|
|
39
|
+
} | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type BizType =
|
|
43
|
+
| "createSession"
|
|
44
|
+
| "addFido"
|
|
45
|
+
| "deleteFido"
|
|
46
|
+
| "registerTotp"
|
|
47
|
+
| "registerEmailOtp"
|
|
48
|
+
| "deleteTotp"
|
|
49
|
+
| "initExport"
|
|
50
|
+
| "completeExport";
|
|
51
|
+
|
|
52
|
+
export interface MfaReceipt {
|
|
53
|
+
mfaId: string;
|
|
54
|
+
mfaConf: string;
|
|
55
|
+
mfaOrgId: string;
|
|
56
|
+
}
|
|
57
|
+
export type MfaRequest = any;
|
|
58
|
+
|
|
59
|
+
export interface MfaAnswer {
|
|
60
|
+
totpCode?: string;
|
|
61
|
+
email?: string;
|
|
62
|
+
emailCode?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface MfaVerifyResult {
|
|
66
|
+
success: boolean;
|
|
67
|
+
receipt: any;
|
|
68
|
+
error?: any;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface MfaFinishResult {
|
|
72
|
+
success: boolean;
|
|
73
|
+
error?: any;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type AccountType = "google" | "x" | "email";
|
|
77
|
+
|
|
78
|
+
export interface CubeAccount {
|
|
79
|
+
userId: string;
|
|
80
|
+
name: string;
|
|
81
|
+
email: string;
|
|
82
|
+
otpEmail: string;
|
|
83
|
+
accountType: AccountType;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface MfaConfig {
|
|
87
|
+
noMfa: boolean;
|
|
88
|
+
hasMfa: boolean;
|
|
89
|
+
account: CubeAccount;
|
|
90
|
+
emailOtp: {
|
|
91
|
+
data: string;
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
};
|
|
94
|
+
fido: {
|
|
95
|
+
data: FidoKey[];
|
|
96
|
+
enabled: boolean;
|
|
97
|
+
};
|
|
98
|
+
totp: {
|
|
99
|
+
data: any;
|
|
100
|
+
enabled: boolean;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type OidcSessionResp = any;
|
|
105
|
+
export type CubeSignerClient = any;
|
|
106
|
+
export type ApiClient = any;
|
|
107
|
+
|
|
108
|
+
export interface CubeUserInfo {
|
|
109
|
+
user_id: string;
|
|
110
|
+
mfa: FidoKey[];
|
|
111
|
+
name?: string;
|
|
112
|
+
email?: string;
|
|
113
|
+
org_ids?: string[];
|
|
114
|
+
orgs?: any[];
|
|
115
|
+
verified_email?: {
|
|
116
|
+
email?: string;
|
|
117
|
+
updated_at?: number;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface TotpInfo {
|
|
122
|
+
id: string;
|
|
123
|
+
url: string;
|
|
124
|
+
secret: string;
|
|
125
|
+
issuer: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface FidoKey {
|
|
129
|
+
type: string;
|
|
130
|
+
id: string;
|
|
131
|
+
name: string;
|
|
132
|
+
updated_at: string;
|
|
133
|
+
status: string;
|
|
134
|
+
user_id: string;
|
|
135
|
+
discoverable: boolean;
|
|
136
|
+
created_at: number;
|
|
137
|
+
last_used_at: number;
|
|
138
|
+
aaguid: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface CubeIdentity {
|
|
142
|
+
id: string;
|
|
143
|
+
preferred_username?: string;
|
|
144
|
+
aud?: any;
|
|
145
|
+
email?: string;
|
|
146
|
+
identity?: {
|
|
147
|
+
iss: string;
|
|
148
|
+
sub: string;
|
|
149
|
+
};
|
|
150
|
+
user_info?: {
|
|
151
|
+
user_id?: string;
|
|
152
|
+
initialized?: boolean;
|
|
153
|
+
configured_mfa?: any[];
|
|
154
|
+
};
|
|
155
|
+
exp_epoch?: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface SeedPhraseExportInfo {
|
|
159
|
+
ready: boolean;
|
|
160
|
+
keyId?: string;
|
|
161
|
+
lastTime?: number;
|
|
162
|
+
duration?: number;
|
|
163
|
+
valid_epoch?: number;
|
|
164
|
+
exp_epoch?: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface CubeRes {
|
|
168
|
+
success: boolean;
|
|
169
|
+
error?: any;
|
|
170
|
+
data?: any;
|
|
171
|
+
message?: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface Mfa {
|
|
175
|
+
created_at?: number;
|
|
176
|
+
created_by: string;
|
|
177
|
+
expires_at: number;
|
|
178
|
+
id: string;
|
|
179
|
+
not_valid_until?: number;
|
|
180
|
+
provenance: "EditPolicy" | "Key" | "Role" | "KeyInRole" | "User";
|
|
181
|
+
receipt?: { confirmation: string; final_approver: string; timestamp: number };
|
|
182
|
+
related_ids?: string[];
|
|
183
|
+
request: { body?: Record<string, unknown>; method: string; path: string };
|
|
184
|
+
status: {
|
|
185
|
+
allowed_approvers: string[];
|
|
186
|
+
allowed_mfa_types?: string[];
|
|
187
|
+
approved_by: { [key: string]: object };
|
|
188
|
+
count: number;
|
|
189
|
+
num_auth_factors: number;
|
|
190
|
+
request_comparer?:
|
|
191
|
+
| "Eq"
|
|
192
|
+
| { EvmTx: { grace?: number; ignore_gas?: boolean; ignore_nonce?: boolean } }
|
|
193
|
+
| { SolanaTx: { ignore_blockhash?: boolean } };
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface UserToken {
|
|
198
|
+
accessToken: string;
|
|
199
|
+
refreshToken: string;
|
|
200
|
+
expireTime: number;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface User {
|
|
204
|
+
userId: string;
|
|
205
|
+
userID?: string;
|
|
206
|
+
accountID?: string;
|
|
207
|
+
tenantID?: string;
|
|
208
|
+
username?: string;
|
|
209
|
+
nickname: string;
|
|
210
|
+
avatar: string;
|
|
211
|
+
freePasswordAuth?: string;
|
|
212
|
+
forbidden?: boolean;
|
|
213
|
+
deleted?: boolean;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface UserAddressType {
|
|
217
|
+
bitcoinP2pkhAddress: string;
|
|
218
|
+
bitcoinP2trAddress: string;
|
|
219
|
+
bitcoinP2shAddress: string;
|
|
220
|
+
bitcoinP2wpkhAddress: string;
|
|
221
|
+
ethereumAddress: string;
|
|
222
|
+
solanaAddress: string;
|
|
223
|
+
tronAddress: string;
|
|
224
|
+
tonAddressTest: string;
|
|
225
|
+
tonAddress: string;
|
|
226
|
+
tonPublicKey: string;
|
|
227
|
+
suiAddress: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface LoginRes {
|
|
231
|
+
userToken?: UserToken;
|
|
232
|
+
user: User;
|
|
233
|
+
accountBaseInfo: any;
|
|
234
|
+
accountWallet: any;
|
|
235
|
+
walletId?: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export enum LoginError {
|
|
239
|
+
FIDO_NOT_ALLOWED = "NotAllowedError",
|
|
240
|
+
MFA_NOT_APPROVED = "MFA not approved yet",
|
|
241
|
+
MFA_REQUIRED = "MFA should not be required after approval",
|
|
242
|
+
OIDC_TOKEN_NOT_FOUND = "Oidc token not found",
|
|
243
|
+
CUBE_IDENTITY_NOT_FOUND = "Cube identity not found",
|
|
244
|
+
CUBE_USER_INFO_NOT_FOUND = "Cube user info not found",
|
|
245
|
+
OIDC_TOKEN_EXPIRED = "ExpiredSignature",
|
|
246
|
+
FAILED_OPEN_POPUP = "Failed to open popup window",
|
|
247
|
+
OAUTH_LOGIN_TIMEOUT = "OAuth login timeout",
|
|
248
|
+
USER_CANCELLED_LOGIN = "User cancelled login",
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface CubeConfig {
|
|
252
|
+
rpId?: string;
|
|
253
|
+
tomoStage: TomoStage;
|
|
254
|
+
cubeSalt?: string;
|
|
255
|
+
cubeStage?: CubeStage;
|
|
256
|
+
tomoClientId: string;
|
|
257
|
+
jwtToken?: string;
|
|
258
|
+
oidcToken?: string;
|
|
259
|
+
name?: string;
|
|
260
|
+
logo?: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface CubeConnectResult {
|
|
264
|
+
walletId: string;
|
|
265
|
+
session: object;
|
|
266
|
+
accountWallet: Record<string, any>;
|
|
267
|
+
token: object;
|
|
268
|
+
user: Record<string, any>;
|
|
269
|
+
}
|