signer-test-sdk-core 0.0.1
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 +81 -0
- package/dist/src/components/OnboardingUI/auth.d.ts +158 -0
- package/dist/src/components/OnboardingUI/auth.js +230 -0
- package/dist/src/components/OnboardingUI/auth.js.map +1 -0
- package/dist/src/components/OnboardingUI/index.d.ts +9 -0
- package/dist/src/components/OnboardingUI/index.js +9 -0
- package/dist/src/components/OnboardingUI/index.js.map +1 -0
- package/dist/src/components/OnboardingUI/types.d.ts +159 -0
- package/dist/src/components/OnboardingUI/types.js +5 -0
- package/dist/src/components/OnboardingUI/types.js.map +1 -0
- package/dist/src/core/AbstraxnWallet.d.ts +162 -0
- package/dist/src/core/AbstraxnWallet.js +593 -0
- package/dist/src/core/AbstraxnWallet.js.map +1 -0
- package/dist/src/core/AuthManager.d.ts +112 -0
- package/dist/src/core/AuthManager.js +685 -0
- package/dist/src/core/AuthManager.js.map +1 -0
- package/dist/src/core/Signer.d.ts +35 -0
- package/dist/src/core/Signer.js +156 -0
- package/dist/src/core/Signer.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +19 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/IAuth.d.ts +26 -0
- package/dist/src/interfaces/IAuth.js +2 -0
- package/dist/src/interfaces/IAuth.js.map +1 -0
- package/dist/src/interfaces/ISigner.d.ts +14 -0
- package/dist/src/interfaces/ISigner.js +2 -0
- package/dist/src/interfaces/ISigner.js.map +1 -0
- package/dist/src/interfaces/IStorage.d.ts +15 -0
- package/dist/src/interfaces/IStorage.js +2 -0
- package/dist/src/interfaces/IStorage.js.map +1 -0
- package/dist/src/interfaces/IWallet.d.ts +45 -0
- package/dist/src/interfaces/IWallet.js +2 -0
- package/dist/src/interfaces/IWallet.js.map +1 -0
- package/dist/src/services/ApiService.d.ts +131 -0
- package/dist/src/services/ApiService.js +626 -0
- package/dist/src/services/ApiService.js.map +1 -0
- package/dist/src/services/TokenService.d.ts +29 -0
- package/dist/src/services/TokenService.js +40 -0
- package/dist/src/services/TokenService.js.map +1 -0
- package/dist/src/services/TurnkeyService.d.ts +54 -0
- package/dist/src/services/TurnkeyService.js +91 -0
- package/dist/src/services/TurnkeyService.js.map +1 -0
- package/dist/src/storage/IndexedDBStorage.d.ts +39 -0
- package/dist/src/storage/IndexedDBStorage.js +280 -0
- package/dist/src/storage/IndexedDBStorage.js.map +1 -0
- package/dist/src/utils/constants.d.ts +52 -0
- package/dist/src/utils/constants.js +78 -0
- package/dist/src/utils/constants.js.map +1 -0
- package/dist/src/utils/errors.d.ts +23 -0
- package/dist/src/utils/errors.js +48 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/helpers.d.ts +12 -0
- package/dist/src/utils/helpers.js +30 -0
- package/dist/src/utils/helpers.js.map +1 -0
- package/dist/src/utils/passkey.d.ts +33 -0
- package/dist/src/utils/passkey.js +122 -0
- package/dist/src/utils/passkey.js.map +1 -0
- package/dist/src/utils/types.d.ts +182 -0
- package/dist/src/utils/types.js +5 -0
- package/dist/src/utils/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import { AuthManager } from './AuthManager';
|
|
2
|
+
import { Signer } from './Signer';
|
|
3
|
+
import { ApiService } from '../services/ApiService';
|
|
4
|
+
import { TurnkeyService } from '../services/TurnkeyService';
|
|
5
|
+
import { TokenService } from '../services/TokenService';
|
|
6
|
+
import { IndexedDBStorage } from '../storage/IndexedDBStorage';
|
|
7
|
+
import { WalletNotConnectedError, AuthenticationError } from '../utils/errors';
|
|
8
|
+
import { DEFAULT_CHAIN_ID, SUPPORTED_CHAINS } from '../utils/constants';
|
|
9
|
+
export class AbstraxnWallet {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.isConnected = false;
|
|
13
|
+
this.address = null;
|
|
14
|
+
this.user = null;
|
|
15
|
+
this.signer = null;
|
|
16
|
+
this.eventHandlers = new Map();
|
|
17
|
+
this.initialized = false;
|
|
18
|
+
// Initialize services
|
|
19
|
+
const storage = new IndexedDBStorage();
|
|
20
|
+
const turnkeyService = new TurnkeyService();
|
|
21
|
+
const tokenService = new TokenService(storage);
|
|
22
|
+
const apiService = new ApiService(config.apiKey, tokenService, turnkeyService);
|
|
23
|
+
this.authManager = new AuthManager(apiService, turnkeyService, tokenService, storage);
|
|
24
|
+
this.currentChainId = config.defaultChainId || DEFAULT_CHAIN_ID;
|
|
25
|
+
// Auto-connect if enabled
|
|
26
|
+
if (config.autoConnect) {
|
|
27
|
+
this.initialize().catch((error) => {
|
|
28
|
+
if (config.enableLogging) {
|
|
29
|
+
console.error('Auto-connect failed:', error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Initialize wallet
|
|
36
|
+
*/
|
|
37
|
+
async initialize() {
|
|
38
|
+
if (this.initialized) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// Initialize Turnkey (internal)
|
|
43
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
44
|
+
await turnkeyService.init();
|
|
45
|
+
// Load user from storage
|
|
46
|
+
await this.authManager.loadUserFromStorage();
|
|
47
|
+
// Check if authenticated
|
|
48
|
+
const isAuthenticated = await this.authManager.isAuthenticated();
|
|
49
|
+
if (isAuthenticated) {
|
|
50
|
+
this.user = this.authManager.getCurrentUser();
|
|
51
|
+
this.isConnected = true;
|
|
52
|
+
// Get address from whoami response if available
|
|
53
|
+
await this.loadAddressFromWhoami();
|
|
54
|
+
this.emit('connect');
|
|
55
|
+
}
|
|
56
|
+
this.initialized = true;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (this.config.enableLogging) {
|
|
60
|
+
console.error('Initialization error:', error);
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Connect wallet
|
|
67
|
+
*/
|
|
68
|
+
async connect() {
|
|
69
|
+
if (!this.initialized) {
|
|
70
|
+
await this.initialize();
|
|
71
|
+
}
|
|
72
|
+
// If already connected, return
|
|
73
|
+
if (this.isConnected && this.user) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Check if user is authenticated
|
|
77
|
+
const isAuthenticated = await this.authManager.isAuthenticated();
|
|
78
|
+
if (isAuthenticated) {
|
|
79
|
+
this.user = this.authManager.getCurrentUser();
|
|
80
|
+
this.isConnected = true;
|
|
81
|
+
// Get address from whoami response if available
|
|
82
|
+
await this.loadAddressFromWhoami();
|
|
83
|
+
this.emit('connect');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// If not authenticated, user needs to login
|
|
87
|
+
// This will be handled by the UI components
|
|
88
|
+
throw new AuthenticationError('User not authenticated. Please login first.');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Disconnect wallet
|
|
92
|
+
*/
|
|
93
|
+
async disconnect() {
|
|
94
|
+
await this.authManager.logout();
|
|
95
|
+
// Clear IndexedDB (Turnkey keys)
|
|
96
|
+
try {
|
|
97
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
98
|
+
const storage = turnkeyService.getStorage();
|
|
99
|
+
await storage.clearIndexedDB();
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (this.config.enableLogging) {
|
|
103
|
+
console.warn('Failed to clear IndexedDB:', error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.isConnected = false;
|
|
107
|
+
this.address = null;
|
|
108
|
+
this.user = null;
|
|
109
|
+
this.signer = null;
|
|
110
|
+
this.emit('disconnect');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get whoami information
|
|
114
|
+
*/
|
|
115
|
+
async getWhoami() {
|
|
116
|
+
if (!this.isConnected || !this.user) {
|
|
117
|
+
throw new WalletNotConnectedError();
|
|
118
|
+
}
|
|
119
|
+
return await this.authManager.getWhoami();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Refresh whoami by making a fresh API call
|
|
123
|
+
* This bypasses the cache and always calls the API
|
|
124
|
+
*/
|
|
125
|
+
async refreshWhoami() {
|
|
126
|
+
if (!this.isConnected || !this.user) {
|
|
127
|
+
throw new WalletNotConnectedError();
|
|
128
|
+
}
|
|
129
|
+
return await this.authManager.refreshWhoami();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Load address from whoami response
|
|
133
|
+
* Backend whoami response includes address directly
|
|
134
|
+
*/
|
|
135
|
+
async loadAddressFromWhoami() {
|
|
136
|
+
try {
|
|
137
|
+
const whoami = await this.authManager.getWhoami();
|
|
138
|
+
if (whoami) {
|
|
139
|
+
// Backend whoami response includes address directly
|
|
140
|
+
if (whoami.address) {
|
|
141
|
+
this.address = whoami.address;
|
|
142
|
+
}
|
|
143
|
+
else if (whoami.wallets && whoami.wallets.length > 0) {
|
|
144
|
+
// Fallback: try to get address from wallets if available
|
|
145
|
+
const firstWallet = whoami.wallets[0];
|
|
146
|
+
if (firstWallet.accounts && firstWallet.accounts.length > 0) {
|
|
147
|
+
this.address = firstWallet.accounts[0].address;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (this.config.enableLogging) {
|
|
154
|
+
console.warn('Failed to load address from whoami:', error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get wallet address
|
|
160
|
+
*/
|
|
161
|
+
async getAddress() {
|
|
162
|
+
if (!this.isConnected || !this.user) {
|
|
163
|
+
throw new WalletNotConnectedError();
|
|
164
|
+
}
|
|
165
|
+
// Try to load address from whoami if not already loaded
|
|
166
|
+
if (!this.address) {
|
|
167
|
+
await this.loadAddressFromWhoami();
|
|
168
|
+
}
|
|
169
|
+
if (!this.address) {
|
|
170
|
+
throw new Error('Address not available. Please ensure wallet is fully initialized.');
|
|
171
|
+
}
|
|
172
|
+
return this.address;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get current chain ID
|
|
176
|
+
*/
|
|
177
|
+
async getChainId() {
|
|
178
|
+
return this.currentChainId;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Switch chain
|
|
182
|
+
*/
|
|
183
|
+
async switchChain(chainId) {
|
|
184
|
+
const chain = this.config.supportedChains?.find((c) => c.id === chainId) ||
|
|
185
|
+
SUPPORTED_CHAINS.find((c) => c.id === chainId);
|
|
186
|
+
if (!chain) {
|
|
187
|
+
throw new Error(`Chain ${chainId} is not supported`);
|
|
188
|
+
}
|
|
189
|
+
this.currentChainId = chainId;
|
|
190
|
+
this.emit('chainChanged', chainId);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get user information
|
|
194
|
+
*/
|
|
195
|
+
async getUserInfo() {
|
|
196
|
+
if (!this.isConnected || !this.user) {
|
|
197
|
+
throw new WalletNotConnectedError();
|
|
198
|
+
}
|
|
199
|
+
return this.user;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Sign transaction
|
|
203
|
+
*/
|
|
204
|
+
async signTransaction(tx) {
|
|
205
|
+
if (!this.isConnected || !this.user) {
|
|
206
|
+
throw new WalletNotConnectedError();
|
|
207
|
+
}
|
|
208
|
+
if (!this.signer) {
|
|
209
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
210
|
+
const apiService = this.authManager.apiService;
|
|
211
|
+
const chain = this.config.supportedChains?.find((c) => c.id === this.currentChainId) ||
|
|
212
|
+
SUPPORTED_CHAINS.find((c) => c.id === this.currentChainId);
|
|
213
|
+
this.signer = new Signer(apiService, turnkeyService, this.user.subOrganizationId, chain?.rpcUrl);
|
|
214
|
+
}
|
|
215
|
+
return await this.signer.signTransaction(tx);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Send transaction
|
|
219
|
+
*/
|
|
220
|
+
async sendTransaction(tx) {
|
|
221
|
+
if (!this.isConnected || !this.user) {
|
|
222
|
+
throw new WalletNotConnectedError();
|
|
223
|
+
}
|
|
224
|
+
if (!this.signer) {
|
|
225
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
226
|
+
const apiService = this.authManager.apiService;
|
|
227
|
+
const chain = this.config.supportedChains?.find((c) => c.id === this.currentChainId) ||
|
|
228
|
+
SUPPORTED_CHAINS.find((c) => c.id === this.currentChainId);
|
|
229
|
+
this.signer = new Signer(apiService, turnkeyService, this.user.subOrganizationId, chain?.rpcUrl);
|
|
230
|
+
}
|
|
231
|
+
return await this.signer.sendTransaction(tx);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Sign transaction using backend API
|
|
235
|
+
* Returns the signed transaction that can be executed by the user
|
|
236
|
+
*/
|
|
237
|
+
async signTransactionViaAPI(unsignedTransaction, fromAddress) {
|
|
238
|
+
if (!this.isConnected || !this.user) {
|
|
239
|
+
throw new WalletNotConnectedError();
|
|
240
|
+
}
|
|
241
|
+
const apiService = this.authManager.apiService;
|
|
242
|
+
const organizationId = this.user.subOrganizationId;
|
|
243
|
+
// Sign transaction via backend API
|
|
244
|
+
const response = await apiService.signTransactionViaBackend(unsignedTransaction, fromAddress, organizationId);
|
|
245
|
+
const signedTransaction = response.signedTransaction;
|
|
246
|
+
if (!signedTransaction) {
|
|
247
|
+
throw new Error('No signed transaction found in response');
|
|
248
|
+
}
|
|
249
|
+
// Ensure signed transaction has 0x prefix
|
|
250
|
+
const signedTx = signedTransaction.startsWith('0x')
|
|
251
|
+
? signedTransaction
|
|
252
|
+
: `0x${signedTransaction}`;
|
|
253
|
+
return { signedTransaction: signedTx };
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Sign and send transaction using backend API
|
|
257
|
+
* This method uses the /sign/transaction endpoint with Bearer token authentication
|
|
258
|
+
* Gets signature from API and then executes the transaction internally
|
|
259
|
+
*/
|
|
260
|
+
async signAndSendTransaction(unsignedTransaction, fromAddress, rpcUrl) {
|
|
261
|
+
if (!this.isConnected || !this.user) {
|
|
262
|
+
throw new WalletNotConnectedError();
|
|
263
|
+
}
|
|
264
|
+
// Sign transaction via backend API
|
|
265
|
+
const { signedTransaction } = await this.signTransactionViaAPI(unsignedTransaction, fromAddress);
|
|
266
|
+
// Get RPC URL
|
|
267
|
+
const chain = this.config.supportedChains?.find((c) => c.id === this.currentChainId) ||
|
|
268
|
+
SUPPORTED_CHAINS.find((c) => c.id === this.currentChainId);
|
|
269
|
+
const targetRpcUrl = rpcUrl || chain?.rpcUrl;
|
|
270
|
+
if (!targetRpcUrl) {
|
|
271
|
+
throw new Error('RPC URL not configured');
|
|
272
|
+
}
|
|
273
|
+
// Send transaction to network
|
|
274
|
+
try {
|
|
275
|
+
const fetchResponse = await fetch(targetRpcUrl, {
|
|
276
|
+
method: 'POST',
|
|
277
|
+
headers: {
|
|
278
|
+
'Content-Type': 'application/json',
|
|
279
|
+
},
|
|
280
|
+
body: JSON.stringify({
|
|
281
|
+
jsonrpc: '2.0',
|
|
282
|
+
method: 'eth_sendRawTransaction',
|
|
283
|
+
params: [signedTransaction],
|
|
284
|
+
id: 1,
|
|
285
|
+
}),
|
|
286
|
+
});
|
|
287
|
+
const data = await fetchResponse.json();
|
|
288
|
+
if (data.error) {
|
|
289
|
+
throw new Error(data.error.message || 'Transaction failed');
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
hash: data.result,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
throw new Error(error instanceof Error ? error.message : 'Failed to send transaction');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Sign message
|
|
301
|
+
*/
|
|
302
|
+
async signMessage(message) {
|
|
303
|
+
if (!this.isConnected || !this.user) {
|
|
304
|
+
throw new WalletNotConnectedError();
|
|
305
|
+
}
|
|
306
|
+
if (!this.signer) {
|
|
307
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
308
|
+
const apiService = this.authManager.apiService;
|
|
309
|
+
const chain = this.config.supportedChains?.find((c) => c.id === this.currentChainId) ||
|
|
310
|
+
SUPPORTED_CHAINS.find((c) => c.id === this.currentChainId);
|
|
311
|
+
this.signer = new Signer(apiService, turnkeyService, this.user.subOrganizationId, chain?.rpcUrl);
|
|
312
|
+
}
|
|
313
|
+
return await this.signer.signMessage(message);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Sign typed data (EIP-712)
|
|
317
|
+
*/
|
|
318
|
+
async signTypedData(data) {
|
|
319
|
+
if (!this.isConnected || !this.user) {
|
|
320
|
+
throw new WalletNotConnectedError();
|
|
321
|
+
}
|
|
322
|
+
if (!this.signer) {
|
|
323
|
+
const turnkeyService = this.authManager.turnkeyService;
|
|
324
|
+
const apiService = this.authManager.apiService;
|
|
325
|
+
const chain = this.config.supportedChains?.find((c) => c.id === this.currentChainId) ||
|
|
326
|
+
SUPPORTED_CHAINS.find((c) => c.id === this.currentChainId);
|
|
327
|
+
this.signer = new Signer(apiService, turnkeyService, this.user.subOrganizationId, chain?.rpcUrl);
|
|
328
|
+
}
|
|
329
|
+
return await this.signer.signTypedData(data);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get wallets
|
|
333
|
+
*/
|
|
334
|
+
async getWallets() {
|
|
335
|
+
if (!this.isConnected || !this.user) {
|
|
336
|
+
throw new WalletNotConnectedError();
|
|
337
|
+
}
|
|
338
|
+
// This would typically fetch from backend
|
|
339
|
+
// For MVP, return user's wallet info
|
|
340
|
+
return [
|
|
341
|
+
{
|
|
342
|
+
walletId: this.user.subOrganizationId,
|
|
343
|
+
addresses: [], // Would be populated from backend
|
|
344
|
+
chainId: this.currentChainId,
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get wallet addresses
|
|
350
|
+
*/
|
|
351
|
+
async getWalletAddresses(walletId) {
|
|
352
|
+
if (!this.isConnected || !this.user) {
|
|
353
|
+
throw new WalletNotConnectedError();
|
|
354
|
+
}
|
|
355
|
+
// This would typically fetch from backend using walletId
|
|
356
|
+
// For MVP, return empty array
|
|
357
|
+
// TODO: Implement backend call to fetch addresses for walletId
|
|
358
|
+
void walletId; // Acknowledge parameter for future implementation
|
|
359
|
+
return [];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Event system
|
|
363
|
+
*/
|
|
364
|
+
on(event, handler) {
|
|
365
|
+
if (!this.eventHandlers.has(event)) {
|
|
366
|
+
this.eventHandlers.set(event, []);
|
|
367
|
+
}
|
|
368
|
+
this.eventHandlers.get(event).push(handler);
|
|
369
|
+
}
|
|
370
|
+
off(event, handler) {
|
|
371
|
+
const handlers = this.eventHandlers.get(event);
|
|
372
|
+
if (handlers) {
|
|
373
|
+
const index = handlers.indexOf(handler);
|
|
374
|
+
if (index > -1) {
|
|
375
|
+
handlers.splice(index, 1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
emit(event, ...args) {
|
|
380
|
+
const handlers = this.eventHandlers.get(event);
|
|
381
|
+
if (handlers) {
|
|
382
|
+
handlers.forEach((handler) => {
|
|
383
|
+
try {
|
|
384
|
+
handler(...args);
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
if (this.config.enableLogging) {
|
|
388
|
+
console.error(`Error in event handler for ${event}:`, error);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Get auth manager (for advanced usage)
|
|
396
|
+
*/
|
|
397
|
+
getAuthManager() {
|
|
398
|
+
return this.authManager;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Login with email OTP (initiate OTP)
|
|
402
|
+
* Returns otpId that can be used to verify OTP
|
|
403
|
+
*/
|
|
404
|
+
async loginWithOTP(email) {
|
|
405
|
+
return await this.authManager.loginWithOTP(email);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Verify OTP and complete authentication
|
|
409
|
+
*/
|
|
410
|
+
async verifyOTP(otpId, otpCode) {
|
|
411
|
+
const user = await this.authManager.verifyOTP(otpId, otpCode);
|
|
412
|
+
// After successful verification, connect the wallet
|
|
413
|
+
this.user = user;
|
|
414
|
+
this.isConnected = true;
|
|
415
|
+
await this.loadAddressFromWhoami();
|
|
416
|
+
this.emit('connect');
|
|
417
|
+
return user;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Login with Google OAuth
|
|
421
|
+
* This will redirect the user to Google OAuth
|
|
422
|
+
*/
|
|
423
|
+
async loginWithGoogle() {
|
|
424
|
+
return await this.authManager.loginWithGoogle();
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Login with Discord OAuth
|
|
428
|
+
*/
|
|
429
|
+
async loginWithDiscord() {
|
|
430
|
+
return await this.authManager.loginWithDiscord();
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Login with X (Twitter) OAuth
|
|
434
|
+
*/
|
|
435
|
+
async loginWithTwitter() {
|
|
436
|
+
return await this.authManager.loginWithTwitter();
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Handle Google OAuth callback
|
|
440
|
+
* Call this after user returns from Google OAuth redirect
|
|
441
|
+
*/
|
|
442
|
+
async handleGoogleCallback() {
|
|
443
|
+
const user = await this.authManager.handleGoogleCallback();
|
|
444
|
+
if (user) {
|
|
445
|
+
// Verify whoami response exists before setting isConnected
|
|
446
|
+
// handleGoogleCallback() already ensures whoami is called and response exists
|
|
447
|
+
const whoamiResponse = await this.authManager.getWhoami();
|
|
448
|
+
if (!whoamiResponse) {
|
|
449
|
+
// If whoami response is not available, don't set connected
|
|
450
|
+
throw new Error('Whoami response not available. Cannot connect wallet.');
|
|
451
|
+
}
|
|
452
|
+
this.user = user;
|
|
453
|
+
this.isConnected = true;
|
|
454
|
+
await this.loadAddressFromWhoami();
|
|
455
|
+
this.emit('connect');
|
|
456
|
+
}
|
|
457
|
+
return user;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Handle Discord OAuth callback
|
|
461
|
+
*/
|
|
462
|
+
async handleDiscordCallback() {
|
|
463
|
+
const user = await this.authManager.handleDiscordCallback();
|
|
464
|
+
if (user) {
|
|
465
|
+
const whoamiResponse = await this.authManager.getWhoami();
|
|
466
|
+
if (!whoamiResponse) {
|
|
467
|
+
throw new Error('Whoami response not available. Cannot connect wallet.');
|
|
468
|
+
}
|
|
469
|
+
this.user = user;
|
|
470
|
+
this.isConnected = true;
|
|
471
|
+
await this.loadAddressFromWhoami();
|
|
472
|
+
this.emit('connect');
|
|
473
|
+
}
|
|
474
|
+
return user;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Handle X (Twitter) OAuth callback
|
|
478
|
+
*/
|
|
479
|
+
async handleTwitterCallback() {
|
|
480
|
+
const user = await this.authManager.handleTwitterCallback();
|
|
481
|
+
if (user) {
|
|
482
|
+
const whoamiResponse = await this.authManager.getWhoami();
|
|
483
|
+
if (!whoamiResponse) {
|
|
484
|
+
throw new Error('Whoami response not available. Cannot connect wallet.');
|
|
485
|
+
}
|
|
486
|
+
this.user = user;
|
|
487
|
+
this.isConnected = true;
|
|
488
|
+
await this.loadAddressFromWhoami();
|
|
489
|
+
this.emit('connect');
|
|
490
|
+
}
|
|
491
|
+
return user;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Signup with passkey
|
|
495
|
+
*/
|
|
496
|
+
async signupWithPasskey() {
|
|
497
|
+
const user = await this.authManager.signupWithPasskey();
|
|
498
|
+
this.user = user;
|
|
499
|
+
this.isConnected = true;
|
|
500
|
+
await this.loadAddressFromWhoami();
|
|
501
|
+
this.emit('connect');
|
|
502
|
+
return user;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Login with passkey
|
|
506
|
+
*/
|
|
507
|
+
async loginWithPasskey() {
|
|
508
|
+
const user = await this.authManager.loginWithPasskey();
|
|
509
|
+
this.user = user;
|
|
510
|
+
this.isConnected = true;
|
|
511
|
+
await this.loadAddressFromWhoami();
|
|
512
|
+
this.emit('connect');
|
|
513
|
+
return user;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Export wallet
|
|
517
|
+
* Exports the private key for the current wallet account
|
|
518
|
+
* If privateKey is provided, decrypts the bundle and returns the result
|
|
519
|
+
* @param targetPublicKey - The public key to encrypt the export bundle for
|
|
520
|
+
* @param privateKey - private key to decrypt the bundle
|
|
521
|
+
* @param blockchain - blockchain type ('evm' or 'solana'). If not provided, defaults to 'evm'
|
|
522
|
+
*/
|
|
523
|
+
async exportWallet(targetPublicKey, privateKey, blockchain) {
|
|
524
|
+
if (!this.isConnected || !this.user) {
|
|
525
|
+
throw new WalletNotConnectedError();
|
|
526
|
+
}
|
|
527
|
+
// Determine blockchain type (default to 'evm' for backward compatibility)
|
|
528
|
+
const blockchainType = blockchain || 'evm';
|
|
529
|
+
// Load whoami to get the appropriate address
|
|
530
|
+
const whoami = await this.authManager.getWhoami();
|
|
531
|
+
if (!whoami) {
|
|
532
|
+
throw new Error('Whoami information not available. Please ensure wallet is fully initialized.');
|
|
533
|
+
}
|
|
534
|
+
let walletAddress;
|
|
535
|
+
if (blockchainType === 'solana') {
|
|
536
|
+
// Get Solana address from whoami
|
|
537
|
+
walletAddress = whoami.solanaAddress;
|
|
538
|
+
if (!walletAddress) {
|
|
539
|
+
throw new Error('Solana address not found. Please ensure your wallet has a Solana address.');
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
// Get EVM address from whoami
|
|
544
|
+
if (whoami.address) {
|
|
545
|
+
walletAddress = whoami.address;
|
|
546
|
+
}
|
|
547
|
+
else if (whoami.wallets && whoami.wallets.length > 0) {
|
|
548
|
+
// Fallback: try to get address from wallets if available
|
|
549
|
+
const firstWallet = whoami.wallets[0];
|
|
550
|
+
if (firstWallet.accounts && firstWallet.accounts.length > 0) {
|
|
551
|
+
walletAddress = firstWallet.accounts[0].address;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// If still no address, try loading from whoami via existing method
|
|
555
|
+
if (!walletAddress) {
|
|
556
|
+
await this.loadAddressFromWhoami();
|
|
557
|
+
walletAddress = this.address || undefined;
|
|
558
|
+
}
|
|
559
|
+
if (!walletAddress) {
|
|
560
|
+
throw new Error('EVM address not found. Please ensure your wallet has an EVM address.');
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const apiService = this.authManager.apiService;
|
|
564
|
+
const organizationId = this.user.subOrganizationId;
|
|
565
|
+
const response = await apiService.exportWalletAccount(organizationId, walletAddress, targetPublicKey);
|
|
566
|
+
// If privateKey is provided, decrypt the bundle
|
|
567
|
+
if (privateKey) {
|
|
568
|
+
try {
|
|
569
|
+
// Dynamically import to avoid issues if dependency is missing or in environments where crypto is not available
|
|
570
|
+
const { decryptExportBundle } = await import('@turnkey/crypto');
|
|
571
|
+
// Prepare decrypt options
|
|
572
|
+
const decryptOptions = {
|
|
573
|
+
exportBundle: response.exportBundle,
|
|
574
|
+
embeddedKey: privateKey,
|
|
575
|
+
organizationId,
|
|
576
|
+
returnMnemonic: false, // We assume wallet export (private key), not mnemonic
|
|
577
|
+
};
|
|
578
|
+
// Add keyFormat for Solana wallets
|
|
579
|
+
if (blockchainType === 'solana') {
|
|
580
|
+
decryptOptions.keyFormat = 'SOLANA';
|
|
581
|
+
}
|
|
582
|
+
const decryptedBundle = await decryptExportBundle(decryptOptions);
|
|
583
|
+
return decryptedBundle;
|
|
584
|
+
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
console.error('Failed to decrypt export bundle:', error);
|
|
587
|
+
throw new Error(`Failed to decrypt export bundle. Error: ${error}`);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return response.exportBundle;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
//# sourceMappingURL=AbstraxnWallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstraxnWallet.js","sourceRoot":"","sources":["../../../src/core/AbstraxnWallet.ts"],"names":[],"mappings":"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"}
|