@unicitylabs/sphere-sdk 0.4.8 → 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.
- package/dist/core/index.cjs +183 -80
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +222 -194
- package/dist/core/index.d.ts +222 -194
- package/dist/core/index.js +183 -80
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +64 -2
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +64 -2
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +61 -4
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +668 -628
- package/dist/impl/nodejs/index.d.ts +668 -628
- package/dist/impl/nodejs/index.js +61 -4
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +183 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +222 -194
- package/dist/index.d.ts +222 -194
- package/dist/index.js +183 -80
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +2 -0
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +2 -0
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.cjs
CHANGED
|
@@ -610,6 +610,8 @@ function disconnect() {
|
|
|
610
610
|
if (cb.timeoutId) clearTimeout(cb.timeoutId);
|
|
611
611
|
});
|
|
612
612
|
connectionCallbacks.length = 0;
|
|
613
|
+
blockSubscribers.length = 0;
|
|
614
|
+
lastBlockHeader = null;
|
|
613
615
|
}
|
|
614
616
|
var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT;
|
|
615
617
|
var init_network = __esm({
|
|
@@ -3511,7 +3513,7 @@ var InstantSplitExecutor = class {
|
|
|
3511
3513
|
token: JSON.stringify(bundle),
|
|
3512
3514
|
proof: null,
|
|
3513
3515
|
// Proof is included in the bundle
|
|
3514
|
-
memo:
|
|
3516
|
+
memo: options?.memo,
|
|
3515
3517
|
sender: {
|
|
3516
3518
|
transportPubkey: senderPubkey
|
|
3517
3519
|
}
|
|
@@ -4070,6 +4072,11 @@ var import_MintCommitment3 = require("@unicitylabs/state-transition-sdk/lib/tran
|
|
|
4070
4072
|
var import_MintTransactionData3 = require("@unicitylabs/state-transition-sdk/lib/transaction/MintTransactionData");
|
|
4071
4073
|
var import_InclusionProofUtils5 = require("@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils");
|
|
4072
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
|
+
}
|
|
4073
4080
|
function enrichWithRegistry(info) {
|
|
4074
4081
|
const registry = TokenRegistry.getInstance();
|
|
4075
4082
|
const def = registry.getDefinition(info.coinId);
|
|
@@ -4368,7 +4375,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4368
4375
|
tombstones = [];
|
|
4369
4376
|
archivedTokens = /* @__PURE__ */ new Map();
|
|
4370
4377
|
forkedTokens = /* @__PURE__ */ new Map();
|
|
4371
|
-
|
|
4378
|
+
_historyCache = [];
|
|
4372
4379
|
nametags = [];
|
|
4373
4380
|
// Payment Requests State (Incoming)
|
|
4374
4381
|
paymentRequests = [];
|
|
@@ -4437,7 +4444,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4437
4444
|
this.tombstones = [];
|
|
4438
4445
|
this.archivedTokens.clear();
|
|
4439
4446
|
this.forkedTokens.clear();
|
|
4440
|
-
this.
|
|
4447
|
+
this._historyCache = [];
|
|
4441
4448
|
this.nametags = [];
|
|
4442
4449
|
this.deps = deps;
|
|
4443
4450
|
this.priceProvider = deps.price ?? null;
|
|
@@ -4488,14 +4495,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4488
4495
|
}
|
|
4489
4496
|
}
|
|
4490
4497
|
await this.loadPendingV5Tokens();
|
|
4491
|
-
|
|
4492
|
-
if (historyData) {
|
|
4493
|
-
try {
|
|
4494
|
-
this.transactionHistory = JSON.parse(historyData);
|
|
4495
|
-
} catch {
|
|
4496
|
-
this.transactionHistory = [];
|
|
4497
|
-
}
|
|
4498
|
-
}
|
|
4498
|
+
await this.loadHistory();
|
|
4499
4499
|
const pending2 = await this.deps.storage.get(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
|
|
4500
4500
|
if (pending2) {
|
|
4501
4501
|
const transfers = JSON.parse(pending2);
|
|
@@ -4582,7 +4582,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4582
4582
|
}
|
|
4583
4583
|
await this.saveToOutbox(result, recipientPubkey);
|
|
4584
4584
|
result.status = "submitted";
|
|
4585
|
-
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);
|
|
4586
4586
|
const transferMode = request.transferMode ?? "instant";
|
|
4587
4587
|
if (splitPlan.requiresSplit && splitPlan.tokenToSplit) {
|
|
4588
4588
|
if (transferMode === "conservative") {
|
|
@@ -4613,7 +4613,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4613
4613
|
updatedAt: Date.now(),
|
|
4614
4614
|
sdkData: JSON.stringify(changeTokenData)
|
|
4615
4615
|
};
|
|
4616
|
-
await this.addToken(changeUiToken
|
|
4616
|
+
await this.addToken(changeUiToken);
|
|
4617
4617
|
this.log(`Conservative split: change token saved: ${changeUiToken.id}`);
|
|
4618
4618
|
await this.deps.transport.sendTokenTransfer(recipientPubkey, {
|
|
4619
4619
|
sourceToken: JSON.stringify(splitResult.tokenForRecipient.toJSON()),
|
|
@@ -4622,7 +4622,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4622
4622
|
});
|
|
4623
4623
|
const splitCommitmentRequestId = splitResult.recipientTransferTx?.data?.requestId ?? splitResult.recipientTransferTx?.requestId;
|
|
4624
4624
|
const splitRequestIdHex = splitCommitmentRequestId instanceof Uint8Array ? Array.from(splitCommitmentRequestId).map((b) => b.toString(16).padStart(2, "0")).join("") : splitCommitmentRequestId ? String(splitCommitmentRequestId) : void 0;
|
|
4625
|
-
await this.removeToken(splitPlan.tokenToSplit.uiToken.id
|
|
4625
|
+
await this.removeToken(splitPlan.tokenToSplit.uiToken.id);
|
|
4626
4626
|
result.tokenTransfers.push({
|
|
4627
4627
|
sourceTokenId: splitPlan.tokenToSplit.uiToken.id,
|
|
4628
4628
|
method: "split",
|
|
@@ -4647,6 +4647,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4647
4647
|
this.deps.transport,
|
|
4648
4648
|
recipientPubkey,
|
|
4649
4649
|
{
|
|
4650
|
+
memo: request.memo,
|
|
4650
4651
|
onChangeTokenCreated: async (changeToken) => {
|
|
4651
4652
|
const changeTokenData = changeToken.toJSON();
|
|
4652
4653
|
const uiToken = {
|
|
@@ -4662,7 +4663,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4662
4663
|
updatedAt: Date.now(),
|
|
4663
4664
|
sdkData: JSON.stringify(changeTokenData)
|
|
4664
4665
|
};
|
|
4665
|
-
await this.addToken(uiToken
|
|
4666
|
+
await this.addToken(uiToken);
|
|
4666
4667
|
this.log(`Change token saved via background: ${uiToken.id}`);
|
|
4667
4668
|
},
|
|
4668
4669
|
onStorageSync: async () => {
|
|
@@ -4677,7 +4678,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4677
4678
|
if (instantResult.backgroundPromise) {
|
|
4678
4679
|
this.pendingBackgroundTasks.push(instantResult.backgroundPromise);
|
|
4679
4680
|
}
|
|
4680
|
-
await this.removeToken(splitPlan.tokenToSplit.uiToken.id
|
|
4681
|
+
await this.removeToken(splitPlan.tokenToSplit.uiToken.id);
|
|
4681
4682
|
result.tokenTransfers.push({
|
|
4682
4683
|
sourceTokenId: splitPlan.tokenToSplit.uiToken.id,
|
|
4683
4684
|
method: "split",
|
|
@@ -4724,20 +4725,25 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4724
4725
|
requestIdHex
|
|
4725
4726
|
});
|
|
4726
4727
|
this.log(`Token ${token.id} sent via ${transferMode.toUpperCase()}, requestId: ${requestIdHex}`);
|
|
4727
|
-
await this.removeToken(token.id
|
|
4728
|
+
await this.removeToken(token.id);
|
|
4728
4729
|
}
|
|
4729
4730
|
result.status = "delivered";
|
|
4730
4731
|
await this.save();
|
|
4731
4732
|
await this.removeFromOutbox(result.id);
|
|
4732
4733
|
result.status = "completed";
|
|
4734
|
+
const sentTokenId = result.tokens[0] ? extractTokenIdFromSdkData(result.tokens[0].sdkData) : void 0;
|
|
4733
4735
|
await this.addToHistory({
|
|
4734
4736
|
type: "SENT",
|
|
4735
4737
|
amount: request.amount,
|
|
4736
4738
|
coinId: request.coinId,
|
|
4737
4739
|
symbol: this.getCoinSymbol(request.coinId),
|
|
4738
4740
|
timestamp: Date.now(),
|
|
4741
|
+
recipientPubkey,
|
|
4739
4742
|
recipientNametag,
|
|
4740
|
-
|
|
4743
|
+
recipientAddress: peerInfo?.directAddress || recipientAddress?.toString() || recipientPubkey,
|
|
4744
|
+
memo: request.memo,
|
|
4745
|
+
transferId: result.id,
|
|
4746
|
+
tokenId: sentTokenId || void 0
|
|
4741
4747
|
});
|
|
4742
4748
|
this.deps.emitEvent("transfer:confirmed", result);
|
|
4743
4749
|
return result;
|
|
@@ -4848,6 +4854,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4848
4854
|
recipientPubkey,
|
|
4849
4855
|
{
|
|
4850
4856
|
...options,
|
|
4857
|
+
memo: request.memo,
|
|
4851
4858
|
onChangeTokenCreated: async (changeToken) => {
|
|
4852
4859
|
const changeTokenData = changeToken.toJSON();
|
|
4853
4860
|
const uiToken = {
|
|
@@ -4863,7 +4870,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4863
4870
|
updatedAt: Date.now(),
|
|
4864
4871
|
sdkData: JSON.stringify(changeTokenData)
|
|
4865
4872
|
};
|
|
4866
|
-
await this.addToken(uiToken
|
|
4873
|
+
await this.addToken(uiToken);
|
|
4867
4874
|
this.log(`Change token saved via background: ${uiToken.id}`);
|
|
4868
4875
|
},
|
|
4869
4876
|
onStorageSync: async () => {
|
|
@@ -4876,15 +4883,20 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4876
4883
|
if (result.backgroundPromise) {
|
|
4877
4884
|
this.pendingBackgroundTasks.push(result.backgroundPromise);
|
|
4878
4885
|
}
|
|
4879
|
-
|
|
4880
|
-
|
|
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);
|
|
4881
4889
|
await this.addToHistory({
|
|
4882
4890
|
type: "SENT",
|
|
4883
4891
|
amount: request.amount,
|
|
4884
4892
|
coinId: request.coinId,
|
|
4885
4893
|
symbol: this.getCoinSymbol(request.coinId),
|
|
4886
4894
|
timestamp: Date.now(),
|
|
4887
|
-
|
|
4895
|
+
recipientPubkey,
|
|
4896
|
+
recipientNametag,
|
|
4897
|
+
recipientAddress: peerInfo?.directAddress || recipientAddress?.toString() || recipientPubkey,
|
|
4898
|
+
memo: request.memo,
|
|
4899
|
+
tokenId: splitTokenId || void 0
|
|
4888
4900
|
});
|
|
4889
4901
|
await this.save();
|
|
4890
4902
|
} else {
|
|
@@ -4915,10 +4927,10 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4915
4927
|
* @param senderPubkey - Sender's public key for verification
|
|
4916
4928
|
* @returns Processing result with finalized token
|
|
4917
4929
|
*/
|
|
4918
|
-
async processInstantSplitBundle(bundle, senderPubkey) {
|
|
4930
|
+
async processInstantSplitBundle(bundle, senderPubkey, memo) {
|
|
4919
4931
|
this.ensureInitialized();
|
|
4920
4932
|
if (!isInstantSplitBundleV5(bundle)) {
|
|
4921
|
-
return this.processInstantSplitBundleSync(bundle, senderPubkey);
|
|
4933
|
+
return this.processInstantSplitBundleSync(bundle, senderPubkey, memo);
|
|
4922
4934
|
}
|
|
4923
4935
|
try {
|
|
4924
4936
|
const deterministicId = `v5split_${bundle.splitGroupId}`;
|
|
@@ -4948,12 +4960,26 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4948
4960
|
updatedAt: Date.now(),
|
|
4949
4961
|
sdkData: JSON.stringify({ _pendingFinalization: pendingData })
|
|
4950
4962
|
};
|
|
4951
|
-
await this.addToken(uiToken
|
|
4963
|
+
await this.addToken(uiToken);
|
|
4952
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
|
+
});
|
|
4953
4977
|
this.deps.emitEvent("transfer:incoming", {
|
|
4954
4978
|
id: bundle.splitGroupId,
|
|
4955
4979
|
senderPubkey,
|
|
4980
|
+
senderNametag: senderInfo.senderNametag,
|
|
4956
4981
|
tokens: [uiToken],
|
|
4982
|
+
memo,
|
|
4957
4983
|
receivedAt: Date.now()
|
|
4958
4984
|
});
|
|
4959
4985
|
await this.save();
|
|
@@ -4973,7 +4999,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4973
4999
|
* Synchronous V4 bundle processing (dev mode only).
|
|
4974
5000
|
* Kept for backward compatibility with V4 bundles.
|
|
4975
5001
|
*/
|
|
4976
|
-
async processInstantSplitBundleSync(bundle, senderPubkey) {
|
|
5002
|
+
async processInstantSplitBundleSync(bundle, senderPubkey, memo) {
|
|
4977
5003
|
try {
|
|
4978
5004
|
const signingService = await this.createSigningService();
|
|
4979
5005
|
const stClient = this.deps.oracle.getStateTransitionClient?.();
|
|
@@ -5033,19 +5059,26 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5033
5059
|
sdkData: JSON.stringify(tokenData)
|
|
5034
5060
|
};
|
|
5035
5061
|
await this.addToken(uiToken);
|
|
5062
|
+
const receivedTokenId = extractTokenIdFromSdkData(uiToken.sdkData);
|
|
5063
|
+
const senderInfo = await this.resolveSenderInfo(senderPubkey);
|
|
5036
5064
|
await this.addToHistory({
|
|
5037
5065
|
type: "RECEIVED",
|
|
5038
5066
|
amount: bundle.amount,
|
|
5039
5067
|
coinId: info.coinId,
|
|
5040
5068
|
symbol: info.symbol,
|
|
5041
5069
|
timestamp: Date.now(),
|
|
5042
|
-
senderPubkey
|
|
5070
|
+
senderPubkey,
|
|
5071
|
+
...senderInfo,
|
|
5072
|
+
memo,
|
|
5073
|
+
tokenId: receivedTokenId || uiToken.id
|
|
5043
5074
|
});
|
|
5044
5075
|
await this.save();
|
|
5045
5076
|
this.deps.emitEvent("transfer:incoming", {
|
|
5046
5077
|
id: bundle.splitGroupId,
|
|
5047
5078
|
senderPubkey,
|
|
5079
|
+
senderNametag: senderInfo.senderNametag,
|
|
5048
5080
|
tokens: [uiToken],
|
|
5081
|
+
memo,
|
|
5049
5082
|
receivedAt: Date.now()
|
|
5050
5083
|
});
|
|
5051
5084
|
}
|
|
@@ -5788,14 +5821,6 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5788
5821
|
sdkData: JSON.stringify(finalizedToken.toJSON())
|
|
5789
5822
|
};
|
|
5790
5823
|
this.tokens.set(tokenId, confirmedToken);
|
|
5791
|
-
await this.addToHistory({
|
|
5792
|
-
type: "RECEIVED",
|
|
5793
|
-
amount: confirmedToken.amount,
|
|
5794
|
-
coinId: confirmedToken.coinId,
|
|
5795
|
-
symbol: confirmedToken.symbol || "UNK",
|
|
5796
|
-
timestamp: Date.now(),
|
|
5797
|
-
senderPubkey: pending2.senderPubkey
|
|
5798
|
-
});
|
|
5799
5824
|
this.log(`V5 token resolved: ${tokenId.slice(0, 8)}...`);
|
|
5800
5825
|
return "resolved";
|
|
5801
5826
|
}
|
|
@@ -5979,10 +6004,9 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5979
6004
|
* the old state is archived and replaced with the incoming one.
|
|
5980
6005
|
*
|
|
5981
6006
|
* @param token - The token to add.
|
|
5982
|
-
* @param skipHistory - When `true`, do not create a `RECEIVED` transaction history entry (default `false`).
|
|
5983
6007
|
* @returns `true` if the token was added, `false` if rejected as duplicate or tombstoned.
|
|
5984
6008
|
*/
|
|
5985
|
-
async addToken(token
|
|
6009
|
+
async addToken(token) {
|
|
5986
6010
|
this.ensureInitialized();
|
|
5987
6011
|
const incomingTokenId = extractTokenIdFromSdkData(token.sdkData);
|
|
5988
6012
|
const incomingStateHash = extractStateHashFromSdkData(token.sdkData);
|
|
@@ -6028,15 +6052,6 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6028
6052
|
}
|
|
6029
6053
|
this.tokens.set(token.id, token);
|
|
6030
6054
|
await this.archiveToken(token);
|
|
6031
|
-
if (!skipHistory && token.coinId && token.amount) {
|
|
6032
|
-
await this.addToHistory({
|
|
6033
|
-
type: "RECEIVED",
|
|
6034
|
-
amount: token.amount,
|
|
6035
|
-
coinId: token.coinId,
|
|
6036
|
-
symbol: token.symbol || "UNK",
|
|
6037
|
-
timestamp: token.createdAt || Date.now()
|
|
6038
|
-
});
|
|
6039
|
-
}
|
|
6040
6055
|
await this.save();
|
|
6041
6056
|
this.log(`Added token ${token.id}, total: ${this.tokens.size}`);
|
|
6042
6057
|
return true;
|
|
@@ -6063,7 +6078,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6063
6078
|
}
|
|
6064
6079
|
}
|
|
6065
6080
|
if (!found) {
|
|
6066
|
-
await this.addToken(token
|
|
6081
|
+
await this.addToken(token);
|
|
6067
6082
|
return;
|
|
6068
6083
|
}
|
|
6069
6084
|
await this.archiveToken(token);
|
|
@@ -6078,10 +6093,8 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6078
6093
|
* entry is created unless `skipHistory` is `true`.
|
|
6079
6094
|
*
|
|
6080
6095
|
* @param tokenId - Local UUID of the token to remove.
|
|
6081
|
-
* @param recipientNametag - Optional nametag of the transfer recipient (for history).
|
|
6082
|
-
* @param skipHistory - When `true`, skip creating a transaction history entry (default `false`).
|
|
6083
6096
|
*/
|
|
6084
|
-
async removeToken(tokenId
|
|
6097
|
+
async removeToken(tokenId) {
|
|
6085
6098
|
this.ensureInitialized();
|
|
6086
6099
|
const token = this.tokens.get(tokenId);
|
|
6087
6100
|
if (!token) return;
|
|
@@ -6099,16 +6112,6 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6099
6112
|
this.log(`Warning: Could not create tombstone for token ${tokenId.slice(0, 8)}... (missing tokenId or stateHash)`);
|
|
6100
6113
|
}
|
|
6101
6114
|
this.tokens.delete(tokenId);
|
|
6102
|
-
if (!skipHistory && token.coinId && token.amount) {
|
|
6103
|
-
await this.addToHistory({
|
|
6104
|
-
type: "SENT",
|
|
6105
|
-
amount: token.amount,
|
|
6106
|
-
coinId: token.coinId,
|
|
6107
|
-
symbol: token.symbol || "UNK",
|
|
6108
|
-
timestamp: Date.now(),
|
|
6109
|
-
recipientNametag
|
|
6110
|
-
});
|
|
6111
|
-
}
|
|
6112
6115
|
await this.save();
|
|
6113
6116
|
}
|
|
6114
6117
|
// ===========================================================================
|
|
@@ -6333,26 +6336,104 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6333
6336
|
* @returns Array of {@link TransactionHistoryEntry} objects in descending timestamp order.
|
|
6334
6337
|
*/
|
|
6335
6338
|
getHistory() {
|
|
6336
|
-
return [...this.
|
|
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 {};
|
|
6337
6359
|
}
|
|
6338
6360
|
/**
|
|
6339
6361
|
* Append an entry to the transaction history.
|
|
6340
6362
|
*
|
|
6341
|
-
* A unique `id`
|
|
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).
|
|
6342
6366
|
*
|
|
6343
|
-
* @param entry - History entry fields (without `id`).
|
|
6367
|
+
* @param entry - History entry fields (without `id` and `dedupKey`).
|
|
6344
6368
|
*/
|
|
6345
6369
|
async addToHistory(entry) {
|
|
6346
6370
|
this.ensureInitialized();
|
|
6371
|
+
const dedupKey = computeHistoryDedupKey(entry.type, entry.tokenId, entry.transferId);
|
|
6347
6372
|
const historyEntry = {
|
|
6348
6373
|
id: crypto.randomUUID(),
|
|
6374
|
+
dedupKey,
|
|
6349
6375
|
...entry
|
|
6350
6376
|
};
|
|
6351
|
-
this.
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
);
|
|
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;
|
|
6356
6437
|
}
|
|
6357
6438
|
// ===========================================================================
|
|
6358
6439
|
// Public API - Nametag
|
|
@@ -6895,14 +6976,27 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6895
6976
|
this.tokens.set(token.id, token);
|
|
6896
6977
|
await this.save();
|
|
6897
6978
|
this.log(`NOSTR-FIRST: Token ${token.id.slice(0, 8)}... added as submitted (unconfirmed)`);
|
|
6979
|
+
const senderInfo = await this.resolveSenderInfo(transfer.senderTransportPubkey);
|
|
6898
6980
|
const incomingTransfer = {
|
|
6899
6981
|
id: transfer.id,
|
|
6900
6982
|
senderPubkey: transfer.senderTransportPubkey,
|
|
6983
|
+
senderNametag: senderInfo.senderNametag,
|
|
6901
6984
|
tokens: [token],
|
|
6902
6985
|
memo: payload.memo,
|
|
6903
6986
|
receivedAt: transfer.timestamp
|
|
6904
6987
|
};
|
|
6905
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
|
+
});
|
|
6906
7000
|
try {
|
|
6907
7001
|
const commitment = await import_TransferCommitment4.TransferCommitment.fromJSON(commitmentInput);
|
|
6908
7002
|
const requestIdBytes = commitment.requestId;
|
|
@@ -6920,7 +7014,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6920
7014
|
attemptCount: 0,
|
|
6921
7015
|
lastAttemptAt: 0,
|
|
6922
7016
|
onProofReceived: async (tokenId) => {
|
|
6923
|
-
await this.finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput
|
|
7017
|
+
await this.finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput);
|
|
6924
7018
|
}
|
|
6925
7019
|
});
|
|
6926
7020
|
} catch (err) {
|
|
@@ -6979,7 +7073,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
6979
7073
|
/**
|
|
6980
7074
|
* Finalize a received token after proof is available
|
|
6981
7075
|
*/
|
|
6982
|
-
async finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput
|
|
7076
|
+
async finalizeReceivedToken(tokenId, sourceTokenInput, commitmentInput) {
|
|
6983
7077
|
try {
|
|
6984
7078
|
const token = this.tokens.get(tokenId);
|
|
6985
7079
|
if (!token) {
|
|
@@ -7027,14 +7121,6 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
7027
7121
|
tokens: [finalizedToken],
|
|
7028
7122
|
tokenTransfers: []
|
|
7029
7123
|
});
|
|
7030
|
-
await this.addToHistory({
|
|
7031
|
-
type: "RECEIVED",
|
|
7032
|
-
amount: finalizedToken.amount,
|
|
7033
|
-
coinId: finalizedToken.coinId,
|
|
7034
|
-
symbol: finalizedToken.symbol,
|
|
7035
|
-
timestamp: Date.now(),
|
|
7036
|
-
senderPubkey
|
|
7037
|
-
});
|
|
7038
7124
|
} catch (error) {
|
|
7039
7125
|
console.error("[Payments] Failed to finalize received token:", error);
|
|
7040
7126
|
const token = this.tokens.get(tokenId);
|
|
@@ -7065,7 +7151,8 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
7065
7151
|
try {
|
|
7066
7152
|
const result = await this.processInstantSplitBundle(
|
|
7067
7153
|
instantBundle,
|
|
7068
|
-
transfer.senderTransportPubkey
|
|
7154
|
+
transfer.senderTransportPubkey,
|
|
7155
|
+
payload.memo
|
|
7069
7156
|
);
|
|
7070
7157
|
if (result.success) {
|
|
7071
7158
|
this.log("INSTANT_SPLIT processed successfully");
|
|
@@ -7183,10 +7270,26 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
7183
7270
|
updatedAt: Date.now(),
|
|
7184
7271
|
sdkData: typeof tokenData === "string" ? tokenData : JSON.stringify(tokenData)
|
|
7185
7272
|
};
|
|
7186
|
-
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
|
+
}
|
|
7187
7289
|
const incomingTransfer = {
|
|
7188
7290
|
id: transfer.id,
|
|
7189
7291
|
senderPubkey: transfer.senderTransportPubkey,
|
|
7292
|
+
senderNametag: senderInfo.senderNametag,
|
|
7190
7293
|
tokens: [token],
|
|
7191
7294
|
memo: payload.memo,
|
|
7192
7295
|
receivedAt: transfer.timestamp
|