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