@zubari/sdk 0.2.7 → 0.3.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.
Files changed (39) hide show
  1. package/dist/{TransactionService-8xSEGoWA.d.mts → TransactionService-DURp3bRL.d.ts} +34 -10
  2. package/dist/{TransactionService-CaIcCoqY.d.ts → TransactionService-DuMJmrG3.d.mts} +34 -10
  3. package/dist/{WalletManager-B1qvFF4K.d.mts → WalletManager-D0xMpgfo.d.mts} +133 -50
  4. package/dist/{WalletManager-CCs4Jsv7.d.ts → WalletManager-DsAg7MwL.d.ts} +133 -50
  5. package/dist/{index-Cx389p_j.d.mts → index-DF0Gf8NK.d.mts} +7 -1
  6. package/dist/{index-Cx389p_j.d.ts → index-DF0Gf8NK.d.ts} +7 -1
  7. package/dist/{index-xZYY0MEX.d.mts → index-N2u4haqL.d.mts} +23 -11
  8. package/dist/{index-BPojlGT6.d.ts → index-kS-xopkl.d.ts} +23 -11
  9. package/dist/index.d.mts +6 -5
  10. package/dist/index.d.ts +6 -5
  11. package/dist/index.js +3070 -1772
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +3070 -1772
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/protocols/index.d.mts +54 -22
  16. package/dist/protocols/index.d.ts +54 -22
  17. package/dist/protocols/index.js +1008 -76
  18. package/dist/protocols/index.js.map +1 -1
  19. package/dist/protocols/index.mjs +1008 -76
  20. package/dist/protocols/index.mjs.map +1 -1
  21. package/dist/react/index.d.mts +5 -4
  22. package/dist/react/index.d.ts +5 -4
  23. package/dist/react/index.js +884 -884
  24. package/dist/react/index.js.map +1 -1
  25. package/dist/react/index.mjs +884 -884
  26. package/dist/react/index.mjs.map +1 -1
  27. package/dist/services/index.d.mts +2 -2
  28. package/dist/services/index.d.ts +2 -2
  29. package/dist/services/index.js +152 -71
  30. package/dist/services/index.js.map +1 -1
  31. package/dist/services/index.mjs +152 -71
  32. package/dist/services/index.mjs.map +1 -1
  33. package/dist/wallet/index.d.mts +5 -4
  34. package/dist/wallet/index.d.ts +5 -4
  35. package/dist/wallet/index.js +1358 -1107
  36. package/dist/wallet/index.js.map +1 -1
  37. package/dist/wallet/index.mjs +1358 -1107
  38. package/dist/wallet/index.mjs.map +1 -1
  39. package/package.json +9 -6
@@ -2,14 +2,14 @@
2
2
 
3
3
  var react = require('react');
4
4
  var ethers = require('ethers');
5
- var viem = require('viem');
6
- var chains = require('viem/chains');
7
5
  var bip39 = require('@scure/bip39');
8
6
  var english = require('@scure/bip39/wordlists/english');
9
7
  var bip32 = require('@scure/bip32');
10
8
  var base = require('@scure/base');
11
9
  var sha256 = require('@noble/hashes/sha256');
12
10
  var ripemd160 = require('@noble/hashes/ripemd160');
11
+ var viem = require('viem');
12
+ var chains = require('viem/chains');
13
13
 
14
14
  // src/react/useWalletManager.ts
15
15
 
@@ -133,1038 +133,1038 @@ function getNetworkConfig(network, isTestnet = false) {
133
133
  };
134
134
  }
135
135
 
136
- // src/security/KeyManager.ts
137
- var KeyManager = class {
138
- static ALGORITHM = "AES-GCM";
139
- static KEY_LENGTH = 256;
140
- static IV_LENGTH = 12;
141
- static SALT_LENGTH = 16;
142
- static PBKDF2_ITERATIONS = 1e5;
143
- /**
144
- * Encrypt a seed phrase with a password
145
- */
146
- static async encryptSeed(seed, password) {
147
- const encoder = new TextEncoder();
148
- const seedData = encoder.encode(seed);
149
- const salt = crypto.getRandomValues(new Uint8Array(this.SALT_LENGTH));
150
- const iv = crypto.getRandomValues(new Uint8Array(this.IV_LENGTH));
151
- const key = await this.deriveKey(password, salt);
152
- const encrypted = await crypto.subtle.encrypt(
153
- { name: this.ALGORITHM, iv },
154
- key,
155
- seedData
156
- );
157
- const combined = new Uint8Array(salt.length + iv.length + encrypted.byteLength);
158
- combined.set(salt, 0);
159
- combined.set(iv, salt.length);
160
- combined.set(new Uint8Array(encrypted), salt.length + iv.length);
161
- return btoa(String.fromCharCode(...combined));
136
+ // src/services/WdkApiClient.ts
137
+ var WdkApiClient = class {
138
+ config;
139
+ constructor(config) {
140
+ this.config = {
141
+ baseUrl: config.baseUrl,
142
+ timeout: config.timeout || 3e4
143
+ };
162
144
  }
163
145
  /**
164
- * Decrypt a seed phrase with a password
146
+ * Generate a new BIP-39 seed phrase using Tether WDK
165
147
  */
166
- static async decryptSeed(encryptedData, password) {
167
- const combined = new Uint8Array(
168
- atob(encryptedData).split("").map((c) => c.charCodeAt(0))
169
- );
170
- const salt = combined.slice(0, this.SALT_LENGTH);
171
- const iv = combined.slice(this.SALT_LENGTH, this.SALT_LENGTH + this.IV_LENGTH);
172
- const encrypted = combined.slice(this.SALT_LENGTH + this.IV_LENGTH);
173
- const key = await this.deriveKey(password, salt);
174
- const decrypted = await crypto.subtle.decrypt(
175
- { name: this.ALGORITHM, iv },
176
- key,
177
- encrypted
178
- );
179
- const decoder = new TextDecoder();
180
- return decoder.decode(decrypted);
148
+ async generateSeed() {
149
+ try {
150
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
151
+ method: "POST",
152
+ headers: {
153
+ "Content-Type": "application/json"
154
+ }
155
+ });
156
+ return await response.json();
157
+ } catch (error) {
158
+ return {
159
+ success: false,
160
+ error: error instanceof Error ? error.message : "Failed to generate seed"
161
+ };
162
+ }
181
163
  }
182
164
  /**
183
- * Derive encryption key from password using PBKDF2
165
+ * Validate a BIP-39 seed phrase
184
166
  */
185
- static async deriveKey(password, salt) {
186
- const encoder = new TextEncoder();
187
- const passwordData = encoder.encode(password);
188
- const keyMaterial = await crypto.subtle.importKey(
189
- "raw",
190
- passwordData,
191
- "PBKDF2",
192
- false,
193
- ["deriveKey"]
194
- );
195
- return crypto.subtle.deriveKey(
196
- {
197
- name: "PBKDF2",
198
- salt: salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength),
199
- iterations: this.PBKDF2_ITERATIONS,
200
- hash: "SHA-256"
201
- },
202
- keyMaterial,
203
- { name: this.ALGORITHM, length: this.KEY_LENGTH },
204
- false,
205
- ["encrypt", "decrypt"]
206
- );
167
+ async validateSeed(seed) {
168
+ try {
169
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
170
+ method: "POST",
171
+ headers: {
172
+ "Content-Type": "application/json"
173
+ },
174
+ body: JSON.stringify({ seed })
175
+ });
176
+ return await response.json();
177
+ } catch (error) {
178
+ return {
179
+ success: false,
180
+ error: error instanceof Error ? error.message : "Failed to validate seed"
181
+ };
182
+ }
207
183
  }
208
184
  /**
209
- * Validate a BIP-39 seed phrase (basic validation)
185
+ * Derive address for a specific chain using Tether WDK
210
186
  */
211
- static validateSeedPhrase(seed) {
212
- const words = seed.trim().split(/\s+/);
213
- const validWordCounts = [12, 15, 18, 21, 24];
214
- return validWordCounts.includes(words.length);
187
+ async deriveAddress(seed, chain, network = "testnet") {
188
+ try {
189
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
190
+ method: "POST",
191
+ headers: {
192
+ "Content-Type": "application/json"
193
+ },
194
+ body: JSON.stringify({ seed, chain, network })
195
+ });
196
+ return await response.json();
197
+ } catch (error) {
198
+ return {
199
+ success: false,
200
+ error: error instanceof Error ? error.message : "Failed to derive address"
201
+ };
202
+ }
215
203
  }
216
204
  /**
217
- * Generate a random encryption key (for backup purposes)
205
+ * Derive addresses for all chains using Tether WDK
218
206
  */
