@unicitylabs/sphere-sdk 0.1.4 → 0.1.6

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.
@@ -2153,50 +2153,56 @@ var NametagMinter = class {
2153
2153
  };
2154
2154
 
2155
2155
  // constants.ts
2156
- var STORAGE_PREFIX = "sphere_";
2157
2156
  var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
2158
- var STORAGE_KEYS = {
2157
+ var STORAGE_KEYS_GLOBAL = {
2159
2158
  /** Encrypted BIP39 mnemonic */
2160
- MNEMONIC: `${STORAGE_PREFIX}mnemonic`,
2159
+ MNEMONIC: "mnemonic",
2161
2160
  /** Encrypted master private key */
2162
- MASTER_KEY: `${STORAGE_PREFIX}master_key`,
2161
+ MASTER_KEY: "master_key",
2163
2162
  /** BIP32 chain code */
2164
- CHAIN_CODE: `${STORAGE_PREFIX}chain_code`,
2163
+ CHAIN_CODE: "chain_code",
2165
2164
  /** HD derivation path (full path like m/44'/0'/0'/0/0) */
2166
- DERIVATION_PATH: `${STORAGE_PREFIX}derivation_path`,
2165
+ DERIVATION_PATH: "derivation_path",
2167
2166
  /** Base derivation path (like m/44'/0'/0' without chain/index) */
2168
- BASE_PATH: `${STORAGE_PREFIX}base_path`,
2167
+ BASE_PATH: "base_path",
2169
2168
  /** Derivation mode: bip32, wif_hmac, legacy_hmac */
2170
- DERIVATION_MODE: `${STORAGE_PREFIX}derivation_mode`,
2169
+ DERIVATION_MODE: "derivation_mode",
2171
2170
  /** Wallet source: mnemonic, file, unknown */
2172
- WALLET_SOURCE: `${STORAGE_PREFIX}wallet_source`,
2171
+ WALLET_SOURCE: "wallet_source",
2173
2172
  /** Wallet existence flag */
2174
- WALLET_EXISTS: `${STORAGE_PREFIX}wallet_exists`,
2175
- /** Registered nametag (legacy - single address) */
2176
- NAMETAG: `${STORAGE_PREFIX}nametag`,
2173
+ WALLET_EXISTS: "wallet_exists",
2177
2174
  /** Current active address index */
2178
- CURRENT_ADDRESS_INDEX: `${STORAGE_PREFIX}current_address_index`,
2179
- /** Address nametags map (JSON: { "0": "alice", "1": "bob" }) */
2180
- ADDRESS_NAMETAGS: `${STORAGE_PREFIX}address_nametags`,
2181
- /** Token data */
2182
- TOKENS: `${STORAGE_PREFIX}tokens`,
2183
- /** Pending transfers */
2184
- PENDING_TRANSFERS: `${STORAGE_PREFIX}pending_transfers`,
2185
- /** Transfer outbox */
2186
- OUTBOX: `${STORAGE_PREFIX}outbox`,
2187
- /** Conversations */
2188
- CONVERSATIONS: `${STORAGE_PREFIX}conversations`,
2189
- /** Messages */
2190
- MESSAGES: `${STORAGE_PREFIX}messages`,
2191
- /** Transaction history */
2192
- TRANSACTION_HISTORY: `${STORAGE_PREFIX}transaction_history`,
2193
- /** Archived tokens (spent token history) */
2194
- ARCHIVED_TOKENS: `${STORAGE_PREFIX}archived_tokens`,
2195
- /** Tombstones (records of deleted/spent tokens) */
2196
- TOMBSTONES: `${STORAGE_PREFIX}tombstones`,
2197
- /** Forked tokens (alternative histories) */
2198
- FORKED_TOKENS: `${STORAGE_PREFIX}forked_tokens`
2175
+ CURRENT_ADDRESS_INDEX: "current_address_index",
2176
+ /** Index of address nametags (JSON: { "0": "alice", "1": "bob" }) - for discovery */
2177
+ ADDRESS_NAMETAGS: "address_nametags"
2178
+ };
2179
+ var STORAGE_KEYS_ADDRESS = {
2180
+ /** Pending transfers for this address */
2181
+ PENDING_TRANSFERS: "pending_transfers",
2182
+ /** Transfer outbox for this address */
2183
+ OUTBOX: "outbox",
2184
+ /** Conversations for this address */
2185
+ CONVERSATIONS: "conversations",
2186
+ /** Messages for this address */
2187
+ MESSAGES: "messages",
2188
+ /** Transaction history for this address */
2189
+ TRANSACTION_HISTORY: "transaction_history"
2199
2190
  };
2191
+ var STORAGE_KEYS = {
2192
+ ...STORAGE_KEYS_GLOBAL,
2193
+ ...STORAGE_KEYS_ADDRESS
2194
+ };
2195
+ function getAddressId(directAddress) {
2196
+ let hash = directAddress;
2197
+ if (hash.startsWith("DIRECT://")) {
2198
+ hash = hash.slice(9);
2199
+ } else if (hash.startsWith("DIRECT:")) {
2200
+ hash = hash.slice(7);
2201
+ }
2202
+ const first = hash.slice(0, 6).toLowerCase();
2203
+ const last = hash.slice(-6).toLowerCase();
2204
+ return `DIRECT_${first}_${last}`;
2205
+ }
2200
2206
  var DEFAULT_BASE_PATH = "m/44'/0'/0'";
2201
2207
  var DEFAULT_DERIVATION_PATH2 = `${DEFAULT_BASE_PATH}/0/0`;
2202
2208
  var LIMITS = {
@@ -2365,6 +2371,7 @@ function txfToToken(tokenId, txf) {
2365
2371
  coinId,
2366
2372
  symbol: isNft ? "NFT" : "UCT",
2367
2373
  name: isNft ? "NFT" : "Token",
2374
+ decimals: isNft ? 0 : 8,
2368
2375
  amount: totalAmount.toString(),
2369
2376
  status: determineTokenStatus(txf),
2370
2377
  createdAt: now,
@@ -2379,9 +2386,6 @@ async function buildTxfStorageData(tokens, meta, options) {
2379
2386
  formatVersion: "2.0"
2380
2387
  }
2381
2388
  };
2382
- if (options?.nametag) {
2383
- storageData._nametag = options.nametag;
2384
- }
2385
2389
  if (options?.tombstones && options.tombstones.length > 0) {
2386
2390
  storageData._tombstones = options.tombstones;
2387
2391
  }
@@ -2521,6 +2525,300 @@ function getCurrentStateHash(txf) {
2521
2525
  return void 0;
2522
2526
  }
2523
2527
 
2528
+ // registry/token-registry.testnet.json
2529
+ var token_registry_testnet_default = [
2530
+ {
2531
+ network: "unicity:testnet",
2532
+ assetKind: "non-fungible",
2533
+ name: "unicity",
2534
+ description: "Unicity testnet token type",
2535
+ id: "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509"
2536
+ },
2537
+ {
2538
+ network: "unicity:testnet",
2539
+ assetKind: "fungible",
2540
+ name: "unicity",
2541
+ symbol: "UCT",
2542
+ decimals: 18,
2543
+ description: "Unicity testnet native coin",
2544
+ icons: [
2545
+ { url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity_logo_32.png" }
2546
+ ],
2547
+ id: "455ad8720656b08e8dbd5bac1f3c73eeea5431565f6c1c3af742b1aa12d41d89"
2548
+ },
2549
+ {
2550
+ network: "unicity:testnet",
2551
+ assetKind: "fungible",
2552
+ name: "unicity-usd",
2553
+ symbol: "USDU",
2554
+ decimals: 6,
2555
+ description: "Unicity testnet USD stablecoin",
2556
+ icons: [
2557
+ { url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/usdu_logo_32.png" }
2558
+ ],
2559
+ id: "8f0f3d7a5e7297be0ee98c63b81bcebb2740f43f616566fc290f9823a54f52d7"
2560
+ },
2561
+ {
2562
+ network: "unicity:testnet",
2563
+ assetKind: "fungible",
2564
+ name: "unicity-eur",
2565
+ symbol: "EURU",
2566
+ decimals: 6,
2567
+ description: "Unicity testnet EUR stablecoin",
2568
+ icons: [
2569
+ { url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/euru_logo_32.png" }
2570
+ ],
2571
+ id: "5e160d5e9fdbb03b553fb9c3f6e6c30efa41fa807be39fb4f18e43776e492925"
2572
+ },
2573
+ {
2574
+ network: "unicity:testnet",
2575
+ assetKind: "fungible",
2576
+ name: "solana",
2577
+ symbol: "SOL",
2578
+ decimals: 9,
2579
+ description: "Solana testnet coin on Unicity",
2580
+ icons: [
2581
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/sol.svg" },
2582
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/sol.png" }
2583
+ ],
2584
+ id: "dee5f8ce778562eec90e9c38a91296a023210ccc76ff4c29d527ac3eb64ade93"
2585
+ },
2586
+ {
2587
+ network: "unicity:testnet",
2588
+ assetKind: "fungible",
2589
+ name: "bitcoin",
2590
+ symbol: "BTC",
2591
+ decimals: 8,
2592
+ description: "Bitcoin testnet coin on Unicity",
2593
+ icons: [
2594
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/btc.svg" },
2595
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/btc.png" }
2596
+ ],
2597
+ id: "86bc190fcf7b2d07c6078de93db803578760148b16d4431aa2f42a3241ff0daa"
2598
+ },
2599
+ {
2600
+ network: "unicity:testnet",
2601
+ assetKind: "fungible",
2602
+ name: "ethereum",
2603
+ symbol: "ETH",
2604
+ decimals: 18,
2605
+ description: "Ethereum testnet coin on Unicity",
2606
+ icons: [
2607
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/eth.svg" },
2608
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/eth.png" }
2609
+ ],
2610
+ id: "3c2450f2fd867e7bb60c6a69d7ad0e53ce967078c201a3ecaa6074ed4c0deafb"
2611
+ },
2612
+ {
2613
+ network: "unicity:testnet",
2614
+ assetKind: "fungible",
2615
+ name: "alpha_test",
2616
+ symbol: "ALPHT",
2617
+ decimals: 8,
2618
+ description: "ALPHA testnet coin on Unicity",
2619
+ icons: [
2620
+ { url: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/alpha_coin.png" }
2621
+ ],
2622
+ id: "cde78ded16ef65818a51f43138031c4284e519300ab0cb60c30a8f9078080e5f"
2623
+ },
2624
+ {
2625
+ network: "unicity:testnet",
2626
+ assetKind: "fungible",
2627
+ name: "tether",
2628
+ symbol: "USDT",
2629
+ decimals: 6,
2630
+ description: "Tether (Ethereum) testnet coin on Unicity",
2631
+ icons: [
2632
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/usdt.svg" },
2633
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/usdt.png" }
2634
+ ],
2635
+ id: "40d25444648418fe7efd433e147187a3a6adf049ac62bc46038bda5b960bf690"
2636
+ },
2637
+ {
2638
+ network: "unicity:testnet",
2639
+ assetKind: "fungible",
2640
+ name: "usd-coin",
2641
+ symbol: "USDC",
2642
+ decimals: 6,
2643
+ description: "USDC (Ethereum) testnet coin on Unicity",
2644
+ icons: [
2645
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/svg/icon/usdc.svg" },
2646
+ { url: "https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/32/icon/usdc.png" }
2647
+ ],
2648
+ id: "2265121770fa6f41131dd9a6cc571e28679263d09a53eb2642e145b5b9a5b0a2"
2649
+ }
2650
+ ];
2651
+
2652
+ // registry/TokenRegistry.ts
2653
+ var TokenRegistry = class _TokenRegistry {
2654
+ static instance = null;
2655
+ definitionsById;
2656
+ definitionsBySymbol;
2657
+ definitionsByName;
2658
+ constructor() {
2659
+ this.definitionsById = /* @__PURE__ */ new Map();
2660
+ this.definitionsBySymbol = /* @__PURE__ */ new Map();
2661
+ this.definitionsByName = /* @__PURE__ */ new Map();
2662
+ this.loadRegistry();
2663
+ }
2664
+ /**
2665
+ * Get singleton instance of TokenRegistry
2666
+ */
2667
+ static getInstance() {
2668
+ if (!_TokenRegistry.instance) {
2669
+ _TokenRegistry.instance = new _TokenRegistry();
2670
+ }
2671
+ return _TokenRegistry.instance;
2672
+ }
2673
+ /**
2674
+ * Reset the singleton instance (useful for testing)
2675
+ */
2676
+ static resetInstance() {
2677
+ _TokenRegistry.instance = null;
2678
+ }
2679
+ /**
2680
+ * Load registry data from bundled JSON
2681
+ */
2682
+ loadRegistry() {
2683
+ const definitions = token_registry_testnet_default;
2684
+ for (const def of definitions) {
2685
+ const idLower = def.id.toLowerCase();
2686
+ this.definitionsById.set(idLower, def);
2687
+ if (def.symbol) {
2688
+ this.definitionsBySymbol.set(def.symbol.toUpperCase(), def);
2689
+ }
2690
+ this.definitionsByName.set(def.name.toLowerCase(), def);
2691
+ }
2692
+ }
2693
+ // ===========================================================================
2694
+ // Lookup Methods
2695
+ // ===========================================================================
2696
+ /**
2697
+ * Get token definition by hex coin ID
2698
+ * @param coinId - 64-character hex string
2699
+ * @returns Token definition or undefined if not found
2700
+ */
2701
+ getDefinition(coinId) {
2702
+ if (!coinId) return void 0;
2703
+ return this.definitionsById.get(coinId.toLowerCase());
2704
+ }
2705
+ /**
2706
+ * Get token definition by symbol (e.g., "UCT", "BTC")
2707
+ * @param symbol - Token symbol (case-insensitive)
2708
+ * @returns Token definition or undefined if not found
2709
+ */
2710
+ getDefinitionBySymbol(symbol) {
2711
+ if (!symbol) return void 0;
2712
+ return this.definitionsBySymbol.get(symbol.toUpperCase());
2713
+ }
2714
+ /**
2715
+ * Get token definition by name (e.g., "bitcoin", "ethereum")
2716
+ * @param name - Token name (case-insensitive)
2717
+ * @returns Token definition or undefined if not found
2718
+ */
2719
+ getDefinitionByName(name) {
2720
+ if (!name) return void 0;
2721
+ return this.definitionsByName.get(name.toLowerCase());
2722
+ }
2723
+ /**
2724
+ * Get token symbol for a coin ID
2725
+ * @param coinId - 64-character hex string
2726
+ * @returns Symbol (e.g., "UCT") or truncated ID if not found
2727
+ */
2728
+ getSymbol(coinId) {
2729
+ const def = this.getDefinition(coinId);
2730
+ if (def?.symbol) {
2731
+ return def.symbol;
2732
+ }
2733
+ return coinId.slice(0, 6).toUpperCase();
2734
+ }
2735
+ /**
2736
+ * Get token name for a coin ID
2737
+ * @param coinId - 64-character hex string
2738
+ * @returns Name (e.g., "Bitcoin") or coin ID if not found
2739
+ */
2740
+ getName(coinId) {
2741
+ const def = this.getDefinition(coinId);
2742
+ if (def?.name) {
2743
+ return def.name.charAt(0).toUpperCase() + def.name.slice(1);
2744
+ }
2745
+ return coinId;
2746
+ }
2747
+ /**
2748
+ * Get decimal places for a coin ID
2749
+ * @param coinId - 64-character hex string
2750
+ * @returns Decimals or 0 if not found
2751
+ */
2752
+ getDecimals(coinId) {
2753
+ const def = this.getDefinition(coinId);
2754
+ return def?.decimals ?? 0;
2755
+ }
2756
+ /**
2757
+ * Get icon URL for a coin ID
2758
+ * @param coinId - 64-character hex string
2759
+ * @param preferPng - Prefer PNG format over SVG
2760
+ * @returns Icon URL or null if not found
2761
+ */
2762
+ getIconUrl(coinId, preferPng = true) {
2763
+ const def = this.getDefinition(coinId);
2764
+ if (!def?.icons || def.icons.length === 0) {
2765
+ return null;
2766
+ }
2767
+ if (preferPng) {
2768
+ const pngIcon = def.icons.find((i) => i.url.toLowerCase().includes(".png"));
2769
+ if (pngIcon) return pngIcon.url;
2770
+ }
2771
+ return def.icons[0].url;
2772
+ }
2773
+ /**
2774
+ * Check if a coin ID is known in the registry
2775
+ * @param coinId - 64-character hex string
2776
+ * @returns true if the coin is in the registry
2777
+ */
2778
+ isKnown(coinId) {
2779
+ return this.definitionsById.has(coinId.toLowerCase());
2780
+ }
2781
+ /**
2782
+ * Get all token definitions
2783
+ * @returns Array of all token definitions
2784
+ */
2785
+ getAllDefinitions() {
2786
+ return Array.from(this.definitionsById.values());
2787
+ }
2788
+ /**
2789
+ * Get all fungible token definitions
2790
+ * @returns Array of fungible token definitions
2791
+ */
2792
+ getFungibleTokens() {
2793
+ return this.getAllDefinitions().filter((def) => def.assetKind === "fungible");
2794
+ }
2795
+ /**
2796
+ * Get all non-fungible token definitions
2797
+ * @returns Array of non-fungible token definitions
2798
+ */
2799
+ getNonFungibleTokens() {
2800
+ return this.getAllDefinitions().filter((def) => def.assetKind === "non-fungible");
2801
+ }
2802
+ /**
2803
+ * Get coin ID by symbol
2804
+ * @param symbol - Token symbol (e.g., "UCT")
2805
+ * @returns Coin ID hex string or undefined if not found
2806
+ */
2807
+ getCoinIdBySymbol(symbol) {
2808
+ const def = this.getDefinitionBySymbol(symbol);
2809
+ return def?.id;
2810
+ }
2811
+ /**
2812
+ * Get coin ID by name
2813
+ * @param name - Token name (e.g., "bitcoin")
2814
+ * @returns Coin ID hex string or undefined if not found
2815
+ */
2816
+ getCoinIdByName(name) {
2817
+ const def = this.getDefinitionByName(name);
2818
+ return def?.id;
2819
+ }
2820
+ };
2821
+
2524
2822
  // modules/payments/PaymentsModule.ts
2525
2823
  import { Token as SdkToken2 } from "@unicitylabs/state-transition-sdk/lib/token/Token";
2526
2824
  import { CoinId as CoinId3 } from "@unicitylabs/state-transition-sdk/lib/token/fungible/CoinId";
@@ -2531,11 +2829,26 @@ import { AddressScheme } from "@unicitylabs/state-transition-sdk/lib/address/Add
2531
2829
  import { UnmaskedPredicate as UnmaskedPredicate3 } from "@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate";
2532
2830
  import { TokenState as TokenState3 } from "@unicitylabs/state-transition-sdk/lib/token/TokenState";
2533
2831
  import { HashAlgorithm as HashAlgorithm3 } from "@unicitylabs/state-transition-sdk/lib/hash/HashAlgorithm";
2832
+ function enrichWithRegistry(info) {
2833
+ const registry = TokenRegistry.getInstance();
2834
+ const def = registry.getDefinition(info.coinId);
2835
+ if (def) {
2836
+ return {
2837
+ ...info,
2838
+ symbol: def.symbol || info.symbol,
2839
+ name: def.name.charAt(0).toUpperCase() + def.name.slice(1),
2840
+ decimals: def.decimals ?? 0,
2841
+ iconUrl: registry.getIconUrl(info.coinId) ?? void 0
2842
+ };
2843
+ }
2844
+ return info;
2845
+ }
2534
2846
  async function parseTokenInfo(tokenData) {
2535
2847
  const defaultInfo = {
2536
2848
  coinId: "ALPHA",
2537
2849
  symbol: "ALPHA",
2538
2850
  name: "Alpha Token",
2851
+ decimals: 0,
2539
2852
  amount: "0"
2540
2853
  };
2541
2854
  try {
@@ -2556,23 +2869,25 @@ async function parseTokenInfo(tokenData) {
2556
2869
  }
2557
2870
  if (coinIdObj instanceof CoinId3) {
2558
2871
  const coinIdHex = coinIdObj.toJSON();
2559
- return {
2872
+ return enrichWithRegistry({
2560
2873
  coinId: coinIdHex,
2561
2874
  symbol: coinIdHex.slice(0, 8),
2562
2875
  name: `Token ${coinIdHex.slice(0, 8)}`,
2876
+ decimals: 0,
2563
2877
  amount: String(amount ?? "0"),
2564
2878
  tokenId: defaultInfo.tokenId
2565
- };
2879
+ });
2566
2880
  } else if (coinIdObj && typeof coinIdObj === "object" && "bytes" in coinIdObj) {
2567
2881
  const bytes = coinIdObj.bytes;
2568
2882
  const coinIdHex = Buffer.isBuffer(bytes) ? bytes.toString("hex") : Array.isArray(bytes) ? Buffer.from(bytes).toString("hex") : String(bytes);
2569
- return {
2883
+ return enrichWithRegistry({
2570
2884
  coinId: coinIdHex,
2571
2885
  symbol: coinIdHex.slice(0, 8),
2572
2886
  name: `Token ${coinIdHex.slice(0, 8)}`,
2887
+ decimals: 0,
2573
2888
  amount: String(amount ?? "0"),
2574
2889
  tokenId: defaultInfo.tokenId
2575
- };
2890
+ });
2576
2891
  }
2577
2892
  }
2578
2893
  }
@@ -2587,13 +2902,14 @@ async function parseTokenInfo(tokenData) {
2587
2902
  if (Array.isArray(firstEntry) && firstEntry.length === 2) {
2588
2903
  const [coinIdHex, amount] = firstEntry;
2589
2904
  const coinIdStr = typeof coinIdHex === "string" ? coinIdHex : String(coinIdHex);
2590
- return {
2905
+ return enrichWithRegistry({
2591
2906
  coinId: coinIdStr,
2592
2907
  symbol: coinIdStr.slice(0, 8),
2593
2908
  name: `Token ${coinIdStr.slice(0, 8)}`,
2909
+ decimals: 0,
2594
2910
  amount: String(amount),
2595
2911
  tokenId: defaultInfo.tokenId
2596
- };
2912
+ });
2597
2913
  }
2598
2914
  }
2599
2915
  }
@@ -2608,25 +2924,27 @@ async function parseTokenInfo(tokenData) {
2608
2924
  const firstEntry = coinData[0];
2609
2925
  if (Array.isArray(firstEntry) && firstEntry.length === 2) {
2610
2926
  const [coinIdHex, amount] = firstEntry;
2611
- return {
2927
+ return enrichWithRegistry({
2612
2928
  coinId: String(coinIdHex),
2613
2929
  symbol: String(coinIdHex).slice(0, 8),
2614
2930
  name: `Token ${String(coinIdHex).slice(0, 8)}`,
2931
+ decimals: 0,
2615
2932
  amount: String(amount),
2616
2933
  tokenId: genesis.tokenId
2617
- };
2934
+ });
2618
2935
  }
2619
2936
  } else if (typeof coinData === "object") {
2620
2937
  const coinEntries = Object.entries(coinData);
2621
2938
  if (coinEntries.length > 0) {
2622
2939
  const [coinId, amount] = coinEntries[0];
2623
- return {
2940
+ return enrichWithRegistry({
2624
2941
  coinId,
2625
2942
  symbol: coinId.slice(0, 8),
2626
2943
  name: `Token ${coinId.slice(0, 8)}`,
2944
+ decimals: 0,
2627
2945
  amount: String(amount),
2628
2946
  tokenId: genesis.tokenId
2629
- };
2947
+ });
2630
2948
  }
2631
2949
  }
2632
2950
  }
@@ -2640,25 +2958,27 @@ async function parseTokenInfo(tokenData) {
2640
2958
  const firstEntry = coinData[0];
2641
2959
  if (Array.isArray(firstEntry) && firstEntry.length === 2) {
2642
2960
  const [coinIdHex, amount] = firstEntry;
2643
- return {
2961
+ return enrichWithRegistry({
2644
2962
  coinId: String(coinIdHex),
2645
2963
  symbol: String(coinIdHex).slice(0, 8),
2646
2964
  name: `Token ${String(coinIdHex).slice(0, 8)}`,
2965
+ decimals: 0,
2647
2966
  amount: String(amount),
2648
2967
  tokenId: defaultInfo.tokenId
2649
- };
2968
+ });
2650
2969
  }
2651
2970
  } else if (typeof coinData === "object") {
2652
2971
  const coinEntries = Object.entries(coinData);
2653
2972
  if (coinEntries.length > 0) {
2654
2973
  const [coinId, amount] = coinEntries[0];
2655
- return {
2974
+ return enrichWithRegistry({
2656
2975
  coinId,
2657
2976
  symbol: coinId.slice(0, 8),
2658
2977
  name: `Token ${coinId.slice(0, 8)}`,
2978
+ decimals: 0,
2659
2979
  amount: String(amount),
2660
2980
  tokenId: defaultInfo.tokenId
2661
- };
2981
+ });
2662
2982
  }
2663
2983
  }
2664
2984
  }
@@ -2840,37 +3160,24 @@ var PaymentsModule = class {
2840
3160
  */
2841
3161
  async load() {
2842
3162
  this.ensureInitialized();
2843
- const data = await this.deps.storage.get(STORAGE_KEYS.TOKENS);
2844
- if (data) {
3163
+ const providers = this.getTokenStorageProviders();
3164
+ for (const [id, provider] of providers) {
2845
3165
  try {
2846
- const parsed = JSON.parse(data);
2847
- const tokens = parsed.tokens || [];
2848
- this.tokens.clear();
2849
- for (const token of tokens) {
2850
- this.tokens.set(token.id, token);
2851
- }
2852
- if (Array.isArray(parsed.tombstones)) {
2853
- this.tombstones = parsed.tombstones.filter(
2854
- (t) => typeof t === "object" && t !== null && typeof t.tokenId === "string" && typeof t.stateHash === "string"
2855
- );
2856
- }
2857
- if (parsed.archivedTokens && typeof parsed.archivedTokens === "object") {
2858
- this.archivedTokens = new Map(Object.entries(parsed.archivedTokens));
2859
- }
2860
- if (parsed.forkedTokens && typeof parsed.forkedTokens === "object") {
2861
- this.forkedTokens = new Map(Object.entries(parsed.forkedTokens));
2862
- }
2863
- if (parsed.nametag) {
2864
- this.nametag = parsed.nametag;
3166
+ const result = await provider.load();
3167
+ if (result.success && result.data) {
3168
+ this.loadFromStorageData(result.data);
3169
+ this.log(`Loaded from provider ${id}: ${this.tokens.size} tokens`);
3170
+ break;
2865
3171
  }
2866
- this.log(`Loaded ${this.tokens.size} tokens, ${this.tombstones.length} tombstones, ${this.archivedTokens.size} archived`);
2867
3172
  } catch (err) {
2868
- console.error("[Payments] Failed to parse stored data:", err);
3173
+ console.error(`[Payments] Failed to load from provider ${id}:`, err);
2869
3174
  }
2870
3175
  }
2871
- await this.loadTokensFromFileStorage();
3176
+ if (this.tokens.size === 0) {
3177
+ await this.loadTokensFromFileStorage();
3178
+ }
2872
3179
  await this.loadNametagFromFileStorage();
2873
- const historyData = await this.deps.storage.get(STORAGE_KEYS.TRANSACTION_HISTORY);
3180
+ const historyData = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
2874
3181
  if (historyData) {
2875
3182
  try {
2876
3183
  this.transactionHistory = JSON.parse(historyData);
@@ -2878,7 +3185,7 @@ var PaymentsModule = class {
2878
3185
  this.transactionHistory = [];
2879
3186
  }
2880
3187
  }
2881
- const pending2 = await this.deps.storage.get(STORAGE_KEYS.PENDING_TRANSFERS);
3188
+ const pending2 = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
2882
3189
  if (pending2) {
2883
3190
  const transfers = JSON.parse(pending2);
2884
3191
  for (const transfer of transfers) {
@@ -2976,6 +3283,8 @@ var PaymentsModule = class {
2976
3283
  coinId: request.coinId,
2977
3284
  symbol: this.getCoinSymbol(request.coinId),
2978
3285
  name: this.getCoinName(request.coinId),
3286
+ decimals: this.getCoinDecimals(request.coinId),
3287
+ iconUrl: this.getCoinIconUrl(request.coinId),
2979
3288
  amount: splitPlan.remainderAmount.toString(),
2980
3289
  status: "confirmed",
2981
3290
  createdAt: Date.now(),
@@ -3044,20 +3353,25 @@ var PaymentsModule = class {
3044
3353
  * Get coin symbol from coinId
3045
3354
  */
3046
3355
  getCoinSymbol(coinId) {
3047
- const symbols = {
3048
- "UCT": "UCT"
3049
- // Add more as needed
3050
- };
3051
- return symbols[coinId] || coinId.slice(0, 6).toUpperCase();
3356
+ return TokenRegistry.getInstance().getSymbol(coinId);
3052
3357
  }
3053
3358
  /**
3054
3359
  * Get coin name from coinId
3055
3360
  */
3056
3361
  getCoinName(coinId) {
3057
- const names = {
3058
- "UCT": "Unicity Token"
3059
- };
3060
- return names[coinId] || coinId;
3362
+ return TokenRegistry.getInstance().getName(coinId);
3363
+ }
3364
+ /**
3365
+ * Get coin decimals from coinId
3366
+ */
3367
+ getCoinDecimals(coinId) {
3368
+ return TokenRegistry.getInstance().getDecimals(coinId);
3369
+ }
3370
+ /**
3371
+ * Get coin icon URL from coinId
3372
+ */
3373
+ getCoinIconUrl(coinId) {
3374
+ return TokenRegistry.getInstance().getIconUrl(coinId) ?? void 0;
3061
3375
  }
3062
3376
  // ===========================================================================
3063
3377
  // Public API - Payment Requests
@@ -3532,6 +3846,8 @@ var PaymentsModule = class {
3532
3846
  coinId: tokenInfo.coinId,
3533
3847
  symbol: tokenInfo.symbol,
3534
3848
  name: tokenInfo.name,
3849
+ decimals: tokenInfo.decimals,
3850
+ iconUrl: tokenInfo.iconUrl,
3535
3851
  amount: tokenInfo.amount,
3536
3852
  status: "confirmed",
3537
3853
  createdAt: data.receivedAt || Date.now(),
@@ -3787,7 +4103,7 @@ var PaymentsModule = class {
3787
4103
  };
3788
4104
  this.transactionHistory.push(historyEntry);
3789
4105
  await this.deps.storage.set(
3790
- STORAGE_KEYS.TRANSACTION_HISTORY,
4106
+ STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY,
3791
4107
  JSON.stringify(this.transactionHistory)
3792
4108
  );
3793
4109
  }
@@ -4327,6 +4643,8 @@ var PaymentsModule = class {
4327
4643
  coinId: tokenInfo.coinId,
4328
4644
  symbol: tokenInfo.symbol,
4329
4645
  name: tokenInfo.name,
4646
+ decimals: tokenInfo.decimals,
4647
+ iconUrl: tokenInfo.iconUrl,
4330
4648
  amount: tokenInfo.amount,
4331
4649
  status: "confirmed",
4332
4650
  createdAt: Date.now(),
@@ -4380,28 +4698,32 @@ var PaymentsModule = class {
4380
4698
  // Private: Storage
4381
4699
  // ===========================================================================
4382
4700
  async save() {
4383
- const tokens = Array.from(this.tokens.values());
4384
- const data = {
4385
- tokens,
4386
- tombstones: this.tombstones.length > 0 ? this.tombstones : void 0,
4387
- archivedTokens: this.archivedTokens.size > 0 ? Object.fromEntries(this.archivedTokens) : void 0,
4388
- forkedTokens: this.forkedTokens.size > 0 ? Object.fromEntries(this.forkedTokens) : void 0,
4389
- nametag: this.nametag || void 0
4390
- };
4391
- await this.deps.storage.set(STORAGE_KEYS.TOKENS, JSON.stringify(data));
4701
+ const providers = this.getTokenStorageProviders();
4702
+ if (providers.size === 0) {
4703
+ this.log("No token storage providers - tokens not persisted");
4704
+ return;
4705
+ }
4706
+ const data = await this.createStorageData();
4707
+ for (const [id, provider] of providers) {
4708
+ try {
4709
+ await provider.save(data);
4710
+ } catch (err) {
4711
+ console.error(`[Payments] Failed to save to provider ${id}:`, err);
4712
+ }
4713
+ }
4392
4714
  }
4393
4715
  async saveToOutbox(transfer, recipient) {
4394
4716
  const outbox = await this.loadOutbox();
4395
4717
  outbox.push({ transfer, recipient, createdAt: Date.now() });
4396
- await this.deps.storage.set(STORAGE_KEYS.OUTBOX, JSON.stringify(outbox));
4718
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.OUTBOX, JSON.stringify(outbox));
4397
4719
  }
4398
4720
  async removeFromOutbox(transferId) {
4399
4721
  const outbox = await this.loadOutbox();
4400
4722
  const filtered = outbox.filter((e) => e.transfer.id !== transferId);
4401
- await this.deps.storage.set(STORAGE_KEYS.OUTBOX, JSON.stringify(filtered));
4723
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.OUTBOX, JSON.stringify(filtered));
4402
4724
  }
4403
4725
  async loadOutbox() {
4404
- const data = await this.deps.storage.get(STORAGE_KEYS.OUTBOX);
4726
+ const data = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.OUTBOX);
4405
4727
  return data ? JSON.parse(data) : [];
4406
4728
  }
4407
4729
  async createStorageData() {
@@ -4414,7 +4736,6 @@ var PaymentsModule = class {
4414
4736
  ipnsName: this.deps.identity.ipnsName ?? ""
4415
4737
  },
4416
4738
  {
4417
- nametag: this.nametag || void 0,
4418
4739
  tombstones: this.tombstones,
4419
4740
  archivedTokens: this.archivedTokens,
4420
4741
  forkedTokens: this.forkedTokens
@@ -5528,6 +5849,7 @@ var Sphere = class _Sphere {
5528
5849
  _derivationMode = "bip32";
5529
5850
  _basePath = DEFAULT_BASE_PATH;
5530
5851
  _currentAddressIndex = 0;
5852
+ /** Map of addressId -> (nametagIndex -> nametag). Supports multiple nametags per address (e.g., from Nostr recovery) */
5531
5853
  _addressNametags = /* @__PURE__ */ new Map();
5532
5854
  // Providers
5533
5855
  _storage;
@@ -5563,9 +5885,9 @@ var Sphere = class _Sphere {
5563
5885
  if (!storage.isConnected()) {
5564
5886
  await storage.connect();
5565
5887
  }
5566
- const mnemonic = await storage.get(STORAGE_KEYS.MNEMONIC);
5888
+ const mnemonic = await storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
5567
5889
  if (mnemonic) return true;
5568
- const masterKey = await storage.get(STORAGE_KEYS.MASTER_KEY);
5890
+ const masterKey = await storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
5569
5891
  if (masterKey) return true;
5570
5892
  return false;
5571
5893
  } catch {
@@ -5736,20 +6058,20 @@ var Sphere = class _Sphere {
5736
6058
  }
5737
6059
  /**
5738
6060
  * Clear wallet data from storage
6061
+ * Note: Token data is cleared via TokenStorageProvider, not here
5739
6062
  */
5740
6063
  static async clear(storage) {
5741
- await storage.remove(STORAGE_KEYS.MNEMONIC);
5742
- await storage.remove(STORAGE_KEYS.MASTER_KEY);
5743
- await storage.remove(STORAGE_KEYS.CHAIN_CODE);
5744
- await storage.remove(STORAGE_KEYS.DERIVATION_PATH);
5745
- await storage.remove(STORAGE_KEYS.BASE_PATH);
5746
- await storage.remove(STORAGE_KEYS.DERIVATION_MODE);
5747
- await storage.remove(STORAGE_KEYS.WALLET_SOURCE);
5748
- await storage.remove(STORAGE_KEYS.WALLET_EXISTS);
5749
- await storage.remove(STORAGE_KEYS.NAMETAG);
5750
- await storage.remove(STORAGE_KEYS.TOKENS);
5751
- await storage.remove(STORAGE_KEYS.PENDING_TRANSFERS);
5752
- await storage.remove(STORAGE_KEYS.OUTBOX);
6064
+ await storage.remove(STORAGE_KEYS_GLOBAL.MNEMONIC);
6065
+ await storage.remove(STORAGE_KEYS_GLOBAL.MASTER_KEY);
6066
+ await storage.remove(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
6067
+ await storage.remove(STORAGE_KEYS_GLOBAL.DERIVATION_PATH);
6068
+ await storage.remove(STORAGE_KEYS_GLOBAL.BASE_PATH);
6069
+ await storage.remove(STORAGE_KEYS_GLOBAL.DERIVATION_MODE);
6070
+ await storage.remove(STORAGE_KEYS_GLOBAL.WALLET_SOURCE);
6071
+ await storage.remove(STORAGE_KEYS_GLOBAL.WALLET_EXISTS);
6072
+ await storage.remove(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
6073
+ await storage.remove(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
6074
+ await storage.remove(STORAGE_KEYS_ADDRESS.OUTBOX);
5753
6075
  if (_Sphere.instance) {
5754
6076
  await _Sphere.instance.destroy();
5755
6077
  }
@@ -6349,22 +6671,47 @@ var Sphere = class _Sphere {
6349
6671
  return this._currentAddressIndex;
6350
6672
  }
6351
6673
  /**
6352
- * Get nametag for a specific address index
6674
+ * Get primary nametag for a specific address
6675
+ *
6676
+ * @param addressId - Address identifier (DIRECT://xxx), defaults to current address
6677
+ * @returns Primary nametag (index 0) or undefined if not registered
6678
+ */
6679
+ getNametagForAddress(addressId) {
6680
+ const id = addressId ?? this.getCurrentAddressId();
6681
+ if (!id) return void 0;
6682
+ const nametagsMap = this._addressNametags.get(id);
6683
+ return nametagsMap?.get(0);
6684
+ }
6685
+ /**
6686
+ * Get all nametags for a specific address
6353
6687
  *
6354
- * @param index - Address index (default: current address)
6355
- * @returns Nametag or undefined if not registered
6688
+ * @param addressId - Address identifier (DIRECT://xxx), defaults to current address
6689
+ * @returns Map of nametagIndex to nametag, or undefined if no nametags
6356
6690
  */
6357
- getNametagForAddress(index) {
6358
- const addressIndex = index ?? this._currentAddressIndex;
6359
- return this._addressNametags.get(addressIndex);
6691
+ getNametagsForAddress(addressId) {
6692
+ const id = addressId ?? this.getCurrentAddressId();
6693
+ if (!id) return void 0;
6694
+ const nametagsMap = this._addressNametags.get(id);
6695
+ return nametagsMap ? new Map(nametagsMap) : void 0;
6360
6696
  }
6361
6697
  /**
6362
6698
  * Get all registered address nametags
6363
6699
  *
6364
- * @returns Map of address index to nametag
6700
+ * @returns Map of addressId to (nametagIndex -> nametag)
6365
6701
  */
6366
6702
  getAllAddressNametags() {
6367
- return new Map(this._addressNametags);
6703
+ const result = /* @__PURE__ */ new Map();
6704
+ this._addressNametags.forEach((nametagsMap, addressId) => {
6705
+ result.set(addressId, new Map(nametagsMap));
6706
+ });
6707
+ return result;
6708
+ }
6709
+ /**
6710
+ * Get current address identifier (DIRECT://xxx format)
6711
+ */
6712
+ getCurrentAddressId() {
6713
+ if (!this._identity?.directAddress) return void 0;
6714
+ return getAddressId(this._identity.directAddress);
6368
6715
  }
6369
6716
  /**
6370
6717
  * Switch to a different address by index
@@ -6396,7 +6743,9 @@ var Sphere = class _Sphere {
6396
6743
  const addressInfo = this.deriveAddress(index, false);
6397
6744
  const ipnsHash = sha256(addressInfo.publicKey, "hex").slice(0, 40);
6398
6745
  const predicateAddress = await deriveL3PredicateAddress(addressInfo.privateKey);
6399
- const nametag = this._addressNametags.get(index);
6746
+ const addressId = getAddressId(predicateAddress);
6747
+ const nametagsMap = this._addressNametags.get(addressId);
6748
+ const nametag = nametagsMap?.get(0);
6400
6749
  this._identity = {
6401
6750
  privateKey: addressInfo.privateKey,
6402
6751
  chainPubkey: addressInfo.publicKey,
@@ -6406,7 +6755,7 @@ var Sphere = class _Sphere {
6406
6755
  nametag
6407
6756
  };
6408
6757
  this._currentAddressIndex = index;
6409
- await this._storage.set(STORAGE_KEYS.CURRENT_ADDRESS_INDEX, index.toString());
6758
+ await this._storage.set(STORAGE_KEYS_GLOBAL.CURRENT_ADDRESS_INDEX, index.toString());
6410
6759
  this._storage.setIdentity(this._identity);
6411
6760
  this._transport.setIdentity(this._identity);
6412
6761
  for (const provider of this._tokenStorageProviders.values()) {
@@ -6645,8 +6994,15 @@ var Sphere = class _Sphere {
6645
6994
  }
6646
6995
  }
6647
6996
  this._identity.nametag = cleanNametag;
6648
- this._addressNametags.set(this._currentAddressIndex, cleanNametag);
6649
- await this._storage.set(STORAGE_KEYS.NAMETAG, cleanNametag);
6997
+ const addressId = this.getCurrentAddressId();
6998
+ if (addressId) {
6999
+ let nametagsMap = this._addressNametags.get(addressId);
7000
+ if (!nametagsMap) {
7001
+ nametagsMap = /* @__PURE__ */ new Map();
7002
+ this._addressNametags.set(addressId, nametagsMap);
7003
+ }
7004
+ nametagsMap.set(0, cleanNametag);
7005
+ }
6650
7006
  await this.persistAddressNametags();
6651
7007
  if (!this._payments.hasNametag()) {
6652
7008
  console.log(`[Sphere] Minting nametag token for @${cleanNametag}...`);
@@ -6665,13 +7021,18 @@ var Sphere = class _Sphere {
6665
7021
  }
6666
7022
  /**
6667
7023
  * Persist address nametags to storage
7024
+ * Format: { "DIRECT://abc...xyz": { "0": "alice", "1": "alice2" }, ... }
6668
7025
  */
6669
7026
  async persistAddressNametags() {
6670
- const nametagsObj = {};
6671
- this._addressNametags.forEach((nametag, index) => {
6672
- nametagsObj[index.toString()] = nametag;
7027
+ const result = {};
7028
+ this._addressNametags.forEach((nametagsMap, addressId) => {
7029
+ const innerObj = {};
7030
+ nametagsMap.forEach((nametag, index) => {
7031
+ innerObj[index.toString()] = nametag;
7032
+ });
7033
+ result[addressId] = innerObj;
6673
7034
  });
6674
- await this._storage.set(STORAGE_KEYS.ADDRESS_NAMETAGS, JSON.stringify(nametagsObj));
7035
+ await this._storage.set(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS, JSON.stringify(result));
6675
7036
  }
6676
7037
  /**
6677
7038
  * Mint a nametag token on-chain (like Sphere wallet and lottery)
@@ -6706,15 +7067,24 @@ var Sphere = class _Sphere {
6706
7067
  }
6707
7068
  /**
6708
7069
  * Load address nametags from storage
7070
+ * Supports new format: { "DIRECT://abc...xyz": { "0": "alice" } }
7071
+ * And legacy format: { "0": "alice" } (migrates to new format on save)
6709
7072
  */
6710
7073
  async loadAddressNametags() {
6711
7074
  try {
6712
- const saved = await this._storage.get(STORAGE_KEYS.ADDRESS_NAMETAGS);
7075
+ const saved = await this._storage.get(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
6713
7076
  if (saved) {
6714
- const nametagsObj = JSON.parse(saved);
7077
+ const parsed = JSON.parse(saved);
6715
7078
  this._addressNametags.clear();
6716
- for (const [indexStr, nametag] of Object.entries(nametagsObj)) {
6717
- this._addressNametags.set(parseInt(indexStr, 10), nametag);
7079
+ for (const [key, value] of Object.entries(parsed)) {
7080
+ if (typeof value === "object" && value !== null) {
7081
+ const nametagsMap = /* @__PURE__ */ new Map();
7082
+ for (const [indexStr, nametag] of Object.entries(value)) {
7083
+ nametagsMap.set(parseInt(indexStr, 10), nametag);
7084
+ }
7085
+ this._addressNametags.set(key, nametagsMap);
7086
+ } else if (typeof value === "string") {
7087
+ }
6718
7088
  }
6719
7089
  }
6720
7090
  } catch {
@@ -6765,8 +7135,17 @@ var Sphere = class _Sphere {
6765
7135
  if (this._identity) {
6766
7136
  this._identity.nametag = recoveredNametag;
6767
7137
  }
6768
- this._addressNametags.set(this._currentAddressIndex, recoveredNametag);
6769
- await this._storage.set(STORAGE_KEYS.NAMETAG, recoveredNametag);
7138
+ const addressId = this.getCurrentAddressId();
7139
+ if (addressId) {
7140
+ let nametagsMap = this._addressNametags.get(addressId);
7141
+ if (!nametagsMap) {
7142
+ nametagsMap = /* @__PURE__ */ new Map();
7143
+ this._addressNametags.set(addressId, nametagsMap);
7144
+ }
7145
+ const nextIndex = nametagsMap.size;
7146
+ nametagsMap.set(nextIndex, recoveredNametag);
7147
+ }
7148
+ await this.persistAddressNametags();
6770
7149
  if (this._transport.registerNametag) {
6771
7150
  await this._transport.registerNametag(
6772
7151
  recoveredNametag,
@@ -6809,22 +7188,22 @@ var Sphere = class _Sphere {
6809
7188
  // ===========================================================================
6810
7189
  async storeMnemonic(mnemonic, derivationPath, basePath) {
6811
7190
  const encrypted = this.encrypt(mnemonic);
6812
- await this._storage.set(STORAGE_KEYS.MNEMONIC, encrypted);
7191
+ await this._storage.set(STORAGE_KEYS_GLOBAL.MNEMONIC, encrypted);
6813
7192
  this._mnemonic = mnemonic;
6814
7193
  this._source = "mnemonic";
6815
7194
  this._derivationMode = "bip32";
6816
7195
  if (derivationPath) {
6817
- await this._storage.set(STORAGE_KEYS.DERIVATION_PATH, derivationPath);
7196
+ await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_PATH, derivationPath);
6818
7197
  }
6819
7198
  const effectiveBasePath = basePath ?? DEFAULT_BASE_PATH;
6820
7199
  this._basePath = effectiveBasePath;
6821
- await this._storage.set(STORAGE_KEYS.BASE_PATH, effectiveBasePath);
6822
- await this._storage.set(STORAGE_KEYS.DERIVATION_MODE, this._derivationMode);
6823
- await this._storage.set(STORAGE_KEYS.WALLET_SOURCE, this._source);
7200
+ await this._storage.set(STORAGE_KEYS_GLOBAL.BASE_PATH, effectiveBasePath);
7201
+ await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_MODE, this._derivationMode);
7202
+ await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_SOURCE, this._source);
6824
7203
  }
6825
7204
  async storeMasterKey(masterKey, chainCode, derivationPath, basePath, derivationMode) {
6826
7205
  const encrypted = this.encrypt(masterKey);
6827
- await this._storage.set(STORAGE_KEYS.MASTER_KEY, encrypted);
7206
+ await this._storage.set(STORAGE_KEYS_GLOBAL.MASTER_KEY, encrypted);
6828
7207
  this._source = "file";
6829
7208
  this._mnemonic = null;
6830
7209
  if (derivationMode) {
@@ -6833,16 +7212,16 @@ var Sphere = class _Sphere {
6833
7212
  this._derivationMode = chainCode ? "bip32" : "wif_hmac";
6834
7213
  }
6835
7214
  if (chainCode) {
6836
- await this._storage.set(STORAGE_KEYS.CHAIN_CODE, chainCode);
7215
+ await this._storage.set(STORAGE_KEYS_GLOBAL.CHAIN_CODE, chainCode);
6837
7216
  }
6838
7217
  if (derivationPath) {
6839
- await this._storage.set(STORAGE_KEYS.DERIVATION_PATH, derivationPath);
7218
+ await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_PATH, derivationPath);
6840
7219
  }
6841
7220
  const effectiveBasePath = basePath ?? DEFAULT_BASE_PATH;
6842
7221
  this._basePath = effectiveBasePath;
6843
- await this._storage.set(STORAGE_KEYS.BASE_PATH, effectiveBasePath);
6844
- await this._storage.set(STORAGE_KEYS.DERIVATION_MODE, this._derivationMode);
6845
- await this._storage.set(STORAGE_KEYS.WALLET_SOURCE, this._source);
7222
+ await this._storage.set(STORAGE_KEYS_GLOBAL.BASE_PATH, effectiveBasePath);
7223
+ await this._storage.set(STORAGE_KEYS_GLOBAL.DERIVATION_MODE, this._derivationMode);
7224
+ await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_SOURCE, this._source);
6846
7225
  }
6847
7226
  /**
6848
7227
  * Mark wallet as fully created (after successful initialization)
@@ -6850,20 +7229,20 @@ var Sphere = class _Sphere {
6850
7229
  * marked as existing after all initialization steps succeed.
6851
7230
  */
6852
7231
  async finalizeWalletCreation() {
6853
- await this._storage.set(STORAGE_KEYS.WALLET_EXISTS, "true");
7232
+ await this._storage.set(STORAGE_KEYS_GLOBAL.WALLET_EXISTS, "true");
6854
7233
  }
6855
7234
  // ===========================================================================
6856
7235
  // Private: Identity Initialization
6857
7236
  // ===========================================================================
6858
7237
  async loadIdentityFromStorage() {
6859
- const encryptedMnemonic = await this._storage.get(STORAGE_KEYS.MNEMONIC);
6860
- const encryptedMasterKey = await this._storage.get(STORAGE_KEYS.MASTER_KEY);
6861
- const chainCode = await this._storage.get(STORAGE_KEYS.CHAIN_CODE);
6862
- const derivationPath = await this._storage.get(STORAGE_KEYS.DERIVATION_PATH);
6863
- const savedBasePath = await this._storage.get(STORAGE_KEYS.BASE_PATH);
6864
- const savedDerivationMode = await this._storage.get(STORAGE_KEYS.DERIVATION_MODE);
6865
- const savedSource = await this._storage.get(STORAGE_KEYS.WALLET_SOURCE);
6866
- const savedAddressIndex = await this._storage.get(STORAGE_KEYS.CURRENT_ADDRESS_INDEX);
7238
+ const encryptedMnemonic = await this._storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
7239
+ const encryptedMasterKey = await this._storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
7240
+ const chainCode = await this._storage.get(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
7241
+ const derivationPath = await this._storage.get(STORAGE_KEYS_GLOBAL.DERIVATION_PATH);
7242
+ const savedBasePath = await this._storage.get(STORAGE_KEYS_GLOBAL.BASE_PATH);
7243
+ const savedDerivationMode = await this._storage.get(STORAGE_KEYS_GLOBAL.DERIVATION_MODE);
7244
+ const savedSource = await this._storage.get(STORAGE_KEYS_GLOBAL.WALLET_SOURCE);
7245
+ const savedAddressIndex = await this._storage.get(STORAGE_KEYS_GLOBAL.CURRENT_ADDRESS_INDEX);
6867
7246
  this._basePath = savedBasePath ?? DEFAULT_BASE_PATH;
6868
7247
  this._derivationMode = savedDerivationMode ?? "bip32";
6869
7248
  this._source = savedSource ?? "unknown";
@@ -6897,12 +7276,13 @@ var Sphere = class _Sphere {
6897
7276
  this._storage.setIdentity(this._identity);
6898
7277
  }
6899
7278
  await this.loadAddressNametags();
6900
- const savedNametag = await this._storage.get(STORAGE_KEYS.NAMETAG);
6901
7279
  if (this._currentAddressIndex > 0 && this._masterKey) {
6902
7280
  const addressInfo = this.deriveAddress(this._currentAddressIndex, false);
6903
7281
  const ipnsHash = sha256(addressInfo.publicKey, "hex").slice(0, 40);
6904
7282
  const predicateAddress = await deriveL3PredicateAddress(addressInfo.privateKey);
6905
- const nametag = this._addressNametags.get(this._currentAddressIndex);
7283
+ const addressId = getAddressId(predicateAddress);
7284
+ const nametagsMap = this._addressNametags.get(addressId);
7285
+ const nametag = nametagsMap?.get(0);
6906
7286
  this._identity = {
6907
7287
  privateKey: addressInfo.privateKey,
6908
7288
  chainPubkey: addressInfo.publicKey,
@@ -6913,25 +7293,12 @@ var Sphere = class _Sphere {
6913
7293
  };
6914
7294
  this._storage.setIdentity(this._identity);
6915
7295
  console.log(`[Sphere] Restored to address ${this._currentAddressIndex}:`, this._identity.l1Address);
6916
- } else {
6917
- if (savedNametag && this._identity) {
6918
- let nametag = savedNametag;
6919
- if (savedNametag.startsWith("{")) {
6920
- try {
6921
- const parsed = JSON.parse(savedNametag);
6922
- nametag = parsed["0"] || parsed[0] || Object.values(parsed)[0];
6923
- } catch {
6924
- }
6925
- }
7296
+ } else if (this._identity) {
7297
+ const addressId = this.getCurrentAddressId();
7298
+ const nametagsMap = addressId ? this._addressNametags.get(addressId) : void 0;
7299
+ const nametag = nametagsMap?.get(0);
7300
+ if (nametag) {
6926
7301
  this._identity.nametag = nametag;
6927
- if (!this._addressNametags.has(0)) {
6928
- this._addressNametags.set(0, nametag);
6929
- }
6930
- } else if (this._identity) {
6931
- const nametag = this._addressNametags.get(0);
6932
- if (nametag) {
6933
- this._identity.nametag = nametag;
6934
- }
6935
7302
  }
6936
7303
  }
6937
7304
  }