@unicitylabs/sphere-sdk 0.6.2 → 0.6.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.
- package/dist/core/index.cjs +4317 -1470
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +350 -3
- package/dist/core/index.d.ts +350 -3
- package/dist/core/index.js +4321 -1452
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +154 -21
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +154 -21
- 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 +150 -21
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +55 -0
- package/dist/impl/nodejs/index.d.ts +55 -0
- package/dist/impl/nodejs/index.js +150 -21
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +4301 -1480
- 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 +4314 -1471
- 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);
|
|
@@ -1673,7 +1683,7 @@ function defaultUUIDGenerator() {
|
|
|
1673
1683
|
var COMPOSING_INDICATOR_KIND = 25050;
|
|
1674
1684
|
var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
|
|
1675
1685
|
var EVENT_KINDS = NOSTR_EVENT_KINDS;
|
|
1676
|
-
var NostrTransportProvider = class {
|
|
1686
|
+
var NostrTransportProvider = class _NostrTransportProvider {
|
|
1677
1687
|
id = "nostr";
|
|
1678
1688
|
name = "Nostr Transport";
|
|
1679
1689
|
type = "p2p";
|
|
@@ -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.
|
|
@@ -2155,11 +2214,11 @@ var NostrTransportProvider = class {
|
|
|
2155
2214
|
return this.resolveNametagInfo(identifier);
|
|
2156
2215
|
}
|
|
2157
2216
|
async resolveNametag(nametag) {
|
|
2158
|
-
this.
|
|
2217
|
+
await this.ensureConnectedForResolve();
|
|
2159
2218
|
return this.nostrClient.queryPubkeyByNametag(nametag);
|
|
2160
2219
|
}
|
|
2161
2220
|
async resolveNametagInfo(nametag) {
|
|
2162
|
-
this.
|
|
2221
|
+
await this.ensureConnectedForResolve();
|
|
2163
2222
|
const binding = await this.nostrClient.queryBindingByNametag(nametag);
|
|
2164
2223
|
if (!binding) {
|
|
2165
2224
|
logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
|
|
@@ -2172,7 +2231,7 @@ var NostrTransportProvider = class {
|
|
|
2172
2231
|
* Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
|
|
2173
2232
|
*/
|
|
2174
2233
|
async resolveAddressInfo(address) {
|
|
2175
|
-
this.
|
|
2234
|
+
await this.ensureConnectedForResolve();
|
|
2176
2235
|
const binding = await this.nostrClient.queryBindingByAddress(address);
|
|
2177
2236
|
if (!binding) return null;
|
|
2178
2237
|
return this.bindingInfoToPeerInfo(binding);
|
|
@@ -2207,7 +2266,7 @@ var NostrTransportProvider = class {
|
|
|
2207
2266
|
* Queries binding events authored by the given pubkey.
|
|
2208
2267
|
*/
|
|
2209
2268
|
async resolveTransportPubkeyInfo(transportPubkey) {
|
|
2210
|
-
this.
|
|
2269
|
+
await this.ensureConnectedForResolve();
|
|
2211
2270
|
const events = await this.queryEvents({
|
|
2212
2271
|
kinds: [EVENT_KINDS.NAMETAG_BINDING],
|
|
2213
2272
|
authors: [transportPubkey],
|
|
@@ -2242,7 +2301,7 @@ var NostrTransportProvider = class {
|
|
|
2242
2301
|
* Used for HD address discovery — single relay query with multi-author filter.
|
|
2243
2302
|
*/
|
|
2244
2303
|
async discoverAddresses(transportPubkeys) {
|
|
2245
|
-
this.
|
|
2304
|
+
await this.ensureConnectedForResolve();
|
|
2246
2305
|
if (transportPubkeys.length === 0) return [];
|
|
2247
2306
|
const events = await this.queryEvents({
|
|
2248
2307
|
kinds: [EVENT_KINDS.NAMETAG_BINDING],
|
|
@@ -2281,7 +2340,10 @@ var NostrTransportProvider = class {
|
|
|
2281
2340
|
* @returns Decrypted nametag or null if none found
|
|
2282
2341
|
*/
|
|
2283
2342
|
async recoverNametag() {
|
|
2284
|
-
this.
|
|
2343
|
+
await this.ensureConnectedForResolve();
|
|
2344
|
+
if (!this.identity) {
|
|
2345
|
+
throw new SphereError("Identity not set", "NOT_INITIALIZED");
|
|
2346
|
+
}
|
|
2285
2347
|
if (!this.identity || !this.keyManager) {
|
|
2286
2348
|
throw new SphereError("Identity not set", "NOT_INITIALIZED");
|
|
2287
2349
|
}
|
|
@@ -2841,6 +2903,10 @@ var NostrTransportProvider = class {
|
|
|
2841
2903
|
chatEoseFired = false;
|
|
2842
2904
|
async subscribeToEvents() {
|
|
2843
2905
|
logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
|
|
2906
|
+
if (this._subscriptionsSuppressed) {
|
|
2907
|
+
logger.debug("Nostr", "subscribeToEvents: suppressed \u2014 mux handles event routing");
|
|
2908
|
+
return;
|
|
2909
|
+
}
|
|
2844
2910
|
if (!this.identity || !this.keyManager || !this.nostrClient) {
|
|
2845
2911
|
logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
|
|
2846
2912
|
return;
|
|
@@ -2867,7 +2933,13 @@ var NostrTransportProvider = class {
|
|
|
2867
2933
|
if (stored) {
|
|
2868
2934
|
since = parseInt(stored, 10);
|
|
2869
2935
|
this.lastEventTs = since;
|
|
2936
|
+
this.fallbackSince = null;
|
|
2870
2937
|
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
2938
|
+
} else if (this.fallbackSince !== null) {
|
|
2939
|
+
since = this.fallbackSince;
|
|
2940
|
+
this.lastEventTs = since;
|
|
2941
|
+
this.fallbackSince = null;
|
|
2942
|
+
logger.debug("Nostr", "Using fallback since timestamp:", since);
|
|
2871
2943
|
} else {
|
|
2872
2944
|
since = Math.floor(Date.now() / 1e3);
|
|
2873
2945
|
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
@@ -2875,6 +2947,7 @@ var NostrTransportProvider = class {
|
|
|
2875
2947
|
} catch (err) {
|
|
2876
2948
|
logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
|
|
2877
2949
|
since = Math.floor(Date.now() / 1e3);
|
|
2950
|
+
this.fallbackSince = null;
|
|
2878
2951
|
}
|
|
2879
2952
|
} else {
|
|
2880
2953
|
since = Math.floor(Date.now() / 1e3) - 86400;
|
|
@@ -3006,6 +3079,31 @@ var NostrTransportProvider = class {
|
|
|
3006
3079
|
throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
|
|
3007
3080
|
}
|
|
3008
3081
|
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Async version of ensureConnected — reconnects if the original transport
|
|
3084
|
+
* lost its WebSocket while subscriptions are suppressed (mux handles events).
|
|
3085
|
+
* Used by resolve methods which are always async.
|
|
3086
|
+
*/
|
|
3087
|
+
async ensureConnectedForResolve() {
|
|
3088
|
+
if (this.isConnected()) return;
|
|
3089
|
+
if (this._subscriptionsSuppressed && this.nostrClient) {
|
|
3090
|
+
logger.debug("Nostr", "Suppressed transport disconnected \u2014 reconnecting for resolve");
|
|
3091
|
+
try {
|
|
3092
|
+
await Promise.race([
|
|
3093
|
+
this.nostrClient.connect(...this.config.relays),
|
|
3094
|
+
new Promise(
|
|
3095
|
+
(_, reject) => setTimeout(() => reject(new Error("reconnect timeout")), 5e3)
|
|
3096
|
+
)
|
|
3097
|
+
]);
|
|
3098
|
+
if (this.nostrClient.isConnected()) {
|
|
3099
|
+
this.status = "connected";
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
} catch {
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
|
|
3106
|
+
}
|
|
3009
3107
|
ensureReady() {
|
|
3010
3108
|
this.ensureConnected();
|
|
3011
3109
|
if (!this.identity) {
|
|
@@ -3027,16 +3125,23 @@ var NostrTransportProvider = class {
|
|
|
3027
3125
|
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
3028
3126
|
*/
|
|
3029
3127
|
createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
|
|
3030
|
-
|
|
3128
|
+
return _NostrTransportProvider.createCustomKindGiftWrap(this.keyManager, recipientPubkeyHex, content, rumorKind);
|
|
3129
|
+
}
|
|
3130
|
+
/**
|
|
3131
|
+
* Create a NIP-17 gift wrap with a custom rumor kind.
|
|
3132
|
+
* Shared between NostrTransportProvider and MultiAddressTransportMux.
|
|
3133
|
+
*/
|
|
3134
|
+
static createCustomKindGiftWrap(keyManager, recipientPubkeyHex, content, rumorKind) {
|
|
3135
|
+
const senderPubkey = keyManager.getPublicKeyHex();
|
|
3031
3136
|
const now = Math.floor(Date.now() / 1e3);
|
|
3032
3137
|
const rumorTags = [["p", recipientPubkeyHex]];
|
|
3033
3138
|
const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
|
|
3034
3139
|
const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
|
|
3035
3140
|
const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
|
|
3036
3141
|
const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
|
|
3037
|
-
const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor),
|
|
3142
|
+
const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), keyManager.getPrivateKey(), recipientPubkeyBytes);
|
|
3038
3143
|
const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
3039
|
-
const seal = import_nostr_js_sdk.Event.create(
|
|
3144
|
+
const seal = import_nostr_js_sdk.Event.create(keyManager, {
|
|
3040
3145
|
kind: import_nostr_js_sdk.EventKinds.SEAL,
|
|
3041
3146
|
tags: [],
|
|
3042
3147
|
content: encryptedRumor,
|
|
@@ -4895,11 +5000,17 @@ var AsyncSerialQueue = class {
|
|
|
4895
5000
|
var WriteBuffer = class {
|
|
4896
5001
|
/** Full TXF data from save() calls — latest wins */
|
|
4897
5002
|
txfData = null;
|
|
5003
|
+
/** IPNS context captured at save() time — ensures flush writes to the correct
|
|
5004
|
+
* IPNS record even if identity changes between save() and flush(). */
|
|
5005
|
+
capturedIpnsKeyPair = null;
|
|
5006
|
+
capturedIpnsName = null;
|
|
4898
5007
|
get isEmpty() {
|
|
4899
5008
|
return this.txfData === null;
|
|
4900
5009
|
}
|
|
4901
5010
|
clear() {
|
|
4902
5011
|
this.txfData = null;
|
|
5012
|
+
this.capturedIpnsKeyPair = null;
|
|
5013
|
+
this.capturedIpnsName = null;
|
|
4903
5014
|
}
|
|
4904
5015
|
/**
|
|
4905
5016
|
* Merge another buffer's contents into this one (for rollback).
|
|
@@ -4908,12 +5019,14 @@ var WriteBuffer = class {
|
|
|
4908
5019
|
mergeFrom(other) {
|
|
4909
5020
|
if (other.txfData && !this.txfData) {
|
|
4910
5021
|
this.txfData = other.txfData;
|
|
5022
|
+
this.capturedIpnsKeyPair = other.capturedIpnsKeyPair;
|
|
5023
|
+
this.capturedIpnsName = other.capturedIpnsName;
|
|
4911
5024
|
}
|
|
4912
5025
|
}
|
|
4913
5026
|
};
|
|
4914
5027
|
|
|
4915
5028
|
// impl/shared/ipfs/ipfs-storage-provider.ts
|
|
4916
|
-
var IpfsStorageProvider = class {
|
|
5029
|
+
var IpfsStorageProvider = class _IpfsStorageProvider {
|
|
4917
5030
|
id = "ipfs";
|
|
4918
5031
|
name = "IPFS Storage";
|
|
4919
5032
|
type = "p2p";
|
|
@@ -4958,7 +5071,12 @@ var IpfsStorageProvider = class {
|
|
|
4958
5071
|
flushDebounceMs;
|
|
4959
5072
|
/** Set to true during shutdown to prevent new flushes */
|
|
4960
5073
|
isShuttingDown = false;
|
|
5074
|
+
/** Stored config for createForAddress() cloning */
|
|
5075
|
+
_config;
|
|
5076
|
+
_statePersistenceCtor;
|
|
4961
5077
|
constructor(config, statePersistence) {
|
|
5078
|
+
this._config = config;
|
|
5079
|
+
this._statePersistenceCtor = statePersistence;
|
|
4962
5080
|
const gateways = config?.gateways ?? getIpfsGatewayUrls();
|
|
4963
5081
|
this.debug = config?.debug ?? false;
|
|
4964
5082
|
this.ipnsLifetimeMs = config?.ipnsLifetimeMs ?? 99 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -5078,6 +5196,7 @@ var IpfsStorageProvider = class {
|
|
|
5078
5196
|
}
|
|
5079
5197
|
async shutdown() {
|
|
5080
5198
|
this.isShuttingDown = true;
|
|
5199
|
+
logger.debug("IPFS-Storage", `shutdown: ipnsName=${this.ipnsName?.slice(0, 20)}..., pendingEmpty=${this.pendingBuffer.isEmpty}, capturedIpns=${this.pendingBuffer.capturedIpnsName?.slice(0, 20) ?? "none"}`);
|
|
5081
5200
|
if (this.flushTimer) {
|
|
5082
5201
|
clearTimeout(this.flushTimer);
|
|
5083
5202
|
this.flushTimer = null;
|
|
@@ -5110,6 +5229,8 @@ var IpfsStorageProvider = class {
|
|
|
5110
5229
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5111
5230
|
}
|
|
5112
5231
|
this.pendingBuffer.txfData = data;
|
|
5232
|
+
this.pendingBuffer.capturedIpnsKeyPair = this.ipnsKeyPair;
|
|
5233
|
+
this.pendingBuffer.capturedIpnsName = this.ipnsName;
|
|
5113
5234
|
this.scheduleFlush();
|
|
5114
5235
|
return { success: true, timestamp: Date.now() };
|
|
5115
5236
|
}
|
|
@@ -5120,8 +5241,12 @@ var IpfsStorageProvider = class {
|
|
|
5120
5241
|
* Perform the actual upload + IPNS publish synchronously.
|
|
5121
5242
|
* Called by executeFlush() and sync() — never by public save().
|
|
5122
5243
|
*/
|
|
5123
|
-
async _doSave(data) {
|
|
5124
|
-
|
|
5244
|
+
async _doSave(data, overrideIpns) {
|
|
5245
|
+
const ipnsKeyPair = overrideIpns?.keyPair ?? this.ipnsKeyPair;
|
|
5246
|
+
const ipnsName = overrideIpns?.name ?? this.ipnsName;
|
|
5247
|
+
const metaAddr = data?._meta?.address;
|
|
5248
|
+
logger.debug("IPFS-Storage", `_doSave: ipnsName=${ipnsName?.slice(0, 20)}..., override=${!!overrideIpns}, meta.address=${metaAddr?.slice(0, 20) ?? "none"}`);
|
|
5249
|
+
if (!ipnsKeyPair || !ipnsName) {
|
|
5125
5250
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5126
5251
|
}
|
|
5127
5252
|
this.emitEvent({ type: "storage:saving", timestamp: Date.now() });
|
|
@@ -5130,7 +5255,7 @@ var IpfsStorageProvider = class {
|
|
|
5130
5255
|
const metaUpdate = {
|
|
5131
5256
|
...data._meta,
|
|
5132
5257
|
version: this.dataVersion,
|
|
5133
|
-
ipnsName
|
|
5258
|
+
ipnsName,
|
|
5134
5259
|
updatedAt: Date.now()
|
|
5135
5260
|
};
|
|
5136
5261
|
if (this.remoteCid) {
|
|
@@ -5142,13 +5267,13 @@ var IpfsStorageProvider = class {
|
|
|
5142
5267
|
const baseSeq = this.ipnsSequenceNumber > this.lastKnownRemoteSequence ? this.ipnsSequenceNumber : this.lastKnownRemoteSequence;
|
|
5143
5268
|
const newSeq = baseSeq + 1n;
|
|
5144
5269
|
const marshalledRecord = await createSignedRecord(
|
|
5145
|
-
|
|
5270
|
+
ipnsKeyPair,
|
|
5146
5271
|
cid,
|
|
5147
5272
|
newSeq,
|
|
5148
5273
|
this.ipnsLifetimeMs
|
|
5149
5274
|
);
|
|
5150
5275
|
const publishResult = await this.httpClient.publishIpns(
|
|
5151
|
-
|
|
5276
|
+
ipnsName,
|
|
5152
5277
|
marshalledRecord
|
|
5153
5278
|
);
|
|
5154
5279
|
if (!publishResult.success) {
|
|
@@ -5163,14 +5288,14 @@ var IpfsStorageProvider = class {
|
|
|
5163
5288
|
this.ipnsSequenceNumber = newSeq;
|
|
5164
5289
|
this.lastCid = cid;
|
|
5165
5290
|
this.remoteCid = cid;
|
|
5166
|
-
this.cache.setIpnsRecord(
|
|
5291
|
+
this.cache.setIpnsRecord(ipnsName, {
|
|
5167
5292
|
cid,
|
|
5168
5293
|
sequence: newSeq,
|
|
5169
5294
|
gateway: "local"
|
|
5170
5295
|
});
|
|
5171
5296
|
this.cache.setContent(cid, updatedData);
|
|
5172
|
-
this.cache.markIpnsFresh(
|
|
5173
|
-
await this.statePersistence.save(
|
|
5297
|
+
this.cache.markIpnsFresh(ipnsName);
|
|
5298
|
+
await this.statePersistence.save(ipnsName, {
|
|
5174
5299
|
sequenceNumber: newSeq.toString(),
|
|
5175
5300
|
lastCid: cid,
|
|
5176
5301
|
version: this.dataVersion
|
|
@@ -5222,7 +5347,8 @@ var IpfsStorageProvider = class {
|
|
|
5222
5347
|
const baseData = active.txfData ?? {
|
|
5223
5348
|
_meta: { version: 0, address: this.identity?.directAddress ?? "", formatVersion: "2.0", updatedAt: 0 }
|
|
5224
5349
|
};
|
|
5225
|
-
const
|
|
5350
|
+
const overrideIpns = active.capturedIpnsKeyPair && active.capturedIpnsName ? { keyPair: active.capturedIpnsKeyPair, name: active.capturedIpnsName } : void 0;
|
|
5351
|
+
const result = await this._doSave(baseData, overrideIpns);
|
|
5226
5352
|
if (!result.success) {
|
|
5227
5353
|
throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
|
|
5228
5354
|
}
|
|
@@ -5525,6 +5651,13 @@ var IpfsStorageProvider = class {
|
|
|
5525
5651
|
log(message) {
|
|
5526
5652
|
logger.debug("IPFS-Storage", message);
|
|
5527
5653
|
}
|
|
5654
|
+
/**
|
|
5655
|
+
* Create an independent instance for a different address.
|
|
5656
|
+
* Shares the same gateway/timeout config but has fresh IPNS state.
|
|
5657
|
+
*/
|
|
5658
|
+
createForAddress() {
|
|
5659
|
+
return new _IpfsStorageProvider(this._config, this._statePersistenceCtor);
|
|
5660
|
+
}
|
|
5528
5661
|
};
|
|
5529
5662
|
|
|
5530
5663
|
// impl/browser/ipfs/browser-ipfs-state-persistence.ts
|