@unicitylabs/sphere-sdk 0.4.9 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3513,7 +3513,7 @@ var InstantSplitExecutor = class {
3513
3513
  token: JSON.stringify(bundle),
3514
3514
  proof: null,
3515
3515
  // Proof is included in the bundle
3516
- memo: "INSTANT_SPLIT_V5",
3516
+ memo: options?.memo,
3517
3517
  sender: {
3518
3518
  transportPubkey: senderPubkey
3519
3519
  }
@@ -4072,6 +4072,11 @@ var import_MintCommitment3 = require("@unicitylabs/state-transition-sdk/lib/tran
4072
4072
  var import_MintTransactionData3 = require("@unicitylabs/state-transition-sdk/lib/transaction/MintTransactionData");
4073
4073
  var import_InclusionProofUtils5 = require("@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils");
4074
4074
  var import_InclusionProof = require("@unicitylabs/state-transition-sdk/lib/transaction/InclusionProof");
4075
+ function computeHistoryDedupKey(type, tokenId, transferId) {
4076
+ if (type === "SENT" && transferId) return `${type}_transfer_${transferId}`;
4077
+ if (tokenId) return `${type}_${tokenId}`;
4078
+ return `${type}_${crypto.randomUUID()}`;
4079
+ }
4075
4080
  function enrichWithRegistry(info) {
4076
4081
  const registry = TokenRegistry.getInstance();
4077
4082
  const def = registry.getDefinition(info.coinId);
@@ -4370,7 +4375,7 @@ var PaymentsModule = class _PaymentsModule {
4370
4375
  tombstones = [];
4371
4376
  archivedTokens = /* @__PURE__ */ new Map();
4372
4377
  forkedTokens = /* @__PURE__ */ new Map();
4373
- transactionHistory = [];
4378
+ _historyCache = [];
4374
4379
  nametags = [];
4375
4380
  // Payment Requests State (Incoming)
4376
4381
  paymentRequests = [];
@@ -4439,7 +4444,7 @@ var PaymentsModule = class _PaymentsModule {
4439
4444
  this.tombstones = [];
4440
4445
  this.archivedTokens.clear();
4441
4446
  this.forkedTokens.clear();
4442
- this.transactionHistory = [];
4447
+ this._historyCache = [];
4443
4448
  this.nametags = [];
4444
4449
  this.deps = deps;
4445
4450
  this.priceProvider = deps.price ?? null;
@@ -4490,14 +4495,7 @@ var PaymentsModule = class _PaymentsModule {
4490
4495
  }
4491
4496
  }
4492
4497
  await this.loadPendingV5Tokens();
4493
- const historyData = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
4494
- if (historyData) {
4495
- try {
4496
- this.transactionHistory = JSON.parse(historyData);
4497
- } catch {
4498
- this.transactionHistory = [];
4499
- }
4500
- }
4498
+ await this.loadHistory();
4501
4499
  const pending2 = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
4502
4500
  if (pending2) {
4503
4501
  const transfers = JSON.parse(pending2);
@@ -4584,7 +4582,7 @@ var PaymentsModule = class _PaymentsModule {
4584
4582
  }
4585
4583
  await this.saveToOutbox(result, recipientPubkey);
4586
4584
  result.status = "submitted";
4587
- const recipientNametag = request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0;
4585
+ const recipientNametag = peerInfo?.nametag || (request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0);
4588
4586
  const transferMode = request.transferMode ?? "instant";
4589
4587
  if (splitPlan.requiresSplit && splitPlan.tokenToSplit) {
4590
4588
  if (transferMode === "conservative") {
@@ -4615,7 +4613,7 @@ var PaymentsModule = class _PaymentsModule {
4615
4613
  updatedAt: Date.now(),
4616
4614
  sdkData: JSON.stringify(changeTokenData)
4617
4615
  };
4618
- await this.addToken(changeUiToken, true);
4616
+ await this.addToken(changeUiToken);
4619
4617
  this.log(`Conservative split: change token saved: ${changeUiToken.id}`);
4620
4618
  await this.deps.transport.sendTokenTransfer(recipientPubkey, {
4621
4619
  sourceToken: JSON.stringify(splitResult.tokenForRecipient.toJSON()),
@@ -4624,7 +4622,7 @@ var PaymentsModule = class _PaymentsModule {
4624
4622
  });
4625
4623
  const splitCommitmentRequestId = splitResult.recipientTransferTx?.data?.requestId ?? splitResult.recipientTransferTx?.requestId;
4626
4624
  const splitRequestIdHex = splitCommitmentRequestId instanceof Uint8Array ? Array.from(splitCommitmentRequestId).map((b) => b.toString(16).padStart(2, "0")).join("") : splitCommitmentRequestId ? String(splitCommitmentRequestId) : void 0;
4627
- await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag, true);
4625
+ await this.removeToken(splitPlan.tokenToSplit.uiToken.id);
4628
4626
  result.tokenTransfers.push({
4629
4627
  sourceTokenId: splitPlan.tokenToSplit.uiToken.id,
4630
4628
  method: "split",
@@ -4649,6 +4647,7 @@ var PaymentsModule = class _PaymentsModule {
4649
4647
  this.deps.transport,
4650
4648
  recipientPubkey,
4651
4649
  {
4650
+ memo: request.memo,
4652
4651
  onChangeTokenCreated: async (changeToken) => {
4653
4652
  const changeTokenData = changeToken.toJSON();
4654
4653
  const uiToken = {
@@ -4664,7 +4663,7 @@ var PaymentsModule = class _PaymentsModule {
4664
4663
  updatedAt: Date.now(),
4665
4664
  sdkData: JSON.stringify(changeTokenData)
4666
4665
  };
4667
- await this.addToken(uiToken, true);
4666
+ await this.addToken(uiToken);
4668
4667
  this.log(`Change token saved via background: ${uiToken.id}`);
4669
4668
  },
4670
4669
  onStorageSync: async () => {
@@ -4679,7 +4678,7 @@ var PaymentsModule = class _PaymentsModule {
4679
4678
  if (instantResult.backgroundPromise) {
4680
4679
  this.pendingBackgroundTasks.push(instantResult.backgroundPromise);
4681
4680
  }
4682
- await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag);
4681
+ await this.removeToken(splitPlan.tokenToSplit.uiToken.id);
4683
4682
  result.tokenTransfers.push({
4684
4683
  sourceTokenId: splitPlan.tokenToSplit.uiToken.id,
4685
4684
  method: "split",
@@ -4726,20 +4725,25 @@ var PaymentsModule = class _PaymentsModule {
4726
4725
  requestIdHex
4727
4726
  });
4728
4727
  this.log(`Token ${token.id} sent via ${transferMode.toUpperCase()}, requestId: ${requestIdHex}`);
4729
- await this.removeToken(token.id, recipientNametag, true);
4728
+ await this.removeToken(token.id);
4730
4729
  }
4731
4730
  result.status = "delivered";
4732
4731
  await this.save();
4733
4732
  await this.removeFromOutbox(result.id);
4734
4733
  result.status = "completed";
4734
+ const sentTokenId = result.tokens[0] ? extractTokenIdFromSdkData(result.tokens[0].sdkData) : void 0;
4735
4735
  await this.addToHistory({
4736
4736
  type: "SENT",
4737
4737
  amount: request.amount,
4738
4738
  coinId: request.coinId,
4739
4739
  symbol: this.getCoinSymbol(request.coinId),
4740
4740
  timestamp: Date.now(),
4741
+ recipientPubkey,
4741
4742
  recipientNametag,
4742
- transferId: result.id
4743
+ recipientAddress: peerInfo?.directAddress || recipientAddress?.toString() || recipientPubkey,
4744
+ memo: request.memo,
4745
+ transferId: result.id,
4746
+ tokenId: sentTokenId || void 0
4743
4747
  });
4744
4748
  this.deps.emitEvent("transfer:confirmed", result);
4745
4749
  return result;
@@ -4850,6 +4854,7 @@ var PaymentsModule = class _PaymentsModule {
4850
4854
  recipientPubkey,
4851
4855
  {
4852
4856
  ...options,
4857
+ memo: request.memo,
4853
4858
  onChangeTokenCreated: async (changeToken) => {
4854
4859
  const changeTokenData = changeToken.toJSON();
4855
4860
  const uiToken = {
@@ -4865,7 +4870,7 @@ var PaymentsModule = class _PaymentsModule {
4865
4870
  updatedAt: Date.now(),
4866
4871
  sdkData: JSON.stringify(changeTokenData)
4867
4872
  };
4868
- await this.addToken(uiToken, true);
4873
+ await this.addToken(uiToken);
4869
4874
  this.log(`Change token saved via background: ${uiToken.id}`);
4870
4875
  },
4871
4876
  onStorageSync: async () => {
@@ -4878,15 +4883,20 @@ var PaymentsModule = class _PaymentsModule {
4878
4883
  if (result.backgroundPromise) {
4879
4884
  this.pendingBackgroundTasks.push(result.backgroundPromise);
4880
4885
  }
4881
- const recipientNametag = request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0;
4882
- await this.removeToken(tokenToSplit.id, recipientNametag, true);
4886
+ await this.removeToken(tokenToSplit.id);
4887
+ const recipientNametag = peerInfo?.nametag || (request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0);
4888
+ const splitTokenId = extractTokenIdFromSdkData(tokenToSplit.sdkData);
4883
4889
  await this.addToHistory({
4884
4890
  type: "SENT",
4885
4891
  amount: request.amount,
4886
4892
  coinId: request.coinId,
4887
4893
  symbol: this.getCoinSymbol(request.coinId),
4888
4894
  timestamp: Date.now(),
4889
- recipientNametag
4895
+ recipientPubkey,
4896
+ recipientNametag,
4897
+ recipientAddress: peerInfo?.directAddress || recipientAddress?.toString() || recipientPubkey,
4898
+ memo: request.memo,
4899
+ tokenId: splitTokenId || void 0
4890
4900
  });
4891
4901
  await this.save();
4892
4902
  } else {
@@ -4917,10 +4927,10 @@ var PaymentsModule = class _PaymentsModule {
4917
4927
  * @param senderPubkey - Sender's public key for verification
4918
4928
  * @returns Processing result with finalized token
4919
4929
  */
4920
- async processInstantSplitBundle(bundle, senderPubkey) {
4930
+ async processInstantSplitBundle(bundle, senderPubkey, memo) {
4921
4931
  this.ensureInitialized();
4922
4932
  if (!isInstantSplitBundleV5(bundle)) {
4923
- return this.processInstantSplitBundleSync(bundle, senderPubkey);
4933
+ return this.processInstantSplitBundleSync(bundle, senderPubkey, memo);
4924
4934
  }
4925
4935
  try {
4926
4936
  const deterministicId = `v5split_${bundle.splitGroupId}`;
@@ -4950,12 +4960,26 @@ var PaymentsModule = class _PaymentsModule {
4950
4960
  updatedAt: Date.now(),
4951
4961
  sdkData: JSON.stringify({ _pendingFinalization: pendingData })
4952
4962
  };
4953
- await this.addToken(uiToken, false);
4963
+ await this.addToken(uiToken);
4954
4964
  this.log(`V5 bundle saved as unconfirmed: ${uiToken.id.slice(0, 8)}...`);
4965
+ const senderInfo = await this.resolveSenderInfo(senderPubkey);
4966
+ await this.addToHistory({
4967
+ type: "RECEIVED",
4968
+ amount: bundle.amount,
4969
+ coinId: bundle.coinId,
4970
+ symbol: uiToken.symbol,
4971
+ timestamp: Date.now(),
4972
+ senderPubkey,
4973
+ ...senderInfo,
4974
+ memo,
4975
+ tokenId: deterministicId
4976
+ });
4955
4977
  this.deps.emitEvent("transfer:incoming", {
4956
4978
  id: bundle.splitGroupId,
4957
4979
  senderPubkey,
4980
+ senderNametag: senderInfo.senderNametag,
4958
4981
  tokens: [uiToken],
4982
+ memo,
4959
4983
  receivedAt: Date.now()
4960
4984
  });
4961
4985
  await this.save();
@@ -4975,7 +4999,7 @@ var PaymentsModule = class _PaymentsModule {
4975
4999
  * Synchronous V4 bundle processing (dev mode only).
4976
5000
  * Kept for backward compatibility with V4 bundles.
4977
5001
  */
4978
- async processInstantSplitBundleSync(bundle, senderPubkey) {
5002
+ async processInstantSplitBundleSync(bundle, senderPubkey, memo) {
4979
5003
  try {
4980
5004
  const signingService = await this.createSigningService();
4981
5005
  const stClient = this.deps.oracle.getStateTransitionClient?.();
@@ -5035,19 +5059,26 @@ var PaymentsModule = class _PaymentsModule {
5035
5059
  sdkData: JSON.stringify(tokenData)
5036
5060
  };
5037
5061
  await this.addToken(uiToken);
5062
+ const receivedTokenId = extractTokenIdFromSdkData(uiToken.sdkData);
5063
+ const senderInfo = await this.resolveSenderInfo(senderPubkey);
5038
5064
  await this.addToHistory({
5039
5065
  type: "RECEIVED",
5040
5066
  amount: bundle.amount,
5041
5067
  coinId: info.coinId,
5042
5068
  symbol: info.symbol,
5043
5069
  timestamp: Date.now(),
5044
- senderPubkey
5070
+ senderPubkey,
5071
+ ...senderInfo,
5072
+ memo,
5073
+ tokenId: receivedTokenId || uiToken.id
5045
5074
  });
5046
5075
  await this.save();
5047
5076
  this.deps.emitEvent("transfer:incoming", {
5048
5077
  id: bundle.splitGroupId,
5049
5078
  senderPubkey,
5079
+ senderNametag: senderInfo.senderNametag,
5050
5080
  tokens: [uiToken],
5081
+ memo,
5051
5082
  receivedAt: Date.now()
5052
5083
  });
5053
5084
  }
@@ -5790,14 +5821,6 @@ var PaymentsModule = class _PaymentsModule {
5790
5821
  sdkData: JSON.stringify(finalizedToken.toJSON())
5791
5822
  };
5792
5823
  this.tokens.set(tokenId, confirmedToken);
5793
- await this.addToHistory({
5794
- type: "RECEIVED",
5795
- amount: confirmedToken.amount,
5796
- coinId: confirmedToken.coinId,
5797
- symbol: confirmedToken.symbol || "UNK",
5798
- timestamp: Date.now(),
5799
- senderPubkey: pending2.senderPubkey
5800
- });
5801
5824
  this.log(`V5 token resolved: ${tokenId.slice(0, 8)}...`);
5802
5825
  return "resolved";
5803
5826
  }
@@ -5981,10 +6004,9 @@ var PaymentsModule = class _PaymentsModule {
5981
6004
  * the old state is archived and replaced with the incoming one.
5982
6005
  *
5983
6006
  * @param token - The token to add.
5984
- * @param skipHistory - When `true`, do not create a `RECEIVED` transaction history entry (default `false`).
5985
6007
  * @returns `true` if the token was added, `false` if rejected as duplicate or tombstoned.
5986
6008
  */
5987
- async addToken(token, skipHistory = false) {
6009
+ async addToken(token) {
5988
6010
  this.ensureInitialized();
5989
6011
  const incomingTokenId = extractTokenIdFromSdkData(token.sdkData);
5990
6012
  const incomingStateHash = extractStateHashFromSdkData(token.sdkData);
@@ -6030,15 +6052,6 @@ var PaymentsModule = class _PaymentsModule {
6030
6052
  }
6031
6053
  this.tokens.set(token.id, token);
6032
6054
  await this.archiveToken(token);
6033
- if (!skipHistory && token.coinId && token.amount) {
6034
- await this.addToHistory({
6035
- type: "RECEIVED",
6036
- amount: token.amount,
6037
- coinId: token.coinId,
6038
- symbol: token.symbol || "UNK",
6039
- timestamp: token.createdAt || Date.now()
6040
- });
6041
- }
6042
6055
  await this.save();
6043
6056
  this.log(`Added token ${token.id}, total: ${this.tokens.size}`);
6044
6057
  return true;
@@ -6065,7 +6078,7 @@ var PaymentsModule = class _PaymentsModule {
6065
6078
  }
6066
6079
  }
6067
6080
  if (!found) {
6068
- await this.addToken(token, true);
6081
+ await this.addToken(token);
6069
6082
  return;
6070
6083
  }
6071
6084
  await this.archiveToken(token);
@@ -6080,10 +6093,8 @@ var PaymentsModule = class _PaymentsModule {
6080
6093
  * entry is created unless `skipHistory` is `true`.
6081
6094
  *
6082
6095
  * @param tokenId - Local UUID of the token to remove.
6083
- * @param recipientNametag - Optional nametag of the transfer recipient (for history).
6084
- * @param skipHistory - When `true`, skip creating a transaction history entry (default `false`).
6085
6096
  */
6086
- async removeToken(tokenId, recipientNametag, skipHistory = false) {
6097
+ async removeToken(tokenId) {
6087
6098
  this.ensureInitialized();
6088
6099
  const token = this.tokens.get(tokenId);
6089
6100
  if (!token) return;
@@ -6101,16 +6112,6 @@ var PaymentsModule = class _PaymentsModule {
6101
6112
  this.log(`Warning: Could not create tombstone for token ${tokenId.slice(0, 8)}... (missing tokenId or stateHash)`);
6102
6113
  }
6103
6114
  this.tokens.delete(tokenId);
6104
- if (!skipHistory && token.coinId && token.amount) {
6105
- await this.addToHistory({
6106
- type: "SENT",
6107
- amount: token.amount,
6108
- coinId: token.coinId,
6109
- symbol: token.symbol || "UNK",
6110
- timestamp: Date.now(),
6111
- recipientNametag
6112
- });
6113
- }
6114
6115
  await this.save();
6115
6116
  }
6116
6117
  // ===========================================================================
@@ -6335,26 +6336,104 @@ var PaymentsModule = class _PaymentsModule {
6335
6336
  * @returns Array of {@link TransactionHistoryEntry} objects in descending timestamp order.
6336
6337
  */
6337
6338
  getHistory() {
6338
- return [...this.transactionHistory].sort((a, b) => b.timestamp - a.timestamp);
6339
+ return [...this._historyCache].sort((a, b) => b.timestamp - a.timestamp);
6340
+ }
6341
+ /**
6342
+ * Best-effort resolve sender's DIRECT address and nametag from their transport pubkey.
6343
+ * Returns empty object if transport doesn't support resolution or lookup fails.
6344
+ */
6345
+ async resolveSenderInfo(senderTransportPubkey) {
6346
+ try {
6347
+ if (this.deps?.transport?.resolveTransportPubkeyInfo) {
6348
+ const peerInfo = await this.deps.transport.resolveTransportPubkeyInfo(senderTransportPubkey);
6349
+ if (peerInfo) {
6350
+ return {
6351
+ senderAddress: peerInfo.directAddress || void 0,
6352
+ senderNametag: peerInfo.nametag || void 0
6353
+ };
6354
+ }
6355
+ }
6356
+ } catch {
6357
+ }
6358
+ return {};
6339
6359
  }
6340
6360
  /**
6341
6361
  * Append an entry to the transaction history.
6342
6362
  *
6343
- * A unique `id` is auto-generated. The entry is immediately persisted to storage.
6363
+ * A unique `id` and `dedupKey` are auto-generated. The entry is persisted to
6364
+ * the local token storage provider's `history` store (IndexedDB / file).
6365
+ * Duplicate entries with the same `dedupKey` are silently ignored (upsert).
6344
6366
  *
6345
- * @param entry - History entry fields (without `id`).
6367
+ * @param entry - History entry fields (without `id` and `dedupKey`).
6346
6368
  */
6347
6369
  async addToHistory(entry) {
6348
6370
  this.ensureInitialized();
6371
+ const dedupKey = computeHistoryDedupKey(entry.type, entry.tokenId, entry.transferId);
6349
6372
  const historyEntry = {
6350
6373
  id: crypto.randomUUID(),
6374
+ dedupKey,
6351
6375
  ...entry
6352
6376
  };
6353
- this.transactionHistory.push(historyEntry);
6354
- await this.deps.storage.set(
6355
- STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY,
6356
- JSON.stringify(this.transactionHistory)
6357
- );
6377
+ const provider = this.getLocalTokenStorageProvider();
6378
+ if (provider?.addHistoryEntry) {
6379
+ await provider.addHistoryEntry(historyEntry);
6380
+ }
6381
+ const existingIdx = this._historyCache.findIndex((e) => e.dedupKey === dedupKey);
6382
+ if (existingIdx >= 0) {
6383
+ this._historyCache[existingIdx] = historyEntry;
6384
+ } else {
6385
+ this._historyCache.push(historyEntry);
6386
+ }
6387
+ this.deps.emitEvent("history:updated", historyEntry);
6388
+ }
6389
+ /**
6390
+ * Load history from the local token storage provider into the in-memory cache.
6391
+ * Also performs one-time migration from legacy KV storage.
6392
+ */
6393
+ async loadHistory() {
6394
+ const provider = this.getLocalTokenStorageProvider();
6395
+ if (provider?.getHistoryEntries) {
6396
+ this._historyCache = await provider.getHistoryEntries();
6397
+ const legacyData = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
6398
+ if (legacyData) {
6399
+ try {
6400
+ const legacyEntries = JSON.parse(legacyData);
6401
+ const records = legacyEntries.map((e) => ({
6402
+ ...e,
6403
+ dedupKey: e.dedupKey || computeHistoryDedupKey(e.type, e.tokenId, e.transferId)
6404
+ }));
6405
+ const imported = await provider.importHistoryEntries?.(records) ?? 0;
6406
+ if (imported > 0) {
6407
+ this._historyCache = await provider.getHistoryEntries();
6408
+ this.log(`Migrated ${imported} history entries from KV to history store`);
6409
+ }
6410
+ await this.deps.storage.remove(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
6411
+ } catch {
6412
+ }
6413
+ }
6414
+ } else {
6415
+ const historyData = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.TRANSACTION_HISTORY);
6416
+ if (historyData) {
6417
+ try {
6418
+ this._historyCache = JSON.parse(historyData);
6419
+ } catch {
6420
+ this._historyCache = [];
6421
+ }
6422
+ }
6423
+ }
6424
+ }
6425
+ /**
6426
+ * Get the first local token storage provider (for history operations).
6427
+ */
6428
+ getLocalTokenStorageProvider() {
6429
+ const providers = this.getTokenStorageProviders();
6430
+ for (const [, provider] of providers) {
6431
+ if (provider.type === "local") return provider;
6432
+ }
6433
+ for (const [, provider] of providers) {
6434
+ return provider;
6435
+ }
6436
+ return null;
6358
6437
  }
6359
6438
  // ===========================================================================
6360
6439
  // Public API - Nametag
@@ -6897,14 +6976,27 @@ var PaymentsModule = class _PaymentsModule {
6897
6976
  this.tokens.set(token.id, token);
6898
6977
  await this.save();
6899
6978
  this.log(`NOSTR-FIRST: Token ${token.id.slice(0, 8)}... added as submitted (unconfirmed)`);
6979
+ const senderInfo = await this.resolveSenderInfo(transfer.senderTransportPubkey);
6900
6980
  const incomingTransfer = {
6901
6981
  id: transfer.id,
6902
6982
  senderPubkey: transfer.senderTransportPubkey,
6983
+ senderNametag: senderInfo.senderNametag,
6903
6984
  tokens: [token],
6904
6985
  memo: payload.memo,
6905
6986
  receivedAt: transfer.timestamp
6906
6987
  };
6907
6988
  this.deps.emitEvent("transfer:incoming", incomingTransfer);
6989
+ await this.addToHistory({
6990
+ type: "RECEIVED",
6991
+ amount: token.amount,
6992
+ coinId: token.coinId,
6993
+ symbol: token.symbol,
6994
+ timestamp: Date.now(),
6995
+ senderPubkey: transfer.senderTransportPubkey,
6996
+ ...senderInfo,
6997
+ memo: payload.memo,
6998
+ tokenId: nostrTokenId || token.id
6999
+ });
6908
7000
  try {
6909
7001
  const commitment = await import_TransferCommitment4.TransferCommitment.fromJSON(commitmentInput);
6910
7002
  const requestIdBytes = commitment.requestId;
@@ -6922,7 +7014,7 @@ var PaymentsModule = class _PaymentsModule {
6922
7014
  attemptCount: 0,
6923
7015
  lastAttemptAt: 0,
6924
7016
  onProofReceived: async (tokenId) => {
6925
- await this.finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput, transfer.senderTransportPubkey);
7017
+ await this.finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput);
6926
7018
  }
6927
7019
  });
6928
7020
  } catch (err) {
@@ -6981,7 +7073,7 @@ var PaymentsModule = class _PaymentsModule {
6981
7073
  /**
6982
7074
  * Finalize a received token after proof is available
6983
7075
  */
6984
- async finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput, senderPubkey) {
7076
+ async finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput) {
6985
7077
  try {
6986
7078
  const token = this.tokens.get(tokenId);
6987
7079
  if (!token) {
@@ -7029,14 +7121,6 @@ var PaymentsModule = class _PaymentsModule {
7029
7121
  tokens: [finalizedToken],
7030
7122
  tokenTransfers: []
7031
7123
  });
7032
- await this.addToHistory({
7033
- type: "RECEIVED",
7034
- amount: finalizedToken.amount,
7035
- coinId: finalizedToken.coinId,
7036
- symbol: finalizedToken.symbol,
7037
- timestamp: Date.now(),
7038
- senderPubkey
7039
- });
7040
7124
  } catch (error) {
7041
7125
  console.error("[Payments] Failed to finalize received token:", error);
7042
7126
  const token = this.tokens.get(tokenId);
@@ -7067,7 +7151,8 @@ var PaymentsModule = class _PaymentsModule {
7067
7151
  try {
7068
7152
  const result = await this.processInstantSplitBundle(
7069
7153
  instantBundle,
7070
- transfer.senderTransportPubkey
7154
+ transfer.senderTransportPubkey,
7155
+ payload.memo
7071
7156
  );
7072
7157
  if (result.success) {
7073
7158
  this.log("INSTANT_SPLIT processed successfully");
@@ -7185,10 +7270,26 @@ var PaymentsModule = class _PaymentsModule {
7185
7270
  updatedAt: Date.now(),
7186
7271
  sdkData: typeof tokenData === "string" ? tokenData : JSON.stringify(tokenData)
7187
7272
  };
7188
- await this.addToken(token);
7273
+ const added = await this.addToken(token);
7274
+ const senderInfo = await this.resolveSenderInfo(transfer.senderTransportPubkey);
7275
+ if (added) {
7276
+ const incomingTokenId = extractTokenIdFromSdkData(token.sdkData);
7277
+ await this.addToHistory({
7278
+ type: "RECEIVED",
7279
+ amount: token.amount,
7280
+ coinId: token.coinId,
7281
+ symbol: token.symbol,
7282
+ timestamp: Date.now(),
7283
+ senderPubkey: transfer.senderTransportPubkey,
7284
+ ...senderInfo,
7285
+ memo: payload.memo,
7286
+ tokenId: incomingTokenId || token.id
7287
+ });
7288
+ }
7189
7289
  const incomingTransfer = {
7190
7290
  id: transfer.id,
7191
7291
  senderPubkey: transfer.senderTransportPubkey,
7292
+ senderNametag: senderInfo.senderNametag,
7192
7293
  tokens: [token],
7193
7294
  memo: payload.memo,
7194
7295
  receivedAt: transfer.timestamp