@unicitylabs/sphere-sdk 0.6.2 → 0.6.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/dist/core/index.cjs +1351 -52
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +342 -3
- package/dist/core/index.d.ts +342 -3
- package/dist/core/index.js +1357 -48
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +109 -11
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +109 -11
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +38 -10
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +38 -10
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +105 -11
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +43 -0
- package/dist/impl/nodejs/index.d.ts +43 -0
- package/dist/impl/nodejs/index.js +105 -11
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +1334 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +1333 -50
- package/dist/index.js.map +1 -1
- package/dist/l1/index.d.cts +717 -0
- package/dist/l1/index.d.ts +717 -0
- package/package.json +1 -1
|
@@ -818,7 +818,7 @@ var STORE_TOKENS = "tokens";
|
|
|
818
818
|
var STORE_META = "meta";
|
|
819
819
|
var STORE_HISTORY = "history";
|
|
820
820
|
var connectionSeq2 = 0;
|
|
821
|
-
var IndexedDBTokenStorageProvider = class {
|
|
821
|
+
var IndexedDBTokenStorageProvider = class _IndexedDBTokenStorageProvider {
|
|
822
822
|
id = "indexeddb-token-storage";
|
|
823
823
|
name = "IndexedDB Token Storage";
|
|
824
824
|
type = "local";
|
|
@@ -1266,6 +1266,16 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
1266
1266
|
db.close();
|
|
1267
1267
|
}
|
|
1268
1268
|
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Create an independent instance for a different address.
|
|
1271
|
+
* The new instance shares the same config but has its own IDB connection.
|
|
1272
|
+
*/
|
|
1273
|
+
createForAddress() {
|
|
1274
|
+
return new _IndexedDBTokenStorageProvider({
|
|
1275
|
+
dbNamePrefix: this.dbNamePrefix,
|
|
1276
|
+
debug: this.debug
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1269
1279
|
};
|
|
1270
1280
|
function createIndexedDBTokenStorageProvider(config) {
|
|
1271
1281
|
return new IndexedDBTokenStorageProvider(config);
|
|
@@ -1682,6 +1692,8 @@ var NostrTransportProvider = class {
|
|
|
1682
1692
|
storage = null;
|
|
1683
1693
|
/** In-memory max event timestamp to avoid read-before-write races in updateLastEventTimestamp. */
|
|
1684
1694
|
lastEventTs = 0;
|
|
1695
|
+
/** Fallback 'since' timestamp for first-time address subscriptions (consumed once). */
|
|
1696
|
+
fallbackSince = null;
|
|
1685
1697
|
identity = null;
|
|
1686
1698
|
keyManager = null;
|
|
1687
1699
|
status = "disconnected";
|
|
@@ -1714,6 +1726,48 @@ var NostrTransportProvider = class {
|
|
|
1714
1726
|
};
|
|
1715
1727
|
this.storage = config.storage ?? null;
|
|
1716
1728
|
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Get the WebSocket factory (used by MultiAddressTransportMux to share the same factory).
|
|
1731
|
+
*/
|
|
1732
|
+
getWebSocketFactory() {
|
|
1733
|
+
return this.config.createWebSocket;
|
|
1734
|
+
}
|
|
1735
|
+
/**
|
|
1736
|
+
* Get the configured relay URLs.
|
|
1737
|
+
*/
|
|
1738
|
+
getConfiguredRelays() {
|
|
1739
|
+
return [...this.config.relays];
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* Get the storage adapter.
|
|
1743
|
+
*/
|
|
1744
|
+
getStorageAdapter() {
|
|
1745
|
+
return this.storage;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Suppress event subscriptions — unsubscribe wallet/chat filters
|
|
1749
|
+
* but keep the connection alive for resolve/identity-binding operations.
|
|
1750
|
+
* Used when MultiAddressTransportMux takes over event handling.
|
|
1751
|
+
*/
|
|
1752
|
+
suppressSubscriptions() {
|
|
1753
|
+
if (!this.nostrClient) return;
|
|
1754
|
+
if (this.walletSubscriptionId) {
|
|
1755
|
+
this.nostrClient.unsubscribe(this.walletSubscriptionId);
|
|
1756
|
+
this.walletSubscriptionId = null;
|
|
1757
|
+
}
|
|
1758
|
+
if (this.chatSubscriptionId) {
|
|
1759
|
+
this.nostrClient.unsubscribe(this.chatSubscriptionId);
|
|
1760
|
+
this.chatSubscriptionId = null;
|
|
1761
|
+
}
|
|
1762
|
+
if (this.mainSubscriptionId) {
|
|
1763
|
+
this.nostrClient.unsubscribe(this.mainSubscriptionId);
|
|
1764
|
+
this.mainSubscriptionId = null;
|
|
1765
|
+
}
|
|
1766
|
+
this._subscriptionsSuppressed = true;
|
|
1767
|
+
logger.debug("Nostr", "Subscriptions suppressed \u2014 mux handles event routing");
|
|
1768
|
+
}
|
|
1769
|
+
// Flag to prevent re-subscription after suppressSubscriptions()
|
|
1770
|
+
_subscriptionsSuppressed = false;
|
|
1717
1771
|
// ===========================================================================
|
|
1718
1772
|
// BaseProvider Implementation
|
|
1719
1773
|
// ===========================================================================
|
|
@@ -1892,6 +1946,8 @@ var NostrTransportProvider = class {
|
|
|
1892
1946
|
// ===========================================================================
|
|
1893
1947
|
async setIdentity(identity) {
|
|
1894
1948
|
this.identity = identity;
|
|
1949
|
+
this.processedEventIds.clear();
|
|
1950
|
+
this.lastEventTs = 0;
|
|
1895
1951
|
const secretKey = import_buffer.Buffer.from(identity.privateKey, "hex");
|
|
1896
1952
|
this.keyManager = import_nostr_js_sdk.NostrKeyManager.fromPrivateKey(secretKey);
|
|
1897
1953
|
const nostrPubkey = this.keyManager.getPublicKeyHex();
|
|
@@ -1934,6 +1990,9 @@ var NostrTransportProvider = class {
|
|
|
1934
1990
|
await this.subscribeToEvents();
|
|
1935
1991
|
}
|
|
1936
1992
|
}
|
|
1993
|
+
setFallbackSince(sinceSeconds) {
|
|
1994
|
+
this.fallbackSince = sinceSeconds;
|
|
1995
|
+
}
|
|
1937
1996
|
/**
|
|
1938
1997
|
* Get the Nostr-format public key (32 bytes / 64 hex chars)
|
|
1939
1998
|
* This is the x-coordinate only, without the 02/03 prefix.
|
|
@@ -2841,6 +2900,10 @@ var NostrTransportProvider = class {
|
|
|
2841
2900
|
chatEoseFired = false;
|
|
2842
2901
|
async subscribeToEvents() {
|
|
2843
2902
|
logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
|
|
2903
|
+
if (this._subscriptionsSuppressed) {
|
|
2904
|
+
logger.debug("Nostr", "subscribeToEvents: suppressed \u2014 mux handles event routing");
|
|
2905
|
+
return;
|
|
2906
|
+
}
|
|
2844
2907
|
if (!this.identity || !this.keyManager || !this.nostrClient) {
|
|
2845
2908
|
logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
|
|
2846
2909
|
return;
|
|
@@ -2867,7 +2930,13 @@ var NostrTransportProvider = class {
|
|
|
2867
2930
|
if (stored) {
|
|
2868
2931
|
since = parseInt(stored, 10);
|
|
2869
2932
|
this.lastEventTs = since;
|
|
2933
|
+
this.fallbackSince = null;
|
|
2870
2934
|
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
2935
|
+
} else if (this.fallbackSince !== null) {
|
|
2936
|
+
since = this.fallbackSince;
|
|
2937
|
+
this.lastEventTs = since;
|
|
2938
|
+
this.fallbackSince = null;
|
|
2939
|
+
logger.debug("Nostr", "Using fallback since timestamp:", since);
|
|
2871
2940
|
} else {
|
|
2872
2941
|
since = Math.floor(Date.now() / 1e3);
|
|
2873
2942
|
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
@@ -2875,6 +2944,7 @@ var NostrTransportProvider = class {
|
|
|
2875
2944
|
} catch (err) {
|
|
2876
2945
|
logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
|
|
2877
2946
|
since = Math.floor(Date.now() / 1e3);
|
|
2947
|
+
this.fallbackSince = null;
|
|
2878
2948
|
}
|
|
2879
2949
|
} else {
|
|
2880
2950
|
since = Math.floor(Date.now() / 1e3) - 86400;
|
|
@@ -4895,11 +4965,17 @@ var AsyncSerialQueue = class {
|
|
|
4895
4965
|
var WriteBuffer = class {
|
|
4896
4966
|
/** Full TXF data from save() calls — latest wins */
|
|
4897
4967
|
txfData = null;
|
|
4968
|
+
/** IPNS context captured at save() time — ensures flush writes to the correct
|
|
4969
|
+
* IPNS record even if identity changes between save() and flush(). */
|
|
4970
|
+
capturedIpnsKeyPair = null;
|
|
4971
|
+
capturedIpnsName = null;
|
|
4898
4972
|
get isEmpty() {
|
|
4899
4973
|
return this.txfData === null;
|
|
4900
4974
|
}
|
|
4901
4975
|
clear() {
|
|
4902
4976
|
this.txfData = null;
|
|
4977
|
+
this.capturedIpnsKeyPair = null;
|
|
4978
|
+
this.capturedIpnsName = null;
|
|
4903
4979
|
}
|
|
4904
4980
|
/**
|
|
4905
4981
|
* Merge another buffer's contents into this one (for rollback).
|
|
@@ -4908,12 +4984,14 @@ var WriteBuffer = class {
|
|
|
4908
4984
|
mergeFrom(other) {
|
|
4909
4985
|
if (other.txfData && !this.txfData) {
|
|
4910
4986
|
this.txfData = other.txfData;
|
|
4987
|
+
this.capturedIpnsKeyPair = other.capturedIpnsKeyPair;
|
|
4988
|
+
this.capturedIpnsName = other.capturedIpnsName;
|
|
4911
4989
|
}
|
|
4912
4990
|
}
|
|
4913
4991
|
};
|
|
4914
4992
|
|
|
4915
4993
|
// impl/shared/ipfs/ipfs-storage-provider.ts
|
|
4916
|
-
var IpfsStorageProvider = class {
|
|
4994
|
+
var IpfsStorageProvider = class _IpfsStorageProvider {
|
|
4917
4995
|
id = "ipfs";
|
|
4918
4996
|
name = "IPFS Storage";
|
|
4919
4997
|
type = "p2p";
|
|
@@ -4958,7 +5036,12 @@ var IpfsStorageProvider = class {
|
|
|
4958
5036
|
flushDebounceMs;
|
|
4959
5037
|
/** Set to true during shutdown to prevent new flushes */
|
|
4960
5038
|
isShuttingDown = false;
|
|
5039
|
+
/** Stored config for createForAddress() cloning */
|
|
5040
|
+
_config;
|
|
5041
|
+
_statePersistenceCtor;
|
|
4961
5042
|
constructor(config, statePersistence) {
|
|
5043
|
+
this._config = config;
|
|
5044
|
+
this._statePersistenceCtor = statePersistence;
|
|
4962
5045
|
const gateways = config?.gateways ?? getIpfsGatewayUrls();
|
|
4963
5046
|
this.debug = config?.debug ?? false;
|
|
4964
5047
|
this.ipnsLifetimeMs = config?.ipnsLifetimeMs ?? 99 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -5078,6 +5161,7 @@ var IpfsStorageProvider = class {
|
|
|
5078
5161
|
}
|
|
5079
5162
|
async shutdown() {
|
|
5080
5163
|
this.isShuttingDown = true;
|
|
5164
|
+
logger.debug("IPFS-Storage", `shutdown: ipnsName=${this.ipnsName?.slice(0, 20)}..., pendingEmpty=${this.pendingBuffer.isEmpty}, capturedIpns=${this.pendingBuffer.capturedIpnsName?.slice(0, 20) ?? "none"}`);
|
|
5081
5165
|
if (this.flushTimer) {
|
|
5082
5166
|
clearTimeout(this.flushTimer);
|
|
5083
5167
|
this.flushTimer = null;
|
|
@@ -5110,6 +5194,8 @@ var IpfsStorageProvider = class {
|
|
|
5110
5194
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5111
5195
|
}
|
|
5112
5196
|
this.pendingBuffer.txfData = data;
|
|
5197
|
+
this.pendingBuffer.capturedIpnsKeyPair = this.ipnsKeyPair;
|
|
5198
|
+
this.pendingBuffer.capturedIpnsName = this.ipnsName;
|
|
5113
5199
|
this.scheduleFlush();
|
|
5114
5200
|
return { success: true, timestamp: Date.now() };
|
|
5115
5201
|
}
|
|
@@ -5120,8 +5206,12 @@ var IpfsStorageProvider = class {
|
|
|
5120
5206
|
* Perform the actual upload + IPNS publish synchronously.
|
|
5121
5207
|
* Called by executeFlush() and sync() — never by public save().
|
|
5122
5208
|
*/
|
|
5123
|
-
async _doSave(data) {
|
|
5124
|
-
|
|
5209
|
+
async _doSave(data, overrideIpns) {
|
|
5210
|
+
const ipnsKeyPair = overrideIpns?.keyPair ?? this.ipnsKeyPair;
|
|
5211
|
+
const ipnsName = overrideIpns?.name ?? this.ipnsName;
|
|
5212
|
+
const metaAddr = data?._meta?.address;
|
|
5213
|
+
logger.debug("IPFS-Storage", `_doSave: ipnsName=${ipnsName?.slice(0, 20)}..., override=${!!overrideIpns}, meta.address=${metaAddr?.slice(0, 20) ?? "none"}`);
|
|
5214
|
+
if (!ipnsKeyPair || !ipnsName) {
|
|
5125
5215
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5126
5216
|
}
|
|
5127
5217
|
this.emitEvent({ type: "storage:saving", timestamp: Date.now() });
|
|
@@ -5130,7 +5220,7 @@ var IpfsStorageProvider = class {
|
|
|
5130
5220
|
const metaUpdate = {
|
|
5131
5221
|
...data._meta,
|
|
5132
5222
|
version: this.dataVersion,
|
|
5133
|
-
ipnsName
|
|
5223
|
+
ipnsName,
|
|
5134
5224
|
updatedAt: Date.now()
|
|
5135
5225
|
};
|
|
5136
5226
|
if (this.remoteCid) {
|
|
@@ -5142,13 +5232,13 @@ var IpfsStorageProvider = class {
|
|
|
5142
5232
|
const baseSeq = this.ipnsSequenceNumber > this.lastKnownRemoteSequence ? this.ipnsSequenceNumber : this.lastKnownRemoteSequence;
|
|
5143
5233
|
const newSeq = baseSeq + 1n;
|
|
5144
5234
|
const marshalledRecord = await createSignedRecord(
|
|
5145
|
-
|
|
5235
|
+
ipnsKeyPair,
|
|
5146
5236
|
cid,
|
|
5147
5237
|
newSeq,
|
|
5148
5238
|
this.ipnsLifetimeMs
|
|
5149
5239
|
);
|
|
5150
5240
|
const publishResult = await this.httpClient.publishIpns(
|
|
5151
|
-
|
|
5241
|
+
ipnsName,
|
|
5152
5242
|
marshalledRecord
|
|
5153
5243
|
);
|
|
5154
5244
|
if (!publishResult.success) {
|
|
@@ -5163,14 +5253,14 @@ var IpfsStorageProvider = class {
|
|
|
5163
5253
|
this.ipnsSequenceNumber = newSeq;
|
|
5164
5254
|
this.lastCid = cid;
|
|
5165
5255
|
this.remoteCid = cid;
|
|
5166
|
-
this.cache.setIpnsRecord(
|
|
5256
|
+
this.cache.setIpnsRecord(ipnsName, {
|
|
5167
5257
|
cid,
|
|
5168
5258
|
sequence: newSeq,
|
|
5169
5259
|
gateway: "local"
|
|
5170
5260
|
});
|
|
5171
5261
|
this.cache.setContent(cid, updatedData);
|
|
5172
|
-
this.cache.markIpnsFresh(
|
|
5173
|
-
await this.statePersistence.save(
|
|
5262
|
+
this.cache.markIpnsFresh(ipnsName);
|
|
5263
|
+
await this.statePersistence.save(ipnsName, {
|
|
5174
5264
|
sequenceNumber: newSeq.toString(),
|
|
5175
5265
|
lastCid: cid,
|
|
5176
5266
|
version: this.dataVersion
|
|
@@ -5222,7 +5312,8 @@ var IpfsStorageProvider = class {
|
|
|
5222
5312
|
const baseData = active.txfData ?? {
|
|
5223
5313
|
_meta: { version: 0, address: this.identity?.directAddress ?? "", formatVersion: "2.0", updatedAt: 0 }
|
|
5224
5314
|
};
|
|
5225
|
-
const
|
|
5315
|
+
const overrideIpns = active.capturedIpnsKeyPair && active.capturedIpnsName ? { keyPair: active.capturedIpnsKeyPair, name: active.capturedIpnsName } : void 0;
|
|
5316
|
+
const result = await this._doSave(baseData, overrideIpns);
|
|
5226
5317
|
if (!result.success) {
|
|
5227
5318
|
throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
|
|
5228
5319
|
}
|
|
@@ -5525,6 +5616,13 @@ var IpfsStorageProvider = class {
|
|
|
5525
5616
|
log(message) {
|
|
5526
5617
|
logger.debug("IPFS-Storage", message);
|
|
5527
5618
|
}
|
|
5619
|
+
/**
|
|
5620
|
+
* Create an independent instance for a different address.
|
|
5621
|
+
* Shares the same gateway/timeout config but has fresh IPNS state.
|
|
5622
|
+
*/
|
|
5623
|
+
createForAddress() {
|
|
5624
|
+
return new _IpfsStorageProvider(this._config, this._statePersistenceCtor);
|
|
5625
|
+
}
|
|
5528
5626
|
};
|
|
5529
5627
|
|
|
5530
5628
|
// impl/browser/ipfs/browser-ipfs-state-persistence.ts
|