@ghostlytools/cli 1.3.2 → 1.3.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/README.md +7 -7
- package/SKILL.md +2 -1
- package/dist/assets/{api-SYPJgFRU.js → api-BCwaCbKh.js} +2 -2
- package/dist/assets/{api-aup3Amud.js → api-Bp_hWAiU.js} +100 -20
- package/dist/assets/api-Bp_hWAiU.js.map +1 -0
- package/dist/assets/{apiKit-DYkVEs6r.js → apiKit-3MLUyuhL.js} +21 -6
- package/dist/assets/apiKit-3MLUyuhL.js.map +1 -0
- package/dist/assets/{apps-DcZKu29s.js → apps-B6gqk4GD.js} +1 -1
- package/dist/assets/{apps-Rbk2HHXb.js → apps-BXw3Ui_3.js} +91 -24
- package/dist/assets/apps-BXw3Ui_3.js.map +1 -0
- package/dist/assets/{arkade-CuWlNnCz.js → arkade-CyplNY_v.js} +2 -2
- package/dist/assets/{arkade-CuWlNnCz.js.map → arkade-CyplNY_v.js.map} +1 -1
- package/dist/assets/{backup-CJWLDHuS.js → backup-BGE4BDzf.js} +6 -6
- package/dist/assets/{backup-CJWLDHuS.js.map → backup-BGE4BDzf.js.map} +1 -1
- package/dist/assets/{backup-CSMw2GHv.js → backup-Cm8ptQQA.js} +1 -1
- package/dist/assets/bark_ffi_wasm_bg-EY2uc0Bx.js.map +1 -1
- package/dist/assets/{buttons-QEnAGWoC.js → buttons-52NT4sA_.js} +4 -4
- package/dist/assets/{buttons-QEnAGWoC.js.map → buttons-52NT4sA_.js.map} +1 -1
- package/dist/assets/buttons-PCvHRlkS.js +2 -0
- package/dist/assets/{envelope-K27mzoyu.js → envelope-CsRRCrL3.js} +2 -2
- package/dist/assets/{envelope-K27mzoyu.js.map → envelope-CsRRCrL3.js.map} +1 -1
- package/dist/assets/{errors-DO5z6h_l.js → errors-B-zMxbcd.js} +6 -5
- package/dist/assets/{errors-DO5z6h_l.js.map → errors-B-zMxbcd.js.map} +1 -1
- package/dist/assets/fedimint_client_wasm_bg-BtHHlFpp.js.map +1 -1
- package/dist/assets/{ghostly_iroh_web-Dvzh3Y6E.js → ghostly_iroh_web-BsAEFIjl.js} +30 -36
- package/dist/assets/ghostly_iroh_web-BsAEFIjl.js.map +1 -0
- package/dist/assets/ghostly_iroh_web_bg.wasm +0 -0
- package/dist/assets/{groupFiles-DHTrTA4I.js → groupFiles-BurezP4Z.js} +47 -21
- package/dist/assets/{groupFiles-DHTrTA4I.js.map → groupFiles-BurezP4Z.js.map} +1 -1
- package/dist/assets/{host-C7hA-Za7.js → host-C74Sy5jT.js} +211 -42
- package/dist/assets/host-C74Sy5jT.js.map +1 -0
- package/dist/assets/{hyperdhtRelay-BVoWY2ua.js → hyperdhtRelay-D0MvfMzX.js} +2 -2
- package/dist/assets/{hyperdhtRelay-BVoWY2ua.js.map → hyperdhtRelay-D0MvfMzX.js.map} +1 -1
- package/dist/assets/{irohWeb-BJPk9bMn.js → irohWeb-DynqwRwl.js} +3 -3
- package/dist/assets/{irohWeb-BJPk9bMn.js.map → irohWeb-DynqwRwl.js.map} +1 -1
- package/dist/assets/{main-DC8cUkDx.js → main-DNzQOdNG.js} +168 -57
- package/dist/assets/main-DNzQOdNG.js.map +1 -0
- package/dist/assets/{mainline-CxbxpoU4.js → mainline-COqCHn1R.js} +2 -2
- package/dist/assets/{mainline-CxbxpoU4.js.map → mainline-COqCHn1R.js.map} +1 -1
- package/dist/assets/{networkReason-D42iNuUB.js → networkReason-WikfjkIw.js} +2 -2
- package/dist/assets/{networkReason-D42iNuUB.js.map → networkReason-WikfjkIw.js.map} +1 -1
- package/dist/assets/{nwc-Cm4sYgLv.js → nwc-ClsjYuyP.js} +3 -3
- package/dist/assets/{nwc-Cm4sYgLv.js.map → nwc-ClsjYuyP.js.map} +1 -1
- package/dist/assets/{nwcProvider-0D7vdPDd.js → nwcProvider-ksMYZra9.js} +2 -2
- package/dist/assets/{nwcProvider-0D7vdPDd.js.map → nwcProvider-ksMYZra9.js.map} +1 -1
- package/dist/assets/{profiles-BHc9pEYg.js → profiles-gPCjLOQq.js} +2 -2
- package/dist/assets/{profiles-BHc9pEYg.js.map → profiles-gPCjLOQq.js.map} +1 -1
- package/dist/assets/{registry-CVdSZW5l.js → registry-CJh9L_kF.js} +17 -32
- package/dist/assets/registry-CJh9L_kF.js.map +1 -0
- package/dist/assets/{registry-CLolR0kM.js → registry-S7SFF_JB.js} +1 -1
- package/dist/assets/{resolve-BnlEajYz.js → resolve-BJxBhU5j.js} +18 -3
- package/dist/assets/resolve-BJxBhU5j.js.map +1 -0
- package/dist/assets/{server-CJNEKxzE.js → server-C05N9q4G.js} +298 -100
- package/dist/assets/server-C05N9q4G.js.map +1 -0
- package/dist/assets/{src-yMUQvdyL.js → src-RQ6OJOUO.js} +322 -104
- package/dist/assets/src-RQ6OJOUO.js.map +1 -0
- package/dist/assets/{turnRefs-B2a8to9q.js → turnRefs-u-U75DFx.js} +2 -2
- package/dist/assets/{turnRefs-B2a8to9q.js.map → turnRefs-u-U75DFx.js.map} +1 -1
- package/dist/assets/{usdt-DesFeDiG.js → usdt-A1B3r3Mq.js} +3 -3
- package/dist/assets/{usdt-DesFeDiG.js.map → usdt-A1B3r3Mq.js.map} +1 -1
- package/dist/ghostly.mjs +1 -1
- package/package.json +1 -1
- package/dist/assets/api-aup3Amud.js.map +0 -1
- package/dist/assets/apiKit-DYkVEs6r.js.map +0 -1
- package/dist/assets/apps-Rbk2HHXb.js.map +0 -1
- package/dist/assets/buttons-CGRqZ7z0.js +0 -2
- package/dist/assets/ghostly_iroh_web-Dvzh3Y6E.js.map +0 -1
- package/dist/assets/host-C7hA-Za7.js.map +0 -1
- package/dist/assets/main-DC8cUkDx.js.map +0 -1
- package/dist/assets/registry-CVdSZW5l.js.map +0 -1
- package/dist/assets/resolve-BnlEajYz.js.map +0 -1
- package/dist/assets/server-CJNEKxzE.js.map +0 -1
- package/dist/assets/src-yMUQvdyL.js.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { n as traceJoin } from "./joinTrace-CjRDFy85.js";
|
|
2
|
-
import { $c as
|
|
2
|
+
import { $c as currentRelays, $i as revokesIdentity, $n as GROUP_FILE_LIMITS, $r as WAKE_CALL_INTERVAL_MS, $t as didDhtFromPublicKey, A as CommunitySession, Aa as forwardedAgain, Ac as devicePingFrame, Ao as rosterAdmin, Ar as newerHead, As as handoffOfferFrame, B as knockRecords, Ba as readReaction, Bc as TURN_MAX, Bi as capsDescriptors, Bn as findEndpoint, Bo as GhostlyHttpError, Br as transferStalled, Bs as readHandoffHave, C as sha256Paced, Ca as parseImageMeta, Cc as DEVICES_CAPABILITY, Ci as readManifest, Cl as randomBytes, Cn as isBitcoinAddress, Cr as beaconRecords, Cs as handoffContext, D as openGroupTyping, Da as RateWindow, Dc as deviceEchoNonce, Dl as utf8Encode, Do as MEMBER_KEY, Dr as lobbyRecords, Ds as handoffEphemeral, E as groupTypingEpoch, Ea as EDIT_RATE_WINDOW_MS, Ec as deviceEchoFrame, El as utf8Decode, Er as lobbyKeys, Es as handoffDigest, Et as normalizeAtprotoHandle, Fa as ReactionWindow, Fc as TURN_RAISE_READ_TIMEOUT_MS, Fr as readLobby, Fs as handoffVersions, G as groupWakeFrame, Ga as replySnippet, Gc as signTurnRelease, Gn as INVITE_TAKEN, Go as decodeControl, Gr as typingActivity, Gs as sealHandoffPiece, H as readKnocks, Ha as wireReaction, Hc as nextTurnPosition, Hn as parseCashuRequestPayload, Ho as parseLocalTarget, Hs as readHandoffPake, I as decodeGroupEntryLink, Ia as nextReactionNumber, Ic as TURN_SETTLE_MS, In as decodeBolt11, Io as DHT_POLL_INTERVALS, Ir as shouldBeHub, Is as newHandoffId, J as GROUP_LIMITS, Jc as turnName, Ji as emptyIdentityLedger, Jn as pairedMessageFits, Jo as RTC_CONFIG, Jr as mayPin, Js as readSetUpdate, K as groupWakes, Ka as BUTTON_ID, Kc as turnInstance, Ki as IdentityExchange, Kn as LIVENESS_PING_MS, Ko as encodeControl, L as encodeGroupEntryLink, La as queueReaction, Lc as classifyTurnRead, Ln as ENDPOINT, Lr as ChatFiles, Ls as readHandoffAck, M as communityHasFrame, Ma as COMMUNITY_REACTION_FRAME, Mc as seedSigner, Mo as verifyCommitSignature, Mr as rankHubs, Ms as handoffReleaseFrame, N as decodeCommunityLink, Na as GROUP_REACTION_FRAME, Nc as webCryptoSigner, No as edgeParams, Nr as readBeacon, Ns as handoffRetryAfter, O as sealGroupTyping, Oa as dhtEditId, Oc as deviceKeyZ32, Oo as commitHash, Or as mergeBeacon, Os as handoffHelloFrame, P as encodeCommunityLink, Pa as REACTION_LIMITS, Po as DirectPathWatch, Pr as readBeaconHead, Ps as handoffStreamKey, Q as frameBytes, Qc as RelayTransport, Qi as receivedIdentityStatus, Qn as parseEngineError, Qr as readPin, Qs as verifySetUpdate, Qt as didDhtDocument, R as entryParams, Ra as reactionEmoji, Rc as turnPutSummary, Ri as CapsExchange, Rn as cashuRequestPayload, Ro as RELAY_POLL_INTERVALS, Rr as FILE_LIMITS, Rs as readHandoffCancel, S as readAppBundleAsync, Sa as parseVideoMeta, Si as newMailbox, Sn as sparkInvoiceDetails, So as canonicalJson, Sr as beaconKeys, Ss as handoffCancelFrame, T as GroupTypingBoard, Ta as EDIT_BUFFER_MS, Tc as HANDOFF_CAPABILITY, Tl as toZ32, Tn as isPubkyKey, To as GROUP_MEMBER_CAP, Tr as freshHubs, Ts as handoffDataFrame, Tt as isAtprotoDid, Ua as pairedReplyAuthor, Uc as readTurnPacket, Un as parseFedimintRequestPayload, Uo as webLocalFetch, Ur as TypingSender, Us as readHandoffTurnFrame, V as mergeKnocks, Va as validReactionNumber, Vc as firstDeviceSetSecret, Vi as dialDescriptors, Vn as isFederationId, Vo as formatLocalTarget, Vs as readHandoffHello, W as GroupWakeLimiter, Wa as readReply, Wc as signTurnPacket, Wi as IDENTITY_REVOCATION_LABEL, Wn as GhostLink, Wo as LIMITS, Ws as readHandoffVerified, X as GROUP_READ_NOTE, Xc as turnVerifierMark, Xi as identityStatement, Xn as engineError, Xr as pinIsNewer, Xs as setUpdateFrame, Yc as turnStatedVerifier, Yi as identityRevocationValue, Yn as pairedMessageFrame, Yr as nextPinNumber, Ys as setAckFrame, Z as GroupSession, Za as STATUS_CARD_LIMITS, Zc as DEFAULT_RELAYS, Zi as newIdentityBinding, Zn as engineText, Zr as pinNumberHolds, Zs as signTombstone, _c as createChatInvite, _i as HOLD_DATED_BACK_MS, _n as validatePaymentTarget, _o as isAppRef, _r as MESH_HUBS, _s as filePartName, a as planAppUpdate, aa as automaticTransport, ac as enrollDigits, ai as wakeRequest, al as withRequestOptions, an as EVM_TEST_CHAINS, ao as arrivalKey, as as serviceIdFromName, at as groupName, b as pacer, ba as parseVoiceMeta, bi as HoldRefusedError, bl as bytesEqual, bn as SPARK_PROVIDER, br as pickMeshHubs, bs as handoffAttemptSucceeded, cc as enrollHelloFrame, cl as createRelayPayload, cn as SEPOLIA_TEST_USDT, co as receivedTimestamp, cs as HANDOFF_DONE, d as APP_BUNDLE_LIMITS, da as DHT_FILE_CAPABILITY, dc as readEnrollHello, di as APPS_CAPABILITY, dn as USDT_PUBLIC_RPC, do as APP_STATEMENT_LIMITS, ds as HANDOFF_OFFER, ea as lastSharedWithMe, ei as WakeLimiter, el as normalizeRelayUrl, en as encodeDidDhtDeactivated, es as parseCallSignal, f as APP_BUNDLE_MAGIC, fa as dhtFileId, fc as verifyEnrollProof, fi as BUTTONS_CAPABILITY, fl as createIdentity, fn as WALLET_NETWORKS, fo as appFingerprint, fs as HANDOFF_PAKE, g as appViewOf, gc as OwnInviteError, gi as HOLD_CAPABILITY, gl as verify, gn as formatPaymentAmount, go as isAppKey, gr as readGroupSignal, gs as HANDOFF_VERIFIED, h as appDigest, ha as sanitizeMime, hc as readDeviceInvite, hi as UPGRADE_CAPABILITY, hl as publicKeyFromZ32, hn as assertWholeSats, ho as isAppHash, hr as groupSignalFrame, hs as HANDOFF_TIMINGS, i as checkAppBeforeRun, ia as TRANSPORTS, ic as enrollCancelReason, ii as relayRequest, il as isDiscoveryBudgetError, in as ETHEREUM_USDT, io as statusCardText, ir as groupFileFallback, is as LEGACY_SERVICES, it as mentionsMember, j as GROUP_READ_NOTE_COMMUNITY, ja as readForwarded, jc as newDeviceSetSecret, jo as rosterHas, jr as pickHubs, js as handoffPakeFrame, k as COMMUNITY_LIMITS, ka as parseLinkPreview, kc as deviceLinkPairing, ko as parseGroupCommit, kr as mergeLobby, ks as handoffManifestFrames, l as readAppStoreSteps, la as DHT_MESSAGE_TTL, lc as enrollProofFrame, li as chatAppId, lo as shownTime, ls as HANDOFF_HAVE, ma as sanitizeFileName, mc as deviceInviteJoinerParams, mi as STATUS_CARD_CAPABILITY, ml as identityFromSeedB64, mn as assertTokenUnits, ms as HANDOFF_REQUEST, n as appStoreDecision, na as emptyProofLedger, ni as newWakeToken, nl as traceLink, no as checkStatusCard, ns as emptyLinkRecords, nt as carryMentions, o as APP_STORE_LIMITS, oc as enrollDoneFrame, oi as checkPushEndpoint, ol as PacketTooLargeError, on as ONCHAIN_PROVIDER, oo as claimedTime, or as readGroupFileMeta, os as HANDOFF_ACK, p as APP_ICON_PATH, pa as formatFileSize, pc as createDeviceInvite, pi as EDIT_CAPABILITY, pl as identityFromSeed, pn as arkAddressPrefix, po as appRef, ps as HANDOFF_PIECE_BYTES, q as parseGroupWakeFrame, qc as turnKeys, qn as PAIRED_FRAME_TOO_LARGE, qr as PIN_LIMITS, r as appUpdateDecision, ra as validExternalKey, rc as enrollCancelFrame, ri as parseWakeFrame, rl as budgetRetryMs, rn as signDidDhtPacket, ro as sameButtonText, rs as HTTP_SERVICE_PROTO, rt as parseCommunityEdit, sc as enrollGrantFrame, si as vapidKeysMatch, sn as PaymentPreflightError, so as heardTime, ss as HANDOFF_CANCEL, t as appRevocationFor, ta as PeerProofs, ti as deviceWakeRequest, tn as encodeDidDhtPacket, tt as GROUP_EDIT_TEXT_BYTES, ua as peekDhtMailbox, uc as readEnrollGrant, ui as isAppVersion, un as TEST_USDT_FAUCET_AMOUNT, ur as CarriedTransport, us as HANDOFF_HELLO, vc as decodeInviteCode, vi as HOLD_LIMITS, vl as sanitizeAvatar, vn as walletNetworkOf, vo as readAppRevocation, vr as mayBeHub, vs as handoffAttemptAllowed, wc as ENROLL_CAPABILITY, wl as toBase64Url, wo as readCanonicalJson, wr as doorHubs, ws as handoffContextProof, xc as inviteOwnership, xi as isHoldUrl, xl as fromBase64Url, xn as sparkAddressKind, xr as COMMUNITY_TOPOLOGY, xs as handoffBusyFrame, y as isAppUrl, ya as fileMessageText, yc as encodeInviteCode, yi as HoldKeys, yl as sanitizeDisplayText, yn as SPARK_NETWORKS, yr as meshHubs, ys as handoffAttemptFailed, z as knockIdentity, za as reactionIsNewer, zc as TURN_LAST_SEQUENCE, zi as DHT_TEXT_CAPABILITY, zn as fedimintRequestPayload, zo as presenceSeenAt, zr as transferEnded, zs as readHandoffDone } from "./src-RQ6OJOUO.js";
|
|
3
3
|
import { i as SourceUnreachableError, n as PROVIDER_PLATFORMS, o as isNothingSpentError, r as SourceConfigError, t as NothingSpentError, u as redact } from "./types-C4_KafL_.js";
|
|
4
4
|
import { t as bitcoindRpc } from "./bitcoindProvider-DGw3xBSa.js";
|
|
5
|
-
import { t as nwc } from "./nwcProvider-
|
|
5
|
+
import { t as nwc } from "./nwcProvider-ksMYZra9.js";
|
|
6
6
|
import { a as clearProfileStores, c as fileStore, d as profileOpenFailure, f as store, i as STORES$1, l as newestWalletTx, m as wrap, n as APP_STORAGE_SCOPE_INDEX, o as databaseName, p as transact, r as CARD_INDEX, s as deleteDatabase, t as APP_STORAGE_CHAT_INDEX, u as openDb } from "./idb-B5L8wuOm.js";
|
|
7
|
-
import { a as sealSeed, i as newDeviceKey, o as unsealSeed, r as intentRepository } from "./networkReason-
|
|
8
|
-
import { $ as setSingleWriterGate, A as LightningCards, B as breezDatabaseInUse, C as FileAppender, D as streamStored, E as storedSize, F as ProviderSources, G as ModeChanged, H as dropBreezDatabase, I as sourceKey, J as networkLabel, K as ModeGate, L as CASHU_MINT_SOURCE, M as isRecoveryPhrase, N as normalizePhrase, P as lightningPaying, Q as setAwayWallets, R as cashuMint, S as WALLET_TYPES, T as removeStored, U as iceServerProblem, V as breezDatabasesFor, W as iceServerSetting, X as refuseAway, Y as awayFrom, Z as requireTurn, _ as crossNetwork, a as storedGroupFiles, b as walletInstances, c as receivedPairedReply, d as paymentAlias, f as paymentWireId, g as createTiming, h as createFailure, i as groupOfFile, j as cardsKey, k as CASHU_CARD, l as replyRef, m as assertConfirmedReal, n as groupFileId, o as groupReply, p as WALLET_NAMES, q as WrongNetworkError, r as groupFileText, s as pairedWireReply, t as GroupFileDesk, u as replyTo, v as paymentNetwork, w as readStored$1, y as paymentNetworksOf, z as breezDatabase } from "./groupFiles-
|
|
9
|
-
import { i as fedimintDatabase, n as createIrohWebEndpoint, o as loadFedimintSdk, r as irohRelayProblem, t as DEFAULT_IROH_RELAYS } from "./irohWeb-
|
|
7
|
+
import { a as sealSeed, i as newDeviceKey, o as unsealSeed, r as intentRepository } from "./networkReason-WikfjkIw.js";
|
|
8
|
+
import { $ as setSingleWriterGate, A as LightningCards, B as breezDatabaseInUse, C as FileAppender, D as streamStored, E as storedSize, F as ProviderSources, G as ModeChanged, H as dropBreezDatabase, I as sourceKey, J as networkLabel, K as ModeGate, L as CASHU_MINT_SOURCE, M as isRecoveryPhrase, N as normalizePhrase, P as lightningPaying, Q as setAwayWallets, R as cashuMint, S as WALLET_TYPES, T as removeStored, U as iceServerProblem, V as breezDatabasesFor, W as iceServerSetting, X as refuseAway, Y as awayFrom, Z as requireTurn, _ as crossNetwork, a as storedGroupFiles, b as walletInstances, c as receivedPairedReply, d as paymentAlias, f as paymentWireId, g as createTiming, h as createFailure, i as groupOfFile, j as cardsKey, k as CASHU_CARD, l as replyRef, m as assertConfirmedReal, n as groupFileId, o as groupReply, p as WALLET_NAMES, q as WrongNetworkError, r as groupFileText, s as pairedWireReply, t as GroupFileDesk, u as replyTo, v as paymentNetwork, w as readStored$1, y as paymentNetworksOf, z as breezDatabase } from "./groupFiles-BurezP4Z.js";
|
|
9
|
+
import { i as fedimintDatabase, n as createIrohWebEndpoint, o as loadFedimintSdk, r as irohRelayProblem, t as DEFAULT_IROH_RELAYS } from "./irohWeb-DynqwRwl.js";
|
|
10
10
|
import { c as isTestMint, d as paysItsOwnInvoices, l as isWorthlessMint, n as DEFAULT_MINTS, o as fakesLightning, r as TEST_MINT, t as BITCOIN_INVOICE_ON_TESTNET, u as mintNetwork } from "./mints-BrlY773j.js";
|
|
11
|
-
import { _ as reserveAdapterIds, f as setOwnDidSource, g as registeredOnchainProviders, h as registeredLightningProviders, l as chosenResolver, n as resolveAtprotoDid, p as onAdaptersChanged, t as assertPublicServer, v as boundedIdentityFetch, y as verifyIdentity } from "./resolve-
|
|
11
|
+
import { _ as reserveAdapterIds, b as testBuild, f as setOwnDidSource, g as registeredOnchainProviders, h as registeredLightningProviders, l as chosenResolver, n as resolveAtprotoDid, p as onAdaptersChanged, t as assertPublicServer, v as boundedIdentityFetch, y as verifyIdentity } from "./resolve-BJxBhU5j.js";
|
|
12
12
|
import { c as fileSpace, f as FILE_BYTES_STEP, o as fileBytes, r as blobDigest, s as fileBytesOf, u as removeFileBytes } from "./fileBytes-Di7VZtmU.js";
|
|
13
|
-
import { n as MAX_BACKUP_BYTES, t as BACKUP_MEDIA_TYPE } from "./envelope-
|
|
13
|
+
import { n as MAX_BACKUP_BYTES, t as BACKUP_MEDIA_TYPE } from "./envelope-CsRRCrL3.js";
|
|
14
14
|
import { t as hyperdhtRelayProblem } from "./hyperdhtRelay-BT_wRxab.js";
|
|
15
|
-
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
16
15
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
16
|
+
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
17
17
|
import { base64, base64url, base64urlnopad, bech32, hex } from "@scure/base";
|
|
18
18
|
import { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from "@noble/hashes/utils.js";
|
|
19
19
|
import { chacha20poly1305 } from "@noble/ciphers/chacha.js";
|
|
@@ -199,7 +199,7 @@ function viewNews(before, after) {
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region ../browser/src/engine/paymentAdapters/usdtWallet.ts
|
|
201
201
|
/** The Ethereum libraries, a large part of the app: loaded once a USDT wallet is made, opened or restored, not with the engine. */
|
|
202
|
-
var loadUsdt = () => import("./usdt-
|
|
202
|
+
var loadUsdt = () => import("./usdt-A1B3r3Mq.js");
|
|
203
203
|
/** Every new profile starts with this wallet: an address to receive on, nothing to set up. */
|
|
204
204
|
var DEFAULT_USDT = {
|
|
205
205
|
network: "ethereum",
|
|
@@ -648,7 +648,7 @@ async function restoreArkDatabase(walletId, snapshot) {
|
|
|
648
648
|
//#endregion
|
|
649
649
|
//#region ../browser/src/engine/paymentAdapters/arkWallet.ts
|
|
650
650
|
/** The Ark SDK, a large part of the app: loaded once an Ark wallet is made, opened or restored, not with the engine. */
|
|
651
|
-
var loadArkade = () => import("./arkade-
|
|
651
|
+
var loadArkade = () => import("./arkade-CyplNY_v.js");
|
|
652
652
|
/** How long a Testnet wallet about to make way for another waits for its server to say what it holds. */
|
|
653
653
|
var RETIRE_READ_MS = 1e4;
|
|
654
654
|
/** Every new profile starts with this wallet: nothing to set up before receiving. */
|
|
@@ -6362,9 +6362,6 @@ var webln = {
|
|
|
6362
6362
|
return WeblnLightning.connect(await findWebln(), host.mode, host.signal);
|
|
6363
6363
|
}
|
|
6364
6364
|
};
|
|
6365
|
-
//#endregion
|
|
6366
|
-
//#region ../browser/src/engine/paymentAdapters/providers/testing.ts
|
|
6367
|
-
var TEST_PROVIDERS_FLAG = "ghostly-test-providers";
|
|
6368
6365
|
var hex$4 = (bytes) => Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
6369
6366
|
var random$1 = (n) => crypto.getRandomValues(new Uint8Array(n));
|
|
6370
6367
|
var uint = (value, length = 1) => {
|
|
@@ -6611,11 +6608,7 @@ var fakeLightning = {
|
|
|
6611
6608
|
kind: "lightning",
|
|
6612
6609
|
description: "In-memory regtest node for tests. Holds nothing.",
|
|
6613
6610
|
networks: ["regtest"],
|
|
6614
|
-
platforms: [
|
|
6615
|
-
"web",
|
|
6616
|
-
"extension",
|
|
6617
|
-
"desktop"
|
|
6618
|
-
],
|
|
6611
|
+
platforms: ["web", "desktop"],
|
|
6619
6612
|
fields: FIELDS,
|
|
6620
6613
|
experimental: true,
|
|
6621
6614
|
validate,
|
|
@@ -6629,11 +6622,7 @@ var fakeOnchain = {
|
|
|
6629
6622
|
kind: "onchain",
|
|
6630
6623
|
description: "In-memory regtest wallet for tests. Holds nothing.",
|
|
6631
6624
|
networks: ["regtest"],
|
|
6632
|
-
platforms: [
|
|
6633
|
-
"web",
|
|
6634
|
-
"extension",
|
|
6635
|
-
"desktop"
|
|
6636
|
-
],
|
|
6625
|
+
platforms: ["web", "desktop"],
|
|
6637
6626
|
fields: FIELDS,
|
|
6638
6627
|
experimental: true,
|
|
6639
6628
|
validate,
|
|
@@ -6644,7 +6633,7 @@ var fakeOnchain = {
|
|
|
6644
6633
|
/** Whether this browser asked for the fake providers (an e2e run sets it before the app starts). */
|
|
6645
6634
|
function testProvidersEnabled() {
|
|
6646
6635
|
try {
|
|
6647
|
-
return globalThis.localStorage?.getItem(
|
|
6636
|
+
return testBuild() && globalThis.localStorage?.getItem("ghostly-test-providers") === "1";
|
|
6648
6637
|
} catch {
|
|
6649
6638
|
return false;
|
|
6650
6639
|
}
|
|
@@ -6714,7 +6703,7 @@ var registry;
|
|
|
6714
6703
|
var loading$1;
|
|
6715
6704
|
var listeners = /* @__PURE__ */ new Set();
|
|
6716
6705
|
function loadIdentityProviders() {
|
|
6717
|
-
return loading$1 ??= import("./registry-
|
|
6706
|
+
return loading$1 ??= import("./registry-S7SFF_JB.js").then((m) => {
|
|
6718
6707
|
registry = m;
|
|
6719
6708
|
for (const listener of listeners) listener();
|
|
6720
6709
|
return m;
|
|
@@ -7734,6 +7723,11 @@ function checkedEvent(raw, maxContentLength = 16384, now = Date.now()) {
|
|
|
7734
7723
|
tags: copy.tags.map((t) => [...t])
|
|
7735
7724
|
};
|
|
7736
7725
|
}
|
|
7726
|
+
/** Whether `raw` is `event` (one already checked) in every field, the tags included. */
|
|
7727
|
+
function sameEvent(event, raw) {
|
|
7728
|
+
const tags = raw.tags;
|
|
7729
|
+
return raw.id === event.id && raw.pubkey === event.pubkey && raw.sig === event.sig && raw.kind === event.kind && raw.created_at === event.created_at && raw.content === event.content && Array.isArray(tags) && tags.length === event.tags.length && event.tags.every((tag, i) => Array.isArray(tags[i]) && tags[i].length === tag.length && tag.every((x, j) => tags[i][j] === x));
|
|
7730
|
+
}
|
|
7737
7731
|
var subscriptionId = () => "ghostly-" + Array.from(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8)), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
7738
7732
|
/** Newest first, ties broken by the lexicographically smaller id (NIP-01's rule for replaceable events). */
|
|
7739
7733
|
var byNewest = (a, b) => b.created_at - a.created_at || a.id.localeCompare(b.id);
|
|
@@ -7806,10 +7800,17 @@ async function readRelays(relays, filter, options = {}) {
|
|
|
7806
7800
|
return;
|
|
7807
7801
|
}
|
|
7808
7802
|
if (frame[0] !== "EVENT") return;
|
|
7809
|
-
const
|
|
7810
|
-
if (!
|
|
7803
|
+
const raw = frame[2];
|
|
7804
|
+
if (!raw || typeof raw !== "object" || !filter.kinds.includes(raw.kind) || filter.authors && !filter.authors.includes(raw.pubkey)) return;
|
|
7805
|
+
const known = typeof raw.id === "string" ? seen.get(raw.id) : void 0;
|
|
7806
|
+
if (known) {
|
|
7807
|
+
if (!sameEvent(known, raw)) return;
|
|
7808
|
+
} else {
|
|
7809
|
+
const event = checkedEvent(raw, maxContentLength);
|
|
7810
|
+
if (!event) return;
|
|
7811
|
+
seen.set(event.id, event);
|
|
7812
|
+
}
|
|
7811
7813
|
replied = true;
|
|
7812
|
-
if (!seen.has(event.id)) seen.set(event.id, event);
|
|
7813
7814
|
if (++count >= maxEvents) finish(true);
|
|
7814
7815
|
};
|
|
7815
7816
|
})));
|
|
@@ -9973,7 +9974,12 @@ var APP_FETCH_LIMITS = {
|
|
|
9973
9974
|
sigBytes: 1024,
|
|
9974
9975
|
/** `ghostly-revoke.json`: at most 4096 signed revocations. */
|
|
9975
9976
|
revocationsBytes: 16777216,
|
|
9976
|
-
|
|
9977
|
+
/** How long the host has to answer (the response's headers). */
|
|
9978
|
+
timeoutMs: 3e4,
|
|
9979
|
+
/** How long the body may go without a byte: a read still arriving is never cut by the clock alone. */
|
|
9980
|
+
idleMs: 3e4,
|
|
9981
|
+
/** A whole read at most: the 16 MiB cap at about 224 kbit/s. */
|
|
9982
|
+
totalMs: 6e5
|
|
9977
9983
|
};
|
|
9978
9984
|
/** A URL this client may read an app, a store or a revocation list from. */
|
|
9979
9985
|
function isAppFetchUrl(value) {
|
|
@@ -9996,10 +10002,22 @@ function boundedAppFetch(options = {}) {
|
|
|
9996
10002
|
if (!isAppFetchUrl(url)) throw new AppFetchError("host", "Apps are read only from raw.githubusercontent.com, or from cdn.jsdelivr.net at a commit, over HTTPS");
|
|
9997
10003
|
if (options.online && !options.online()) throw new AppFetchError("offline", "Offline");
|
|
9998
10004
|
const fetcher = options.fetcher ?? globalThis.fetch.bind(globalThis);
|
|
10005
|
+
const controller = new AbortController();
|
|
10006
|
+
const cut = () => {
|
|
10007
|
+
controller.abort(new DOMException("The read took too long", "TimeoutError"));
|
|
10008
|
+
};
|
|
10009
|
+
const total = setTimeout(cut, options.totalMs ?? APP_FETCH_LIMITS.totalMs);
|
|
10010
|
+
let idle = setTimeout(cut, options.timeoutMs ?? APP_FETCH_LIMITS.timeoutMs);
|
|
10011
|
+
const heard = () => {
|
|
10012
|
+
clearTimeout(idle);
|
|
10013
|
+
idle = setTimeout(cut, options.idleMs ?? APP_FETCH_LIMITS.idleMs);
|
|
10014
|
+
};
|
|
10015
|
+
const failure = (error) => controller.signal.aborted ? new AppFetchError("slow", "That took too long on this connection") : new AppFetchError("network", error instanceof Error ? error.message : String(error));
|
|
10016
|
+
const { signal } = controller;
|
|
9999
10017
|
let response;
|
|
10000
10018
|
try {
|
|
10001
10019
|
response = await fetcher(url, {
|
|
10002
|
-
signal
|
|
10020
|
+
signal,
|
|
10003
10021
|
credentials: "omit",
|
|
10004
10022
|
referrerPolicy: "no-referrer",
|
|
10005
10023
|
cache: "no-store",
|
|
@@ -10007,38 +10025,55 @@ function boundedAppFetch(options = {}) {
|
|
|
10007
10025
|
...peek && { headers: { range: `bytes=0-${maxBytes - 1}` } }
|
|
10008
10026
|
});
|
|
10009
10027
|
} catch (error) {
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
if (!response.ok) {
|
|
10014
|
-
await response.body?.cancel().catch(() => {});
|
|
10015
|
-
throw new AppFetchError("status", `The host answered ${response.status}`, response.status);
|
|
10016
|
-
}
|
|
10017
|
-
if (!peek && Number(response.headers.get("content-length")) > maxBytes) {
|
|
10018
|
-
await response.body?.cancel().catch(() => {});
|
|
10019
|
-
throw new AppFetchError("too-large", "Too large");
|
|
10028
|
+
clearTimeout(total);
|
|
10029
|
+
clearTimeout(idle);
|
|
10030
|
+
throw failure(error);
|
|
10020
10031
|
}
|
|
10032
|
+
heard();
|
|
10021
10033
|
const parts = [];
|
|
10022
10034
|
let length = 0;
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10035
|
+
try {
|
|
10036
|
+
if (response.url && response.url !== url && !isAppFetchUrl(response.url)) throw new AppFetchError("host", "The host sent the request elsewhere");
|
|
10037
|
+
if (!response.ok) {
|
|
10038
|
+
await response.body?.cancel().catch(() => {});
|
|
10039
|
+
throw new AppFetchError("status", `The host answered ${response.status}`, response.status);
|
|
10040
|
+
}
|
|
10041
|
+
if (!peek && Number(response.headers.get("content-length")) > maxBytes) {
|
|
10042
|
+
await response.body?.cancel().catch(() => {});
|
|
10043
|
+
throw new AppFetchError("too-large", "Too large");
|
|
10044
|
+
}
|
|
10045
|
+
const reader = response.body?.getReader();
|
|
10046
|
+
if (reader) {
|
|
10047
|
+
const stop = () => {
|
|
10048
|
+
reader.cancel().catch(() => {});
|
|
10049
|
+
};
|
|
10050
|
+
signal.addEventListener("abort", stop);
|
|
10051
|
+
try {
|
|
10052
|
+
for (;;) {
|
|
10053
|
+
const { done, value } = await reader.read();
|
|
10054
|
+
if (signal.aborted) throw failure(signal.reason);
|
|
10055
|
+
if (done) break;
|
|
10056
|
+
heard();
|
|
10057
|
+
if (length + value.length > maxBytes) {
|
|
10058
|
+
if (!peek) throw new AppFetchError("too-large", "Too large");
|
|
10059
|
+
parts.push(value.subarray(0, maxBytes - length));
|
|
10060
|
+
length = maxBytes;
|
|
10061
|
+
break;
|
|
10062
|
+
}
|
|
10063
|
+
parts.push(value);
|
|
10064
|
+
length += value.length;
|
|
10065
|
+
}
|
|
10066
|
+
} catch (error) {
|
|
10067
|
+
if (error instanceof AppFetchError) throw error;
|
|
10068
|
+
throw failure(error);
|
|
10069
|
+
} finally {
|
|
10070
|
+
signal.removeEventListener("abort", stop);
|
|
10071
|
+
await reader.cancel().catch(() => {});
|
|
10033
10072
|
}
|
|
10034
|
-
parts.push(value);
|
|
10035
|
-
length += value.length;
|
|
10036
10073
|
}
|
|
10037
|
-
} catch (error) {
|
|
10038
|
-
if (error instanceof AppFetchError) throw error;
|
|
10039
|
-
throw new AppFetchError("network", error instanceof Error ? error.message : String(error));
|
|
10040
10074
|
} finally {
|
|
10041
|
-
|
|
10075
|
+
clearTimeout(total);
|
|
10076
|
+
clearTimeout(idle);
|
|
10042
10077
|
}
|
|
10043
10078
|
const bytes = new Uint8Array(length);
|
|
10044
10079
|
let at = 0;
|
|
@@ -18687,6 +18722,7 @@ var FileDesk = class {
|
|
|
18687
18722
|
announced: /* @__PURE__ */ new Map(),
|
|
18688
18723
|
saving: Promise.resolve(),
|
|
18689
18724
|
lastSaved: /* @__PURE__ */ new Map(),
|
|
18725
|
+
unsaved: /* @__PURE__ */ new Map(),
|
|
18690
18726
|
files: void 0
|
|
18691
18727
|
};
|
|
18692
18728
|
made.files = new ChatFiles({
|
|
@@ -18726,6 +18762,7 @@ var FileDesk = class {
|
|
|
18726
18762
|
const chat = this.chat(linkId);
|
|
18727
18763
|
if (open) chat.files.attach();
|
|
18728
18764
|
else chat.files.detach();
|
|
18765
|
+
if (!open) for (const [id, { record }] of [...chat.unsaved]) this.save(chat, id, record);
|
|
18729
18766
|
for (const record of chat.files.records()) this.show(linkId, chat, record, chat.files.transferred(record.direction, record.id));
|
|
18730
18767
|
this.deps.changed();
|
|
18731
18768
|
}
|
|
@@ -18911,6 +18948,8 @@ var FileDesk = class {
|
|
|
18911
18948
|
const wireId = out ? fileId.slice(`${linkId}-out-`.length) : [...chat.local].find(([, local]) => local === fileId)?.[0];
|
|
18912
18949
|
if (!wireId) return;
|
|
18913
18950
|
chat.files.forget(out ? "out" : "in", wireId);
|
|
18951
|
+
clearTimeout(chat.unsaved.get(fileId)?.timer);
|
|
18952
|
+
chat.unsaved.delete(fileId);
|
|
18914
18953
|
if (!out) {
|
|
18915
18954
|
chat.local.delete(wireId);
|
|
18916
18955
|
chat.announced.delete(wireId);
|
|
@@ -18928,7 +18967,9 @@ var FileDesk = class {
|
|
|
18928
18967
|
}
|
|
18929
18968
|
/** The chat went away: its transfers stop here. */
|
|
18930
18969
|
drop(linkId) {
|
|
18931
|
-
this.chats.get(linkId)
|
|
18970
|
+
const chat = this.chats.get(linkId);
|
|
18971
|
+
chat?.files.detach();
|
|
18972
|
+
for (const { timer } of chat?.unsaved.values() ?? []) clearTimeout(timer);
|
|
18932
18973
|
this.chats.delete(linkId);
|
|
18933
18974
|
for (const id of [
|
|
18934
18975
|
...this.moved.keys(),
|
|
@@ -19114,23 +19155,45 @@ var FileDesk = class {
|
|
|
19114
19155
|
this.show(linkId, chat, record, transferred, progress);
|
|
19115
19156
|
if (offered) this.deps.flush?.();
|
|
19116
19157
|
const id = record.direction === "out" ? outgoingFileId(linkId, record.id) : chat.local.get(record.id);
|
|
19117
|
-
const now = Date.now();
|
|
19118
|
-
if (!progress || now -
|
|
19119
|
-
|
|
19120
|
-
const
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19158
|
+
const now = Date.now(), last = chat.lastSaved.get(id) ?? 0;
|
|
19159
|
+
if (!progress || now - last >= SAVE_EVERY_MS) this.save(chat, id, record);
|
|
19160
|
+
else {
|
|
19161
|
+
const held = chat.unsaved.get(id);
|
|
19162
|
+
if (held) held.record = record;
|
|
19163
|
+
else {
|
|
19164
|
+
const timer = setTimeout(() => {
|
|
19165
|
+
const newest = chat.unsaved.get(id);
|
|
19166
|
+
if (newest) this.save(chat, id, newest.record);
|
|
19167
|
+
}, last + SAVE_EVERY_MS - now);
|
|
19168
|
+
timer.unref?.();
|
|
19169
|
+
chat.unsaved.set(id, {
|
|
19170
|
+
record,
|
|
19171
|
+
timer
|
|
19172
|
+
});
|
|
19173
|
+
}
|
|
19130
19174
|
}
|
|
19131
19175
|
if (record.state === "done" && record.direction === "in") this.deps.wireIds(linkId)?.add(record.id);
|
|
19132
19176
|
this.deps.changed(progress ? 250 : 50);
|
|
19133
19177
|
}
|
|
19178
|
+
/** Writes a transfer's record and the view of it, after the chat's writes before it; what was held back goes with it. */
|
|
19179
|
+
save(chat, id, record) {
|
|
19180
|
+
const held = chat.unsaved.get(id);
|
|
19181
|
+
if (held) {
|
|
19182
|
+
clearTimeout(held.timer);
|
|
19183
|
+
chat.unsaved.delete(id);
|
|
19184
|
+
}
|
|
19185
|
+
chat.lastSaved.set(id, Date.now());
|
|
19186
|
+
const transfer = this.deps.transfers.get(id);
|
|
19187
|
+
chat.saving = chat.saving.then(() => fileStore.patch(id, {
|
|
19188
|
+
wire3: record,
|
|
19189
|
+
...transfer && { transfer: {
|
|
19190
|
+
state: transfer.state,
|
|
19191
|
+
transferred: transfer.transferred,
|
|
19192
|
+
size: transfer.size,
|
|
19193
|
+
error: transfer.error
|
|
19194
|
+
} }
|
|
19195
|
+
})).catch(() => {});
|
|
19196
|
+
}
|
|
19134
19197
|
show(linkId, chat, record, transferred, progress = false) {
|
|
19135
19198
|
const id = record.direction === "out" ? outgoingFileId(linkId, record.id) : chat.local.get(record.id);
|
|
19136
19199
|
if (!id) return;
|
|
@@ -23726,8 +23789,12 @@ var MeshHubs = class {
|
|
|
23726
23789
|
else if (!live.myHubs.length) for (const key of [...this.host.edges(groupId).keys(), ...hubs]) out.add(key);
|
|
23727
23790
|
else {
|
|
23728
23791
|
for (const key of live.myHubs) out.add(key);
|
|
23729
|
-
const admin = session.admin;
|
|
23730
|
-
|
|
23792
|
+
const admin = session.admin, mine = this.host.edges(groupId);
|
|
23793
|
+
const hubUp = live.myHubs.some((key) => {
|
|
23794
|
+
const id = mine.get(key);
|
|
23795
|
+
return !!id && this.host.linkReady(id);
|
|
23796
|
+
});
|
|
23797
|
+
if (admin && (legacy.includes(admin) || !hubUp)) out.add(admin);
|
|
23731
23798
|
}
|
|
23732
23799
|
if (session.isAdmin) for (const key of legacy) out.add(key);
|
|
23733
23800
|
}
|
|
@@ -26807,6 +26874,7 @@ var Groups = class {
|
|
|
26807
26874
|
attach(state, frames = []) {
|
|
26808
26875
|
const session = new GroupSession(state, {
|
|
26809
26876
|
clock: () => this.now(),
|
|
26877
|
+
nick: () => this.host.myNick?.(),
|
|
26810
26878
|
seqFloor: () => this.host.seqFloor?.() ?? 0,
|
|
26811
26879
|
adminWork: () => this.host.adminWork?.(state.id) ?? true,
|
|
26812
26880
|
adminTurn: () => this.host.adminTurn?.(state.id) ?? Promise.resolve(true),
|
|
@@ -27179,10 +27247,7 @@ function mergeGroupPay(current, frame, author, members) {
|
|
|
27179
27247
|
...next,
|
|
27180
27248
|
by: frame.by
|
|
27181
27249
|
};
|
|
27182
|
-
if (next.
|
|
27183
|
-
...next,
|
|
27184
|
-
by: next.claims[0]
|
|
27185
|
-
};
|
|
27250
|
+
if (next.from === "*" && next.rail === "lightning" && next.by) next = (({ by: _, ...rest }) => rest)(next);
|
|
27186
27251
|
if (next.state === "paid" && next.from !== "*" && !next.by) next = {
|
|
27187
27252
|
...next,
|
|
27188
27253
|
by: next.from
|
|
@@ -27213,7 +27278,7 @@ function authoredNote(p, at, all, current, memberOf = () => void 0) {
|
|
|
27213
27278
|
const from = p.group ? "*" : at.peer;
|
|
27214
27279
|
if (!from) return null;
|
|
27215
27280
|
const payment = all.find((x) => x.kind === "payment" && x.direction === "in" && x.requestId === p.id && x.state === "settled");
|
|
27216
|
-
const by = !p.group ? from : payment ? memberOf(payment.linkId) :
|
|
27281
|
+
const by = !p.group ? from : payment ? memberOf(payment.linkId) : void 0;
|
|
27217
27282
|
const st = p.state === "settled" ? "paid" : p.state === "failed" || p.state === "reclaimed" ? "closed" : "open";
|
|
27218
27283
|
return {
|
|
27219
27284
|
...base,
|
|
@@ -27269,7 +27334,6 @@ var GroupPayments = class {
|
|
|
27269
27334
|
if (!frame || !membership) return;
|
|
27270
27335
|
const next = mergeGroupPay((await this.load(groupId)).get(frame.id), frame, author, membership.members);
|
|
27271
27336
|
if (next) await this.write(groupId, membership.me, next);
|
|
27272
|
-
await this.author();
|
|
27273
27337
|
});
|
|
27274
27338
|
}
|
|
27275
27339
|
/** Says what changed about this device's own payments in groups. The engine calls it whenever payments change. */
|
|
@@ -28208,6 +28272,8 @@ var TICK_MS = 3e4;
|
|
|
28208
28272
|
/** The contact's pointer is read this often while something is outstanding either way, else rarely. */
|
|
28209
28273
|
var POLL_BUSY_MS = 3e4;
|
|
28210
28274
|
var POLL_IDLE_MS = 3e5;
|
|
28275
|
+
/** No two reads of the contact's pointer come closer than this, whatever asked for them. */
|
|
28276
|
+
var POLL_GAP_MS = 5e3;
|
|
28211
28277
|
/** The manifest and its addresses are signed again before they get this old (they live seven days). */
|
|
28212
28278
|
var RENEW_AFTER_MS = 3456e5;
|
|
28213
28279
|
/** My pointer is published again this often while something is held, in case a relay forgot it. */
|
|
@@ -28242,6 +28308,9 @@ var HoldEngine = class {
|
|
|
28242
28308
|
/** Chats whose pointer the relays' request budget held back: it goes out as soon as the budget frees a request. */
|
|
28243
28309
|
pointerDue = /* @__PURE__ */ new Set();
|
|
28244
28310
|
retryTimer = null;
|
|
28311
|
+
/** A read the contact's word asked for, one waiting per chat, and when the last such read went out. */
|
|
28312
|
+
peerPolls = /* @__PURE__ */ new Map();
|
|
28313
|
+
lastPeerPoll = /* @__PURE__ */ new Map();
|
|
28245
28314
|
constructor(host) {
|
|
28246
28315
|
this.host = host;
|
|
28247
28316
|
}
|
|
@@ -28262,6 +28331,8 @@ var HoldEngine = class {
|
|
|
28262
28331
|
if (this.timer) clearTimeout(this.timer);
|
|
28263
28332
|
if (this.retryTimer) clearTimeout(this.retryTimer);
|
|
28264
28333
|
this.timer = this.retryTimer = null;
|
|
28334
|
+
for (const timer of this.peerPolls.values()) clearTimeout(timer);
|
|
28335
|
+
this.peerPolls.clear();
|
|
28265
28336
|
await Promise.allSettled([...this.chains.values()]);
|
|
28266
28337
|
}
|
|
28267
28338
|
serialize(linkId, run) {
|
|
@@ -28343,7 +28414,24 @@ var HoldEngine = class {
|
|
|
28343
28414
|
if (said.peerTop !== void 0 && said.peerTop > hold.inSeq) this.expecting.set(linkId, said.peerTop);
|
|
28344
28415
|
});
|
|
28345
28416
|
this.host.changed();
|
|
28346
|
-
if (this.expecting.has(linkId)) this.
|
|
28417
|
+
if (this.expecting.has(linkId)) this.peerPoll(linkId);
|
|
28418
|
+
}
|
|
28419
|
+
/**
|
|
28420
|
+
* The contact says it holds items for this side: its pointer is read soon, but at the pace the chat's own reads keep.
|
|
28421
|
+
* Only this person's action (`wake`) skips the gap; the contact's word, however often it comes, makes one read wait
|
|
28422
|
+
* per chat, never within `POLL_GAP_MS` of the last read nor within `POLL_BUSY_MS` of the last read it asked for.
|
|
28423
|
+
*/
|
|
28424
|
+
peerPoll(linkId) {
|
|
28425
|
+
if (!this.running || this.peerPolls.has(linkId)) return;
|
|
28426
|
+
const at = Math.max((this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS, (this.lastPeerPoll.get(linkId) ?? -Infinity) + POLL_BUSY_MS);
|
|
28427
|
+
this.peerPolls.set(linkId, setTimeout(() => {
|
|
28428
|
+
this.peerPolls.delete(linkId);
|
|
28429
|
+
const hold = this.state(linkId);
|
|
28430
|
+
if (!this.running || !this.expecting.has(linkId) || !hold.enabled || !hold.peerAllows || !this.keysFor(linkId)) return;
|
|
28431
|
+
if ((this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS > this.now()) return this.peerPoll(linkId);
|
|
28432
|
+
this.lastPeerPoll.set(linkId, this.now());
|
|
28433
|
+
this.serialize(linkId, () => this.poll(linkId)).catch(() => {});
|
|
28434
|
+
}, Math.max(0, at - this.now())));
|
|
28347
28435
|
}
|
|
28348
28436
|
/** Ways of paying the contact allowed at the last session, whatever the hold settings; undefined before any. */
|
|
28349
28437
|
lastPeerMethods(linkId) {
|
|
@@ -28560,6 +28648,9 @@ var HoldEngine = class {
|
|
|
28560
28648
|
this.errors.delete(linkId);
|
|
28561
28649
|
this.chains.delete(linkId);
|
|
28562
28650
|
this.pointerDue.delete(linkId);
|
|
28651
|
+
clearTimeout(this.peerPolls.get(linkId));
|
|
28652
|
+
this.peerPolls.delete(linkId);
|
|
28653
|
+
this.lastPeerPoll.delete(linkId);
|
|
28563
28654
|
}
|
|
28564
28655
|
/**
|
|
28565
28656
|
* Publishes my pointer. One the relays' request budget held back is no failure: the item is stored, the pointer is
|
|
@@ -28661,7 +28752,7 @@ var HoldEngine = class {
|
|
|
28661
28752
|
await this.serialize(linkId, () => this.maintain(linkId)).catch(() => {});
|
|
28662
28753
|
const busy = hold.outbox.some((e) => e.state !== "failed") || this.expecting.has(linkId);
|
|
28663
28754
|
const due = (this.lastPoll.get(linkId) ?? 0) + (busy ? POLL_BUSY_MS : POLL_IDLE_MS) <= this.now();
|
|
28664
|
-
if (hold.peerAllows && (all || due) && (this.lastPoll.get(linkId) ?? 0) +
|
|
28755
|
+
if (hold.peerAllows && (all || due) && (this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS <= this.now()) await this.serialize(linkId, () => this.poll(linkId)).catch(() => {});
|
|
28665
28756
|
}
|
|
28666
28757
|
if (this.running) this.timer = setTimeout(() => void this.tick(), TICK_MS);
|
|
28667
28758
|
}
|
|
@@ -30841,6 +30932,9 @@ var CashuWallet = class CashuWallet {
|
|
|
30841
30932
|
});
|
|
30842
30933
|
const written = (await this.swapsAt(mint)).filter((s) => s.kind === "receive");
|
|
30843
30934
|
let swap = written.find((s) => s.token === token);
|
|
30935
|
+
const own = payment?.(0, mint);
|
|
30936
|
+
const sameRecord = (a, b) => a?.id === b?.id && a?.linkId === b?.linkId && a?.direction === b?.direction;
|
|
30937
|
+
if (swap && !sameRecord(swap.payment, own)) throw engineError("ecashBeingReceived");
|
|
30844
30938
|
if (swap?.finished) return {
|
|
30845
30939
|
amount: swap.tx?.amount ?? 0,
|
|
30846
30940
|
mint,
|
|
@@ -31621,6 +31715,18 @@ var METHOD_NAME = {
|
|
|
31621
31715
|
var allows = (link, method) => method === "arkade" ? link.supportsArkPayments : method === "bark" ? link.supportsBarkPayments : method === "bitcoin" ? link.supportsBitcoinPayments : method === "fedimint" ? link.supportsFedimintPayments : method === "spark" ? link.supportsSparkPayments : link.supportsUsdtPayments;
|
|
31622
31716
|
/** Federation ecash is counted in msats; a chat counts whole sats. */
|
|
31623
31717
|
var fedimintSats = (msats) => Math.floor(msats / 1e3);
|
|
31718
|
+
/**
|
|
31719
|
+
* Which notes these are, whatever the spelling: the Fedimint client drops whitespace anywhere and reads URL-safe or
|
|
31720
|
+
* standard base64, so the digest is of the bytes. Text that is no base64 is digested without its whitespace.
|
|
31721
|
+
*/
|
|
31722
|
+
function fedimintNotesDigest(notes) {
|
|
31723
|
+
const text = notes.replace(/\s+/g, "");
|
|
31724
|
+
try {
|
|
31725
|
+
return digestHex(toBase64Url(fromBase64Url(text.replace(/=+$/, ""))));
|
|
31726
|
+
} catch {
|
|
31727
|
+
return digestHex(text);
|
|
31728
|
+
}
|
|
31729
|
+
}
|
|
31624
31730
|
/** The distinct wallets of a per-network set (one object may stand for both). */
|
|
31625
31731
|
var distinct = (each) => [...new Set(WALLET_NETWORKS.map((n) => each[n]))];
|
|
31626
31732
|
/**
|
|
@@ -33634,8 +33740,9 @@ var PaymentDesk = class {
|
|
|
33634
33740
|
await refuse(`${networkLabel(walletNetworkOf(network))} Fedimint is off in this chat`);
|
|
33635
33741
|
return;
|
|
33636
33742
|
}
|
|
33637
|
-
const digest =
|
|
33638
|
-
const
|
|
33743
|
+
const digest = fedimintNotesDigest(notes);
|
|
33744
|
+
const spelled = digestHex(notes.trim());
|
|
33745
|
+
const before = [...this.payments.values()].find((p) => (p.notesDigest === digest || p.notesDigest === spelled) && p.direction === "in" && p.kind === "payment");
|
|
33639
33746
|
if (before) {
|
|
33640
33747
|
link.sendPaymentResult({
|
|
33641
33748
|
id: payment.id,
|
|
@@ -34511,6 +34618,11 @@ var DEFAULT_SETTINGS = {
|
|
|
34511
34618
|
var CARD_RESTORE_MOST = 50;
|
|
34512
34619
|
var CARD_RESTORE_MS = 6048e5;
|
|
34513
34620
|
/**
|
|
34621
|
+
* A look for those cards reads the chat's whole history, so a chat starts one at a time, at most once this often: a
|
|
34622
|
+
* contact that says `edit/1` again and again on a session gets one look now and one more after the gap, whatever the count.
|
|
34623
|
+
*/
|
|
34624
|
+
var CARD_RESTORE_EVERY_MS = 3e4;
|
|
34625
|
+
/**
|
|
34514
34626
|
* A round trip that moved is shown at once, and written to disk by itself (relaxed, no disk sync of its own) at most
|
|
34515
34627
|
* this often: a 15 s sample on an internet path moves by 10 ms most of the time. A power cut loses at most this much
|
|
34516
34628
|
* of the round trip's drift, never a row; any other change to the story writes the latest round trip with it.
|
|
@@ -34567,6 +34679,8 @@ var SPARE_INVITE_WARM_AFTER_TAKE_MS = 3e4;
|
|
|
34567
34679
|
* first 11 s, and read nothing more for the rest of the minute, the others' answers included (bug hunt r7a, 2026-09-29).
|
|
34568
34680
|
*/
|
|
34569
34681
|
var STARTUP_QUIET_MS = 15e3;
|
|
34682
|
+
/** At start, how long links start in one task before the page gets the thread back (`startNow`). */
|
|
34683
|
+
var START_SLICE_MS = 10;
|
|
34570
34684
|
var SPARE_INVITE_MAX_AGE_MS = 9e5;
|
|
34571
34685
|
/** How far before this clock a warm packet is dated (`warmKey`): further than a contact's clock is ever behind. */
|
|
34572
34686
|
var WARM_DATED_BACK_MS = 864e5;
|
|
@@ -34709,8 +34823,12 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34709
34823
|
/** Other profiles of this device, looked at for new messages (WISP 04 § Checking other profiles). */
|
|
34710
34824
|
profilePeek;
|
|
34711
34825
|
/** Whether this device's WebRTC attempts say direct connections are blocked on its network (`directPath.ts`). */
|
|
34712
|
-
directPath = new DirectPathWatch(() => {
|
|
34713
|
-
if (
|
|
34826
|
+
directPath = new DirectPathWatch((blocked) => {
|
|
34827
|
+
if (this.shuttingDown) return;
|
|
34828
|
+
this.emitState();
|
|
34829
|
+
if (blocked) {
|
|
34830
|
+
for (const [linkId, live] of this.links) if (live.stored.group && !live.link?.isDataLinkOpen) this.edgeWithoutRtc(linkId);
|
|
34831
|
+
}
|
|
34714
34832
|
});
|
|
34715
34833
|
/** Whether this device's clock seems to be off, from what the relays' answers and several contacts' packets say (`clockWatch.ts`). */
|
|
34716
34834
|
clock = new ClockWatch(() => {
|
|
@@ -34720,9 +34838,11 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34720
34838
|
/**
|
|
34721
34839
|
* Edges of groups whose WebRTC did not connect (`edgeWithoutRtc`): they go on as an app with no WebRTC does, over a
|
|
34722
34840
|
* native transport, until the member is seen online again after a packet said it was gone (`away`, `edgeRtcPresence`).
|
|
34723
|
-
* Not kept: the next start tries WebRTC first again.
|
|
34841
|
+
* Not kept: the next start tries WebRTC first again. `held`: it stays native on a return too, until the network changes.
|
|
34724
34842
|
*/
|
|
34725
34843
|
edgeRtcOff = /* @__PURE__ */ new Map();
|
|
34844
|
+
/** Edges put back on WebRTC by a return (`edgeRtcPresence`) since the network last changed: failing again holds them native. */
|
|
34845
|
+
edgeRtcRetried = /* @__PURE__ */ new Set();
|
|
34726
34846
|
pollIntervals;
|
|
34727
34847
|
localFetch;
|
|
34728
34848
|
links = /* @__PURE__ */ new Map();
|
|
@@ -34814,6 +34934,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34814
34934
|
outboxes = /* @__PURE__ */ new Map();
|
|
34815
34935
|
/** My edits on their way, per 1:1 chat (WISP 400 § Edits). */
|
|
34816
34936
|
editQueues = /* @__PURE__ */ new Map();
|
|
34937
|
+
/** Per 1:1 chat, its look for cards to send again (`restoreCardsSoon`): when the last began, and what waits. */
|
|
34938
|
+
cardRestores = /* @__PURE__ */ new Map();
|
|
34817
34939
|
/** The contacts' edits of messages not here yet. */
|
|
34818
34940
|
editBuffer = new EditBuffer();
|
|
34819
34941
|
/** Received status card updates, applied at most once a second per message (WISP 405 · Status Cards). */
|
|
@@ -35380,7 +35502,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
35380
35502
|
subject
|
|
35381
35503
|
}),
|
|
35382
35504
|
publish: (seed, records) => this.transport.publish(identityFromSeed(seed), records),
|
|
35383
|
-
resolve: async (key) => (await this.transport.resolve(key))?.records ?? null
|
|
35505
|
+
resolve: async (key) => (await this.transport.resolve(key, { background: true }))?.records ?? null
|
|
35384
35506
|
});
|
|
35385
35507
|
/** The profile's did:dht: a key of its own, public, never tied to a chat (WISP 310-did-dht). */
|
|
35386
35508
|
did = new ProfileDid({
|
|
@@ -35935,7 +36057,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
35935
36057
|
const fresh = !this.walletFeedbackIds.has(tx.id);
|
|
35936
36058
|
this.walletFeedbackIds.add(tx.id);
|
|
35937
36059
|
if (this.walletFeedbackReady && fresh && tx.amount > 0 && tx.timestamp >= this.feedbackStartedAt) {
|
|
35938
|
-
if (tx.kind === "lightning-in" || tx.kind === "ecash-in") this.feedback("coin", tx.id, void 0, false, tx.note === "Test coins from the test mint" ? "testcoins" : void 0);
|
|
36060
|
+
if (tx.kind === "lightning-in" || tx.kind === "ecash-in") this.feedback("coin", tx.id, void 0, false, tx.kind === "lightning-in" && tx.note === "Test coins from the test mint" ? "testcoins" : void 0);
|
|
35939
36061
|
if (tx.kind === "lightning-out") this.feedback("confirmed", tx.id);
|
|
35940
36062
|
}
|
|
35941
36063
|
}
|
|
@@ -36074,12 +36196,16 @@ var GhostlyNode = class GhostlyNode {
|
|
|
36074
36196
|
if (note) this.reactionNotes.set(`group:${group.id}`, note);
|
|
36075
36197
|
}
|
|
36076
36198
|
this.publicProfiles.start();
|
|
36199
|
+
const pause = pacer(START_SLICE_MS);
|
|
36077
36200
|
if (this.networkOn) for (const linkId of this.nativeStartOrder([...history.keys()])) {
|
|
36201
|
+
if (!this.networkOn || this.shuttingDown) break;
|
|
36078
36202
|
const messages = history.get(linkId);
|
|
36079
36203
|
if (!this.links.has(linkId)) continue;
|
|
36080
36204
|
this.startLink(linkId, messages);
|
|
36081
36205
|
if (!this.links.get(linkId)?.stored.group) this.refreshPublicProfiles({ linkId }).catch(() => {});
|
|
36206
|
+
await pause();
|
|
36082
36207
|
}
|
|
36208
|
+
if (this.shuttingDown) return;
|
|
36083
36209
|
this.emitState();
|
|
36084
36210
|
if (this.networkOn) {
|
|
36085
36211
|
this.hold.start();
|
|
@@ -36512,6 +36638,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
36512
36638
|
this.publicProfiles.stop();
|
|
36513
36639
|
this.publicActivity.clear();
|
|
36514
36640
|
for (const queue of this.editQueues.values()) queue.stop();
|
|
36641
|
+
for (const restore of this.cardRestores.values()) clearTimeout(restore.timer);
|
|
36642
|
+
this.cardRestores.clear();
|
|
36515
36643
|
this.groupEdits.stop();
|
|
36516
36644
|
this.reactions.stop();
|
|
36517
36645
|
this.cardEdits.stop();
|
|
@@ -37468,11 +37596,13 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37468
37596
|
this.outboxes.delete(linkId);
|
|
37469
37597
|
this.editQueues.get(linkId)?.stop();
|
|
37470
37598
|
this.editQueues.delete(linkId);
|
|
37599
|
+
clearTimeout(this.cardRestores.get(linkId)?.timer);
|
|
37600
|
+
this.cardRestores.delete(linkId);
|
|
37471
37601
|
this.editBuffer.forget(linkId);
|
|
37472
37602
|
live.carried?.stop();
|
|
37603
|
+
this.links.delete(linkId);
|
|
37473
37604
|
live.link?.stop(true);
|
|
37474
37605
|
live.caps?.stop();
|
|
37475
|
-
this.links.delete(linkId);
|
|
37476
37606
|
this.identities.forget(linkId);
|
|
37477
37607
|
this.nostrSocial.forgetLink(linkId);
|
|
37478
37608
|
this.hold.forgetLink(linkId);
|
|
@@ -37487,9 +37617,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37487
37617
|
renameLink({ linkId, label }) {
|
|
37488
37618
|
const live = this.links.get(linkId);
|
|
37489
37619
|
if (!live) return;
|
|
37620
|
+
const clean = sanitizeDisplayText(label.trim().replace(/\s+/gu, " "), 48)?.replace(/ {2,}/g, " ");
|
|
37490
37621
|
live.stored = {
|
|
37491
37622
|
...live.stored,
|
|
37492
|
-
label:
|
|
37623
|
+
label: clean
|
|
37493
37624
|
};
|
|
37494
37625
|
db.patchLink(linkId, { label: live.stored.label });
|
|
37495
37626
|
this.emitState();
|
|
@@ -37519,6 +37650,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37519
37650
|
this.transport.networkChanged?.();
|
|
37520
37651
|
this.directPath.reset();
|
|
37521
37652
|
}
|
|
37653
|
+
if (params.network) {
|
|
37654
|
+
for (const off of this.edgeRtcOff.values()) off.held = false;
|
|
37655
|
+
this.edgeRtcRetried.clear();
|
|
37656
|
+
}
|
|
37522
37657
|
if (params.network) for (const failed of this.nativeFailed.values()) {
|
|
37523
37658
|
failed.at = 0;
|
|
37524
37659
|
failed.wait = 0;
|
|
@@ -38009,6 +38144,42 @@ var GhostlyNode = class GhostlyNode {
|
|
|
38009
38144
|
}
|
|
38010
38145
|
if (changed.length) await this.messagesChanged(linkId, changed);
|
|
38011
38146
|
}
|
|
38147
|
+
/**
|
|
38148
|
+
* `restoreCards`, then what waits goes. One look at a time per chat, at most once per `CARD_RESTORE_EVERY_MS`: asked
|
|
38149
|
+
* again while one runs or within the gap, one more look goes once it is over, and what waits still goes at once (the
|
|
38150
|
+
* edit queue reads the history once a session).
|
|
38151
|
+
*/
|
|
38152
|
+
restoreCardsSoon(linkId) {
|
|
38153
|
+
const flush = () => this.editsFor(linkId).flush().catch(() => {});
|
|
38154
|
+
let state = this.cardRestores.get(linkId);
|
|
38155
|
+
if (!state) this.cardRestores.set(linkId, state = {
|
|
38156
|
+
at: -Infinity,
|
|
38157
|
+
busy: false,
|
|
38158
|
+
again: false
|
|
38159
|
+
});
|
|
38160
|
+
if (state.busy) {
|
|
38161
|
+
state.again = true;
|
|
38162
|
+
return;
|
|
38163
|
+
}
|
|
38164
|
+
const wait = state.at + CARD_RESTORE_EVERY_MS - Date.now();
|
|
38165
|
+
if (wait > 0) {
|
|
38166
|
+
state.timer ??= setTimeout(() => {
|
|
38167
|
+
state.timer = void 0;
|
|
38168
|
+
if (this.cardRestores.get(linkId) === state) this.restoreCardsSoon(linkId);
|
|
38169
|
+
}, wait);
|
|
38170
|
+
flush();
|
|
38171
|
+
return;
|
|
38172
|
+
}
|
|
38173
|
+
state.busy = true;
|
|
38174
|
+
state.at = Date.now();
|
|
38175
|
+
this.restoreCards(linkId).catch(() => {}).then(flush).finally(() => {
|
|
38176
|
+
state.busy = false;
|
|
38177
|
+
if (state.again && this.cardRestores.get(linkId) === state) {
|
|
38178
|
+
state.again = false;
|
|
38179
|
+
this.restoreCardsSoon(linkId);
|
|
38180
|
+
}
|
|
38181
|
+
});
|
|
38182
|
+
}
|
|
38012
38183
|
/** My edits in one 1:1 chat on their way to the contact. */
|
|
38013
38184
|
editsFor(linkId) {
|
|
38014
38185
|
let queue = this.editQueues.get(linkId);
|
|
@@ -39962,8 +40133,15 @@ var GhostlyNode = class GhostlyNode {
|
|
|
39962
40133
|
if (typing === true && this.settings.sendTyping !== false) this.groups.setTyping(groupId, true, typingActivity(kind, status));
|
|
39963
40134
|
else this.groups.setTyping(groupId, false);
|
|
39964
40135
|
}
|
|
40136
|
+
/**
|
|
40137
|
+
* A call's signaling: read the contact's record fast, for its `_call`. A compatibility chat's only: a paired chat's
|
|
40138
|
+
* signals go only over its live session (WISP 601), so a read finds nothing for the call, and its data link keeps
|
|
40139
|
+
* its own fast reads (an offer's look would be cut short by a call's `fast: false`).
|
|
40140
|
+
*/
|
|
39965
40141
|
setFastPoll({ linkId, fast }) {
|
|
39966
|
-
this.links.get(linkId)
|
|
40142
|
+
const live = this.links.get(linkId);
|
|
40143
|
+
if (live?.stored.profile) return;
|
|
40144
|
+
live?.link?.session.setFastPoll(fast);
|
|
39967
40145
|
}
|
|
39968
40146
|
/** Used by the viewer: a request to a service some peer shares with us. */
|
|
39969
40147
|
async request(peerPubKeyZ32, serviceId, request) {
|
|
@@ -40224,7 +40402,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
40224
40402
|
for (const url of defaults) try {
|
|
40225
40403
|
answered.push((await this.wallet.checkMint(url)).url);
|
|
40226
40404
|
} catch (error) {
|
|
40227
|
-
|
|
40405
|
+
const unreachable = error instanceof Error ? parseEngineError(error.message) : null;
|
|
40406
|
+
last = unreachable?.code === "mintUnreachable" ? Object.assign(engineError("hostUnreachable", unreachable.values), { cause: error }) : error;
|
|
40228
40407
|
}
|
|
40229
40408
|
if (!answered.length) throw last instanceof Error ? last : /* @__PURE__ */ new Error("No mint answered");
|
|
40230
40409
|
await this.updateSettings({ settings: {
|
|
@@ -41902,6 +42081,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
41902
42081
|
if (!live?.stored.group) return;
|
|
41903
42082
|
this.links.delete(linkId);
|
|
41904
42083
|
this.edgeRtcOff.delete(linkId);
|
|
42084
|
+
this.edgeRtcRetried.delete(linkId);
|
|
41905
42085
|
this.groupWakeReceived.delete(linkId);
|
|
41906
42086
|
this.quietEdges.delete(linkId);
|
|
41907
42087
|
this.groupNativeWaiting.delete(linkId);
|
|
@@ -42182,15 +42362,19 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42182
42362
|
},
|
|
42183
42363
|
onDirectEvidence: (evidence) => {
|
|
42184
42364
|
this.directPath.note(peer, evidence);
|
|
42185
|
-
if (
|
|
42365
|
+
if (evidence !== "open" && evidence !== "closed") this.edgeWithoutRtc(linkId);
|
|
42186
42366
|
},
|
|
42187
42367
|
onAnswersRefused: () => {
|
|
42188
|
-
|
|
42368
|
+
this.edgeWithoutRtc(linkId);
|
|
42189
42369
|
},
|
|
42190
42370
|
onDataLinkState: (state) => {
|
|
42191
42371
|
traceJoin(group, `link.${state}`, { role });
|
|
42192
42372
|
if (state === "open" || live.dataLink === "open") live.lastSyncAt = Date.now();
|
|
42193
42373
|
if (state === "open" && !entry) this.groups.edgeOpen(group, peer);
|
|
42374
|
+
if (state === "open") {
|
|
42375
|
+
const off = this.edgeRtcOff.get(linkId);
|
|
42376
|
+
if (off) off.held = true;
|
|
42377
|
+
}
|
|
42194
42378
|
if (state === "open" && !entry && member()) this.desk.replay(linkId).catch(() => {});
|
|
42195
42379
|
live.dataLink = state;
|
|
42196
42380
|
if (entry && state !== "open" && live.entryDone) this.closeGroupLink(linkId).catch(() => {});
|
|
@@ -42232,13 +42416,19 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42232
42416
|
* app with no WebRTC (WISP 902 § Transports): it runs its native endpoints and says so in its packet (`_tr`, with no
|
|
42233
42417
|
* `webrtc/1`), the member's app starts its own for it as it does for a Linux Desktop, and the two meet over Iroh
|
|
42234
42418
|
* through its relay. Until the member comes back (`edgeRtcPresence`), or for this run of the app.
|
|
42419
|
+
* An entry session of a group's link too: there, the admin's packet was seen and the session never went live, and the
|
|
42420
|
+
* join stayed at "Let in: getting the group's keys" for as long as the joiner waited (2026-10-16).
|
|
42235
42421
|
*/
|
|
42236
42422
|
async edgeWithoutRtc(linkId) {
|
|
42237
42423
|
const live = this.links.get(linkId);
|
|
42238
|
-
if (!live?.link || !live.stored.group ||
|
|
42424
|
+
if (!live?.link || !live.stored.group || this.shuttingDown || this.options.webrtcGroupLinks) return;
|
|
42239
42425
|
if (this.edgeRtcOff.has(linkId) || this.keepsGroupNative(live.stored) || !Object.keys(this.nativeFactories).length) return;
|
|
42240
|
-
this.edgeRtcOff.set(linkId, {
|
|
42426
|
+
this.edgeRtcOff.set(linkId, {
|
|
42427
|
+
away: false,
|
|
42428
|
+
held: this.edgeRtcRetried.has(linkId)
|
|
42429
|
+
});
|
|
42241
42430
|
traceLink(live.myPubKeyZ32, "edge-rtc-off", {});
|
|
42431
|
+
if (live.stored.groupEntry) traceJoin(live.stored.group, "link.native", { role: live.stored.groupEntry });
|
|
42242
42432
|
await this.restartEdge(linkId);
|
|
42243
42433
|
}
|
|
42244
42434
|
/**
|
|
@@ -42247,7 +42437,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42247
42437
|
* not a network that blocks direct connections. Held native for this whole run, the edge said so in its packet, the
|
|
42248
42438
|
* member's app followed on its next starts, and past the group links' native slots members stayed unreachable for as
|
|
42249
42439
|
* long as this app ran (2026-10-09). The edge tries WebRTC again, its `_tr` with `webrtc/1` again (WISP 902 §
|
|
42250
|
-
* Transports)
|
|
42440
|
+
* Transports). Not an edge held native (`held`: it failed again after a return, or went live natively), nor while
|
|
42441
|
+
* this device's attempts say its network blocks direct connections: a member's packet that carries a WebRTC signal
|
|
42442
|
+
* and its `_tr` can leave its `_svc` out for size and read as gone, and on a VPN each such return put the edge back on
|
|
42443
|
+
* a WebRTC that died again (2026-10-16). A network that really blocks it costs one more failed attempt per network.
|
|
42251
42444
|
*/
|
|
42252
42445
|
edgeRtcPresence(linkId, presence) {
|
|
42253
42446
|
const off = this.edgeRtcOff.get(linkId);
|
|
@@ -42256,9 +42449,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42256
42449
|
off.away = true;
|
|
42257
42450
|
return;
|
|
42258
42451
|
}
|
|
42259
|
-
if (!off.away) return;
|
|
42452
|
+
if (!off.away || off.held || this.directPath.blocked) return;
|
|
42260
42453
|
const live = this.links.get(linkId);
|
|
42261
42454
|
this.edgeRtcOff.delete(linkId);
|
|
42455
|
+
this.edgeRtcRetried.add(linkId);
|
|
42262
42456
|
if (live) traceLink(live.myPubKeyZ32, "edge-rtc-back", {});
|
|
42263
42457
|
this.groupNativeWaiting.delete(linkId);
|
|
42264
42458
|
this.nativeFailed.delete(linkId);
|
|
@@ -42273,6 +42467,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42273
42467
|
await link.stop(false).catch(() => {});
|
|
42274
42468
|
if (this.links.get(linkId) !== live || live.link || this.shuttingDown || !this.networkOn) return;
|
|
42275
42469
|
this.startEdge(linkId);
|
|
42470
|
+
if (live.stored.groupEntry) this.links.get(linkId)?.link?.expectPeer();
|
|
42276
42471
|
}
|
|
42277
42472
|
startLink(linkId, messages) {
|
|
42278
42473
|
const live = this.links.get(linkId);
|
|
@@ -42510,7 +42705,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42510
42705
|
onMessageEdit: stored.profile && !stored.group ? (edit) => this.receiveEdit(linkId, edit) : void 0,
|
|
42511
42706
|
onEditReceipt: stored.profile && !stored.group ? (id, e) => this.editsFor(linkId).received(id, e) : void 0,
|
|
42512
42707
|
onEditSupport: (supported) => {
|
|
42513
|
-
if (supported && stored.profile && !stored.group) this.
|
|
42708
|
+
if (supported && stored.profile && !stored.group) this.restoreCardsSoon(linkId);
|
|
42514
42709
|
},
|
|
42515
42710
|
onWakeSupport: (supported) => {
|
|
42516
42711
|
if (supported && stored.profile && !stored.group) this.shareWake(linkId);
|
|
@@ -42536,6 +42731,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42536
42731
|
if (peer && !live.stored.group) this.clock.peer(peer, packetAt, readBefore, readAt);
|
|
42537
42732
|
},
|
|
42538
42733
|
onDataLinkState: (state) => {
|
|
42734
|
+
if (this.links.get(linkId) !== live) return;
|
|
42539
42735
|
const was = live.dataLink;
|
|
42540
42736
|
live.dataLink = state;
|
|
42541
42737
|
if (state === "open") {
|
|
@@ -42645,10 +42841,12 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42645
42841
|
return held.digest;
|
|
42646
42842
|
},
|
|
42647
42843
|
onFileIncoming: (file) => this.receiveFile(linkId, file),
|
|
42844
|
+
onFileRoom: async () => (await fileBytes()).room(),
|
|
42648
42845
|
onFileProgress: (id, transferred, direction) => this.fileProgress(this.localFileId(linkId, id, direction), transferred),
|
|
42649
42846
|
onFileComplete: (id, direction) => this.fileSettled(this.localFileId(linkId, id, direction, { failed: false }), void 0, linkId),
|
|
42650
42847
|
onFilesFrame: (frame) => this.fileDesk.handle(linkId, frame),
|
|
42651
42848
|
onFilesSession: (open) => {
|
|
42849
|
+
if (this.links.get(linkId) !== live) return;
|
|
42652
42850
|
this.fileDesk.session(linkId, open);
|
|
42653
42851
|
if (open) this.sayWithdrawnFiles(linkId);
|
|
42654
42852
|
},
|
|
@@ -42782,7 +42980,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42782
42980
|
get nativeFactories() {
|
|
42783
42981
|
const relay = this.relaysHyperdht ? this.hyperdhtRelay : "";
|
|
42784
42982
|
return {
|
|
42785
|
-
...relay ? { "hyperdht/1": async (seedB64) => (await import("./hyperdhtRelay-
|
|
42983
|
+
...relay ? { "hyperdht/1": async (seedB64) => (await import("./hyperdhtRelay-D0MvfMzX.js")).createRelayedHyperEndpoint(seedB64, relay) } : {},
|
|
42786
42984
|
...this.options.nativeTransports,
|
|
42787
42985
|
...this.ownIrohRelays ? { "iroh/1": (seedB64) => this.options.nativeTransports["iroh/1"](seedB64, this.settings.irohRelays?.length ? { relays: [...this.settings.irohRelays] } : {}) } : {},
|
|
42788
42986
|
...this.options.irohWeb ? { "iroh/1": (seedB64) => createIrohWebEndpoint(seedB64, { relays: this.irohRelays }) } : {}
|
|
@@ -43631,4 +43829,4 @@ function signalKind(signal) {
|
|
|
43631
43829
|
//#endregion
|
|
43632
43830
|
export { EngineServer };
|
|
43633
43831
|
|
|
43634
|
-
//# sourceMappingURL=server-
|
|
43832
|
+
//# sourceMappingURL=server-C05N9q4G.js.map
|