@unicitylabs/sphere-sdk 0.1.3 → 0.1.4

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.
@@ -1445,6 +1445,7 @@ var L1PaymentsModule = class {
1445
1445
  _chainCode;
1446
1446
  _addresses = [];
1447
1447
  _wallet;
1448
+ _transport;
1448
1449
  constructor(config) {
1449
1450
  this._config = {
1450
1451
  electrumUrl: config?.electrumUrl ?? "wss://fulcrum.alpha.unicity.network:50004",
@@ -1457,13 +1458,14 @@ var L1PaymentsModule = class {
1457
1458
  this._identity = deps.identity;
1458
1459
  this._chainCode = deps.chainCode;
1459
1460
  this._addresses = deps.addresses ?? [];
1461
+ this._transport = deps.transport;
1460
1462
  this._wallet = {
1461
1463
  masterPrivateKey: deps.identity.privateKey,
1462
1464
  chainCode: deps.chainCode,
1463
1465
  addresses: [
1464
1466
  {
1465
- address: deps.identity.address,
1466
- publicKey: deps.identity.publicKey,
1467
+ address: deps.identity.l1Address,
1468
+ publicKey: deps.identity.chainPubkey,
1467
1469
  privateKey: deps.identity.privateKey,
1468
1470
  path: "m/0",
1469
1471
  index: 0
@@ -1471,7 +1473,7 @@ var L1PaymentsModule = class {
1471
1473
  ]
1472
1474
  };
1473
1475
  for (const addr of this._addresses) {
1474
- if (addr !== deps.identity.address) {
1476
+ if (addr !== deps.identity.l1Address) {
1475
1477
  this._wallet.addresses.push({
1476
1478
  address: addr,
1477
1479
  path: null,
@@ -1494,18 +1496,64 @@ var L1PaymentsModule = class {
1494
1496
  this._addresses = [];
1495
1497
  this._wallet = void 0;
1496
1498
  }
1499
+ /**
1500
+ * Check if a string looks like an L1 address (alpha1... or alphat1...)
1501
+ */
1502
+ isL1Address(value) {
1503
+ return value.startsWith("alpha1") || value.startsWith("alphat1");
1504
+ }
1505
+ /**
1506
+ * Resolve recipient to L1 address
1507
+ * Supports: L1 address (alpha1...), nametag (with or without @)
1508
+ */
1509
+ async resolveL1Address(recipient) {
1510
+ if (recipient.startsWith("@")) {
1511
+ const nametag = recipient.slice(1);
1512
+ return this.resolveNametagToL1Address(nametag);
1513
+ }
1514
+ if (this.isL1Address(recipient)) {
1515
+ return recipient;
1516
+ }
1517
+ try {
1518
+ const l1Address = await this.resolveNametagToL1Address(recipient);
1519
+ return l1Address;
1520
+ } catch {
1521
+ throw new Error(
1522
+ `Recipient "${recipient}" is not a valid nametag or L1 address. Use @nametag for explicit nametag or a valid alpha1... address.`
1523
+ );
1524
+ }
1525
+ }
1526
+ /**
1527
+ * Resolve nametag to L1 address using transport provider
1528
+ */
1529
+ async resolveNametagToL1Address(nametag) {
1530
+ if (!this._transport?.resolveNametagInfo) {
1531
+ throw new Error("Transport provider does not support nametag resolution");
1532
+ }
1533
+ const info = await this._transport.resolveNametagInfo(nametag);
1534
+ if (!info) {
1535
+ throw new Error(`Nametag not found: ${nametag}`);
1536
+ }
1537
+ if (!info.l1Address) {
1538
+ throw new Error(
1539
+ `Nametag @${nametag} does not have L1 address information. The owner needs to update their nametag registration.`
1540
+ );
1541
+ }
1542
+ return info.l1Address;
1543
+ }
1497
1544
  async send(request) {
1498
1545
  this.ensureInitialized();
1499
1546
  if (!this._wallet || !this._identity) {
1500
1547
  return { success: false, error: "No wallet available" };
1501
1548
  }
1502
1549
  try {
1550
+ const recipientAddress = await this.resolveL1Address(request.to);
1503
1551
  const amountAlpha = parseInt(request.amount, 10) / 1e8;
1504
1552
  const results = await sendAlpha(
1505
1553
  this._wallet,
1506
- request.to,
1554
+ recipientAddress,
1507
1555
  amountAlpha,
1508
- this._identity.address
1556
+ this._identity.l1Address
1509
1557
  );
1510
1558
  if (results && results.length > 0) {
1511
1559
  const txids = results.map((r) => r.txid);
@@ -1727,8 +1775,8 @@ var L1PaymentsModule = class {
1727
1775
  }
1728
1776
  _getWatchedAddresses() {
1729
1777
  const addresses = [...this._addresses];
1730
- if (this._identity?.address && !addresses.includes(this._identity.address)) {
1731
- addresses.unshift(this._identity.address);
1778
+ if (this._identity?.l1Address && !addresses.includes(this._identity.l1Address)) {
1779
+ addresses.unshift(this._identity.l1Address);
1732
1780
  }
1733
1781
  return addresses;
1734
1782
  }
@@ -2570,12 +2618,10 @@ function getCurrentStateHash(txf) {
2570
2618
 
2571
2619
  // modules/payments/PaymentsModule.ts
2572
2620
  var import_Token4 = require("@unicitylabs/state-transition-sdk/lib/token/Token");
2573
- var import_TokenId3 = require("@unicitylabs/state-transition-sdk/lib/token/TokenId");
2574
2621
  var import_CoinId3 = require("@unicitylabs/state-transition-sdk/lib/token/fungible/CoinId");
2575
2622
  var import_TransferCommitment2 = require("@unicitylabs/state-transition-sdk/lib/transaction/TransferCommitment");
2576
2623
  var import_TransferTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/TransferTransaction");
2577
2624
  var import_SigningService = require("@unicitylabs/state-transition-sdk/lib/sign/SigningService");
2578
- var import_ProxyAddress = require("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2579
2625
  var import_AddressScheme = require("@unicitylabs/state-transition-sdk/lib/address/AddressScheme");
2580
2626
  var import_UnmaskedPredicate3 = require("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate");
2581
2627
  var import_TokenState3 = require("@unicitylabs/state-transition-sdk/lib/token/TokenState");
@@ -2866,7 +2912,8 @@ var PaymentsModule = class {
2866
2912
  this.l1.initialize({
2867
2913
  identity: deps.identity,
2868
2914
  chainCode: deps.chainCode,
2869
- addresses: deps.l1Addresses
2915
+ addresses: deps.l1Addresses,
2916
+ transport: deps.transport
2870
2917
  });
2871
2918
  }
2872
2919
  this.unsubscribeTransfers = deps.transport.onTokenTransfer((transfer) => {
@@ -3263,7 +3310,7 @@ var PaymentsModule = class {
3263
3310
  }
3264
3311
  const request = {
3265
3312
  id: transportRequest.id,
3266
- senderPubkey: transportRequest.senderPubkey,
3313
+ senderPubkey: transportRequest.senderTransportPubkey,
3267
3314
  amount: transportRequest.request.amount,
3268
3315
  coinId: transportRequest.request.coinId,
3269
3316
  symbol: transportRequest.request.coinId,
@@ -3375,7 +3422,7 @@ var PaymentsModule = class {
3375
3422
  }
3376
3423
  const response = {
3377
3424
  id: transportResponse.id,
3378
- responderPubkey: transportResponse.responderPubkey,
3425
+ responderPubkey: transportResponse.responderTransportPubkey,
3379
3426
  requestId: transportResponse.response.requestId,
3380
3427
  responseType: transportResponse.response.responseType,
3381
3428
  message: transportResponse.response.message,
@@ -4129,6 +4176,23 @@ var PaymentsModule = class {
4129
4176
  // ===========================================================================
4130
4177
  // Private: Transfer Operations
4131
4178
  // ===========================================================================
4179
+ /**
4180
+ * Detect if a string is an L3 address (not a nametag)
4181
+ * Returns true for: hex pubkeys (64+ chars), PROXY:, DIRECT: prefixed addresses
4182
+ */
4183
+ isL3Address(value) {
4184
+ if (value.startsWith("PROXY:") || value.startsWith("DIRECT:")) {
4185
+ return true;
4186
+ }
4187
+ if (value.length >= 64 && /^[0-9a-fA-F]+$/.test(value)) {
4188
+ return true;
4189
+ }
4190
+ return false;
4191
+ }
4192
+ /**
4193
+ * Resolve recipient to Nostr pubkey for messaging
4194
+ * Supports: nametag (with or without @), hex pubkey
4195
+ */
4132
4196
  async resolveRecipient(recipient) {
4133
4197
  if (recipient.startsWith("@")) {
4134
4198
  const nametag = recipient.slice(1);
@@ -4138,7 +4202,19 @@ var PaymentsModule = class {
4138
4202
  }
4139
4203
  return pubkey;
4140
4204
  }
4141
- return recipient;
4205
+ if (this.isL3Address(recipient)) {
4206
+ return recipient;
4207
+ }
4208
+ if (this.deps?.transport.resolveNametag) {
4209
+ const pubkey = await this.deps.transport.resolveNametag(recipient);
4210
+ if (pubkey) {
4211
+ this.log(`Resolved "${recipient}" as nametag to pubkey`);
4212
+ return pubkey;
4213
+ }
4214
+ }
4215
+ throw new Error(
4216
+ `Recipient "${recipient}" is not a valid nametag or address. Use @nametag for explicit nametag or a valid hex pubkey/PROXY:/DIRECT: address.`
4217
+ );
4142
4218
  }
4143
4219
  /**
4144
4220
  * Create SDK TransferCommitment for a token transfer
@@ -4170,19 +4246,74 @@ var PaymentsModule = class {
4170
4246
  return import_SigningService.SigningService.createFromSecret(privateKeyBytes);
4171
4247
  }
4172
4248
  /**
4173
- * Resolve recipient to IAddress
4249
+ * Create DirectAddress from a public key using UnmaskedPredicateReference
4250
+ */
4251
+ async createDirectAddressFromPubkey(pubkeyHex) {
4252
+ const { UnmaskedPredicateReference: UnmaskedPredicateReference3 } = await import("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicateReference");
4253
+ const { TokenType: TokenType3 } = await import("@unicitylabs/state-transition-sdk/lib/token/TokenType");
4254
+ const UNICITY_TOKEN_TYPE_HEX3 = "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509";
4255
+ const tokenType = new TokenType3(Buffer.from(UNICITY_TOKEN_TYPE_HEX3, "hex"));
4256
+ const pubkeyBytes = new Uint8Array(
4257
+ pubkeyHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
4258
+ );
4259
+ const addressRef = await UnmaskedPredicateReference3.create(
4260
+ tokenType,
4261
+ "secp256k1",
4262
+ pubkeyBytes,
4263
+ import_HashAlgorithm3.HashAlgorithm.SHA256
4264
+ );
4265
+ return addressRef.toAddress();
4266
+ }
4267
+ /**
4268
+ * Resolve nametag to 33-byte compressed public key using resolveNametagInfo
4269
+ * Returns null if nametag not found or publicKey not available
4270
+ */
4271
+ async resolveNametagToPublicKey(nametag) {
4272
+ if (!this.deps?.transport.resolveNametagInfo) {
4273
+ this.log("resolveNametagInfo not available on transport");
4274
+ return null;
4275
+ }
4276
+ const info = await this.deps.transport.resolveNametagInfo(nametag);
4277
+ if (!info) {
4278
+ this.log(`Nametag "${nametag}" not found`);
4279
+ return null;
4280
+ }
4281
+ if (!info.chainPubkey) {
4282
+ this.log(`Nametag "${nametag}" has no 33-byte chainPubkey (legacy event)`);
4283
+ return null;
4284
+ }
4285
+ return info.chainPubkey;
4286
+ }
4287
+ /**
4288
+ * Resolve recipient to IAddress for L3 transfers
4289
+ * Supports: nametag (with or without @), PROXY:, DIRECT:, hex pubkey
4174
4290
  */
4175
4291
  async resolveRecipientAddress(recipient) {
4292
+ const { AddressFactory } = await import("@unicitylabs/state-transition-sdk/lib/address/AddressFactory");
4176
4293
  if (recipient.startsWith("@")) {
4177
4294
  const nametag = recipient.slice(1);
4178
- const tokenId2 = await import_TokenId3.TokenId.fromNameTag(nametag);
4179
- return import_ProxyAddress.ProxyAddress.fromTokenId(tokenId2);
4295
+ const publicKey2 = await this.resolveNametagToPublicKey(nametag);
4296
+ if (publicKey2) {
4297
+ this.log(`Resolved @${nametag} to 33-byte publicKey for DirectAddress`);
4298
+ return this.createDirectAddressFromPubkey(publicKey2);
4299
+ }
4300
+ throw new Error(`Nametag "${nametag}" not found or missing publicKey`);
4180
4301
  }
4181
- const pubkeyBytes = new Uint8Array(
4182
- recipient.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
4302
+ if (recipient.startsWith("PROXY:") || recipient.startsWith("DIRECT:")) {
4303
+ return AddressFactory.createAddress(recipient);
4304
+ }
4305
+ if (recipient.length === 66 && /^[0-9a-fA-F]+$/.test(recipient)) {
4306
+ this.log(`Creating DirectAddress from 33-byte compressed pubkey`);
4307
+ return this.createDirectAddressFromPubkey(recipient);
4308
+ }
4309
+ const publicKey = await this.resolveNametagToPublicKey(recipient);
4310
+ if (publicKey) {
4311
+ this.log(`Resolved "${recipient}" as nametag to 33-byte publicKey for DirectAddress`);
4312
+ return this.createDirectAddressFromPubkey(publicKey);
4313
+ }
4314
+ throw new Error(
4315
+ `Recipient "${recipient}" is not a valid nametag or L3 address. Use @nametag for explicit nametag or a valid 33-byte hex pubkey/PROXY:/DIRECT: address.`
4183
4316
  );
4184
- const tokenId = new import_TokenId3.TokenId(pubkeyBytes.slice(0, 32));
4185
- return import_ProxyAddress.ProxyAddress.fromTokenId(tokenId);
4186
4317
  }
4187
4318
  async handleIncomingTransfer(transfer) {
4188
4319
  try {
@@ -4240,7 +4371,39 @@ var PaymentsModule = class {
4240
4371
  }
4241
4372
  }
4242
4373
  } else {
4243
- tokenData = sourceTokenInput;
4374
+ this.log("Finalizing DIRECT address transfer for state tracking...");
4375
+ try {
4376
+ const signingService = await this.createSigningService();
4377
+ const transferSalt = transferTx.data.salt;
4378
+ const recipientPredicate = await import_UnmaskedPredicate3.UnmaskedPredicate.create(
4379
+ sourceToken.id,
4380
+ sourceToken.type,
4381
+ signingService,
4382
+ import_HashAlgorithm3.HashAlgorithm.SHA256,
4383
+ transferSalt
4384
+ );
4385
+ const recipientState = new import_TokenState3.TokenState(recipientPredicate, null);
4386
+ const stClient = this.deps.oracle.getStateTransitionClient?.();
4387
+ const trustBase = this.deps.oracle.getTrustBase?.();
4388
+ if (!stClient || !trustBase) {
4389
+ this.log("Cannot finalize DIRECT transfer - missing client, using source token");
4390
+ tokenData = sourceTokenInput;
4391
+ } else {
4392
+ finalizedSdkToken = await stClient.finalizeTransaction(
4393
+ trustBase,
4394
+ sourceToken,
4395
+ recipientState,
4396
+ transferTx,
4397
+ []
4398
+ // No nametag tokens needed for DIRECT
4399
+ );
4400
+ tokenData = finalizedSdkToken.toJSON();
4401
+ this.log("DIRECT transfer finalized successfully");
4402
+ }
4403
+ } catch (finalizeError) {
4404
+ this.log("DIRECT finalization failed, using source token:", finalizeError);
4405
+ tokenData = sourceTokenInput;
4406
+ }
4244
4407
  }
4245
4408
  } else if (payload.token) {
4246
4409
  tokenData = payload.token;
@@ -4274,7 +4437,7 @@ var PaymentsModule = class {
4274
4437
  await this.addToken(token);
4275
4438
  const incomingTransfer = {
4276
4439
  id: transfer.id,
4277
- senderPubkey: transfer.senderPubkey,
4440
+ senderPubkey: transfer.senderTransportPubkey,
4278
4441
  tokens: [token],
4279
4442
  memo: payload.memo,
4280
4443
  receivedAt: transfer.timestamp
@@ -4342,7 +4505,7 @@ var PaymentsModule = class {
4342
4505
  tokens,
4343
4506
  {
4344
4507
  version: 1,
4345
- address: this.deps.identity.address,
4508
+ address: this.deps.identity.l1Address,
4346
4509
  ipnsName: this.deps.identity.ipnsName ?? ""
4347
4510
  },
4348
4511
  {
@@ -4446,7 +4609,7 @@ var CommunicationsModule = class {
4446
4609
  const eventId = await this.deps.transport.sendMessage(recipientPubkey, content);
4447
4610
  const message = {
4448
4611
  id: eventId,
4449
- senderPubkey: this.deps.identity.publicKey,
4612
+ senderPubkey: this.deps.identity.chainPubkey,
4450
4613
  senderNametag: this.deps.identity.nametag,
4451
4614
  recipientPubkey,
4452
4615
  content,
@@ -4473,7 +4636,7 @@ var CommunicationsModule = class {
4473
4636
  getConversations() {
4474
4637
  const conversations = /* @__PURE__ */ new Map();
4475
4638
  for (const message of this.messages.values()) {
4476
- const peer = message.senderPubkey === this.deps?.identity.publicKey ? message.recipientPubkey : message.senderPubkey;
4639
+ const peer = message.senderPubkey === this.deps?.identity.chainPubkey ? message.recipientPubkey : message.senderPubkey;
4477
4640
  if (!conversations.has(peer)) {
4478
4641
  conversations.set(peer, []);
4479
4642
  }
@@ -4503,7 +4666,7 @@ var CommunicationsModule = class {
4503
4666
  */
4504
4667
  getUnreadCount(peerPubkey) {
4505
4668
  let messages = Array.from(this.messages.values()).filter(
4506
- (m) => !m.isRead && m.senderPubkey !== this.deps?.identity.publicKey
4669
+ (m) => !m.isRead && m.senderPubkey !== this.deps?.identity.chainPubkey
4507
4670
  );
4508
4671
  if (peerPubkey) {
4509
4672
  messages = messages.filter((m) => m.senderPubkey === peerPubkey);
@@ -4528,7 +4691,7 @@ var CommunicationsModule = class {
4528
4691
  const eventId = await this.deps.transport.publishBroadcast?.(content, tags);
4529
4692
  const message = {
4530
4693
  id: eventId ?? crypto.randomUUID(),
4531
- authorPubkey: this.deps.identity.publicKey,
4694
+ authorPubkey: this.deps.identity.chainPubkey,
4532
4695
  authorNametag: this.deps.identity.nametag,
4533
4696
  content,
4534
4697
  timestamp: Date.now(),
@@ -4579,11 +4742,12 @@ var CommunicationsModule = class {
4579
4742
  // Private: Message Handling
4580
4743
  // ===========================================================================
4581
4744
  handleIncomingMessage(msg) {
4582
- if (msg.senderPubkey === this.deps?.identity.publicKey) return;
4745
+ if (msg.senderTransportPubkey === this.deps?.identity.chainPubkey) return;
4583
4746
  const message = {
4584
4747
  id: msg.id,
4585
- senderPubkey: msg.senderPubkey,
4586
- recipientPubkey: this.deps.identity.publicKey,
4748
+ senderPubkey: msg.senderTransportPubkey,
4749
+ senderNametag: msg.senderNametag,
4750
+ recipientPubkey: this.deps.identity.chainPubkey,
4587
4751
  content: msg.content,
4588
4752
  timestamp: msg.timestamp,
4589
4753
  isRead: false
@@ -4605,7 +4769,7 @@ var CommunicationsModule = class {
4605
4769
  handleIncomingBroadcast(incoming) {
4606
4770
  const message = {
4607
4771
  id: incoming.id,
4608
- authorPubkey: incoming.authorPubkey,
4772
+ authorPubkey: incoming.authorTransportPubkey,
4609
4773
  content: incoming.content,
4610
4774
  timestamp: incoming.timestamp,
4611
4775
  tags: incoming.tags
@@ -5432,6 +5596,7 @@ var import_SigningService2 = require("@unicitylabs/state-transition-sdk/lib/sign
5432
5596
  var import_TokenType2 = require("@unicitylabs/state-transition-sdk/lib/token/TokenType");
5433
5597
  var import_HashAlgorithm4 = require("@unicitylabs/state-transition-sdk/lib/hash/HashAlgorithm");
5434
5598
  var import_UnmaskedPredicateReference2 = require("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicateReference");
5599
+ var import_nostr_js_sdk = require("@unicitylabs/nostr-js-sdk");
5435
5600
  var UNICITY_TOKEN_TYPE_HEX2 = "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509";
5436
5601
  async function deriveL3PredicateAddress(privateKey) {
5437
5602
  const secret = Buffer.from(privateKey, "hex");
@@ -5589,6 +5754,8 @@ var Sphere = class _Sphere {
5589
5754
  _Sphere.instance = sphere;
5590
5755
  if (options.nametag) {
5591
5756
  await sphere.registerNametag(options.nametag);
5757
+ } else {
5758
+ await sphere.recoverNametagFromNostr();
5592
5759
  }
5593
5760
  return sphere;
5594
5761
  }
@@ -5651,6 +5818,9 @@ var Sphere = class _Sphere {
5651
5818
  }
5652
5819
  await sphere.initializeProviders();
5653
5820
  await sphere.initializeModules();
5821
+ if (!options.nametag) {
5822
+ await sphere.recoverNametagFromNostr();
5823
+ }
5654
5824
  await sphere.finalizeWalletCreation();
5655
5825
  sphere._initialized = true;
5656
5826
  _Sphere.instance = sphere;
@@ -5724,9 +5894,9 @@ var Sphere = class _Sphere {
5724
5894
  get identity() {
5725
5895
  if (!this._identity) return null;
5726
5896
  return {
5727
- publicKey: this._identity.publicKey,
5728
- address: this._identity.address,
5729
- predicateAddress: this._identity.predicateAddress,
5897
+ chainPubkey: this._identity.chainPubkey,
5898
+ l1Address: this._identity.l1Address,
5899
+ directAddress: this._identity.directAddress,
5730
5900
  ipnsName: this._identity.ipnsName,
5731
5901
  nametag: this._identity.nametag
5732
5902
  };
@@ -5843,7 +6013,7 @@ var Sphere = class _Sphere {
5843
6013
  if (this._masterKey) {
5844
6014
  address0 = this.deriveAddress(0).address;
5845
6015
  } else if (this._identity) {
5846
- address0 = this._identity.address;
6016
+ address0 = this._identity.l1Address;
5847
6017
  }
5848
6018
  } catch {
5849
6019
  }
@@ -5890,8 +6060,8 @@ var Sphere = class _Sphere {
5890
6060
  } catch {
5891
6061
  if (i === 0 && this._identity) {
5892
6062
  addresses.push({
5893
- address: this._identity.address,
5894
- publicKey: this._identity.publicKey,
6063
+ address: this._identity.l1Address,
6064
+ publicKey: this._identity.chainPubkey,
5895
6065
  path: this.getDefaultAddressPath(),
5896
6066
  index: 0
5897
6067
  });
@@ -5970,7 +6140,7 @@ var Sphere = class _Sphere {
5970
6140
  } catch {
5971
6141
  if (i === 0 && this._identity) {
5972
6142
  addresses.push({
5973
- address: this._identity.address,
6143
+ address: this._identity.l1Address,
5974
6144
  path: this.getDefaultAddressPath(),
5975
6145
  index: 0,
5976
6146
  isChange: false
@@ -6324,9 +6494,9 @@ var Sphere = class _Sphere {
6324
6494
  const nametag = this._addressNametags.get(index);
6325
6495
  this._identity = {
6326
6496
  privateKey: addressInfo.privateKey,
6327
- publicKey: addressInfo.publicKey,
6328
- address: addressInfo.address,
6329
- predicateAddress,
6497
+ chainPubkey: addressInfo.publicKey,
6498
+ l1Address: addressInfo.address,
6499
+ directAddress: predicateAddress,
6330
6500
  ipnsName: "12D3KooW" + ipnsHash,
6331
6501
  nametag
6332
6502
  };
@@ -6339,13 +6509,13 @@ var Sphere = class _Sphere {
6339
6509
  }
6340
6510
  await this.reinitializeModulesForNewAddress();
6341
6511
  this.emitEvent("identity:changed", {
6342
- address: this._identity.address,
6343
- predicateAddress: this._identity.predicateAddress,
6344
- publicKey: this._identity.publicKey,
6512
+ l1Address: this._identity.l1Address,
6513
+ directAddress: this._identity.directAddress,
6514
+ chainPubkey: this._identity.chainPubkey,
6345
6515
  nametag: this._identity.nametag,
6346
6516
  addressIndex: index
6347
6517
  });
6348
- console.log(`[Sphere] Switched to address ${index}:`, this._identity.address);
6518
+ console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
6349
6519
  }
6350
6520
  /**
6351
6521
  * Re-initialize modules after address switch
@@ -6403,7 +6573,7 @@ var Sphere = class _Sphere {
6403
6573
  );
6404
6574
  return {
6405
6575
  ...info,
6406
- address: "alpha1" + info.address.slice(0, 38)
6576
+ address: publicKeyToAddress(info.publicKey, "alpha")
6407
6577
  };
6408
6578
  }
6409
6579
  /**
@@ -6430,11 +6600,10 @@ var Sphere = class _Sphere {
6430
6600
  path
6431
6601
  );
6432
6602
  const publicKey = getPublicKey(derived.privateKey);
6433
- const addressHash = hash160(publicKey);
6434
6603
  return {
6435
6604
  privateKey: derived.privateKey,
6436
6605
  publicKey,
6437
- address: "alpha1" + addressHash.slice(0, 38),
6606
+ address: publicKeyToAddress(publicKey, "alpha"),
6438
6607
  path,
6439
6608
  index
6440
6609
  };
@@ -6522,6 +6691,17 @@ var Sphere = class _Sphere {
6522
6691
  hasNametag() {
6523
6692
  return !!this._identity?.nametag;
6524
6693
  }
6694
+ /**
6695
+ * Get the PROXY address for the current nametag
6696
+ * PROXY addresses are derived from the nametag hash and require
6697
+ * the nametag token to claim funds sent to them
6698
+ * @returns PROXY address string or undefined if no nametag
6699
+ */
6700
+ getProxyAddress() {
6701
+ const nametag = this._identity?.nametag;
6702
+ if (!nametag) return void 0;
6703
+ return `PROXY:${(0, import_nostr_js_sdk.hashNametag)(nametag)}`;
6704
+ }
6525
6705
  /**
6526
6706
  * Register a nametag for the current active address
6527
6707
  * Each address can have its own independent nametag
@@ -6550,7 +6730,11 @@ var Sphere = class _Sphere {
6550
6730
  throw new Error(`Nametag already registered for address ${this._currentAddressIndex}: @${this._identity.nametag}`);
6551
6731
  }
6552
6732
  if (this._transport.registerNametag) {
6553
- const success = await this._transport.registerNametag(cleanNametag, this._identity.publicKey);
6733
+ const success = await this._transport.registerNametag(
6734
+ cleanNametag,
6735
+ this._identity.chainPubkey,
6736
+ this._identity.directAddress || ""
6737
+ );
6554
6738
  if (!success) {
6555
6739
  throw new Error("Failed to register nametag. It may already be taken.");
6556
6740
  }
@@ -6644,7 +6828,11 @@ var Sphere = class _Sphere {
6644
6828
  return;
6645
6829
  }
6646
6830
  try {
6647
- const success = await this._transport.registerNametag(nametag, this._identity.publicKey);
6831
+ const success = await this._transport.registerNametag(
6832
+ nametag,
6833
+ this._identity.chainPubkey,
6834
+ this._identity.directAddress || ""
6835
+ );
6648
6836
  if (success) {
6649
6837
  console.log(`[Sphere] Nametag @${nametag} synced with Nostr`);
6650
6838
  } else {
@@ -6654,6 +6842,38 @@ var Sphere = class _Sphere {
6654
6842
  console.warn(`[Sphere] Nametag sync failed:`, error);
6655
6843
  }
6656
6844
  }
6845
+ /**
6846
+ * Recover nametag from Nostr after wallet import
6847
+ * Searches for encrypted nametag events authored by this wallet's pubkey
6848
+ * and decrypts them to restore the nametag association
6849
+ */
6850
+ async recoverNametagFromNostr() {
6851
+ if (this._identity?.nametag) {
6852
+ return;
6853
+ }
6854
+ if (!this._transport.recoverNametag) {
6855
+ return;
6856
+ }
6857
+ try {
6858
+ const recoveredNametag = await this._transport.recoverNametag();
6859
+ if (recoveredNametag) {
6860
+ if (this._identity) {
6861
+ this._identity.nametag = recoveredNametag;
6862
+ }
6863
+ this._addressNametags.set(this._currentAddressIndex, recoveredNametag);
6864
+ await this._storage.set(STORAGE_KEYS.NAMETAG, recoveredNametag);
6865
+ if (this._transport.registerNametag) {
6866
+ await this._transport.registerNametag(
6867
+ recoveredNametag,
6868
+ this._identity.chainPubkey,
6869
+ this._identity.directAddress || ""
6870
+ );
6871
+ }
6872
+ this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
6873
+ }
6874
+ } catch {
6875
+ }
6876
+ }
6657
6877
  /**
6658
6878
  * Validate nametag format
6659
6879
  */
@@ -6780,57 +7000,64 @@ var Sphere = class _Sphere {
6780
7000
  const nametag = this._addressNametags.get(this._currentAddressIndex);
6781
7001
  this._identity = {
6782
7002
  privateKey: addressInfo.privateKey,
6783
- publicKey: addressInfo.publicKey,
6784
- address: addressInfo.address,
6785
- predicateAddress,
7003
+ chainPubkey: addressInfo.publicKey,
7004
+ l1Address: addressInfo.address,
7005
+ directAddress: predicateAddress,
6786
7006
  ipnsName: "12D3KooW" + ipnsHash,
6787
7007
  nametag
6788
7008
  };
6789
7009
  this._storage.setIdentity(this._identity);
6790
- console.log(`[Sphere] Restored to address ${this._currentAddressIndex}:`, this._identity.address);
7010
+ console.log(`[Sphere] Restored to address ${this._currentAddressIndex}:`, this._identity.l1Address);
6791
7011
  } else {
6792
7012
  if (savedNametag && this._identity) {
6793
- this._identity.nametag = savedNametag;
7013
+ let nametag = savedNametag;
7014
+ if (savedNametag.startsWith("{")) {
7015
+ try {
7016
+ const parsed = JSON.parse(savedNametag);
7017
+ nametag = parsed["0"] || parsed[0] || Object.values(parsed)[0];
7018
+ } catch {
7019
+ }
7020
+ }
7021
+ this._identity.nametag = nametag;
6794
7022
  if (!this._addressNametags.has(0)) {
6795
- this._addressNametags.set(0, savedNametag);
7023
+ this._addressNametags.set(0, nametag);
6796
7024
  }
6797
- console.log("[Sphere] Restored nametag:", savedNametag);
6798
7025
  } else if (this._identity) {
6799
7026
  const nametag = this._addressNametags.get(0);
6800
7027
  if (nametag) {
6801
7028
  this._identity.nametag = nametag;
6802
- console.log("[Sphere] Restored nametag from map:", nametag);
6803
7029
  }
6804
7030
  }
6805
7031
  }
6806
7032
  }
6807
7033
  async initializeIdentityFromMnemonic(mnemonic, derivationPath) {
6808
- const path = derivationPath ?? DEFAULT_DERIVATION_PATH2;
7034
+ const basePath = derivationPath ?? DEFAULT_BASE_PATH;
7035
+ const fullPath = `${basePath}/0/0`;
6809
7036
  const masterKey = identityFromMnemonicSync(mnemonic);
6810
7037
  const derivedKey = deriveKeyAtPath(
6811
7038
  masterKey.privateKey,
6812
7039
  masterKey.chainCode,
6813
- `${path}/0/0`
7040
+ fullPath
6814
7041
  );
6815
7042
  const publicKey = getPublicKey(derivedKey.privateKey);
6816
- const addressHash = hash160(publicKey);
7043
+ const address = publicKeyToAddress(publicKey, "alpha");
6817
7044
  const ipnsHash = sha256(publicKey, "hex").slice(0, 40);
6818
7045
  const predicateAddress = await deriveL3PredicateAddress(derivedKey.privateKey);
6819
7046
  this._identity = {
6820
7047
  privateKey: derivedKey.privateKey,
6821
- publicKey,
6822
- address: "alpha1" + addressHash.slice(0, 38),
6823
- predicateAddress,
7048
+ chainPubkey: publicKey,
7049
+ l1Address: address,
7050
+ directAddress: predicateAddress,
6824
7051
  ipnsName: "12D3KooW" + ipnsHash
6825
7052
  };
6826
7053
  this._masterKey = masterKey;
6827
- console.log("[Sphere] Identity initialized from mnemonic, path:", path);
6828
7054
  }
6829
7055
  async initializeIdentityFromMasterKey(masterKey, chainCode, derivationPath) {
6830
- const path = derivationPath ?? DEFAULT_DERIVATION_PATH2;
7056
+ const basePath = derivationPath ?? DEFAULT_BASE_PATH;
7057
+ const fullPath = `${basePath}/0/0`;
6831
7058
  let privateKey;
6832
7059
  if (chainCode) {
6833
- const derivedKey = deriveKeyAtPath(masterKey, chainCode, `${path}/0/0`);
7060
+ const derivedKey = deriveKeyAtPath(masterKey, chainCode, fullPath);
6834
7061
  privateKey = derivedKey.privateKey;
6835
7062
  this._masterKey = {
6836
7063
  privateKey: masterKey,
@@ -6841,17 +7068,16 @@ var Sphere = class _Sphere {
6841
7068
  this._masterKey = null;
6842
7069
  }
6843
7070
  const publicKey = getPublicKey(privateKey);
6844
- const addressHash = hash160(publicKey);
7071
+ const address = publicKeyToAddress(publicKey, "alpha");
6845
7072
  const ipnsHash = sha256(publicKey, "hex").slice(0, 40);
6846
7073
  const predicateAddress = await deriveL3PredicateAddress(privateKey);
6847
7074
  this._identity = {
6848
7075
  privateKey,
6849
- publicKey,
6850
- address: "alpha1" + addressHash.slice(0, 38),
6851
- predicateAddress,
7076
+ chainPubkey: publicKey,
7077
+ l1Address: address,
7078
+ directAddress: predicateAddress,
6852
7079
  ipnsName: "12D3KooW" + ipnsHash
6853
7080
  };
6854
- console.log("[Sphere] Identity initialized from master key, path:", path, "chainCode:", !!chainCode);
6855
7081
  }
6856
7082
  // ===========================================================================
6857
7083
  // Private: Provider & Module Initialization