@unicitylabs/sphere-sdk 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -152,7 +152,7 @@ const providers = createBrowserProviders({
152
152
  oracle: { url: 'https://custom-aggregator.example.com' }, // custom oracle
153
153
  });
154
154
 
155
- // Enable L1 with network defaults
155
+ // L1 is enabled by default — customize if needed
156
156
  const providers = createBrowserProviders({
157
157
  network: 'testnet',
158
158
  l1: { enableVesting: true }, // uses testnet electrum URL automatically
@@ -332,17 +332,20 @@ sphere.payments.onPaymentRequest((request) => {
332
332
  Access L1 payments through `sphere.payments.l1`:
333
333
 
334
334
  ```typescript
335
- // L1 configuration is optional (has defaults)
335
+ // L1 is enabled by default with lazy Fulcrum connection.
336
+ // Connection to Fulcrum is deferred until first L1 operation.
336
337
  const { sphere } = await Sphere.init({
337
338
  ...providers,
338
339
  autoGenerate: true,
339
- l1: {
340
- electrumUrl: 'wss://fulcrum.alpha.unicity.network:50004', // default
341
- defaultFeeRate: 10, // sat/byte, default
342
- enableVesting: true, // default
343
- },
340
+ // L1 config is optional — defaults are applied automatically:
341
+ // electrumUrl: network-specific (mainnet: fulcrum.alpha.unicity.network)
342
+ // defaultFeeRate: 10 sat/byte
343
+ // enableVesting: true
344
344
  });
345
345
 
346
+ // To explicitly disable L1:
347
+ // const { sphere } = await Sphere.init({ ...providers, l1: null });
348
+
346
349
  // Get L1 balance
347
350
  const balance = await sphere.payments.l1.getBalance();
348
351
  console.log('L1 Balance:', balance.total);
@@ -847,14 +850,6 @@ const providers = createBrowserProviders({
847
850
  },
848
851
  });
849
852
 
850
- // Enable multiple sync backends
851
- const providers = createBrowserProviders({
852
- network: 'mainnet',
853
- tokenSync: {
854
- ipfs: { enabled: true, useDht: true },
855
- cloud: { enabled: true, provider: 'aws', bucket: 'my-backup' }, // future
856
- },
857
- });
858
853
  ```
859
854
 
860
855
  ## Token Sync Backends
@@ -864,7 +859,7 @@ The SDK supports multiple token sync backends that can be enabled independently:
864
859
  | Backend | Status | Description |
865
860
  |---------|--------|-------------|
866
861
  | `ipfs` | ✅ Ready | Decentralized IPFS/IPNS with Helia browser DHT |
867
- | `mongodb` | Ready | MongoDB for centralized token storage |
862
+ | `mongodb` | 🚧 Planned | MongoDB for centralized token storage |
868
863
  | `file` | 🚧 Planned | Local file system (Node.js) |
869
864
  | `cloud` | 🚧 Planned | Cloud storage (AWS S3, GCP, Azure) |
870
865
 
@@ -880,29 +875,6 @@ const providers = createBrowserProviders({
880
875
  },
881
876
  },
882
877
  });
883
-
884
- // Enable MongoDB sync
885
- const providers = createBrowserProviders({
886
- network: 'mainnet',
887
- tokenSync: {
888
- mongodb: {
889
- enabled: true,
890
- uri: 'mongodb://localhost:27017',
891
- database: 'sphere_wallet',
892
- collection: 'tokens',
893
- },
894
- },
895
- });
896
-
897
- // Multiple backends for redundancy
898
- const providers = createBrowserProviders({
899
- tokenSync: {
900
- ipfs: { enabled: true },
901
- mongodb: { enabled: true, uri: 'mongodb://localhost:27017', database: 'wallet' },
902
- file: { enabled: true, directory: './tokens', format: 'txf' },
903
- cloud: { enabled: true, provider: 'aws', bucket: 'wallet-backup' },
904
- },
905
- });
906
878
  ```
907
879
 
908
880
  ## Custom Token Storage Provider
@@ -985,32 +957,32 @@ const { sphere } = await Sphere.init({
985
957
 
986
958
  ## Dynamic Provider Management (Runtime)
987
959
 
988
- After `Sphere.init()` is called, you can add/remove token storage providers dynamically through UI:
960
+ After `Sphere.init()` is called, you can add/remove token storage providers dynamically:
989
961
 
990
962
  ```typescript
991
- import { createMongoDbStorageProvider } from './my-mongodb-provider';
963
+ import { createIpfsStorageProvider } from '@unicitylabs/sphere-sdk/impl/browser/ipfs';
992
964
 
993
- // Add a new provider at runtime (e.g., user enables MongoDB sync in settings)
994
- const mongoProvider = createMongoDbStorageProvider({
995
- uri: 'mongodb://localhost:27017',
996
- database: 'sphere_wallet',
965
+ // Add a new provider at runtime (e.g., user enables IPFS sync in settings)
966
+ const ipfsProvider = createIpfsStorageProvider({
967
+ gateways: ['https://ipfs.io'],
968
+ useDht: true,
997
969
  });
998
970
 
999
- await sphere.addTokenStorageProvider(mongoProvider);
971
+ await sphere.addTokenStorageProvider(ipfsProvider);
1000
972
 
1001
973
  // Provider is now active and will be used in sync operations
1002
974
 
1003
975
  // Check if provider exists
1004
- if (sphere.hasTokenStorageProvider('mongodb-token-storage')) {
1005
- console.log('MongoDB sync is enabled');
976
+ if (sphere.hasTokenStorageProvider('ipfs-token-storage')) {
977
+ console.log('IPFS sync is enabled');
1006
978
  }
1007
979
 
1008
980
  // Get all active providers
1009
981
  const providers = sphere.getTokenStorageProviders();
1010
982
  console.log('Active providers:', Array.from(providers.keys()));
1011
983
 
1012
- // Remove a provider (e.g., user disables MongoDB sync)
1013
- await sphere.removeTokenStorageProvider('mongodb-token-storage');
984
+ // Remove a provider (e.g., user disables IPFS sync)
985
+ await sphere.removeTokenStorageProvider('ipfs-token-storage');
1014
986
 
1015
987
  // Listen for per-provider sync events
1016
988
  sphere.on('sync:provider', (event) => {
@@ -1026,25 +998,6 @@ sphere.on('sync:provider', (event) => {
1026
998
  await sphere.payments.sync();
1027
999
  ```
1028
1000
 
1029
- ### Multiple Providers Example
1030
-
1031
- ```typescript
1032
- // User configures multiple sync backends via UI
1033
- const ipfsProvider = createIpfsStorageProvider({ gateways: ['https://ipfs.io'] });
1034
- const mongoProvider = createMongoDbStorageProvider({ uri: 'mongodb://...' });
1035
- const s3Provider = createS3StorageProvider({ bucket: 'wallet-backup' });
1036
-
1037
- // Add all providers
1038
- await sphere.addTokenStorageProvider(ipfsProvider);
1039
- await sphere.addTokenStorageProvider(mongoProvider);
1040
- await sphere.addTokenStorageProvider(s3Provider);
1041
-
1042
- // Sync syncs with ALL active providers
1043
- // If one fails, others continue (fault-tolerant)
1044
- const result = await sphere.payments.sync();
1045
- console.log(`Synced: +${result.added} -${result.removed}`);
1046
- ```
1047
-
1048
1001
  ## Dynamic Relay Management
1049
1002
 
1050
1003
  Nostr relays can be added or removed at runtime through the transport provider:
@@ -1553,7 +1553,7 @@ var L1PaymentsModule = class {
1553
1553
  _transport;
1554
1554
  constructor(config) {
1555
1555
  this._config = {
1556
- electrumUrl: config?.electrumUrl ?? "wss://fulcrum.alpha.unicity.network:50004",
1556
+ electrumUrl: config?.electrumUrl ?? "wss://fulcrum.unicity.network:50004",
1557
1557
  network: config?.network ?? "mainnet",
1558
1558
  defaultFeeRate: config?.defaultFeeRate ?? 10,
1559
1559
  enableVesting: config?.enableVesting ?? true
@@ -1585,10 +1585,17 @@ var L1PaymentsModule = class {
1585
1585
  });
1586
1586
  }
1587
1587
  }
1588
- if (this._config.electrumUrl) {
1588
+ this._initialized = true;
1589
+ }
1590
+ /**
1591
+ * Ensure the Fulcrum WebSocket is connected. Called lazily before any
1592
+ * operation that needs the network. If the singleton is already connected
1593
+ * (e.g. by the address scanner), this is a no-op.
1594
+ */
1595
+ async ensureConnected() {
1596
+ if (!isWebSocketConnected() && this._config.electrumUrl) {
1589
1597
  await connect(this._config.electrumUrl);
1590
1598
  }
1591
- this._initialized = true;
1592
1599
  }
1593
1600
  destroy() {
1594
1601
  if (isWebSocketConnected()) {
@@ -1646,6 +1653,7 @@ var L1PaymentsModule = class {
1646
1653
  }
1647
1654
  async send(request) {
1648
1655
  this.ensureInitialized();
1656
+ await this.ensureConnected();
1649
1657
  if (!this._wallet || !this._identity) {
1650
1658
  return { success: false, error: "No wallet available" };
1651
1659
  }
@@ -1680,6 +1688,7 @@ var L1PaymentsModule = class {
1680
1688
  }
1681
1689
  async getBalance() {
1682
1690
  this.ensureInitialized();
1691
+ await this.ensureConnected();
1683
1692
  const addresses = this._getWatchedAddresses();
1684
1693
  let totalAlpha = 0;
1685
1694
  let vestedSats = BigInt(0);
@@ -1711,6 +1720,7 @@ var L1PaymentsModule = class {
1711
1720
  }
1712
1721
  async getUtxos() {
1713
1722
  this.ensureInitialized();
1723
+ await this.ensureConnected();
1714
1724
  const result = [];
1715
1725
  const currentHeight = await getCurrentBlockHeight();
1716
1726
  const allUtxos = await this._getAllUtxos();
@@ -1746,42 +1756,73 @@ var L1PaymentsModule = class {
1746
1756
  return result;
1747
1757
  }
1748
1758
  async getHistory(limit) {
1759
+ await this.ensureConnected();
1749
1760
  this.ensureInitialized();
1750
1761
  const addresses = this._getWatchedAddresses();
1751
1762
  const transactions = [];
1752
1763
  const seenTxids = /* @__PURE__ */ new Set();
1753
1764
  const currentHeight = await getCurrentBlockHeight();
1765
+ const txCache = /* @__PURE__ */ new Map();
1766
+ const fetchTx = async (txid) => {
1767
+ if (txCache.has(txid)) return txCache.get(txid);
1768
+ const detail = await getTransaction(txid);
1769
+ txCache.set(txid, detail);
1770
+ return detail;
1771
+ };
1772
+ const addressSet = new Set(addresses.map((a) => a.toLowerCase()));
1754
1773
  for (const address of addresses) {
1755
1774
  const history = await getTransactionHistory(address);
1756
1775
  for (const item of history) {
1757
1776
  if (seenTxids.has(item.tx_hash)) continue;
1758
1777
  seenTxids.add(item.tx_hash);
1759
- const tx = await getTransaction(item.tx_hash);
1778
+ const tx = await fetchTx(item.tx_hash);
1760
1779
  if (!tx) continue;
1761
- const isSend = tx.vin?.some(
1762
- (vin) => addresses.includes(vin.txid ?? "")
1763
- );
1764
- let amount = "0";
1780
+ let isSend = false;
1781
+ for (const vin of tx.vin ?? []) {
1782
+ if (!vin.txid) continue;
1783
+ const prevTx = await fetchTx(vin.txid);
1784
+ if (prevTx?.vout?.[vin.vout]) {
1785
+ const prevOut = prevTx.vout[vin.vout];
1786
+ const prevAddrs = [
1787
+ ...prevOut.scriptPubKey?.addresses ?? [],
1788
+ ...prevOut.scriptPubKey?.address ? [prevOut.scriptPubKey.address] : []
1789
+ ];
1790
+ if (prevAddrs.some((a) => addressSet.has(a.toLowerCase()))) {
1791
+ isSend = true;
1792
+ break;
1793
+ }
1794
+ }
1795
+ }
1796
+ let amountToUs = 0;
1797
+ let amountToOthers = 0;
1765
1798
  let txAddress = address;
1799
+ let externalAddress = "";
1766
1800
  if (tx.vout) {
1767
1801
  for (const vout of tx.vout) {
1768
- const voutAddresses = vout.scriptPubKey?.addresses ?? [];
1769
- if (vout.scriptPubKey?.address) {
1770
- voutAddresses.push(vout.scriptPubKey.address);
1771
- }
1772
- const matchedAddr = voutAddresses.find((a) => addresses.includes(a));
1773
- if (matchedAddr) {
1774
- amount = Math.floor((vout.value ?? 0) * 1e8).toString();
1775
- txAddress = matchedAddr;
1776
- break;
1802
+ const voutAddresses = [
1803
+ ...vout.scriptPubKey?.addresses ?? [],
1804
+ ...vout.scriptPubKey?.address ? [vout.scriptPubKey.address] : []
1805
+ ];
1806
+ const isOurs = voutAddresses.some((a) => addressSet.has(a.toLowerCase()));
1807
+ const valueSats = Math.floor((vout.value ?? 0) * 1e8);
1808
+ if (isOurs) {
1809
+ amountToUs += valueSats;
1810
+ if (!txAddress) txAddress = voutAddresses[0];
1811
+ } else {
1812
+ amountToOthers += valueSats;
1813
+ if (!externalAddress && voutAddresses.length > 0) {
1814
+ externalAddress = voutAddresses[0];
1815
+ }
1777
1816
  }
1778
1817
  }
1779
1818
  }
1819
+ const amount = isSend ? amountToOthers.toString() : amountToUs.toString();
1820
+ const displayAddress = isSend ? externalAddress || txAddress : txAddress;
1780
1821
  transactions.push({
1781
1822
  txid: item.tx_hash,
1782
1823
  type: isSend ? "send" : "receive",
1783
1824
  amount,
1784
- address: txAddress,
1825
+ address: displayAddress,
1785
1826
  confirmations: item.height > 0 ? currentHeight - item.height : 0,
1786
1827
  timestamp: tx.time ? tx.time * 1e3 : Date.now(),
1787
1828
  blockHeight: item.height > 0 ? item.height : void 0
@@ -1793,6 +1834,7 @@ var L1PaymentsModule = class {
1793
1834
  }
1794
1835
  async getTransaction(txid) {
1795
1836
  this.ensureInitialized();
1837
+ await this.ensureConnected();
1796
1838
  const tx = await getTransaction(txid);
1797
1839
  if (!tx) return null;
1798
1840
  const addresses = this._getWatchedAddresses();
@@ -1828,6 +1870,7 @@ var L1PaymentsModule = class {
1828
1870
  }
1829
1871
  async estimateFee(to, amount) {
1830
1872
  this.ensureInitialized();
1873
+ await this.ensureConnected();
1831
1874
  if (!this._wallet) {
1832
1875
  return { fee: "0", feeRate: this._config.defaultFeeRate ?? 10 };
1833
1876
  }
@@ -2347,7 +2390,9 @@ var STORAGE_KEYS_GLOBAL = {
2347
2390
  /** Nametag cache per address (separate from tracked addresses registry) */
2348
2391
  ADDRESS_NAMETAGS: "address_nametags",
2349
2392
  /** Active addresses registry (JSON: TrackedAddressesStorage) */
2350
- TRACKED_ADDRESSES: "tracked_addresses"
2393
+ TRACKED_ADDRESSES: "tracked_addresses",
2394
+ /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
2395
+ LAST_WALLET_EVENT_TS: "last_wallet_event_ts"
2351
2396
  };
2352
2397
  var STORAGE_KEYS_ADDRESS = {
2353
2398
  /** Pending transfers for this address */
@@ -3751,7 +3796,7 @@ async function parseTokenInfo(tokenData) {
3751
3796
  try {
3752
3797
  const sdkToken = await import_Token6.Token.fromJSON(data);
3753
3798
  if (sdkToken.id) {
3754
- defaultInfo.tokenId = sdkToken.id.toString();
3799
+ defaultInfo.tokenId = sdkToken.id.toJSON();
3755
3800
  }
3756
3801
  if (sdkToken.coins && sdkToken.coins.coins) {
3757
3802
  const rawCoins = sdkToken.coins.coins;
@@ -4042,8 +4087,7 @@ var PaymentsModule = class _PaymentsModule {
4042
4087
  maxRetries: config?.maxRetries ?? 3,
4043
4088
  debug: config?.debug ?? false
4044
4089
  };
4045
- const l1Enabled = config?.l1?.electrumUrl && config.l1.electrumUrl.length > 0;
4046
- this.l1 = l1Enabled ? new L1PaymentsModule(config?.l1) : null;
4090
+ this.l1 = config?.l1 === null ? null : new L1PaymentsModule(config?.l1);
4047
4091
  }
4048
4092
  /** Get module configuration */
4049
4093
  getConfig() {
@@ -4705,13 +4749,16 @@ var PaymentsModule = class _PaymentsModule {
4705
4749
  if (this.paymentRequests.find((r) => r.id === transportRequest.id)) {
4706
4750
  return;
4707
4751
  }
4752
+ const coinId = transportRequest.request.coinId;
4753
+ const registry = TokenRegistry.getInstance();
4754
+ const coinDef = registry.getDefinition(coinId);
4708
4755
  const request = {
4709
4756
  id: transportRequest.id,
4710
4757
  senderPubkey: transportRequest.senderTransportPubkey,
4758
+ senderNametag: transportRequest.senderNametag,
4711
4759
  amount: transportRequest.request.amount,
4712
- coinId: transportRequest.request.coinId,
4713
- symbol: transportRequest.request.coinId,
4714
- // Use coinId as symbol for now
4760
+ coinId,
4761
+ symbol: coinDef?.symbol || coinId.slice(0, 8),
4715
4762
  message: transportRequest.request.message,
4716
4763
  recipientNametag: transportRequest.request.recipientNametag,
4717
4764
  requestId: transportRequest.request.requestId,
@@ -7730,8 +7777,8 @@ var Sphere = class _Sphere {
7730
7777
  if (options.nametag) {
7731
7778
  await sphere.registerNametag(options.nametag);
7732
7779
  } else {
7733
- await sphere.syncIdentityWithTransport();
7734
7780
  await sphere.recoverNametagFromTransport();
7781
+ await sphere.syncIdentityWithTransport();
7735
7782
  }
7736
7783
  return sphere;
7737
7784
  }
@@ -7778,9 +7825,14 @@ var Sphere = class _Sphere {
7778
7825
  if (!options.mnemonic && !options.masterKey) {
7779
7826
  throw new Error("Either mnemonic or masterKey is required");
7780
7827
  }
7828
+ console.log("[Sphere.import] Starting import...");
7829
+ console.log("[Sphere.import] Clearing existing wallet data...");
7781
7830
  await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
7831
+ console.log("[Sphere.import] Clear done");
7782
7832
  if (!options.storage.isConnected()) {
7833
+ console.log("[Sphere.import] Reconnecting storage...");
7783
7834
  await options.storage.connect();
7835
+ console.log("[Sphere.import] Storage reconnected");
7784
7836
  }
7785
7837
  const sphere = new _Sphere(
7786
7838
  options.storage,
@@ -7794,9 +7846,12 @@ var Sphere = class _Sphere {
7794
7846
  if (!_Sphere.validateMnemonic(options.mnemonic)) {
7795
7847
  throw new Error("Invalid mnemonic");
7796
7848
  }
7849
+ console.log("[Sphere.import] Storing mnemonic...");
7797
7850
  await sphere.storeMnemonic(options.mnemonic, options.derivationPath, options.basePath);
7851
+ console.log("[Sphere.import] Initializing identity from mnemonic...");
7798
7852
  await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
7799
7853
  } else if (options.masterKey) {
7854
+ console.log("[Sphere.import] Storing master key...");
7800
7855
  await sphere.storeMasterKey(
7801
7856
  options.masterKey,
7802
7857
  options.chainCode,
@@ -7804,24 +7859,35 @@ var Sphere = class _Sphere {
7804
7859
  options.basePath,
7805
7860
  options.derivationMode
7806
7861
  );
7862
+ console.log("[Sphere.import] Initializing identity from master key...");
7807
7863
  await sphere.initializeIdentityFromMasterKey(
7808
7864
  options.masterKey,
7809
7865
  options.chainCode,
7810
7866
  options.derivationPath
7811
7867
  );
7812
7868
  }
7869
+ console.log("[Sphere.import] Initializing providers...");
7813
7870
  await sphere.initializeProviders();
7871
+ console.log("[Sphere.import] Providers initialized. Initializing modules...");
7814
7872
  await sphere.initializeModules();
7873
+ console.log("[Sphere.import] Modules initialized");
7815
7874
  if (!options.nametag) {
7875
+ console.log("[Sphere.import] Recovering nametag from transport...");
7816
7876
  await sphere.recoverNametagFromTransport();
7877
+ console.log("[Sphere.import] Nametag recovery done");
7878
+ await sphere.syncIdentityWithTransport();
7817
7879
  }
7880
+ console.log("[Sphere.import] Finalizing wallet creation...");
7818
7881
  await sphere.finalizeWalletCreation();
7819
7882
  sphere._initialized = true;
7820
7883
  _Sphere.instance = sphere;
7884
+ console.log("[Sphere.import] Tracking address 0...");
7821
7885
  await sphere.ensureAddressTracked(0);
7822
7886
  if (options.nametag) {
7887
+ console.log("[Sphere.import] Registering nametag...");
7823
7888
  await sphere.registerNametag(options.nametag);
7824
7889
  }
7890
+ console.log("[Sphere.import] Import complete");
7825
7891
  return sphere;
7826
7892
  }
7827
7893
  /**
@@ -7846,6 +7912,10 @@ var Sphere = class _Sphere {
7846
7912
  static async clear(storageOrOptions) {
7847
7913
  const storage = "get" in storageOrOptions ? storageOrOptions : storageOrOptions.storage;
7848
7914
  const tokenStorage = "get" in storageOrOptions ? void 0 : storageOrOptions.tokenStorage;
7915
+ if (!storage.isConnected()) {
7916
+ await storage.connect();
7917
+ }
7918
+ console.log("[Sphere.clear] Removing storage keys...");
7849
7919
  await storage.remove(STORAGE_KEYS_GLOBAL.MNEMONIC);
7850
7920
  await storage.remove(STORAGE_KEYS_GLOBAL.MASTER_KEY);
7851
7921
  await storage.remove(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
@@ -7858,12 +7928,30 @@ var Sphere = class _Sphere {
7858
7928
  await storage.remove(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
7859
7929
  await storage.remove(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
7860
7930
  await storage.remove(STORAGE_KEYS_ADDRESS.OUTBOX);
7931
+ console.log("[Sphere.clear] Storage keys removed");
7861
7932
  if (tokenStorage?.clear) {
7862
- await tokenStorage.clear();
7933
+ console.log("[Sphere.clear] Clearing token storage...");
7934
+ try {
7935
+ await Promise.race([
7936
+ tokenStorage.clear(),
7937
+ new Promise(
7938
+ (_, reject) => setTimeout(() => reject(new Error("tokenStorage.clear() timed out after 2s")), 2e3)
7939
+ )
7940
+ ]);
7941
+ console.log("[Sphere.clear] Token storage cleared");
7942
+ } catch (err) {
7943
+ console.warn("[Sphere.clear] Token storage clear failed/timed out:", err);
7944
+ }
7863
7945
  }
7946
+ console.log("[Sphere.clear] Destroying vesting classifier...");
7864
7947
  await vestingClassifier.destroy();
7948
+ console.log("[Sphere.clear] Vesting classifier destroyed");
7865
7949
  if (_Sphere.instance) {
7950
+ console.log("[Sphere.clear] Destroying Sphere instance...");
7866
7951
  await _Sphere.instance.destroy();
7952
+ console.log("[Sphere.clear] Sphere instance destroyed");
7953
+ } else {
7954
+ console.log("[Sphere.clear] No Sphere instance to destroy");
7867
7955
  }
7868
7956
  }
7869
7957
  /**
@@ -8244,7 +8332,8 @@ var Sphere = class _Sphere {
8244
8332
  storage: options.storage,
8245
8333
  transport: options.transport,
8246
8334
  oracle: options.oracle,
8247
- tokenStorage: options.tokenStorage
8335
+ tokenStorage: options.tokenStorage,
8336
+ l1: options.l1
8248
8337
  });
8249
8338
  return { success: true, mnemonic };
8250
8339
  }
@@ -8257,7 +8346,8 @@ var Sphere = class _Sphere {
8257
8346
  storage: options.storage,
8258
8347
  transport: options.transport,
8259
8348
  oracle: options.oracle,
8260
- tokenStorage: options.tokenStorage
8349
+ tokenStorage: options.tokenStorage,
8350
+ l1: options.l1
8261
8351
  });
8262
8352
  return { success: true };
8263
8353
  }
@@ -8316,7 +8406,8 @@ var Sphere = class _Sphere {
8316
8406
  transport: options.transport,
8317
8407
  oracle: options.oracle,
8318
8408
  tokenStorage: options.tokenStorage,
8319
- nametag: options.nametag
8409
+ nametag: options.nametag,
8410
+ l1: options.l1
8320
8411
  });
8321
8412
  return { success: true, sphere, mnemonic };
8322
8413
  }
@@ -8345,7 +8436,8 @@ var Sphere = class _Sphere {
8345
8436
  transport: options.transport,
8346
8437
  oracle: options.oracle,
8347
8438
  tokenStorage: options.tokenStorage,
8348
- nametag: options.nametag
8439
+ nametag: options.nametag,
8440
+ l1: options.l1
8349
8441
  });
8350
8442
  return { success: true, sphere };
8351
8443
  }
@@ -8376,7 +8468,8 @@ var Sphere = class _Sphere {
8376
8468
  transport: options.transport,
8377
8469
  oracle: options.oracle,
8378
8470
  tokenStorage: options.tokenStorage,
8379
- nametag: options.nametag
8471
+ nametag: options.nametag,
8472
+ l1: options.l1
8380
8473
  });
8381
8474
  return { success: true, sphere };
8382
8475
  }
@@ -8395,7 +8488,8 @@ var Sphere = class _Sphere {
8395
8488
  storage: options.storage,
8396
8489
  transport: options.transport,
8397
8490
  oracle: options.oracle,
8398
- tokenStorage: options.tokenStorage
8491
+ tokenStorage: options.tokenStorage,
8492
+ l1: options.l1
8399
8493
  });
8400
8494
  if (result.success) {
8401
8495
  const sphere2 = _Sphere.getInstance();
@@ -8444,7 +8538,8 @@ var Sphere = class _Sphere {
8444
8538
  transport: options.transport,
8445
8539
  oracle: options.oracle,
8446
8540
  tokenStorage: options.tokenStorage,
8447
- nametag: options.nametag
8541
+ nametag: options.nametag,
8542
+ l1: options.l1
8448
8543
  });
8449
8544
  return { success: true, sphere: sphere2, mnemonic };
8450
8545
  }
@@ -8457,7 +8552,8 @@ var Sphere = class _Sphere {
8457
8552
  transport: options.transport,
8458
8553
  oracle: options.oracle,
8459
8554
  tokenStorage: options.tokenStorage,
8460
- nametag: options.nametag
8555
+ nametag: options.nametag,
8556
+ l1: options.l1
8461
8557
  });
8462
8558
  return { success: true, sphere };
8463
8559
  }
@@ -9320,35 +9416,40 @@ var Sphere = class _Sphere {
9320
9416
  if (this._identity?.nametag) {
9321
9417
  return;
9322
9418
  }
9323
- if (!this._transport.recoverNametag) {
9419
+ let recoveredNametag = null;
9420
+ if (this._transport.recoverNametag) {
9421
+ try {
9422
+ recoveredNametag = await this._transport.recoverNametag();
9423
+ } catch {
9424
+ }
9425
+ }
9426
+ if (!recoveredNametag && this._transport.resolveAddressInfo && this._identity?.l1Address) {
9427
+ try {
9428
+ const info = await this._transport.resolveAddressInfo(this._identity.l1Address);
9429
+ if (info?.nametag) {
9430
+ recoveredNametag = info.nametag;
9431
+ }
9432
+ } catch {
9433
+ }
9434
+ }
9435
+ if (!recoveredNametag) {
9324
9436
  return;
9325
9437
  }
9326
9438
  try {
9327
- const recoveredNametag = await this._transport.recoverNametag();
9328
- if (recoveredNametag) {
9329
- if (this._identity) {
9330
- this._identity.nametag = recoveredNametag;
9331
- await this._updateCachedProxyAddress();
9332
- }
9333
- const entry = await this.ensureAddressTracked(this._currentAddressIndex);
9334
- let nametags = this._addressNametags.get(entry.addressId);
9335
- if (!nametags) {
9336
- nametags = /* @__PURE__ */ new Map();
9337
- this._addressNametags.set(entry.addressId, nametags);
9338
- }
9339
- const nextIndex = nametags.size;
9340
- nametags.set(nextIndex, recoveredNametag);
9341
- await this.persistAddressNametags();
9342
- if (this._transport.publishIdentityBinding) {
9343
- await this._transport.publishIdentityBinding(
9344
- this._identity.chainPubkey,
9345
- this._identity.l1Address,
9346
- this._identity.directAddress || "",
9347
- recoveredNametag
9348
- );
9349
- }
9350
- this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
9439
+ if (this._identity) {
9440
+ this._identity.nametag = recoveredNametag;
9441
+ await this._updateCachedProxyAddress();
9351
9442
  }
9443
+ const entry = await this.ensureAddressTracked(this._currentAddressIndex);
9444
+ let nametags = this._addressNametags.get(entry.addressId);
9445
+ if (!nametags) {
9446
+ nametags = /* @__PURE__ */ new Map();
9447
+ this._addressNametags.set(entry.addressId, nametags);
9448
+ }
9449
+ const nextIndex = nametags.size;
9450
+ nametags.set(nextIndex, recoveredNametag);
9451
+ await this.persistAddressNametags();
9452
+ this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
9352
9453
  } catch {
9353
9454
  }
9354
9455
  }
@@ -9557,8 +9658,12 @@ var Sphere = class _Sphere {
9557
9658
  for (const provider of this._tokenStorageProviders.values()) {
9558
9659
  provider.setIdentity(this._identity);
9559
9660
  }
9560
- await this._storage.connect();
9561
- await this._transport.connect();
9661
+ if (!this._storage.isConnected()) {
9662
+ await this._storage.connect();
9663
+ }
9664
+ if (!this._transport.isConnected()) {
9665
+ await this._transport.connect();
9666
+ }
9562
9667
  await this._oracle.initialize();
9563
9668
  for (const provider of this._tokenStorageProviders.values()) {
9564
9669
  await provider.initialize();