219
- static generateBackupKey() {
220
- const bytes = crypto.getRandomValues(new Uint8Array(32));
221
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
222
- }
223
- };
224
-
225
- // src/storage/SecureStorage.ts
226
- var KeychainStorageAdapter = class {
227
- serviceName;
228
- constructor(serviceName = "com.zubari.wallet") {
229
- this.serviceName = serviceName;
230
- }
231
- async setItem(key, value) {
232
- if (typeof global !== "undefined" && global.KeychainModule) {
233
- await global.KeychainModule.setItem(this.serviceName, key, value);
234
- } else {
235
- throw new Error("Keychain not available on this platform");
207
+ async deriveAllAddresses(seed, network = "testnet") {
208
+ try {
209
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
210
+ method: "POST",
211
+ headers: {
212
+ "Content-Type": "application/json"
213
+ },
214
+ body: JSON.stringify({ seed, network })
215
+ });
216
+ return await response.json();
217
+ } catch (error) {
218
+ return {
219
+ success: false,
220
+ error: error instanceof Error ? error.message : "Failed to derive addresses"
221
+ };
236
222
  }
237
223
  }
238
- async getItem(key) {
239
- if (typeof global !== "undefined" && global.KeychainModule) {
240
- return global.KeychainModule.getItem(this.serviceName, key);
224
+ /**
225
+ * Send a transaction on a specific chain using Tether WDK
226
+ */
227
+ async sendTransaction(seed, chain, to, amount, network = "testnet") {
228
+ try {
229
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
230
+ method: "POST",
231
+ headers: {
232
+ "Content-Type": "application/json"
233
+ },
234
+ body: JSON.stringify({ seed, chain, to, amount, network })
235
+ });
236
+ return await response.json();
237
+ } catch (error) {
238
+ return {
239
+ success: false,
240
+ error: error instanceof Error ? error.message : "Failed to send transaction"
241
+ };
241
242
  }
242
- throw new Error("Keychain not available on this platform");
243
243
  }
244
- async removeItem(key) {
245
- if (typeof global !== "undefined" && global.KeychainModule) {
246
- await global.KeychainModule.removeItem(this.serviceName, key);
247
- } else {
248
- throw new Error("Keychain not available on this platform");
244
+ /**
245
+ * Get transaction history for an address on a specific chain
246
+ * Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
247
+ */
248
+ async getTransactionHistory(seed, chain, network = "testnet", limit = 10) {
249
+ try {
250
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
251
+ method: "POST",
252
+ headers: {
253
+ "Content-Type": "application/json"
254
+ },
255
+ body: JSON.stringify({ seed, chain, network, limit })
256
+ });
257
+ return await response.json();
258
+ } catch (error) {
259
+ return {
260
+ success: false,
261
+ error: error instanceof Error ? error.message : "Failed to get transaction history"
262
+ };
249
263
  }
250
264
  }
251
- async hasItem(key) {
252
- const value = await this.getItem(key);
253
- return value !== null;
254
- }
255
- async clear() {
256
- if (typeof global !== "undefined" && global.KeychainModule) {
257
- await global.KeychainModule.clear(this.serviceName);
258
- } else {
259
- throw new Error("Keychain not available on this platform");
265
+ /**
266
+ * Get transaction status by hash
267
+ * Fetches from blockchain explorers to check confirmation status
268
+ */
269
+ async getTransactionStatus(txHash, chain, network = "testnet") {
270
+ try {
271
+ const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
272
+ method: "POST",
273
+ headers: {
274
+ "Content-Type": "application/json"
275
+ },
276
+ body: JSON.stringify({ txHash, chain, network })
277
+ });
278
+ return await response.json();
279
+ } catch (error) {
280
+ return {
281
+ success: false,
282
+ error: error instanceof Error ? error.message : "Failed to get transaction status"
283
+ };
260
284
  }
261
285
  }
262
286
  };
