pribado-seed-proxy-sdk 2.0.0

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/dist/index.mjs ADDED
@@ -0,0 +1,780 @@
1
+ // src/client.ts
2
+ import { ethers as ethers2 } from "ethers";
3
+
4
+ // src/types.ts
5
+ var SAPPHIRE_MAINNET_CHAIN_ID = 23294;
6
+ var CONTRACT_ADDRESS = "0xabE5D482AceFED95E0D37dA89bC63F941f02f9A0";
7
+ var KEY_TYPE_SEED = 0;
8
+ var KEY_TYPE_PRIVATE_KEY = 1;
9
+ var SeedProxyErrorCode = /* @__PURE__ */ ((SeedProxyErrorCode2) => {
10
+ SeedProxyErrorCode2["INVALID_CONFIG"] = "INVALID_CONFIG";
11
+ SeedProxyErrorCode2["MISSING_API_KEY"] = "MISSING_API_KEY";
12
+ SeedProxyErrorCode2["INVALID_PASSWORD"] = "INVALID_PASSWORD";
13
+ SeedProxyErrorCode2["INVALID_KEY"] = "INVALID_KEY";
14
+ SeedProxyErrorCode2["KEY_NOT_FOUND"] = "KEY_NOT_FOUND";
15
+ SeedProxyErrorCode2["KEY_INACTIVE"] = "KEY_INACTIVE";
16
+ SeedProxyErrorCode2["AUTHENTICATION_FAILED"] = "AUTHENTICATION_FAILED";
17
+ SeedProxyErrorCode2["INVALID_SEED_PHRASE"] = "INVALID_SEED_PHRASE";
18
+ SeedProxyErrorCode2["INVALID_PRIVATE_KEY"] = "INVALID_PRIVATE_KEY";
19
+ SeedProxyErrorCode2["INVALID_ADDRESS"] = "INVALID_ADDRESS";
20
+ SeedProxyErrorCode2["INVALID_TRANSACTION"] = "INVALID_TRANSACTION";
21
+ SeedProxyErrorCode2["REGISTRATION_FAILED"] = "REGISTRATION_FAILED";
22
+ SeedProxyErrorCode2["SIGNING_FAILED"] = "SIGNING_FAILED";
23
+ SeedProxyErrorCode2["ROTATION_FAILED"] = "ROTATION_FAILED";
24
+ SeedProxyErrorCode2["REVOCATION_FAILED"] = "REVOCATION_FAILED";
25
+ SeedProxyErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
26
+ SeedProxyErrorCode2["TIMEOUT"] = "TIMEOUT";
27
+ SeedProxyErrorCode2["RATE_LIMITED"] = "RATE_LIMITED";
28
+ SeedProxyErrorCode2["GAS_LIMIT_EXCEEDED"] = "GAS_LIMIT_EXCEEDED";
29
+ return SeedProxyErrorCode2;
30
+ })(SeedProxyErrorCode || {});
31
+ var SeedProxyError = class extends Error {
32
+ constructor(message, code, cause) {
33
+ super(message);
34
+ this.code = code;
35
+ this.cause = cause;
36
+ this.name = "SeedProxyError";
37
+ }
38
+ };
39
+
40
+ // src/crypto.ts
41
+ import { ethers } from "ethers";
42
+ function validateSeedPhrase(phrase) {
43
+ if (!phrase || typeof phrase !== "string") return false;
44
+ const words = phrase.trim().toLowerCase().split(/\s+/);
45
+ if (words.length !== 12 && words.length !== 24) return false;
46
+ return words.every((word) => /^[a-z]+$/.test(word));
47
+ }
48
+ function validatePrivateKey(key) {
49
+ if (!key || typeof key !== "string") return false;
50
+ const cleanKey = key.startsWith("0x") ? key.slice(2) : key;
51
+ return /^[0-9a-fA-F]{64}$/.test(cleanKey);
52
+ }
53
+ function validateAddress(address) {
54
+ try {
55
+ return ethers.isAddress(address);
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+ function generateProxyKeyId(isL2S = false) {
61
+ const randomBytes = ethers.randomBytes(32);
62
+ const hex = ethers.hexlify(randomBytes).slice(2);
63
+ return isL2S ? `priv_secret${hex}` : `priv_${hex}`;
64
+ }
65
+ function hashProxyKey(proxyKeyId) {
66
+ let keyBytes;
67
+ if (proxyKeyId.startsWith("priv_secret")) {
68
+ keyBytes = "0x" + proxyKeyId.slice(11);
69
+ } else if (proxyKeyId.startsWith("priv_")) {
70
+ keyBytes = "0x" + proxyKeyId.slice(5);
71
+ } else {
72
+ keyBytes = proxyKeyId;
73
+ }
74
+ return ethers.keccak256(ethers.solidityPacked(["bytes32"], [keyBytes]));
75
+ }
76
+ function parseProxyKey(proxyKeyId) {
77
+ if (proxyKeyId.startsWith("priv_secret")) {
78
+ return "0x" + proxyKeyId.slice(11);
79
+ } else if (proxyKeyId.startsWith("priv_")) {
80
+ return "0x" + proxyKeyId.slice(5);
81
+ }
82
+ return proxyKeyId;
83
+ }
84
+ async function deriveKey(password, salt) {
85
+ const encoder = new TextEncoder();
86
+ const passwordKey = await crypto.subtle.importKey(
87
+ "raw",
88
+ encoder.encode(password),
89
+ "PBKDF2",
90
+ false,
91
+ ["deriveBits", "deriveKey"]
92
+ );
93
+ return crypto.subtle.deriveKey(
94
+ {
95
+ name: "PBKDF2",
96
+ salt: salt.buffer,
97
+ iterations: 1e5,
98
+ hash: "SHA-256"
99
+ },
100
+ passwordKey,
101
+ { name: "AES-GCM", length: 256 },
102
+ false,
103
+ ["encrypt", "decrypt"]
104
+ );
105
+ }
106
+ async function encryptSeedPhrase(seedPhrase, password) {
107
+ const encoder = new TextEncoder();
108
+ const data = encoder.encode(seedPhrase);
109
+ const salt = crypto.getRandomValues(new Uint8Array(16));
110
+ const iv = crypto.getRandomValues(new Uint8Array(12));
111
+ const key = await deriveKey(password, salt);
112
+ const encrypted = await crypto.subtle.encrypt(
113
+ { name: "AES-GCM", iv },
114
+ key,
115
+ data
116
+ );
117
+ const combined = new Uint8Array(salt.length + iv.length + encrypted.byteLength);
118
+ combined.set(salt, 0);
119
+ combined.set(iv, salt.length);
120
+ combined.set(new Uint8Array(encrypted), salt.length + iv.length);
121
+ return btoa(String.fromCharCode(...combined));
122
+ }
123
+ async function decryptSeedPhrase(encryptedBlob, password) {
124
+ const combined = Uint8Array.from(atob(encryptedBlob), (c) => c.charCodeAt(0));
125
+ const salt = combined.slice(0, 16);
126
+ const iv = combined.slice(16, 28);
127
+ const ciphertext = combined.slice(28);
128
+ const key = await deriveKey(password, salt);
129
+ const decrypted = await crypto.subtle.decrypt(
130
+ { name: "AES-GCM", iv },
131
+ key,
132
+ ciphertext
133
+ );
134
+ return new TextDecoder().decode(decrypted);
135
+ }
136
+ function wordToBytes32(word) {
137
+ const bytes = ethers.toUtf8Bytes(word);
138
+ const padded = ethers.zeroPadBytes(bytes, 32);
139
+ return padded;
140
+ }
141
+ function bytes32ToWord(bytes32) {
142
+ try {
143
+ const hex = bytes32.replace(/0+$/, "");
144
+ if (hex.length <= 2) return "";
145
+ return ethers.toUtf8String(hex);
146
+ } catch {
147
+ return "";
148
+ }
149
+ }
150
+ function encodeSeedWords(seedPhrase) {
151
+ const wordList = seedPhrase.trim().split(/\s+/);
152
+ const words = [];
153
+ for (let i = 0; i < 12; i++) {
154
+ if (i < wordList.length) {
155
+ words.push(wordToBytes32(wordList[i]));
156
+ } else {
157
+ words.push(ethers.zeroPadBytes("0x", 32));
158
+ }
159
+ }
160
+ return { words, count: wordList.length };
161
+ }
162
+ function decodeSeedWords(words, count) {
163
+ const wordList = [];
164
+ for (let i = 0; i < count; i++) {
165
+ const word = bytes32ToWord(words[i]);
166
+ if (word) wordList.push(word);
167
+ }
168
+ return wordList.join(" ");
169
+ }
170
+ function hashOwner(address) {
171
+ return ethers.keccak256(ethers.solidityPacked(["address"], [address]));
172
+ }
173
+ function labelToBytes32(label) {
174
+ const bytes = ethers.toUtf8Bytes(label.slice(0, 31));
175
+ return ethers.zeroPadBytes(bytes, 32);
176
+ }
177
+ function bytes32ToLabel(bytes32) {
178
+ try {
179
+ const hex = bytes32.replace(/0+$/, "");
180
+ if (hex.length <= 2) return "";
181
+ return ethers.toUtf8String(hex);
182
+ } catch {
183
+ return "";
184
+ }
185
+ }
186
+ function deriveAddress(seedPhrase) {
187
+ try {
188
+ const wallet = ethers.Wallet.fromPhrase(seedPhrase);
189
+ return wallet.address;
190
+ } catch {
191
+ throw new Error("Invalid seed phrase");
192
+ }
193
+ }
194
+
195
+ // src/client.ts
196
+ var SeedProxyClient = class {
197
+ constructor(config) {
198
+ this.abortController = null;
199
+ if (!config.baseUrl) {
200
+ throw new SeedProxyError(
201
+ "baseUrl is required",
202
+ "INVALID_CONFIG" /* INVALID_CONFIG */
203
+ );
204
+ }
205
+ this.config = {
206
+ baseUrl: config.baseUrl.replace(/\/$/, ""),
207
+ // Remove trailing slash
208
+ apiKey: config.apiKey || "",
209
+ defaultStorage: config.defaultStorage || "l2s",
210
+ timeout: config.timeout || 3e4
211
+ };
212
+ }
213
+ // =========================================================================
214
+ // Vault Registration
215
+ // =========================================================================
216
+ /**
217
+ * Register a new seed phrase vault
218
+ *
219
+ * The seed phrase is encrypted client-side before being sent to the server.
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * const result = await client.registerVault({
224
+ * seedPhrase: 'word1 word2 ... word12',
225
+ * password: 'secure-password',
226
+ * label: 'My Main Wallet',
227
+ * ownerAddress: '0x...',
228
+ * storageType: 'l2s' // or 'sapphire'
229
+ * });
230
+ *
231
+ * console.log('Proxy Key:', result.proxyKeyId);
232
+ * // Save this key securely - it's needed for authentication
233
+ * ```
234
+ */
235
+ async registerVault(params) {
236
+ const secret = params.secret || params.seedPhrase || "";
237
+ const isPrivateKey = secret.startsWith("0x") && secret.length === 66;
238
+ const keyType = params.keyType || (isPrivateKey ? "privateKey" : "seed");
239
+ if (keyType === "seed") {
240
+ if (!validateSeedPhrase(secret)) {
241
+ throw new SeedProxyError(
242
+ "Invalid seed phrase. Must be 12 or 24 words.",
243
+ "INVALID_SEED_PHRASE" /* INVALID_SEED_PHRASE */
244
+ );
245
+ }
246
+ } else if (keyType === "privateKey") {
247
+ if (!validatePrivateKey(secret)) {
248
+ throw new SeedProxyError(
249
+ "Invalid private key. Must be 0x + 64 hex characters.",
250
+ "INVALID_PRIVATE_KEY" /* INVALID_PRIVATE_KEY */
251
+ );
252
+ }
253
+ }
254
+ if (!params.password || params.password.length < 6) {
255
+ throw new SeedProxyError(
256
+ "Password must be at least 6 characters",
257
+ "INVALID_PASSWORD" /* INVALID_PASSWORD */
258
+ );
259
+ }
260
+ if (!validateAddress(params.ownerAddress)) {
261
+ throw new SeedProxyError(
262
+ "Invalid owner address",
263
+ "INVALID_ADDRESS" /* INVALID_ADDRESS */
264
+ );
265
+ }
266
+ const storageType = params.storageType || this.config.defaultStorage;
267
+ try {
268
+ const encryptedSecret = await encryptSeedPhrase(secret, params.password);
269
+ const proxyKeyId = generateProxyKeyId(storageType === "l2s");
270
+ const keyHash = hashProxyKey(proxyKeyId);
271
+ const response = await this.request("/api/sdk/register", {
272
+ method: "POST",
273
+ body: {
274
+ proxyKeyId,
275
+ keyHash,
276
+ encryptedSeed: encryptedSecret,
277
+ keyType,
278
+ // 'seed' or 'privateKey'
279
+ label: params.label || "Unnamed Vault",
280
+ ownerAddress: params.ownerAddress,
281
+ storageType
282
+ }
283
+ });
284
+ if (!response.success) {
285
+ throw new SeedProxyError(
286
+ response.error || "Registration failed",
287
+ "REGISTRATION_FAILED" /* REGISTRATION_FAILED */
288
+ );
289
+ }
290
+ return {
291
+ success: true,
292
+ proxyKeyId,
293
+ vaultIndex: response.data?.vaultIndex,
294
+ txHash: response.data?.txHash
295
+ };
296
+ } catch (error) {
297
+ if (error instanceof SeedProxyError) throw error;
298
+ throw new SeedProxyError(
299
+ "Failed to register vault",
300
+ "REGISTRATION_FAILED" /* REGISTRATION_FAILED */,
301
+ error
302
+ );
303
+ }
304
+ }
305
+ // =========================================================================
306
+ // Authentication (Login with Proxy Key)
307
+ // =========================================================================
308
+ /**
309
+ * Authenticate using a proxy key to recover the seed phrase
310
+ *
311
+ * This also rotates the key for security (one-time use).
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * const result = await client.authenticate({
316
+ * proxyKeyId: 'priv_abc123...',
317
+ * password: 'your-password'
318
+ * });
319
+ *
320
+ * if (result.success) {
321
+ * console.log('Seed:', result.seedPhrase);
322
+ * console.log('New Key:', result.newProxyKeyId);
323
+ * // Store the new key for next login
324
+ * }
325
+ * ```
326
+ */
327
+ async authenticate(params) {
328
+ if (!params.proxyKeyId || !params.proxyKeyId.startsWith("priv_")) {
329
+ throw new SeedProxyError(
330
+ "Invalid proxy key ID format",
331
+ "INVALID_KEY" /* INVALID_KEY */
332
+ );
333
+ }
334
+ if (!params.password) {
335
+ throw new SeedProxyError(
336
+ "Password is required",
337
+ "INVALID_PASSWORD" /* INVALID_PASSWORD */
338
+ );
339
+ }
340
+ try {
341
+ const verification = await this.verifyKey({ proxyKeyId: params.proxyKeyId });
342
+ if (!verification.exists || !verification.valid) {
343
+ throw new SeedProxyError(
344
+ "Key not found or invalid",
345
+ "KEY_NOT_FOUND" /* KEY_NOT_FOUND */
346
+ );
347
+ }
348
+ if (!verification.isActive) {
349
+ throw new SeedProxyError(
350
+ "Key has been revoked or already used",
351
+ "KEY_INACTIVE" /* KEY_INACTIVE */
352
+ );
353
+ }
354
+ const response = await this.request("/api/sdk/getSeed", {
355
+ method: "POST",
356
+ body: {
357
+ proxyKeyId: params.proxyKeyId,
358
+ keyHash: hashProxyKey(params.proxyKeyId)
359
+ }
360
+ });
361
+ if (!response.success || !response.data?.encryptedSeed) {
362
+ throw new SeedProxyError(
363
+ response.error || "Failed to retrieve seed",
364
+ "AUTHENTICATION_FAILED" /* AUTHENTICATION_FAILED */
365
+ );
366
+ }
367
+ let seedPhrase;
368
+ try {
369
+ seedPhrase = await decryptSeedPhrase(response.data.encryptedSeed, params.password);
370
+ } catch {
371
+ throw new SeedProxyError(
372
+ "Incorrect password",
373
+ "INVALID_PASSWORD" /* INVALID_PASSWORD */
374
+ );
375
+ }
376
+ const rotation = await this.rotateKey({
377
+ proxyKeyId: params.proxyKeyId,
378
+ password: params.password
379
+ });
380
+ return {
381
+ success: true,
382
+ seedPhrase,
383
+ newProxyKeyId: rotation.newProxyKeyId
384
+ };
385
+ } catch (error) {
386
+ if (error instanceof SeedProxyError) throw error;
387
+ throw new SeedProxyError(
388
+ "Authentication failed",
389
+ "AUTHENTICATION_FAILED" /* AUTHENTICATION_FAILED */,
390
+ error
391
+ );
392
+ }
393
+ }
394
+ // =========================================================================
395
+ // Key Verification
396
+ // =========================================================================
397
+ /**
398
+ * Verify if a proxy key exists and is active
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * const result = await client.verifyKey({ proxyKeyId: 'priv_abc123...' });
403
+ *
404
+ * if (result.valid && result.isActive) {
405
+ * console.log('Key is valid and can be used');
406
+ * }
407
+ * ```
408
+ */
409
+ async verifyKey(params) {
410
+ try {
411
+ const response = await this.request("/api/keybridge", {
412
+ method: "GET",
413
+ query: { proxyId: params.proxyKeyId }
414
+ });
415
+ return {
416
+ exists: response.data?.exists || false,
417
+ valid: response.data?.valid || response.data?.exists || false,
418
+ isActive: response.data?.isActive || false,
419
+ vaultIndex: response.data?.vaultIndex,
420
+ type: response.data?.type
421
+ };
422
+ } catch {
423
+ return {
424
+ exists: false,
425
+ valid: false,
426
+ isActive: false
427
+ };
428
+ }
429
+ }
430
+ // =========================================================================
431
+ // Key Rotation
432
+ // =========================================================================
433
+ /**
434
+ * Rotate a proxy key (invalidates old key, generates new one)
435
+ *
436
+ * @example
437
+ * ```typescript
438
+ * const result = await client.rotateKey({
439
+ * proxyKeyId: 'priv_old...',
440
+ * password: 'your-password'
441
+ * });
442
+ *
443
+ * console.log('New key:', result.newProxyKeyId);
444
+ * ```
445
+ */
446
+ async rotateKey(params) {
447
+ const isL2S = params.proxyKeyId.startsWith("priv_secret");
448
+ const newProxyKeyId = generateProxyKeyId(isL2S);
449
+ const oldKeyHash = hashProxyKey(params.proxyKeyId);
450
+ const newKeyHash = hashProxyKey(newProxyKeyId);
451
+ try {
452
+ const response = await this.request("/api/sdk/rotate", {
453
+ method: "POST",
454
+ body: {
455
+ oldProxyKeyId: params.proxyKeyId,
456
+ oldKeyHash,
457
+ newKeyHash,
458
+ isL2S
459
+ }
460
+ });
461
+ if (!response.success) {
462
+ throw new SeedProxyError(
463
+ response.error || "Rotation failed",
464
+ "ROTATION_FAILED" /* ROTATION_FAILED */
465
+ );
466
+ }
467
+ return {
468
+ success: true,
469
+ newProxyKeyId
470
+ };
471
+ } catch (error) {
472
+ if (error instanceof SeedProxyError) throw error;
473
+ throw new SeedProxyError(
474
+ "Key rotation failed",
475
+ "ROTATION_FAILED" /* ROTATION_FAILED */,
476
+ error
477
+ );
478
+ }
479
+ }
480
+ // =========================================================================
481
+ // Key Revocation
482
+ // =========================================================================
483
+ /**
484
+ * Permanently revoke a proxy key
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * const result = await client.revokeKey({
489
+ * proxyKeyId: 'priv_abc123...',
490
+ * password: 'your-password'
491
+ * });
492
+ * ```
493
+ */
494
+ async revokeKey(params) {
495
+ try {
496
+ const response = await this.request("/api/sdk/revoke", {
497
+ method: "POST",
498
+ body: {
499
+ proxyKeyId: params.proxyKeyId,
500
+ keyHash: hashProxyKey(params.proxyKeyId)
501
+ }
502
+ });
503
+ return {
504
+ success: response.success,
505
+ txHash: response.data?.txHash,
506
+ error: response.error
507
+ };
508
+ } catch (error) {
509
+ if (error instanceof SeedProxyError) throw error;
510
+ throw new SeedProxyError(
511
+ "Revocation failed",
512
+ "REVOCATION_FAILED" /* REVOCATION_FAILED */,
513
+ error
514
+ );
515
+ }
516
+ }
517
+ // =========================================================================
518
+ // List Vaults
519
+ // =========================================================================
520
+ /**
521
+ * List all vaults for an owner address
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * const vaults = await client.listVaults('0x...');
526
+ *
527
+ * for (const vault of vaults) {
528
+ * console.log(vault.label, vault.type, vault.isActive);
529
+ * }
530
+ * ```
531
+ */
532
+ async listVaults(ownerAddress) {
533
+ if (!validateAddress(ownerAddress)) {
534
+ throw new SeedProxyError(
535
+ "Invalid owner address",
536
+ "INVALID_ADDRESS" /* INVALID_ADDRESS */
537
+ );
538
+ }
539
+ try {
540
+ const response = await this.request("/api/sdk/vaults", {
541
+ method: "GET",
542
+ query: { owner: ownerAddress }
543
+ });
544
+ return response.data?.vaults || [];
545
+ } catch {
546
+ return [];
547
+ }
548
+ }
549
+ // =========================================================================
550
+ // Message Signing (Advanced)
551
+ // =========================================================================
552
+ /**
553
+ * Sign a message using the seed stored in a vault
554
+ *
555
+ * This decrypts the seed temporarily to sign, then clears it from memory.
556
+ *
557
+ * @example
558
+ * ```typescript
559
+ * const result = await client.signMessage({
560
+ * proxyKeyId: 'priv_abc123...',
561
+ * password: 'your-password',
562
+ * message: 'Hello, World!'
563
+ * });
564
+ *
565
+ * console.log('Signature:', result.signature);
566
+ * ```
567
+ */
568
+ async signMessage(params) {
569
+ try {
570
+ const authResult = await this.authenticate({
571
+ proxyKeyId: params.proxyKeyId,
572
+ password: params.password
573
+ });
574
+ if (!authResult.success || !authResult.seedPhrase) {
575
+ throw new SeedProxyError(
576
+ "Authentication failed",
577
+ "AUTHENTICATION_FAILED" /* AUTHENTICATION_FAILED */
578
+ );
579
+ }
580
+ const wallet = ethers2.Wallet.fromPhrase(authResult.seedPhrase);
581
+ const signature = await wallet.signMessage(params.message);
582
+ const sig = ethers2.Signature.from(signature);
583
+ return {
584
+ success: true,
585
+ signature,
586
+ v: sig.v,
587
+ r: sig.r,
588
+ s: sig.s,
589
+ newProxyKeyId: authResult.newProxyKeyId,
590
+ signerAddress: wallet.address
591
+ };
592
+ } catch (error) {
593
+ if (error instanceof SeedProxyError) throw error;
594
+ throw new SeedProxyError(
595
+ "Signing failed",
596
+ "SIGNING_FAILED" /* SIGNING_FAILED */,
597
+ error
598
+ );
599
+ }
600
+ }
601
+ // =========================================================================
602
+ // Transaction Signing (Advanced)
603
+ // =========================================================================
604
+ /**
605
+ * Sign a transaction using the seed stored in a vault
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * const result = await client.signTransaction({
610
+ * proxyKeyId: 'priv_abc123...',
611
+ * password: 'your-password',
612
+ * transaction: {
613
+ * to: '0x...',
614
+ * value: '1000000000000000000', // 1 ETH in wei
615
+ * chainId: 1
616
+ * }
617
+ * });
618
+ *
619
+ * // Broadcast the signed transaction
620
+ * const txHash = await provider.sendTransaction(result.signedTransaction);
621
+ * ```
622
+ */
623
+ async signTransaction(params) {
624
+ try {
625
+ const authResult = await this.authenticate({
626
+ proxyKeyId: params.proxyKeyId,
627
+ password: params.password
628
+ });
629
+ if (!authResult.success || !authResult.seedPhrase) {
630
+ throw new SeedProxyError(
631
+ "Authentication failed",
632
+ "AUTHENTICATION_FAILED" /* AUTHENTICATION_FAILED */
633
+ );
634
+ }
635
+ const wallet = ethers2.Wallet.fromPhrase(authResult.seedPhrase);
636
+ const tx = {
637
+ to: params.transaction.to,
638
+ value: params.transaction.value ? BigInt(params.transaction.value) : void 0,
639
+ data: params.transaction.data,
640
+ nonce: params.transaction.nonce,
641
+ gasLimit: params.transaction.gasLimit ? BigInt(params.transaction.gasLimit) : void 0,
642
+ gasPrice: params.transaction.gasPrice ? BigInt(params.transaction.gasPrice) : void 0,
643
+ maxFeePerGas: params.transaction.maxFeePerGas ? BigInt(params.transaction.maxFeePerGas) : void 0,
644
+ maxPriorityFeePerGas: params.transaction.maxPriorityFeePerGas ? BigInt(params.transaction.maxPriorityFeePerGas) : void 0,
645
+ chainId: params.transaction.chainId
646
+ };
647
+ const signedTx = await wallet.signTransaction(tx);
648
+ return {
649
+ success: true,
650
+ signedTransaction: signedTx
651
+ };
652
+ } catch (error) {
653
+ if (error instanceof SeedProxyError) throw error;
654
+ throw new SeedProxyError(
655
+ "Transaction signing failed",
656
+ "SIGNING_FAILED" /* SIGNING_FAILED */,
657
+ error
658
+ );
659
+ }
660
+ }
661
+ // =========================================================================
662
+ // Utility Methods
663
+ // =========================================================================
664
+ /**
665
+ * Get the configured base URL
666
+ */
667
+ getBaseUrl() {
668
+ return this.config.baseUrl;
669
+ }
670
+ /**
671
+ * Get the default storage type
672
+ */
673
+ getDefaultStorage() {
674
+ return this.config.defaultStorage;
675
+ }
676
+ /**
677
+ * Cancel any pending requests
678
+ */
679
+ cancelPendingRequests() {
680
+ if (this.abortController) {
681
+ this.abortController.abort();
682
+ this.abortController = null;
683
+ }
684
+ }
685
+ // =========================================================================
686
+ // Private Methods
687
+ // =========================================================================
688
+ async request(endpoint, options) {
689
+ this.abortController = new AbortController();
690
+ let url = `${this.config.baseUrl}${endpoint}`;
691
+ if (options.query) {
692
+ const params = new URLSearchParams(options.query);
693
+ url += `?${params.toString()}`;
694
+ }
695
+ const headers = {
696
+ "Content-Type": "application/json"
697
+ };
698
+ if (this.config.apiKey) {
699
+ headers["X-API-Key"] = this.config.apiKey;
700
+ }
701
+ try {
702
+ const response = await fetch(url, {
703
+ method: options.method,
704
+ headers,
705
+ body: options.body ? JSON.stringify(options.body) : void 0,
706
+ signal: this.abortController.signal
707
+ });
708
+ const data = await response.json();
709
+ if (!response.ok) {
710
+ throw new SeedProxyError(
711
+ data.error || `HTTP ${response.status}`,
712
+ "NETWORK_ERROR" /* NETWORK_ERROR */
713
+ );
714
+ }
715
+ return data;
716
+ } catch (error) {
717
+ if (error instanceof SeedProxyError) throw error;
718
+ if (error.name === "AbortError") {
719
+ throw new SeedProxyError(
720
+ "Request cancelled",
721
+ "TIMEOUT" /* TIMEOUT */
722
+ );
723
+ }
724
+ throw new SeedProxyError(
725
+ "Network error",
726
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
727
+ error
728
+ );
729
+ }
730
+ }
731
+ };
732
+ function createSeedProxyClient(config) {
733
+ return new SeedProxyClient(config);
734
+ }
735
+
736
+ // src/index.ts
737
+ var VERSION = "2.0.0";
738
+ export {
739
+ CONTRACT_ADDRESS,
740
+ KEY_TYPE_PRIVATE_KEY,
741
+ KEY_TYPE_SEED,
742
+ SAPPHIRE_MAINNET_CHAIN_ID,
743
+ SeedProxyClient,
744
+ SeedProxyError,
745
+ SeedProxyErrorCode,
746
+ VERSION,
747
+ bytes32ToLabel,
748
+ createSeedProxyClient,
749
+ decodeSeedWords,
750
+ decryptSeedPhrase,
751
+ createSeedProxyClient as default,
752
+ deriveAddress,
753
+ encodeSeedWords,
754
+ encryptSeedPhrase,
755
+ generateProxyKeyId,
756
+ hashOwner,
757
+ hashProxyKey,
758
+ labelToBytes32,
759
+ parseProxyKey,
760
+ validateAddress,
761
+ validatePrivateKey,
762
+ validateSeedPhrase
763
+ };
764
+ /**
765
+ * Pribado Seed Proxy SDK
766
+ *
767
+ * Main Client Class - HTTP-based integration for secure seed management
768
+ *
769
+ * @author Ralph Lawrence Pecayo
770
+ * @license MIT
771
+ */
772
+ /**
773
+ * Pribado Seed Proxy SDK
774
+ *
775
+ * Secure encrypted endpoints for Web3 wallets
776
+ *
777
+ * @packageDocumentation
778
+ * @author Ralph Lawrence Pecayo
779
+ * @license MIT
780
+ */