263
- var KeystoreStorageAdapter = class {
264
- alias;
265
- constructor(alias = "zubari_wallet_keys") {
266
- this.alias = alias;
287
+ var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
288
+ var wdkApiClient = null;
289
+ function getWdkApiClient(baseUrl) {
290
+ if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
291
+ wdkApiClient = new WdkApiClient({
292
+ baseUrl: baseUrl || DEFAULT_API_URL
293
+ });
267
294
  }
268
- async setItem(key, value) {
269
- if (typeof global !== "undefined" && global.KeystoreModule) {
270
- await global.KeystoreModule.setItem(this.alias, key, value);
271
- } else {
272
- throw new Error("Keystore not available on this platform");
273
- }
274
- }
275
- async getItem(key) {
276
- if (typeof global !== "undefined" && global.KeystoreModule) {
277
- return global.KeystoreModule.getItem(this.alias, key);
278
- }
279
- throw new Error("Keystore not available on this platform");
280
- }
281
- async removeItem(key) {
282
- if (typeof global !== "undefined" && global.KeystoreModule) {
283
- await global.KeystoreModule.removeItem(this.alias, key);
284
- } else {
285
- throw new Error("Keystore not available on this platform");
286
- }
287
- }
288
- async hasItem(key) {
289
- const value = await this.getItem(key);
290
- return value !== null;
291
- }
292
- async clear() {
293
- if (typeof global !== "undefined" && global.KeystoreModule) {
294
- await global.KeystoreModule.clear(this.alias);
295
- } else {
296
- throw new Error("Keystore not available on this platform");
295
+ return wdkApiClient;
296
+ }
297
+ var DERIVATION_PATHS2 = {
298
+ ethereum: "m/44'/60'/0'/0/0",
299
+ bitcoin_mainnet: "m/84'/0'/0'/0/0",
300
+ bitcoin_testnet: "m/84'/1'/0'/0/0",
301
+ ton: "m/44'/607'/0'/0'/0'",
302
+ tron: "m/44'/195'/0'/0/0",
303
+ solana: "m/44'/501'/0'/0'",
304
+ spark: "m/44'/998'/0'/0/0"
305
+ };
306
+ function deriveEthereumAddress(seed) {
307
+ const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
308
+ return hdNode.address;
309
+ }
310
+ function deriveBitcoinAddress(seed, network = "testnet") {
311
+ try {
312
+ const seedBytes = bip39.mnemonicToSeedSync(seed);
313
+ const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
314
+ const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
315
+ const child = hdKey.derive(path);
316
+ if (!child.publicKey) {
317
+ throw new Error("Failed to derive public key");
297
318
  }
319
+ const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
320
+ const witnessVersion = 0;
321
+ const words = base.bech32.toWords(pubKeyHash);
322
+ words.unshift(witnessVersion);
323
+ const hrp = network === "testnet" ? "tb" : "bc";
324
+ const address = base.bech32.encode(hrp, words);
325
+ return address;
326
+ } catch (error) {
327
+ console.error("Bitcoin address derivation failed:", error);
328
+ throw error;
298
329
  }
299
- };
300
- var WebEncryptedStorageAdapter = class {
301
- encryptionKey = null;
302
- storagePrefix;
303
- constructor(storagePrefix = "zubari_") {
304
- this.storagePrefix = storagePrefix;
330
+ }
331
+ async function deriveSolanaAddress(seed) {
332
+ try {
333
+ const [ed25519, nacl, bs58Module] = await Promise.all([
334
+ import('ed25519-hd-key'),
335
+ import('tweetnacl'),
336
+ import('bs58')
337
+ ]);
338
+ const bs58 = bs58Module.default || bs58Module;
339
+ const seedBytes = bip39.mnemonicToSeedSync(seed);
340
+ const derived = ed25519.derivePath(DERIVATION_PATHS2.solana, Buffer.from(seedBytes).toString("hex"));
341
+ const keypair = nacl.sign.keyPair.fromSeed(new Uint8Array(derived.key));
342
+ return bs58.encode(keypair.publicKey);
343
+ } catch (error) {
344
+ console.error("Solana address derivation failed:", error);
345
+ throw error;
305
346
  }
306
- /**
307
- * Initialize with a password-derived key
308
- */
309
- async initialize(password) {
310
- const encoder = new TextEncoder();
311
- const salt = this.getSalt();
312
- const keyMaterial = await crypto.subtle.importKey(
313
- "raw",
314
- encoder.encode(password),
315
- "PBKDF2",
316
- false,
317
- ["deriveKey"]
318
- );
319
- this.encryptionKey = await crypto.subtle.deriveKey(
320
- {
321
- name: "PBKDF2",
322
- salt: salt.buffer,
323
- iterations: 1e5,
324
- hash: "SHA-256"
325
- },
326
- keyMaterial,
327
- { name: "AES-GCM", length: 256 },
328
- false,
329
- ["encrypt", "decrypt"]
330
- );
347
+ }
348
+ async function deriveTonAddress(seed) {
349
+ try {
350
+ const [ed25519, nacl] = await Promise.all([
351
+ import('ed25519-hd-key'),
352
+ import('tweetnacl')
353
+ ]);
354
+ const seedBytes = bip39.mnemonicToSeedSync(seed);
355
+ const derived = ed25519.derivePath(DERIVATION_PATHS2.ton, Buffer.from(seedBytes).toString("hex"));
356
+ const keypair = nacl.sign.keyPair.fromSeed(new Uint8Array(derived.key));
357
+ const publicKey = keypair.publicKey;
358
+ const workchain = 0;
359
+ const flags = 17;
360
+ const hash = sha256.sha256(publicKey);
361
+ const addressData = new Uint8Array(34);
362
+ addressData[0] = flags;
363
+ addressData[1] = workchain;
364
+ addressData.set(hash, 2);
365
+ const crc = crc16(addressData);
366
+ const fullAddress = new Uint8Array(36);
367
+ fullAddress.set(addressData);
368
+ fullAddress[34] = crc >> 8 & 255;
369
+ fullAddress[35] = crc & 255;
370
+ const base64 = btoa(String.fromCharCode(...fullAddress)).replace(/\+/g, "-").replace(/\//g, "_");
371
+ return base64;
372
+ } catch (error) {
373
+ console.error("TON address derivation failed:", error);
374
+ throw error;
331
375
  }
332
- getSalt() {
333
- const saltKey = `${this.storagePrefix}salt`;
334
- let saltHex = localStorage.getItem(saltKey);
335
- if (!saltHex) {
336
- const salt = crypto.getRandomValues(new Uint8Array(16));
337
- saltHex = Array.from(salt).map((b) => b.toString(16).padStart(2, "0")).join("");
338
- localStorage.setItem(saltKey, saltHex);
376
+ }
377
+ function crc16(data) {
378
+ let crc = 0;
379
+ for (const byte of data) {
380
+ crc ^= byte << 8;
381
+ for (let i = 0; i < 8; i++) {
382
+ crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
383
+ crc &= 65535;
339
384
  }
340
- return new Uint8Array(
341
- saltHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
342
- );
343
385
  }
344
- async setItem(key, value) {
345
- if (!this.encryptionKey) {
346
- throw new Error("Storage not initialized. Call initialize() first.");
386
+ return crc;
387
+ }
388
+ function deriveTronAddress(seed) {
389
+ try {
390
+ const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.tron);
391
+ const ethAddressHex = hdNode.address.slice(2).toLowerCase();
392
+ const addressBytes = new Uint8Array(21);
393
+ addressBytes[0] = 65;
394
+ for (let i = 0; i < 20; i++) {
395
+ addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
347
396
  }
348
- const encoder = new TextEncoder();
349
- const iv = crypto.getRandomValues(new Uint8Array(12));
350
- const encrypted = await crypto.subtle.encrypt(
351
- { name: "AES-GCM", iv },
352
- this.encryptionKey,
353
- encoder.encode(value)
354
- );
355
- const combined = new Uint8Array(iv.length + encrypted.byteLength);
356
- combined.set(iv);
357
- combined.set(new Uint8Array(encrypted), iv.length);
358
- const base64 = btoa(String.fromCharCode(...combined));
359
- localStorage.setItem(`${this.storagePrefix}${key}`, base64);
397
+ const tronBase58check = base.base58check(sha256.sha256);
398
+ return tronBase58check.encode(addressBytes);
399
+ } catch (error) {
400
+ console.error("TRON address derivation failed:", error);
401
+ throw error;
360
402
  }
361
- async getItem(key) {
362
- if (!this.encryptionKey) {
363
- throw new Error("Storage not initialized. Call initialize() first.");
364
- }
365
- const base64 = localStorage.getItem(`${this.storagePrefix}${key}`);
366
- if (!base64) return null;
367
- try {
368
- const combined = new Uint8Array(
369
- atob(base64).split("").map((c) => c.charCodeAt(0))
370
- );
371
- const iv = combined.slice(0, 12);
372
- const encrypted = combined.slice(12);
373
- const decrypted = await crypto.subtle.decrypt(
374
- { name: "AES-GCM", iv },
375
- this.encryptionKey,
376
- encrypted
377
- );
378
- const decoder = new TextDecoder();
379
- return decoder.decode(decrypted);
380
- } catch {
381
- return null;
403
+ }
404
+ function deriveSparkAddress(seed, network = "testnet") {
405
+ try {
406
+ const seedBytes = bip39.mnemonicToSeedSync(seed);
407
+ const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
408
+ const child = hdKey.derive(DERIVATION_PATHS2.spark);
409
+ if (!child.publicKey) {
410
+ throw new Error("Failed to derive public key");
382
411
  }
412
+ const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
413
+ const witnessVersion = 0;
414
+ const words = base.bech32.toWords(pubKeyHash);
415
+ words.unshift(witnessVersion);
416
+ const hrp = network === "testnet" ? "tsp" : "sp";
417
+ const address = base.bech32.encode(hrp, words);
418
+ return address;
419
+ } catch (error) {
420
+ console.error("Spark address derivation failed:", error);
421
+ throw error;
383
422
  }
384
- async removeItem(key) {
385
- localStorage.removeItem(`${this.storagePrefix}${key}`);
386
- }
387
- async hasItem(key) {
388
- return localStorage.getItem(`${this.storagePrefix}${key}`) !== null;
389
- }
390
- async clear() {
391
- const keysToRemove = [];
392
- for (let i = 0; i < localStorage.length; i++) {
393
- const key = localStorage.key(i);
394
- if (key?.startsWith(this.storagePrefix)) {
395
- keysToRemove.push(key);
396
- }
397
- }
398
- keysToRemove.forEach((key) => localStorage.removeItem(key));
423
+ }
424
+ async function deriveAllAddresses(seed, network = "testnet") {
425
+ const addresses = {
426
+ ethereum: null,
427
+ bitcoin: null,
428
+ ton: null,
429
+ tron: null,
430
+ solana: null,
431
+ spark: null
432
+ };
433
+ try {
434
+ addresses.ethereum = deriveEthereumAddress(seed);
435
+ } catch (e) {
436
+ console.error("ETH derivation failed:", e);
399
437
  }
400
- };
401
- var MemoryStorageAdapter = class {
402
- storage = /* @__PURE__ */ new Map();
403
- async setItem(key, value) {
404
- this.storage.set(key, value);
438
+ try {
439
+ addresses.bitcoin = deriveBitcoinAddress(seed, network);
440
+ } catch (e) {
441
+ console.error("BTC derivation failed:", e);
405
442
  }
406
- async getItem(key) {
407
- return this.storage.get(key) || null;
443
+ try {
444
+ addresses.spark = deriveSparkAddress(seed, network);
445
+ } catch (e) {
446
+ console.error("Spark derivation failed:", e);
408
447
  }
409
- async removeItem(key) {
410
- this.storage.delete(key);
448
+ try {
449
+ addresses.tron = deriveTronAddress(seed);
450
+ } catch (e) {
451
+ console.error("TRON derivation failed:", e);
411
452
  }
412
- async hasItem(key) {
413
- return this.storage.has(key);
453
+ const [solResult, tonResult] = await Promise.allSettled([
454
+ deriveSolanaAddress(seed),
455
+ deriveTonAddress(seed)
456
+ ]);
457
+ if (solResult.status === "fulfilled") {
458
+ addresses.solana = solResult.value;
459
+ } else {
460
+ console.error("SOL derivation failed:", solResult.reason);
414
461
  }
415
- async clear() {
416
- this.storage.clear();
462
+ if (tonResult.status === "fulfilled") {
463
+ addresses.ton = tonResult.value;
464
+ } else {
465
+ console.error("TON derivation failed:", tonResult.reason);
417
466
  }
418
- };
419
- function createSecureStorage() {
420
- if (typeof global !== "undefined" && global.nativeModuleProxy !== void 0) {
421
- const Platform = global.Platform;
422
- if (Platform?.OS === "ios") {
423
- return new KeychainStorageAdapter();
424
- } else if (Platform?.OS === "android") {
425
- return new KeystoreStorageAdapter();
426
- }
467
+ return addresses;
468
+ }
469
+ function isValidSeed(seed) {
470
+ return bip39.validateMnemonic(seed, english.wordlist);
471
+ }
472
+ function generateSeedPhrase() {
473
+ return bip39.generateMnemonic(english.wordlist);
474
+ }
475
+
476
+ // src/services/ZubariWdkService.ts
477
+ var DEFAULT_API_URL2 = "https://ckgwifsxka.us-east-2.awsapprunner.com";
478
+ function isBrowser() {
479
+ return typeof window !== "undefined" && typeof window.document !== "undefined";
480
+ }
481
+ var dynamicImport = new Function("specifier", "return import(specifier)");
482
+ async function canUseNativeWdk() {
483
+ if (isBrowser()) {
484
+ return false;
427
485
  }
428
- if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
429
- return new WebEncryptedStorageAdapter();
486
+ try {
487
+ await dynamicImport("@tetherto/wdk");
488
+ return true;
489
+ } catch {
490
+ return false;
430
491
  }
431
- return new MemoryStorageAdapter();
432
492
  }
433
-
434
- // src/services/WdkApiClient.ts
435
- var WdkApiClient = class {
493
+ var ZubariWdkService = class {
436
494
  config;
437
- constructor(config) {
495
+ apiClient;
496
+ nativeWdkService = null;
497
+ initialized = false;
498
+ useNativeWdk = false;
499
+ constructor(config = {}) {
438
500
  this.config = {
439
- baseUrl: config.baseUrl,
501
+ network: config.network || "testnet",
502
+ apiUrl: config.apiUrl || process.env.NEXT_PUBLIC_API_URL || DEFAULT_API_URL2,
503
+ forceApi: config.forceApi ?? false,
440
504
  timeout: config.timeout || 3e4
441
505
  };
506
+ this.apiClient = getWdkApiClient(this.config.apiUrl);
442
507
  }
443
508
  /**
444
- * Generate a new BIP-39 seed phrase using Tether WDK
509
+ * Initialize the service and determine the best strategy
510
+ */
511
+ async initialize() {
512
+ if (this.initialized) return;
513
+ if (isBrowser() || this.config.forceApi) {
514
+ this.useNativeWdk = false;
515
+ this.initialized = true;
516
+ return;
517
+ }
518
+ if (await canUseNativeWdk()) {
519
+ try {
520
+ const WdkServiceModule = await dynamicImport("./WdkService");
521
+ const WdkService = WdkServiceModule.WdkService || WdkServiceModule.default;
522
+ this.nativeWdkService = new WdkService({
523
+ network: this.config.network
524
+ });
525
+ this.useNativeWdk = true;
526
+ } catch (error) {
527
+ console.warn("Failed to initialize native WDK, falling back to API:", error);
528
+ this.useNativeWdk = false;
529
+ }
530
+ }
531
+ this.initialized = true;
532
+ }
533
+ /**
534
+ * Get the current execution mode
535
+ */
536
+ getMode() {
537
+ if (this.useNativeWdk) return "native";
538
+ if (isBrowser()) return "api";
539
+ return "api";
540
+ }
541
+ /**
542
+ * Check if running in browser
543
+ */
544
+ isBrowserEnvironment() {
545
+ return isBrowser();
546
+ }
547
+ /**
548
+ * Generate a new BIP-39 seed phrase (12 words)
445
549
  */
446
550
  async generateSeed() {
551
+ await this.initialize();
447
552
  try {
448
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
449
- method: "POST",
450
- headers: {
451
- "Content-Type": "application/json"
452
- }
453
- });
454
- return await response.json();
553
+ const response = await this.apiClient.generateSeed();
554
+ if (response.success && response.seed) {
555
+ return response.seed;
556
+ }
455
557
  } catch (error) {
456
- return {
457
- success: false,
458
- error: error instanceof Error ? error.message : "Failed to generate seed"
459
- };
558
+ console.warn("API seed generation failed:", error);
460
559
  }
560
+ if (this.useNativeWdk && this.nativeWdkService) {
561
+ try {
562
+ const wdk = this.nativeWdkService;
563
+ return await wdk.generateSeedPhrase();
564
+ } catch (error) {
565
+ console.warn("Native WDK seed generation failed:", error);
566
+ }
567
+ }
568
+ return generateSeedPhrase();
461
569
  }
462
570
  /**
463
571
  * Validate a BIP-39 seed phrase
464
572
  */
465
573
  async validateSeed(seed) {
574
+ await this.initialize();
466
575
  try {
467
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
468
- method: "POST",
469
- headers: {
470
- "Content-Type": "application/json"
471
- },
472
- body: JSON.stringify({ seed })
473
- });
474
- return await response.json();
576
+ const response = await this.apiClient.validateSeed(seed);
577
+ if (response.success) {
578
+ return response.isValid ?? false;
579
+ }
475
580
  } catch (error) {
476
- return {
477
- success: false,
478
- error: error instanceof Error ? error.message : "Failed to validate seed"
479
- };
581
+ console.warn("API seed validation failed:", error);
582
+ }
583
+ if (this.useNativeWdk && this.nativeWdkService) {
584
+ try {
585
+ const wdk = this.nativeWdkService;
586
+ return await wdk.isValidSeed(seed);
587
+ } catch (error) {
588
+ console.warn("Native WDK seed validation failed:", error);
589
+ }
480
590
  }
591
+ return isValidSeed(seed);
481
592
  }
482
593
  /**
483
- * Derive address for a specific chain using Tether WDK
594
+ * Derive address for a specific chain using WDK API
595
+ *
596
+ * For Ethereum, falls back to local derivation if API fails.
597
+ * For other chains, WDK API is required - no placeholder fallback.
484
598
  */
485
- async deriveAddress(seed, chain, network = "testnet") {
599
+ async deriveAddress(seed, chain) {
600
+ await this.initialize();
601
+ const path = this.getDerivationPath(chain);
486
602
  try {
487
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
488
- method: "POST",
489
- headers: {
490
- "Content-Type": "application/json"
491
- },
492
- body: JSON.stringify({ seed, chain, network })
493
- });
494
- return await response.json();
603
+ const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
604
+ if (response.success && response.address) {
605
+ return {
606
+ chain,
607
+ address: response.address,
608
+ path: response.path || path
609
+ };
610
+ }
611
+ } catch (error) {
612
+ console.warn(`API address derivation failed for ${chain}:`, error);
613
+ if (chain === "ethereum") {
614
+ return this.deriveBrowserAddress(seed, chain);
615
+ }
616
+ }
617
+ if (this.useNativeWdk && this.nativeWdkService) {
618
+ try {
619
+ const wdk = this.nativeWdkService;
620
+ await wdk.initialize(seed);
621
+ return await wdk.deriveAddress(chain);
622
+ } catch (error) {
623
+ console.warn(`Native WDK address derivation failed for ${chain}:`, error);
624
+ }
625
+ }
626
+ if (chain === "ethereum") {
627
+ return this.deriveBrowserAddress(seed, chain);
628
+ }
629
+ throw new Error(
630
+ `WDK API required for ${chain} address derivation. Ensure the backend is running.`
631
+ );
632
+ }
633
+ /**
634
+ * Derive addresses for all supported chains using WDK API
635
+ *
636
+ * Uses the backend WDK API for real cryptographically valid addresses.
637
+ * No placeholder fallback - WDK API is required for multi-chain addresses.
638
+ */
639
+ async deriveAllAddresses(seed) {
640
+ await this.initialize();
641
+ try {
642
+ const response = await this.apiClient.deriveAllAddresses(seed, this.config.network);
643
+ if (response.success && response.addresses) {
644
+ const extractAddress = (value) => {
645
+ if (!value) return null;
646
+ if (typeof value === "string") return value;
647
+ if (typeof value === "object" && value !== null && "address" in value) {
648
+ return value.address;
649
+ }
650
+ return null;
651
+ };
652
+ return {
653
+ ethereum: extractAddress(response.addresses.ethereum),
654
+ bitcoin: extractAddress(response.addresses.bitcoin),
655
+ ton: extractAddress(response.addresses.ton),
656
+ tron: extractAddress(response.addresses.tron),
657
+ solana: extractAddress(response.addresses.solana),
658
+ spark: extractAddress(response.addresses.spark)
659
+ };
660
+ }
495
661
  } catch (error) {
496
- return {
497
- success: false,
498
- error: error instanceof Error ? error.message : "Failed to derive address"
499
- };
662
+ console.warn("API address derivation failed:", error);
663
+ }
664
+ if (this.useNativeWdk && this.nativeWdkService) {
665
+ try {
666
+ const wdk = this.nativeWdkService;
667
+ await wdk.initialize(seed);
668
+ return await wdk.deriveAllAddresses();
669
+ } catch (error) {
670
+ console.warn("Native WDK multi-chain derivation failed:", error);
671
+ }
500
672
  }
673
+ throw new Error(
674
+ "Tether WDK API required for multi-chain address derivation. Service temporarily unavailable."
675
+ );
501
676
  }
502
677
  /**
503
- * Derive addresses for all chains using Tether WDK
678
+ * Get balances for all chains
504
679
  */
505
- async deriveAllAddresses(seed, network = "testnet") {
680
+ async getAllBalances(seed) {
681
+ await this.initialize();
506
682
  try {
507
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
683
+ const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balances`, {
508
684
  method: "POST",
509
- headers: {
510
- "Content-Type": "application/json"
511
- },
512
- body: JSON.stringify({ seed, network })
685
+ headers: { "Content-Type": "application/json" },
686
+ body: JSON.stringify({ seed, network: this.config.network })
513
687
  });
514
- return await response.json();
688
+ if (response.ok) {
689
+ const data = await response.json();
690
+ if (data.success) {
691
+ return data.balances;
692
+ }
693
+ }
515
694
  } catch (error) {
516
- return {
517
- success: false,
518
- error: error instanceof Error ? error.message : "Failed to derive addresses"
519
- };
695
+ console.warn("Failed to fetch balances:", error);
520
696
  }
697
+ return {};
521
698
  }
522
699
  /**
523
- * Send a transaction on a specific chain using Tether WDK
700
+ * Get fee rates for a chain
524
701
  */
525
- async sendTransaction(seed, chain, to, amount, network = "testnet") {
702
+ async getFeeRates(seed, chain) {
703
+ await this.initialize();
526
704
  try {
527
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
705
+ const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
528
706
  method: "POST",
529
- headers: {
530
- "Content-Type": "application/json"
531
- },
532
- body: JSON.stringify({ seed, chain, to, amount, network })
707
+ headers: { "Content-Type": "application/json" },
708
+ body: JSON.stringify({ seed, chain, network: this.config.network })
533
709
  });
534
- return await response.json();
710
+ if (response.ok) {
711
+ const data = await response.json();
712
+ if (data.success && data.feeRates) {
713
+ return data.feeRates;
714
+ }
715
+ }
535
716
  } catch (error) {
536
- return {
537
- success: false,
538
- error: error instanceof Error ? error.message : "Failed to send transaction"
539
- };
717
+ console.warn(`Failed to fetch fee rates for ${chain}:`, error);
540
718
  }
719
+ return { slow: "0", normal: "0", fast: "0" };
541
720
  }
542
721
  /**
543
- * Get transaction history for an address on a specific chain
544
- * Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
722
+ * Estimate transaction fee
545
723
  */
546
- async getTransactionHistory(seed, chain, network = "testnet", limit = 10) {
724
+ async estimateFee(seed, chain, to, amount) {
725
+ await this.initialize();
547
726
  try {
548
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
727
+ const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
549
728
  method: "POST",
550
- headers: {
551
- "Content-Type": "application/json"
552
- },
553
- body: JSON.stringify({ seed, chain, network, limit })
729
+ headers: { "Content-Type": "application/json" },
730
+ body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
554
731
  });
555
- return await response.json();
732
+ if (response.ok) {
733
+ const data = await response.json();
734
+ if (data.success) {
735
+ return { fee: data.fee, symbol: data.symbol };
736
+ }
737
+ }
556
738
  } catch (error) {
557
- return {
558
- success: false,
559
- error: error instanceof Error ? error.message : "Failed to get transaction history"
560
- };
739
+ console.warn(`Failed to estimate fee for ${chain}:`, error);
561
740
  }
741
+ return { fee: "0", symbol: this.getChainSymbol(chain) };
562
742
  }
563
743
  /**
564
- * Get transaction status by hash
565
- * Fetches from blockchain explorers to check confirmation status
744
+ * Send a transaction
566
745
  */
567
- async getTransactionStatus(txHash, chain, network = "testnet") {
746
+ async sendTransaction(seed, chain, to, amount) {
747
+ await this.initialize();
568
748
  try {
569
- const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
749
+ const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
570
750
  method: "POST",
571
- headers: {
572
- "Content-Type": "application/json"
573
- },
574
- body: JSON.stringify({ txHash, chain, network })
751
+ headers: { "Content-Type": "application/json" },
752
+ body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
575
753
  });
576
- return await response.json();
577
- } catch (error) {
578
- return {
579
- success: false,
580
- error: error instanceof Error ? error.message : "Failed to get transaction status"
581
- };
582
- }
583
- }
584
- };
585
- var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
586
- var wdkApiClient = null;
587
- function getWdkApiClient(baseUrl) {
588
- if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
589
- wdkApiClient = new WdkApiClient({
590
- baseUrl: baseUrl || DEFAULT_API_URL
591
- });
592
- }
593
- return wdkApiClient;
594
- }
595
- var DERIVATION_PATHS2 = {
596
- ethereum: "m/44'/60'/0'/0/0",
597
- bitcoin_mainnet: "m/84'/0'/0'/0/0",
598
- bitcoin_testnet: "m/84'/1'/0'/0/0",
599
- ton: "m/44'/607'/0'/0'/0'",
600
- tron: "m/44'/195'/0'/0/0",
601
- solana: "m/44'/501'/0'/0'",
602
- spark: "m/44'/998'/0'/0/0"
603
- };
604
- function deriveEthereumAddress(seed) {
605
- const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
606
- return hdNode.address;
607
- }
608
- function deriveBitcoinAddress(seed, network = "testnet") {
609
- try {
610
- const seedBytes = bip39.mnemonicToSeedSync(seed);
611
- const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
612
- const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
613
- const child = hdKey.derive(path);
614
- if (!child.publicKey) {
615
- throw new Error("Failed to derive public key");
616
- }
617
- const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
618
- const witnessVersion = 0;
619
- const words = base.bech32.toWords(pubKeyHash);
620
- words.unshift(witnessVersion);
621
- const hrp = network === "testnet" ? "tb" : "bc";
622
- const address = base.bech32.encode(hrp, words);
623
- return address;
624
- } catch (error) {
625
- console.error("Bitcoin address derivation failed:", error);
626
- throw error;
627
- }
628
- }
629
- async function deriveSolanaAddress(seed) {
630
- try {
631
- const [ed25519, nacl, bs58Module] = await Promise.all([
632
- import('ed25519-hd-key'),
633
- import('tweetnacl'),
634
- import('bs58')
635
- ]);
636
- const bs58 = bs58Module.default || bs58Module;
637
- const seedBytes = bip39.mnemonicToSeedSync(seed);
638
- const derived = ed25519.derivePath(DERIVATION_PATHS2.solana, Buffer.from(seedBytes).toString("hex"));
639
- const keypair = nacl.sign.keyPair.fromSeed(new Uint8Array(derived.key));
640
- return bs58.encode(keypair.publicKey);
641
- } catch (error) {
642
- console.error("Solana address derivation failed:", error);
643
- throw error;
644
- }
645
- }
646
- async function deriveTonAddress(seed) {
647
- try {
648
- const [ed25519, nacl] = await Promise.all([
649
- import('ed25519-hd-key'),
650
- import('tweetnacl')
651
- ]);
652
- const seedBytes = bip39.mnemonicToSeedSync(seed);
653
- const derived = ed25519.derivePath(DERIVATION_PATHS2.ton, Buffer.from(seedBytes).toString("hex"));
654
- const keypair = nacl.sign.keyPair.fromSeed(new Uint8Array(derived.key));
655
- const publicKey = keypair.publicKey;
656
- const workchain = 0;
657
- const flags = 17;
658
- const hash = sha256.sha256(publicKey);
659
- const addressData = new Uint8Array(34);
660
- addressData[0] = flags;
661
- addressData[1] = workchain;
662
- addressData.set(hash, 2);
663
- const crc = crc16(addressData);
664
- const fullAddress = new Uint8Array(36);
665
- fullAddress.set(addressData);
666
- fullAddress[34] = crc >> 8 & 255;
667
- fullAddress[35] = crc & 255;
668
- const base64 = btoa(String.fromCharCode(...fullAddress)).replace(/\+/g, "-").replace(/\//g, "_");
669
- return base64;
670
- } catch (error) {
671
- console.error("TON address derivation failed:", error);
672
- throw error;
673
- }
674
- }
675
- function crc16(data) {
676
- let crc = 0;
677
- for (const byte of data) {
678
- crc ^= byte << 8;
679
- for (let i = 0; i < 8; i++) {
680
- crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
681
- crc &= 65535;
682
- }
683
- }
684
- return crc;
685
- }
686
- function deriveTronAddress(seed) {
687
- try {
688
- const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.tron);
689
- const ethAddressHex = hdNode.address.slice(2).toLowerCase();
690
- const addressBytes = new Uint8Array(21);
691
- addressBytes[0] = 65;
692
- for (let i = 0; i < 20; i++) {
693
- addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
754
+ if (response.ok) {
755
+ const data = await response.json();
756
+ let txHash = data.txHash || data.transactionHash || data.hash;
757
+ if (txHash && typeof txHash === "object" && "hash" in txHash) {
758
+ txHash = txHash.hash;
759
+ }
760
+ if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
761
+ console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
762
+ }
763
+ return {
764
+ success: data.success,
765
+ txHash,
766
+ from: data.from,
767
+ to: data.to,
768
+ amount: data.amount,
769
+ chain: data.chain,
770
+ network: data.network
771
+ };
772
+ }
773
+ const errorData = await response.json().catch(() => ({}));
774
+ return {
775
+ success: false,
776
+ error: errorData.error || `HTTP ${response.status}`
777
+ };
778
+ } catch (error) {
779
+ return {
780
+ success: false,
781
+ error: error instanceof Error ? error.message : "Transaction failed"
782
+ };
694
783
  }
695
- const tronBase58check = base.base58check(sha256.sha256);
696
- return tronBase58check.encode(addressBytes);
697
- } catch (error) {
698
- console.error("TRON address derivation failed:", error);
699
- throw error;
700
784
  }
701
- }
702
- function deriveSparkAddress(seed, network = "testnet") {
703
- try {
704
- const seedBytes = bip39.mnemonicToSeedSync(seed);
705
- const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
706
- const child = hdKey.derive(DERIVATION_PATHS2.spark);
707
- if (!child.publicKey) {
708
- throw new Error("Failed to derive public key");
709
- }
710
- const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
711
- const witnessVersion = 0;
712
- const words = base.bech32.toWords(pubKeyHash);
713
- words.unshift(witnessVersion);
714
- const hrp = network === "testnet" ? "tsp" : "sp";
715
- const address = base.bech32.encode(hrp, words);
716
- return address;
717
- } catch (error) {
718
- console.error("Spark address derivation failed:", error);
719
- throw error;
785
+ /**
786
+ * Get the network configuration
787
+ */
788
+ getNetwork() {
789
+ return this.config.network;
720
790
  }
721
- }
722
- async function deriveAllAddresses(seed, network = "testnet") {
723
- const addresses = {
724
- ethereum: null,
725
- bitcoin: null,
726
- ton: null,
727
- tron: null,
728
- solana: null,
729
- spark: null
730
- };
731
- try {
732
- addresses.ethereum = deriveEthereumAddress(seed);
733
- } catch (e) {
734
- console.error("ETH derivation failed:", e);
791
+ /**
792
+ * Get API URL
793
+ */
794
+ getApiUrl() {
795
+ return this.config.apiUrl;
735
796
  }
736
- try {
737
- addresses.bitcoin = deriveBitcoinAddress(seed, network);
738
- } catch (e) {
739
- console.error("BTC derivation failed:", e);
797
+ // ==========================================
798
+ // Private Helper Methods
799
+ // ==========================================
800
+ getDerivationPath(chain) {
801
+ const paths = {
802
+ bitcoin: this.config.network === "testnet" ? "m/84'/1'/0'/0/0" : "m/84'/0'/0'/0/0",
803
+ ethereum: "m/44'/60'/0'/0/0",
804
+ ton: "m/44'/607'/0'/0'/0'",
805
+ tron: "m/44'/195'/0'/0/0",
806
+ solana: "m/44'/501'/0'/0'",
807
+ spark: "m/44'/998'/0'/0/0"
808
+ };
809
+ return paths[chain];
740
810
  }
741
- try {
742
- addresses.spark = deriveSparkAddress(seed, network);
743
- } catch (e) {
744
- console.error("Spark derivation failed:", e);
811
+ getChainSymbol(chain) {
812
+ const symbols = {
813
+ ethereum: "ETH",
814
+ bitcoin: "BTC",
815
+ ton: "TON",
816
+ tron: "TRX",
817
+ solana: "SOL",
818
+ spark: "SAT"
819
+ };
820
+ return symbols[chain];
745
821
  }
746
- try {
747
- addresses.tron = deriveTronAddress(seed);
748
- } catch (e) {
749
- console.error("TRON derivation failed:", e);
822
+ /**
823
+ * Derive address using browser-compatible libraries
824
+ */
825
+ async deriveBrowserAddress(seed, chain) {
826
+ const path = this.getDerivationPath(chain);
827
+ try {
828
+ let address;
829
+ switch (chain) {
830
+ case "ethereum":
831
+ address = deriveEthereumAddress(seed);
832
+ break;
833
+ case "bitcoin":
834
+ address = deriveBitcoinAddress(seed, this.config.network);
835
+ break;
836
+ case "tron":
837
+ address = deriveTronAddress(seed);
838
+ break;
839
+ case "spark":
840
+ address = deriveSparkAddress(seed, this.config.network);
841
+ break;
842
+ case "solana":
843
+ address = await deriveSolanaAddress(seed);
844
+ break;
845
+ case "ton":
846
+ address = await deriveTonAddress(seed);
847
+ break;
848
+ default:
849
+ throw new Error(`Unsupported chain: ${chain}`);
850
+ }
851
+ return { chain, address, path };
852
+ } catch (error) {
853
+ console.error(`Browser derivation failed for ${chain}:`, error);
854
+ throw error;
855
+ }
750
856
  }
751
- const [solResult, tonResult] = await Promise.allSettled([
752
- deriveSolanaAddress(seed),
753
- deriveTonAddress(seed)
754
- ]);
755
- if (solResult.status === "fulfilled") {
756
- addresses.solana = solResult.value;
757
- } else {
758
- console.error("SOL derivation failed:", solResult.reason);
857
+ /**
858
+ * Derive all addresses using browser-compatible libraries
859
+ */
860
+ async deriveAllBrowserAddresses(seed) {
861
+ return deriveAllAddresses(seed, this.config.network);
759
862
  }
760
- if (tonResult.status === "fulfilled") {
761
- addresses.ton = tonResult.value;
762
- } else {
763
- console.error("TON derivation failed:", tonResult.reason);
863
+ };
864
+ var defaultService = null;
865
+ function getZubariWdkService(config) {
866
+ if (!defaultService || config && config.network !== defaultService.getNetwork()) {
867
+ defaultService = new ZubariWdkService(config);
764
868
  }
765
- return addresses;
766
- }
767
- function isValidSeed(seed) {
768
- return bip39.validateMnemonic(seed, english.wordlist);
769
- }
770
- function generateSeedPhrase() {
771
- return bip39.generateMnemonic(english.wordlist);
869
+ return defaultService;
772
870
  }
773
871
 
774
- // src/services/ZubariWdkService.ts
775
- var DEFAULT_API_URL2 = "https://ckgwifsxka.us-east-2.awsapprunner.com";
776
- function isBrowser() {
777
- return typeof window !== "undefined" && typeof window.document !== "undefined";
778
- }
779
- var dynamicImport = new Function("specifier", "return import(specifier)");
780
- async function canUseNativeWdk() {
781
- if (isBrowser()) {
782
- return false;
783
- }
784
- try {
785
- await dynamicImport("@tetherto/wdk");
786
- return true;
787
- } catch {
788
- return false;
789
- }
790
- }
791
- var ZubariWdkService = class {
792
- config;
793
- apiClient;
794
- nativeWdkService = null;
795
- initialized = false;
796
- useNativeWdk = false;
797
- constructor(config = {}) {
798
- this.config = {
799
- network: config.network || "testnet",
800
- apiUrl: config.apiUrl || process.env.NEXT_PUBLIC_API_URL || DEFAULT_API_URL2,
801
- forceApi: config.forceApi ?? false,
802
- timeout: config.timeout || 3e4
803
- };
804
- this.apiClient = getWdkApiClient(this.config.apiUrl);
872
+ // src/security/KeyManager.ts
873
+ var KeyManager = class {
874
+ static ALGORITHM = "AES-GCM";
875
+ static KEY_LENGTH = 256;
876
+ static IV_LENGTH = 12;
877
+ static SALT_LENGTH = 16;
878
+ static PBKDF2_ITERATIONS = 1e5;
879
+ /**
880
+ * Encrypt a seed phrase with a password
881
+ */
882
+ static async encryptSeed(seed, password) {
883
+ const encoder = new TextEncoder();
884
+ const seedData = encoder.encode(seed);
885
+ const salt = crypto.getRandomValues(new Uint8Array(this.SALT_LENGTH));
886
+ const iv = crypto.getRandomValues(new Uint8Array(this.IV_LENGTH));
887
+ const key = await this.deriveKey(password, salt);
888
+ const encrypted = await crypto.subtle.encrypt(
889
+ { name: this.ALGORITHM, iv },
890
+ key,
891
+ seedData
892
+ );
893
+ const combined = new Uint8Array(salt.length + iv.length + encrypted.byteLength);
894
+ combined.set(salt, 0);
895
+ combined.set(iv, salt.length);
896
+ combined.set(new Uint8Array(encrypted), salt.length + iv.length);
897
+ return btoa(String.fromCharCode(...combined));
805
898
  }
806
899
  /**
807
- * Initialize the service and determine the best strategy
900
+ * Decrypt a seed phrase with a password
808
901
  */
809
- async initialize() {
810
- if (this.initialized) return;
811
- if (isBrowser() || this.config.forceApi) {
812
- this.useNativeWdk = false;
813
- this.initialized = true;
814
- return;
815
- }
816
- if (await canUseNativeWdk()) {
817
- try {
818
- const WdkServiceModule = await dynamicImport("./WdkService");
819
- const WdkService = WdkServiceModule.WdkService || WdkServiceModule.default;
820
- this.nativeWdkService = new WdkService({
821
- network: this.config.network
822
- });
823
- this.useNativeWdk = true;
824
- } catch (error) {
825
- console.warn("Failed to initialize native WDK, falling back to API:", error);
826
- this.useNativeWdk = false;
827
- }
828
- }
829
- this.initialized = true;
902
+ static async decryptSeed(encryptedData, password) {
903
+ const combined = new Uint8Array(
904
+ atob(encryptedData).split("").map((c) => c.charCodeAt(0))
905
+ );
906
+ const salt = combined.slice(0, this.SALT_LENGTH);
907
+ const iv = combined.slice(this.SALT_LENGTH, this.SALT_LENGTH + this.IV_LENGTH);
908
+ const encrypted = combined.slice(this.SALT_LENGTH + this.IV_LENGTH);
909
+ const key = await this.deriveKey(password, salt);
910
+ const decrypted = await crypto.subtle.decrypt(
911
+ { name: this.ALGORITHM, iv },
912
+ key,
913
+ encrypted
914
+ );
915
+ const decoder = new TextDecoder();
916
+ return decoder.decode(decrypted);
830
917
  }
831
918
  /**
832
- * Get the current execution mode
919
+ * Derive encryption key from password using PBKDF2
833
920
  */
834
- getMode() {
835
- if (this.useNativeWdk) return "native";
836
- if (isBrowser()) return "api";
837
- return "api";
921
+ static async deriveKey(password, salt) {
922
+ const encoder = new TextEncoder();
923
+ const passwordData = encoder.encode(password);
924
+ const keyMaterial = await crypto.subtle.importKey(
925
+ "raw",
926
+ passwordData,
927
+ "PBKDF2",
928
+ false,
929
+ ["deriveKey"]
930
+ );
931
+ return crypto.subtle.deriveKey(
932
+ {
933
+ name: "PBKDF2",
934
+ salt: salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength),
935
+ iterations: this.PBKDF2_ITERATIONS,
936
+ hash: "SHA-256"
937
+ },
938
+ keyMaterial,
939
+ { name: this.ALGORITHM, length: this.KEY_LENGTH },
940
+ false,
941
+ ["encrypt", "decrypt"]
942
+ );
838
943
  }
839
944
  /**
840
- * Check if running in browser
945
+ * Validate a BIP-39 seed phrase (basic validation)
841
946
  */
842
- isBrowserEnvironment() {
843
- return isBrowser();
947
+ static validateSeedPhrase(seed) {
948
+ const words = seed.trim().split(/\s+/);
949
+ const validWordCounts = [12, 15, 18, 21, 24];
950
+ return validWordCounts.includes(words.length);
844
951
  }
845
952
  /**
846
- * Generate a new BIP-39 seed phrase (12 words)
953
+ * Generate a random encryption key (for backup purposes)
847
954
  */
848
- async generateSeed() {
849
- await this.initialize();
850
- try {
851
- const response = await this.apiClient.generateSeed();
852
- if (response.success && response.seed) {
853
- return response.seed;
854
- }
855
- } catch (error) {
856
- console.warn("API seed generation failed:", error);
955
+ static generateBackupKey() {
956
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
957
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
958
+ }
959
+ };
960
+
961
+ // src/storage/SecureStorage.ts
962
+ var KeychainStorageAdapter = class {
963
+ serviceName;
964
+ constructor(serviceName = "com.zubari.wallet") {
965
+ this.serviceName = serviceName;
966
+ }
967
+ async setItem(key, value) {
968
+ if (typeof global !== "undefined" && global.KeychainModule) {
969
+ await global.KeychainModule.setItem(this.serviceName, key, value);
970
+ } else {
971
+ throw new Error("Keychain not available on this platform");
857
972
  }
858
- if (this.useNativeWdk && this.nativeWdkService) {
859
- try {
860
- const wdk = this.nativeWdkService;
861
- return await wdk.generateSeedPhrase();
862
- } catch (error) {
863
- console.warn("Native WDK seed generation failed:", error);
864
- }
973
+ }
974
+ async getItem(key) {
975
+ if (typeof global !== "undefined" && global.KeychainModule) {
976
+ return global.KeychainModule.getItem(this.serviceName, key);
865
977
  }
866
- return generateSeedPhrase();
978
+ throw new Error("Keychain not available on this platform");
867
979
  }
868
- /**
869
- * Validate a BIP-39 seed phrase
870
- */
871
- async validateSeed(seed) {
872
- await this.initialize();
873
- try {
874
- const response = await this.apiClient.validateSeed(seed);
875
- if (response.success) {
876
- return response.isValid ?? false;
877
- }
878
- } catch (error) {
879
- console.warn("API seed validation failed:", error);
980
+ async removeItem(key) {
981
+ if (typeof global !== "undefined" && global.KeychainModule) {
982
+ await global.KeychainModule.removeItem(this.serviceName, key);
983
+ } else {
984
+ throw new Error("Keychain not available on this platform");
880
985
  }
881
- if (this.useNativeWdk && this.nativeWdkService) {
882
- try {
883
- const wdk = this.nativeWdkService;
884
- return await wdk.isValidSeed(seed);
885
- } catch (error) {
886
- console.warn("Native WDK seed validation failed:", error);
887
- }
986
+ }
987
+ async hasItem(key) {
988
+ const value = await this.getItem(key);
989
+ return value !== null;
990
+ }
991
+ async clear() {
992
+ if (typeof global !== "undefined" && global.KeychainModule) {
993
+ await global.KeychainModule.clear(this.serviceName);
994
+ } else {
995
+ throw new Error("Keychain not available on this platform");
888
996
  }
889
- return isValidSeed(seed);
890
997
  }
891
- /**
892
- * Derive address for a specific chain using WDK API
893
- *
894
- * For Ethereum, falls back to local derivation if API fails.
895
- * For other chains, WDK API is required - no placeholder fallback.
896
- */
897
- async deriveAddress(seed, chain) {
898
- await this.initialize();
899
- const path = this.getDerivationPath(chain);
900
- try {
901
- const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
902
- if (response.success && response.address) {
903
- return {
904
- chain,
905
- address: response.address,
906
- path: response.path || path
907
- };
908
- }
909
- } catch (error) {
910
- console.warn(`API address derivation failed for ${chain}:`, error);
911
- if (chain === "ethereum") {
912
- return this.deriveBrowserAddress(seed, chain);
913
- }
998
+ };
999
+ var KeystoreStorageAdapter = class {
1000
+ alias;
1001
+ constructor(alias = "zubari_wallet_keys") {
1002
+ this.alias = alias;
1003
+ }
1004
+ async setItem(key, value) {
1005
+ if (typeof global !== "undefined" && global.KeystoreModule) {
1006
+ await global.KeystoreModule.setItem(this.alias, key, value);
1007
+ } else {
1008
+ throw new Error("Keystore not available on this platform");
914
1009
  }
915
- if (this.useNativeWdk && this.nativeWdkService) {
916
- try {
917
- const wdk = this.nativeWdkService;
918
- await wdk.initialize(seed);
919
- return await wdk.deriveAddress(chain);
920
- } catch (error) {
921
- console.warn(`Native WDK address derivation failed for ${chain}:`, error);
922
- }
1010
+ }
1011
+ async getItem(key) {
1012
+ if (typeof global !== "undefined" && global.KeystoreModule) {
1013
+ return global.KeystoreModule.getItem(this.alias, key);
923
1014
  }
924
- if (chain === "ethereum") {
925
- return this.deriveBrowserAddress(seed, chain);
1015
+ throw new Error("Keystore not available on this platform");
1016
+ }
1017
+ async removeItem(key) {
1018
+ if (typeof global !== "undefined" && global.KeystoreModule) {
1019
+ await global.KeystoreModule.removeItem(this.alias, key);
1020
+ } else {
1021
+ throw new Error("Keystore not available on this platform");
1022
+ }
1023
+ }
1024
+ async hasItem(key) {
1025
+ const value = await this.getItem(key);
1026
+ return value !== null;
1027
+ }
1028
+ async clear() {
1029
+ if (typeof global !== "undefined" && global.KeystoreModule) {
1030
+ await global.KeystoreModule.clear(this.alias);
1031
+ } else {
1032
+ throw new Error("Keystore not available on this platform");
926
1033
  }
927
- throw new Error(
928
- `WDK API required for ${chain} address derivation. Ensure the backend is running.`
929
- );
1034
+ }
1035
+ };
1036
+ var WebEncryptedStorageAdapter = class {
1037
+ encryptionKey = null;
1038
+ storagePrefix;
1039
+ constructor(storagePrefix = "zubari_") {
1040
+ this.storagePrefix = storagePrefix;
930
1041
  }
931
1042
  /**
932
- * Derive addresses for all supported chains using WDK API
933
- *
934
- * Uses the backend WDK API for real cryptographically valid addresses.
935
- * No placeholder fallback - WDK API is required for multi-chain addresses.
1043
+ * Initialize with a password-derived key
936
1044
  */
937
- async deriveAllAddresses(seed) {
938
- await this.initialize();
939
- try {
940
- const response = await this.apiClient.deriveAllAddresses(seed, this.config.network);
941
- if (response.success && response.addresses) {
942
- const extractAddress = (value) => {
943
- if (!value) return null;
944
- if (typeof value === "string") return value;
945
- if (typeof value === "object" && value !== null && "address" in value) {
946
- return value.address;
947
- }
948
- return null;
949
- };
950
- return {
951
- ethereum: extractAddress(response.addresses.ethereum),
952
- bitcoin: extractAddress(response.addresses.bitcoin),
953
- ton: extractAddress(response.addresses.ton),
954
- tron: extractAddress(response.addresses.tron),
955
- solana: extractAddress(response.addresses.solana),
956
- spark: extractAddress(response.addresses.spark)
957
- };
958
- }
959
- } catch (error) {
960
- console.warn("API address derivation failed:", error);
961
- }
962
- if (this.useNativeWdk && this.nativeWdkService) {
963
- try {
964
- const wdk = this.nativeWdkService;
965
- await wdk.initialize(seed);
966
- return await wdk.deriveAllAddresses();
967
- } catch (error) {
968
- console.warn("Native WDK multi-chain derivation failed:", error);
969
- }
1045
+ async initialize(password) {
1046
+ const encoder = new TextEncoder();
1047
+ const salt = this.getSalt();
1048
+ const keyMaterial = await crypto.subtle.importKey(
1049
+ "raw",
1050
+ encoder.encode(password),
1051
+ "PBKDF2",
1052
+ false,
1053
+ ["deriveKey"]
1054
+ );
1055
+ this.encryptionKey = await crypto.subtle.deriveKey(
1056
+ {
1057
+ name: "PBKDF2",
1058
+ salt: salt.buffer,
1059
+ iterations: 1e5,
1060
+ hash: "SHA-256"
1061
+ },
1062
+ keyMaterial,
1063
+ { name: "AES-GCM", length: 256 },
1064
+ false,
1065
+ ["encrypt", "decrypt"]
1066
+ );
1067
+ }
1068
+ getSalt() {
1069
+ const saltKey = `${this.storagePrefix}salt`;
1070
+ let saltHex = localStorage.getItem(saltKey);
1071
+ if (!saltHex) {
1072
+ const salt = crypto.getRandomValues(new Uint8Array(16));
1073
+ saltHex = Array.from(salt).map((b) => b.toString(16).padStart(2, "0")).join("");
1074
+ localStorage.setItem(saltKey, saltHex);
970
1075
  }
971
- throw new Error(
972
- "Tether WDK API required for multi-chain address derivation. Service temporarily unavailable."
1076
+ return new Uint8Array(
1077
+ saltHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
973
1078
  );
974
1079
  }
975
- /**
976
- * Get balances for all chains
977
- */
978
- async getAllBalances(seed) {
979
- await this.initialize();
980
- try {
981
- const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balances`, {
982
- method: "POST",
983
- headers: { "Content-Type": "application/json" },
984
- body: JSON.stringify({ seed, network: this.config.network })
985
- });
986
- if (response.ok) {
987
- const data = await response.json();
988
- if (data.success) {
989
- return data.balances;
990
- }
991
- }
992
- } catch (error) {
993
- console.warn("Failed to fetch balances:", error);
1080
+ async setItem(key, value) {
1081
+ if (!this.encryptionKey) {
1082
+ throw new Error("Storage not initialized. Call initialize() first.");
994
1083
  }
995
- return {};
1084
+ const encoder = new TextEncoder();
1085
+ const iv = crypto.getRandomValues(new Uint8Array(12));
1086
+ const encrypted = await crypto.subtle.encrypt(
1087
+ { name: "AES-GCM", iv },
1088
+ this.encryptionKey,
1089
+ encoder.encode(value)
1090
+ );
1091
+ const combined = new Uint8Array(iv.length + encrypted.byteLength);
1092
+ combined.set(iv);
1093
+ combined.set(new Uint8Array(encrypted), iv.length);
1094
+ const base64 = btoa(String.fromCharCode(...combined));
1095
+ localStorage.setItem(`${this.storagePrefix}${key}`, base64);
996
1096
  }
997
- /**
998
- * Get fee rates for a chain
999
- */
1000
- async getFeeRates(seed, chain) {
1001
- await this.initialize();
1002
- try {
1003
- const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
1004
- method: "POST",
1005
- headers: { "Content-Type": "application/json" },
1006
- body: JSON.stringify({ seed, chain, network: this.config.network })
1007
- });
1008
- if (response.ok) {
1009
- const data = await response.json();
1010
- if (data.success && data.feeRates) {
1011
- return data.feeRates;
1012
- }
1013
- }
1014
- } catch (error) {
1015
- console.warn(`Failed to fetch fee rates for ${chain}:`, error);
1097
+ async getItem(key) {
1098
+ if (!this.encryptionKey) {
1099
+ throw new Error("Storage not initialized. Call initialize() first.");
1016
1100
  }
1017
- return { slow: "0", normal: "0", fast: "0" };
1018
- }
1019
- /**
1020
- * Estimate transaction fee
1021
- */
1022
- async estimateFee(seed, chain, to, amount) {
1023
- await this.initialize();
1101
+ const base64 = localStorage.getItem(`${this.storagePrefix}${key}`);
1102
+ if (!base64) return null;
1024
1103
  try {
1025
- const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
1026
- method: "POST",
1027
- headers: { "Content-Type": "application/json" },
1028
- body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
1029
- });
1030
- if (response.ok) {
1031
- const data = await response.json();
1032
- if (data.success) {
1033
- return { fee: data.fee, symbol: data.symbol };
1034
- }
1035
- }
1036
- } catch (error) {
1037
- console.warn(`Failed to estimate fee for ${chain}:`, error);
1104
+ const combined = new Uint8Array(
1105
+ atob(base64).split("").map((c) => c.charCodeAt(0))
1106
+ );
1107
+ const iv = combined.slice(0, 12);
1108
+ const encrypted = combined.slice(12);
1109
+ const decrypted = await crypto.subtle.decrypt(
1110
+ { name: "AES-GCM", iv },
1111
+ this.encryptionKey,
1112
+ encrypted
1113
+ );
1114
+ const decoder = new TextDecoder();
1115
+ return decoder.decode(decrypted);
1116
+ } catch {
1117
+ return null;
1038
1118
  }
1039
- return { fee: "0", symbol: this.getChainSymbol(chain) };
1040
1119
  }
1041
- /**
1042
- * Send a transaction
1043
- */
1044
- async sendTransaction(seed, chain, to, amount) {
1045
- await this.initialize();
1046
- try {
1047
- const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
1048
- method: "POST",
1049
- headers: { "Content-Type": "application/json" },
1050
- body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
1051
- });
1052
- if (response.ok) {
1053
- const data = await response.json();
1054
- let txHash = data.txHash || data.transactionHash || data.hash;
1055
- if (txHash && typeof txHash === "object" && "hash" in txHash) {
1056
- txHash = txHash.hash;
1057
- }
1058
- if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
1059
- console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
1060
- }
1061
- return {
1062
- success: data.success,
1063
- txHash,
1064
- from: data.from,
1065
- to: data.to,
1066
- amount: data.amount,
1067
- chain: data.chain,
1068
- network: data.network
1069
- };
1120
+ async removeItem(key) {
1121
+ localStorage.removeItem(`${this.storagePrefix}${key}`);
1122
+ }
1123
+ async hasItem(key) {
1124
+ return localStorage.getItem(`${this.storagePrefix}${key}`) !== null;
1125
+ }
1126
+ async clear() {
1127
+ const keysToRemove = [];
1128
+ for (let i = 0; i < localStorage.length; i++) {
1129
+ const key = localStorage.key(i);
1130
+ if (key?.startsWith(this.storagePrefix)) {
1131
+ keysToRemove.push(key);
1070
1132
  }
1071
- const errorData = await response.json().catch(() => ({}));
1072
- return {
1073
- success: false,
1074
- error: errorData.error || `HTTP ${response.status}`
1075
- };
1076
- } catch (error) {
1077
- return {
1078
- success: false,
1079
- error: error instanceof Error ? error.message : "Transaction failed"
1080
- };
1081
1133
  }
1134
+ keysToRemove.forEach((key) => localStorage.removeItem(key));
1082
1135
  }
1083
- /**
1084
- * Get the network configuration
1085
- */
1086
- getNetwork() {
1087
- return this.config.network;
1088
- }
1089
- /**
1090
- * Get API URL
1091
- */
1092
- getApiUrl() {
1093
- return this.config.apiUrl;
1136
+ };
1137
+ var MemoryStorageAdapter = class {
1138
+ storage = /* @__PURE__ */ new Map();
1139
+ async setItem(key, value) {
1140
+ this.storage.set(key, value);
1094
1141
  }
1095
- // ==========================================
1096
- // Private Helper Methods
1097
- // ==========================================
1098
- getDerivationPath(chain) {
1099
- const paths = {
1100
- bitcoin: this.config.network === "testnet" ? "m/84'/1'/0'/0/0" : "m/84'/0'/0'/0/0",
1101
- ethereum: "m/44'/60'/0'/0/0",
1102
- ton: "m/44'/607'/0'/0'/0'",
1103
- tron: "m/44'/195'/0'/0/0",
1104
- solana: "m/44'/501'/0'/0'",
1105
- spark: "m/44'/998'/0'/0/0"
1106
- };
1107
- return paths[chain];
1142
+ async getItem(key) {
1143
+ return this.storage.get(key) || null;
1108
1144
  }
1109
- getChainSymbol(chain) {
1110
- const symbols = {
1111
- ethereum: "ETH",
1112
- bitcoin: "BTC",
1113
- ton: "TON",
1114
- tron: "TRX",
1115
- solana: "SOL",
1116
- spark: "SAT"
1117
- };
1118
- return symbols[chain];
1145
+ async removeItem(key) {
1146
+ this.storage.delete(key);
1119
1147
  }
1120
- /**
1121
- * Derive address using browser-compatible libraries
1122
- */
1123
- async deriveBrowserAddress(seed, chain) {
1124
- const path = this.getDerivationPath(chain);
1125
- try {
1126
- let address;
1127
- switch (chain) {
1128
- case "ethereum":
1129
- address = deriveEthereumAddress(seed);
1130
- break;
1131
- case "bitcoin":
1132
- address = deriveBitcoinAddress(seed, this.config.network);
1133
- break;
1134
- case "tron":
1135
- address = deriveTronAddress(seed);
1136
- break;
1137
- case "spark":
1138
- address = deriveSparkAddress(seed, this.config.network);
1139
- break;
1140
- case "solana":
1141
- address = await deriveSolanaAddress(seed);
1142
- break;
1143
- case "ton":
1144
- address = await deriveTonAddress(seed);
1145
- break;
1146
- default:
1147
- throw new Error(`Unsupported chain: ${chain}`);
1148
- }
1149
- return { chain, address, path };
1150
- } catch (error) {
1151
- console.error(`Browser derivation failed for ${chain}:`, error);
1152
- throw error;
1153
- }
1148
+ async hasItem(key) {
1149
+ return this.storage.has(key);
1154
1150
  }
1155
- /**
1156
- * Derive all addresses using browser-compatible libraries
1157
- */
1158
- async deriveAllBrowserAddresses(seed) {
1159
- return deriveAllAddresses(seed, this.config.network);
1151
+ async clear() {
1152
+ this.storage.clear();
1160
1153
  }
1161
1154
  };
1162
- var defaultService = null;
1163
- function getZubariWdkService(config) {
1164
- if (!defaultService || config && config.network !== defaultService.getNetwork()) {
1165
- defaultService = new ZubariWdkService(config);
1155
+ function createSecureStorage() {
1156
+ if (typeof global !== "undefined" && global.nativeModuleProxy !== void 0) {
1157
+ const Platform = global.Platform;
1158
+ if (Platform?.OS === "ios") {
1159
+ return new KeychainStorageAdapter();
1160
+ } else if (Platform?.OS === "android") {
1161
+ return new KeystoreStorageAdapter();
1162
+ }
1166
1163
  }
1167
- return defaultService;
1164
+ if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
1165
+ return new WebEncryptedStorageAdapter();
1166
+ }
1167
+ return new MemoryStorageAdapter();
1168
1168
  }
1169
1169
 
1170
1170
  // src/wallet/WalletManager.ts