@ghostlytools/cli 1.3.1 → 1.3.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/README.md +6 -6
- package/dist/assets/{api-Dq2QXQDk.js → api-B1fADtqd.js} +65 -20
- package/dist/assets/api-B1fADtqd.js.map +1 -0
- package/dist/assets/{api-TiB5QSG9.js → api-Bg7bh_6E.js} +2 -2
- package/dist/assets/{apiKit-CA2x5GJF.js → apiKit-BsUZPHLn.js} +44 -33
- package/dist/assets/apiKit-BsUZPHLn.js.map +1 -0
- package/dist/assets/{apps-BxV9i_Y4.js → apps-BaUNt-5c.js} +91 -24
- package/dist/assets/apps-BaUNt-5c.js.map +1 -0
- package/dist/assets/{apps-C-T8jeji.js → apps-DepomCiX.js} +1 -1
- package/dist/assets/{arkade-C_qDmHnm.js → arkade-CNnMaoEQ.js} +4 -4
- package/dist/assets/arkade-CNnMaoEQ.js.map +1 -0
- package/dist/assets/{backup-Bugnn3Ue.js → backup-B5Q1W-Ey.js} +1 -1
- package/dist/assets/{backup-CnMN2oUK.js → backup-Bbz3lyC5.js} +6 -6
- package/dist/assets/{backup-CnMN2oUK.js.map → backup-Bbz3lyC5.js.map} +1 -1
- package/dist/assets/buttons-CUd7j0ZA.js +2 -0
- package/dist/assets/{buttons-CvNBzh2S.js → buttons-DS1iURp8.js} +4 -4
- package/dist/assets/{buttons-CvNBzh2S.js.map → buttons-DS1iURp8.js.map} +1 -1
- package/dist/assets/{envelope-WjingYSc.js → envelope-fNC941z4.js} +2 -2
- package/dist/assets/{envelope-WjingYSc.js.map → envelope-fNC941z4.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/{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-IEUW3DQz.js → groupFiles-6qnLCnOm.js} +82 -29
- package/dist/assets/groupFiles-6qnLCnOm.js.map +1 -0
- package/dist/assets/{host-CWt-jtqz.js → host-Dj3C1fn3.js} +305 -68
- package/dist/assets/host-Dj3C1fn3.js.map +1 -0
- package/dist/assets/{hyperdhtRelay-CPYwSLLS.js → hyperdhtRelay-CrgYQN-g.js} +2 -2
- package/dist/assets/{hyperdhtRelay-CPYwSLLS.js.map → hyperdhtRelay-CrgYQN-g.js.map} +1 -1
- package/dist/assets/{irohWeb-4oChIOIp.js → irohWeb-DSyLp5Re.js} +3 -3
- package/dist/assets/{irohWeb-4oChIOIp.js.map → irohWeb-DSyLp5Re.js.map} +1 -1
- package/dist/assets/{main-DbqcdShN.js → main-BDd11Yd1.js} +159 -54
- package/dist/assets/main-BDd11Yd1.js.map +1 -0
- package/dist/assets/{mainline-ZkiOnevs.js → mainline-CLTo0nGa.js} +2 -2
- package/dist/assets/{mainline-ZkiOnevs.js.map → mainline-CLTo0nGa.js.map} +1 -1
- package/dist/assets/{networkReason-CetKkTPo.js → networkReason-DwcadZz5.js} +2 -2
- package/dist/assets/{networkReason-CetKkTPo.js.map → networkReason-DwcadZz5.js.map} +1 -1
- package/dist/assets/{nwc-CgkqyvsE.js → nwc-BNFyyECH.js} +3 -3
- package/dist/assets/{nwc-CgkqyvsE.js.map → nwc-BNFyyECH.js.map} +1 -1
- package/dist/assets/{nwcProvider-4eVz_8HP.js → nwcProvider-BbjJOfLD.js} +2 -2
- package/dist/assets/{nwcProvider-4eVz_8HP.js.map → nwcProvider-BbjJOfLD.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-DlAKO0Fy.js → registry-CoLHpxkb.js} +17 -32
- package/dist/assets/registry-CoLHpxkb.js.map +1 -0
- package/dist/assets/{registry-OBJBnHVQ.js → registry-DoTb6uEr.js} +1 -1
- package/dist/assets/{resolve-CouHhCpJ.js → resolve-BIDJ-UUl.js} +18 -3
- package/dist/assets/resolve-BIDJ-UUl.js.map +1 -0
- package/dist/assets/{server-Ss0gJ-nw.js → server-Bx3RGkBC.js} +380 -116
- package/dist/assets/server-Bx3RGkBC.js.map +1 -0
- package/dist/assets/{src-DDzSERyc.js → src-D7gcJElT.js} +470 -242
- package/dist/assets/src-D7gcJElT.js.map +1 -0
- package/dist/assets/{turnRefs-B87dtrHM.js → turnRefs-PN644M9o.js} +2 -2
- package/dist/assets/{turnRefs-B87dtrHM.js.map → turnRefs-PN644M9o.js.map} +1 -1
- package/dist/assets/{usdt-Fj8CQO2z.js → usdt-B2TLRlYa.js} +3 -3
- package/dist/assets/{usdt-Fj8CQO2z.js.map → usdt-B2TLRlYa.js.map} +1 -1
- package/dist/ghostly.mjs +1 -1
- package/package.json +1 -1
- package/dist/assets/api-Dq2QXQDk.js.map +0 -1
- package/dist/assets/apiKit-CA2x5GJF.js.map +0 -1
- package/dist/assets/apps-BxV9i_Y4.js.map +0 -1
- package/dist/assets/arkade-C_qDmHnm.js.map +0 -1
- package/dist/assets/buttons-Bj7Vf7Pn.js +0 -2
- package/dist/assets/ghostly_iroh_web-Dvzh3Y6E.js.map +0 -1
- package/dist/assets/groupFiles-IEUW3DQz.js.map +0 -1
- package/dist/assets/host-CWt-jtqz.js.map +0 -1
- package/dist/assets/main-DbqcdShN.js.map +0 -1
- package/dist/assets/registry-DlAKO0Fy.js.map +0 -1
- package/dist/assets/resolve-CouHhCpJ.js.map +0 -1
- package/dist/assets/server-Ss0gJ-nw.js.map +0 -1
- package/dist/assets/src-DDzSERyc.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-D7gcJElT.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-BbjJOfLD.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-DwcadZz5.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-6qnLCnOm.js";
|
|
9
|
+
import { i as fedimintDatabase, n as createIrohWebEndpoint, o as loadFedimintSdk, r as irohRelayProblem, t as DEFAULT_IROH_RELAYS } from "./irohWeb-DSyLp5Re.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-BIDJ-UUl.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-fNC941z4.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-B2TLRlYa.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-CNnMaoEQ.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. */
|
|
@@ -664,7 +664,7 @@ var checkProviders = (network, ...urls) => {
|
|
|
664
664
|
provider,
|
|
665
665
|
asset: "BTC",
|
|
666
666
|
unit: "sat",
|
|
667
|
-
address:
|
|
667
|
+
address: `${arkAddressPrefix(network)}configuration`,
|
|
668
668
|
expiresAt: Date.now() + 6e4
|
|
669
669
|
});
|
|
670
670
|
};
|
|
@@ -1253,7 +1253,7 @@ var BarkAdapter = class BarkAdapter {
|
|
|
1253
1253
|
provider,
|
|
1254
1254
|
asset: "BTC",
|
|
1255
1255
|
unit: "sat",
|
|
1256
|
-
address:
|
|
1256
|
+
address: `${barkAddressPrefix(config.network)}configuration`,
|
|
1257
1257
|
expiresAt: Date.now() + 6e4
|
|
1258
1258
|
});
|
|
1259
1259
|
}
|
|
@@ -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-DoTb6uEr.js").then((m) => {
|
|
6718
6707
|
registry = m;
|
|
6719
6708
|
for (const listener of listeners) listener();
|
|
6720
6709
|
return m;
|
|
@@ -9895,7 +9884,8 @@ async function copyForForward(sourceId, target) {
|
|
|
9895
9884
|
const source = await fileStore.get(sourceId);
|
|
9896
9885
|
if (!source?.metadata) throw new Error("The file is not on this device any more");
|
|
9897
9886
|
const size = storedSize(source);
|
|
9898
|
-
|
|
9887
|
+
const checked = source.wire3 ? source.wire3.state === "done" : !source.group || source.transfer?.state === "done";
|
|
9888
|
+
if (source.direction === "in" && !checked || await bytesHere(source) !== size) throw new Error("The file has not arrived yet");
|
|
9899
9889
|
const { file, linkId, wireId, timestamp } = target;
|
|
9900
9890
|
const metadata = {
|
|
9901
9891
|
name: file.name,
|
|
@@ -9972,7 +9962,12 @@ var APP_FETCH_LIMITS = {
|
|
|
9972
9962
|
sigBytes: 1024,
|
|
9973
9963
|
/** `ghostly-revoke.json`: at most 4096 signed revocations. */
|
|
9974
9964
|
revocationsBytes: 16777216,
|
|
9975
|
-
|
|
9965
|
+
/** How long the host has to answer (the response's headers). */
|
|
9966
|
+
timeoutMs: 3e4,
|
|
9967
|
+
/** How long the body may go without a byte: a read still arriving is never cut by the clock alone. */
|
|
9968
|
+
idleMs: 3e4,
|
|
9969
|
+
/** A whole read at most: the 16 MiB cap at about 224 kbit/s. */
|
|
9970
|
+
totalMs: 6e5
|
|
9976
9971
|
};
|
|
9977
9972
|
/** A URL this client may read an app, a store or a revocation list from. */
|
|
9978
9973
|
function isAppFetchUrl(value) {
|
|
@@ -9995,10 +9990,22 @@ function boundedAppFetch(options = {}) {
|
|
|
9995
9990
|
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");
|
|
9996
9991
|
if (options.online && !options.online()) throw new AppFetchError("offline", "Offline");
|
|
9997
9992
|
const fetcher = options.fetcher ?? globalThis.fetch.bind(globalThis);
|
|
9993
|
+
const controller = new AbortController();
|
|
9994
|
+
const cut = () => {
|
|
9995
|
+
controller.abort(new DOMException("The read took too long", "TimeoutError"));
|
|
9996
|
+
};
|
|
9997
|
+
const total = setTimeout(cut, options.totalMs ?? APP_FETCH_LIMITS.totalMs);
|
|
9998
|
+
let idle = setTimeout(cut, options.timeoutMs ?? APP_FETCH_LIMITS.timeoutMs);
|
|
9999
|
+
const heard = () => {
|
|
10000
|
+
clearTimeout(idle);
|
|
10001
|
+
idle = setTimeout(cut, options.idleMs ?? APP_FETCH_LIMITS.idleMs);
|
|
10002
|
+
};
|
|
10003
|
+
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));
|
|
10004
|
+
const { signal } = controller;
|
|
9998
10005
|
let response;
|
|
9999
10006
|
try {
|
|
10000
10007
|
response = await fetcher(url, {
|
|
10001
|
-
signal
|
|
10008
|
+
signal,
|
|
10002
10009
|
credentials: "omit",
|
|
10003
10010
|
referrerPolicy: "no-referrer",
|
|
10004
10011
|
cache: "no-store",
|
|
@@ -10006,38 +10013,55 @@ function boundedAppFetch(options = {}) {
|
|
|
10006
10013
|
...peek && { headers: { range: `bytes=0-${maxBytes - 1}` } }
|
|
10007
10014
|
});
|
|
10008
10015
|
} catch (error) {
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
if (!response.ok) {
|
|
10013
|
-
await response.body?.cancel().catch(() => {});
|
|
10014
|
-
throw new AppFetchError("status", `The host answered ${response.status}`, response.status);
|
|
10015
|
-
}
|
|
10016
|
-
if (!peek && Number(response.headers.get("content-length")) > maxBytes) {
|
|
10017
|
-
await response.body?.cancel().catch(() => {});
|
|
10018
|
-
throw new AppFetchError("too-large", "Too large");
|
|
10016
|
+
clearTimeout(total);
|
|
10017
|
+
clearTimeout(idle);
|
|
10018
|
+
throw failure(error);
|
|
10019
10019
|
}
|
|
10020
|
+
heard();
|
|
10020
10021
|
const parts = [];
|
|
10021
10022
|
let length = 0;
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10023
|
+
try {
|
|
10024
|
+
if (response.url && response.url !== url && !isAppFetchUrl(response.url)) throw new AppFetchError("host", "The host sent the request elsewhere");
|
|
10025
|
+
if (!response.ok) {
|
|
10026
|
+
await response.body?.cancel().catch(() => {});
|
|
10027
|
+
throw new AppFetchError("status", `The host answered ${response.status}`, response.status);
|
|
10028
|
+
}
|
|
10029
|
+
if (!peek && Number(response.headers.get("content-length")) > maxBytes) {
|
|
10030
|
+
await response.body?.cancel().catch(() => {});
|
|
10031
|
+
throw new AppFetchError("too-large", "Too large");
|
|
10032
|
+
}
|
|
10033
|
+
const reader = response.body?.getReader();
|
|
10034
|
+
if (reader) {
|
|
10035
|
+
const stop = () => {
|
|
10036
|
+
reader.cancel().catch(() => {});
|
|
10037
|
+
};
|
|
10038
|
+
signal.addEventListener("abort", stop);
|
|
10039
|
+
try {
|
|
10040
|
+
for (;;) {
|
|
10041
|
+
const { done, value } = await reader.read();
|
|
10042
|
+
if (signal.aborted) throw failure(signal.reason);
|
|
10043
|
+
if (done) break;
|
|
10044
|
+
heard();
|
|
10045
|
+
if (length + value.length > maxBytes) {
|
|
10046
|
+
if (!peek) throw new AppFetchError("too-large", "Too large");
|
|
10047
|
+
parts.push(value.subarray(0, maxBytes - length));
|
|
10048
|
+
length = maxBytes;
|
|
10049
|
+
break;
|
|
10050
|
+
}
|
|
10051
|
+
parts.push(value);
|
|
10052
|
+
length += value.length;
|
|
10053
|
+
}
|
|
10054
|
+
} catch (error) {
|
|
10055
|
+
if (error instanceof AppFetchError) throw error;
|
|
10056
|
+
throw failure(error);
|
|
10057
|
+
} finally {
|
|
10058
|
+
signal.removeEventListener("abort", stop);
|
|
10059
|
+
await reader.cancel().catch(() => {});
|
|
10032
10060
|
}
|
|
10033
|
-
parts.push(value);
|
|
10034
|
-
length += value.length;
|
|
10035
10061
|
}
|
|
10036
|
-
} catch (error) {
|
|
10037
|
-
if (error instanceof AppFetchError) throw error;
|
|
10038
|
-
throw new AppFetchError("network", error instanceof Error ? error.message : String(error));
|
|
10039
10062
|
} finally {
|
|
10040
|
-
|
|
10063
|
+
clearTimeout(total);
|
|
10064
|
+
clearTimeout(idle);
|
|
10041
10065
|
}
|
|
10042
10066
|
const bytes = new Uint8Array(length);
|
|
10043
10067
|
let at = 0;
|
|
@@ -10372,6 +10396,10 @@ var Apps = class {
|
|
|
10372
10396
|
/** What each `ref\0scope` holds, read once from its counter row and kept in step by the writes here. */
|
|
10373
10397
|
usage = /* @__PURE__ */ new Map();
|
|
10374
10398
|
queues = /* @__PURE__ */ new Map();
|
|
10399
|
+
/** The keys read of each `ref\0scope` running, and the one every call made while it runs shares after it. */
|
|
10400
|
+
keyReads = /* @__PURE__ */ new Map();
|
|
10401
|
+
/** Uninstalls begun per reference, for this engine's life: a storage write that waited its turn across one is refused. */
|
|
10402
|
+
uninstalls = /* @__PURE__ */ new Map();
|
|
10375
10403
|
timer = null;
|
|
10376
10404
|
/** Drops what `staged` holds past `STAGED.ms`, set while it holds anything: a closed install screen sends no call. */
|
|
10377
10405
|
sweep = null;
|
|
@@ -11659,6 +11687,8 @@ var Apps = class {
|
|
|
11659
11687
|
STORES$1.appStorage,
|
|
11660
11688
|
...builtIn ? [STORES$1.settings] : []
|
|
11661
11689
|
], "readwrite");
|
|
11690
|
+
this.uninstalls.set(ref, (this.uninstalls.get(ref) ?? 0) + 1);
|
|
11691
|
+
this.held.delete(ref);
|
|
11662
11692
|
tx.objectStore(STORES$1.apps).delete(ref);
|
|
11663
11693
|
tx.objectStore(STORES$1.appStorage).delete(rowsOf(ref));
|
|
11664
11694
|
if (builtIn) markBuiltIns(tx.objectStore(STORES$1.settings), (marks) => {
|
|
@@ -11737,6 +11767,7 @@ var Apps = class {
|
|
|
11737
11767
|
* it, so the app can make room.
|
|
11738
11768
|
*/
|
|
11739
11769
|
async storageSet({ ref, scope, key, value, digest }) {
|
|
11770
|
+
const uninstalls = this.uninstalls.get(ref);
|
|
11740
11771
|
const app = await this.runningOrFail(ref, digest);
|
|
11741
11772
|
const where = this.scopeOf(scope), name = this.keyOf(key);
|
|
11742
11773
|
let text;
|
|
@@ -11767,6 +11798,10 @@ var Apps = class {
|
|
|
11767
11798
|
this.usage.delete(`${app.ref}\0${where}`);
|
|
11768
11799
|
fail("bad-scope", "Not a chat of this profile");
|
|
11769
11800
|
}
|
|
11801
|
+
if (this.uninstalls.get(app.ref) !== uninstalls) {
|
|
11802
|
+
this.usage.delete(`${app.ref}\0${where}`);
|
|
11803
|
+
fail("not-installed", "This app is not installed");
|
|
11804
|
+
}
|
|
11770
11805
|
writing.put({
|
|
11771
11806
|
ref: app.ref,
|
|
11772
11807
|
scope: where,
|
|
@@ -11806,7 +11841,28 @@ var Apps = class {
|
|
|
11806
11841
|
}
|
|
11807
11842
|
async storageKeys({ ref, scope, digest }) {
|
|
11808
11843
|
const app = await this.runningOrFail(ref, digest);
|
|
11809
|
-
|
|
11844
|
+
const where = this.scopeOf(scope);
|
|
11845
|
+
return this.keysOnce(`${app.ref}\0${where}`, async () => {
|
|
11846
|
+
return (await wrap((await store(STORES$1.appStorage, "readonly")).getAllKeys(keysOf(app.ref, where)))).map((k) => k[2]);
|
|
11847
|
+
});
|
|
11848
|
+
}
|
|
11849
|
+
/**
|
|
11850
|
+
* One read of a scope's keys at a time. Every call made while one runs shares the single read that starts after it, so
|
|
11851
|
+
* it still sees each write done before it was made: 50 calls a second on a full scope held the profile's database,
|
|
11852
|
+
* a chat message's write waited 17 s behind them.
|
|
11853
|
+
*/
|
|
11854
|
+
keysOnce(id, read) {
|
|
11855
|
+
const waiting = this.keyReads.get(id);
|
|
11856
|
+
if (waiting) return waiting.next ??= waiting.running.then(() => this.keysStart(id, read), () => this.keysStart(id, read));
|
|
11857
|
+
return this.keysStart(id, read);
|
|
11858
|
+
}
|
|
11859
|
+
keysStart(id, read) {
|
|
11860
|
+
const slot = { running: read() };
|
|
11861
|
+
this.keyReads.set(id, slot);
|
|
11862
|
+
slot.running.catch(() => {}).then(() => {
|
|
11863
|
+
if (this.keyReads.get(id) === slot && !slot.next) this.keyReads.delete(id);
|
|
11864
|
+
});
|
|
11865
|
+
return slot.running;
|
|
11810
11866
|
}
|
|
11811
11867
|
/** An app's storage in every scope, as export files (WISP 1200 § Where installed apps live), offered before an uninstall. */
|
|
11812
11868
|
async exportData({ ref }) {
|
|
@@ -18654,6 +18710,7 @@ var FileDesk = class {
|
|
|
18654
18710
|
announced: /* @__PURE__ */ new Map(),
|
|
18655
18711
|
saving: Promise.resolve(),
|
|
18656
18712
|
lastSaved: /* @__PURE__ */ new Map(),
|
|
18713
|
+
unsaved: /* @__PURE__ */ new Map(),
|
|
18657
18714
|
files: void 0
|
|
18658
18715
|
};
|
|
18659
18716
|
made.files = new ChatFiles({
|
|
@@ -18693,6 +18750,7 @@ var FileDesk = class {
|
|
|
18693
18750
|
const chat = this.chat(linkId);
|
|
18694
18751
|
if (open) chat.files.attach();
|
|
18695
18752
|
else chat.files.detach();
|
|
18753
|
+
if (!open) for (const [id, { record }] of [...chat.unsaved]) this.save(chat, id, record);
|
|
18696
18754
|
for (const record of chat.files.records()) this.show(linkId, chat, record, chat.files.transferred(record.direction, record.id));
|
|
18697
18755
|
this.deps.changed();
|
|
18698
18756
|
}
|
|
@@ -18878,6 +18936,8 @@ var FileDesk = class {
|
|
|
18878
18936
|
const wireId = out ? fileId.slice(`${linkId}-out-`.length) : [...chat.local].find(([, local]) => local === fileId)?.[0];
|
|
18879
18937
|
if (!wireId) return;
|
|
18880
18938
|
chat.files.forget(out ? "out" : "in", wireId);
|
|
18939
|
+
clearTimeout(chat.unsaved.get(fileId)?.timer);
|
|
18940
|
+
chat.unsaved.delete(fileId);
|
|
18881
18941
|
if (!out) {
|
|
18882
18942
|
chat.local.delete(wireId);
|
|
18883
18943
|
chat.announced.delete(wireId);
|
|
@@ -18895,7 +18955,9 @@ var FileDesk = class {
|
|
|
18895
18955
|
}
|
|
18896
18956
|
/** The chat went away: its transfers stop here. */
|
|
18897
18957
|
drop(linkId) {
|
|
18898
|
-
this.chats.get(linkId)
|
|
18958
|
+
const chat = this.chats.get(linkId);
|
|
18959
|
+
chat?.files.detach();
|
|
18960
|
+
for (const { timer } of chat?.unsaved.values() ?? []) clearTimeout(timer);
|
|
18899
18961
|
this.chats.delete(linkId);
|
|
18900
18962
|
for (const id of [
|
|
18901
18963
|
...this.moved.keys(),
|
|
@@ -19081,23 +19143,45 @@ var FileDesk = class {
|
|
|
19081
19143
|
this.show(linkId, chat, record, transferred, progress);
|
|
19082
19144
|
if (offered) this.deps.flush?.();
|
|
19083
19145
|
const id = record.direction === "out" ? outgoingFileId(linkId, record.id) : chat.local.get(record.id);
|
|
19084
|
-
const now = Date.now();
|
|
19085
|
-
if (!progress || now -
|
|
19086
|
-
|
|
19087
|
-
const
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
19093
|
-
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
|
|
19146
|
+
const now = Date.now(), last = chat.lastSaved.get(id) ?? 0;
|
|
19147
|
+
if (!progress || now - last >= SAVE_EVERY_MS) this.save(chat, id, record);
|
|
19148
|
+
else {
|
|
19149
|
+
const held = chat.unsaved.get(id);
|
|
19150
|
+
if (held) held.record = record;
|
|
19151
|
+
else {
|
|
19152
|
+
const timer = setTimeout(() => {
|
|
19153
|
+
const newest = chat.unsaved.get(id);
|
|
19154
|
+
if (newest) this.save(chat, id, newest.record);
|
|
19155
|
+
}, last + SAVE_EVERY_MS - now);
|
|
19156
|
+
timer.unref?.();
|
|
19157
|
+
chat.unsaved.set(id, {
|
|
19158
|
+
record,
|
|
19159
|
+
timer
|
|
19160
|
+
});
|
|
19161
|
+
}
|
|
19097
19162
|
}
|
|
19098
19163
|
if (record.state === "done" && record.direction === "in") this.deps.wireIds(linkId)?.add(record.id);
|
|
19099
19164
|
this.deps.changed(progress ? 250 : 50);
|
|
19100
19165
|
}
|
|
19166
|
+
/** Writes a transfer's record and the view of it, after the chat's writes before it; what was held back goes with it. */
|
|
19167
|
+
save(chat, id, record) {
|
|
19168
|
+
const held = chat.unsaved.get(id);
|
|
19169
|
+
if (held) {
|
|
19170
|
+
clearTimeout(held.timer);
|
|
19171
|
+
chat.unsaved.delete(id);
|
|
19172
|
+
}
|
|
19173
|
+
chat.lastSaved.set(id, Date.now());
|
|
19174
|
+
const transfer = this.deps.transfers.get(id);
|
|
19175
|
+
chat.saving = chat.saving.then(() => fileStore.patch(id, {
|
|
19176
|
+
wire3: record,
|
|
19177
|
+
...transfer && { transfer: {
|
|
19178
|
+
state: transfer.state,
|
|
19179
|
+
transferred: transfer.transferred,
|
|
19180
|
+
size: transfer.size,
|
|
19181
|
+
error: transfer.error
|
|
19182
|
+
} }
|
|
19183
|
+
})).catch(() => {});
|
|
19184
|
+
}
|
|
19101
19185
|
show(linkId, chat, record, transferred, progress = false) {
|
|
19102
19186
|
const id = record.direction === "out" ? outgoingFileId(linkId, record.id) : chat.local.get(record.id);
|
|
19103
19187
|
if (!id) return;
|
|
@@ -23693,8 +23777,12 @@ var MeshHubs = class {
|
|
|
23693
23777
|
else if (!live.myHubs.length) for (const key of [...this.host.edges(groupId).keys(), ...hubs]) out.add(key);
|
|
23694
23778
|
else {
|
|
23695
23779
|
for (const key of live.myHubs) out.add(key);
|
|
23696
|
-
const admin = session.admin;
|
|
23697
|
-
|
|
23780
|
+
const admin = session.admin, mine = this.host.edges(groupId);
|
|
23781
|
+
const hubUp = live.myHubs.some((key) => {
|
|
23782
|
+
const id = mine.get(key);
|
|
23783
|
+
return !!id && this.host.linkReady(id);
|
|
23784
|
+
});
|
|
23785
|
+
if (admin && (legacy.includes(admin) || !hubUp)) out.add(admin);
|
|
23698
23786
|
}
|
|
23699
23787
|
if (session.isAdmin) for (const key of legacy) out.add(key);
|
|
23700
23788
|
}
|
|
@@ -24483,6 +24571,11 @@ var ACCEPT_AGAINS = 5;
|
|
|
24483
24571
|
var REWELCOME_MS = ACCEPT_AGAIN_MS / 2;
|
|
24484
24572
|
/** Invitee side: the invitations one contact chat may have waiting here at a time. More are answered as declined. */
|
|
24485
24573
|
var MAX_INVITATIONS_PER_CHAT = 4;
|
|
24574
|
+
/** Invitee side, removed and invited again: the chat that let me into the group I kept, if it is its admin's. */
|
|
24575
|
+
var keptAdminChat = (kept) => {
|
|
24576
|
+
const admin = kept?.state && rosterAdmin(kept.state.chain[kept.state.chain.length - 1].m);
|
|
24577
|
+
return admin ? kept.contacts?.[admin] : void 0;
|
|
24578
|
+
};
|
|
24486
24579
|
/** What an invitation says of its group, kept as a claim within what a group can be: an epoch from 0, a roster of 1 to the most a group holds. */
|
|
24487
24580
|
function invitationClaims(frame) {
|
|
24488
24581
|
const e = Number.isSafeInteger(frame.e) ? frame.e : 0, n = Number.isSafeInteger(frame.n) ? frame.n : 1;
|
|
@@ -25026,7 +25119,7 @@ var Groups = class {
|
|
|
25026
25119
|
const previous = group.previous;
|
|
25027
25120
|
if (!previous) return this.forget(group.id, false);
|
|
25028
25121
|
if (owed) previous.declined = owed;
|
|
25029
|
-
else delete previous.declined;
|
|
25122
|
+
else if (previous.declined?.linkId === group.invitation?.linkId) delete previous.declined;
|
|
25030
25123
|
this.acceptSaid.delete(group.id);
|
|
25031
25124
|
this.stored.set(group.id, previous);
|
|
25032
25125
|
if (previous.state) this.attach(previous.state);
|
|
@@ -25902,7 +25995,7 @@ var Groups = class {
|
|
|
25902
25995
|
return;
|
|
25903
25996
|
}
|
|
25904
25997
|
if (existing?.state && existing.state.status === "active") {
|
|
25905
|
-
if (this.sessions.get(g)?.admin === frame.admin) this.host.sendOnLink(linkId, {
|
|
25998
|
+
if (this.sessions.get(g)?.admin === frame.admin && existing.contacts?.[frame.admin] === linkId) this.host.sendOnLink(linkId, {
|
|
25906
25999
|
t: "group-decline",
|
|
25907
26000
|
g
|
|
25908
26001
|
});
|
|
@@ -25910,7 +26003,7 @@ var Groups = class {
|
|
|
25910
26003
|
}
|
|
25911
26004
|
if (existing?.invitation?.seedB64 && (existing.invitation.linkId !== linkId || existing.invitation.admin !== frame.admin)) return;
|
|
25912
26005
|
if (existing?.left && (existing.left.admin !== frame.admin || existing.contacts?.[existing.left.admin] !== linkId)) return;
|
|
25913
|
-
if (existing?.invitation && !existing.state && existing.invitation.linkId !== linkId && !existing.invitation.genesis && !existing.invitation.takenBack) return;
|
|
26006
|
+
if (existing?.invitation && !existing.state && existing.invitation.linkId !== linkId && !(existing.invitation.genesis && linkId === keptAdminChat(existing.previous)) && !existing.invitation.takenBack) return;
|
|
25914
26007
|
if ([...this.stored.values()].filter((x) => x.invitation && !x.invitation.takenBack).length >= 32) return;
|
|
25915
26008
|
if (!(existing?.invitation && !existing.invitation.takenBack && existing.invitation.linkId === linkId) && [...this.stored.values()].filter((x) => x.invitation?.linkId === linkId && !x.invitation.takenBack).length >= MAX_INVITATIONS_PER_CHAT) {
|
|
25916
26009
|
try {
|
|
@@ -26044,10 +26137,12 @@ var Groups = class {
|
|
|
26044
26137
|
const group = this.stored.get(g);
|
|
26045
26138
|
if (!group?.invitation?.seedB64 || group.invitation.linkId !== linkId || !Array.isArray(frame.commits)) return;
|
|
26046
26139
|
if (group.invitation.pieces.reduce((n, p) => n + p.commits.length, 0) + frame.commits.length > 1024) return;
|
|
26140
|
+
const commits = frame.commits.map(parseGroupCommit);
|
|
26141
|
+
if (commits.some((c) => !c || c.g !== g)) return;
|
|
26047
26142
|
group.invitation.pieces.push({
|
|
26048
26143
|
t: "group-chain",
|
|
26049
26144
|
g,
|
|
26050
|
-
commits
|
|
26145
|
+
commits
|
|
26051
26146
|
});
|
|
26052
26147
|
return;
|
|
26053
26148
|
}
|
|
@@ -26767,6 +26862,7 @@ var Groups = class {
|
|
|
26767
26862
|
attach(state, frames = []) {
|
|
26768
26863
|
const session = new GroupSession(state, {
|
|
26769
26864
|
clock: () => this.now(),
|
|
26865
|
+
nick: () => this.host.myNick?.(),
|
|
26770
26866
|
seqFloor: () => this.host.seqFloor?.() ?? 0,
|
|
26771
26867
|
adminWork: () => this.host.adminWork?.(state.id) ?? true,
|
|
26772
26868
|
adminTurn: () => this.host.adminTurn?.(state.id) ?? Promise.resolve(true),
|
|
@@ -27139,10 +27235,7 @@ function mergeGroupPay(current, frame, author, members) {
|
|
|
27139
27235
|
...next,
|
|
27140
27236
|
by: frame.by
|
|
27141
27237
|
};
|
|
27142
|
-
if (next.
|
|
27143
|
-
...next,
|
|
27144
|
-
by: next.claims[0]
|
|
27145
|
-
};
|
|
27238
|
+
if (next.from === "*" && next.rail === "lightning" && next.by) next = (({ by: _, ...rest }) => rest)(next);
|
|
27146
27239
|
if (next.state === "paid" && next.from !== "*" && !next.by) next = {
|
|
27147
27240
|
...next,
|
|
27148
27241
|
by: next.from
|
|
@@ -27173,7 +27266,7 @@ function authoredNote(p, at, all, current, memberOf = () => void 0) {
|
|
|
27173
27266
|
const from = p.group ? "*" : at.peer;
|
|
27174
27267
|
if (!from) return null;
|
|
27175
27268
|
const payment = all.find((x) => x.kind === "payment" && x.direction === "in" && x.requestId === p.id && x.state === "settled");
|
|
27176
|
-
const by = !p.group ? from : payment ? memberOf(payment.linkId) :
|
|
27269
|
+
const by = !p.group ? from : payment ? memberOf(payment.linkId) : void 0;
|
|
27177
27270
|
const st = p.state === "settled" ? "paid" : p.state === "failed" || p.state === "reclaimed" ? "closed" : "open";
|
|
27178
27271
|
return {
|
|
27179
27272
|
...base,
|
|
@@ -27229,7 +27322,6 @@ var GroupPayments = class {
|
|
|
27229
27322
|
if (!frame || !membership) return;
|
|
27230
27323
|
const next = mergeGroupPay((await this.load(groupId)).get(frame.id), frame, author, membership.members);
|
|
27231
27324
|
if (next) await this.write(groupId, membership.me, next);
|
|
27232
|
-
await this.author();
|
|
27233
27325
|
});
|
|
27234
27326
|
}
|
|
27235
27327
|
/** Says what changed about this device's own payments in groups. The engine calls it whenever payments change. */
|
|
@@ -28168,6 +28260,8 @@ var TICK_MS = 3e4;
|
|
|
28168
28260
|
/** The contact's pointer is read this often while something is outstanding either way, else rarely. */
|
|
28169
28261
|
var POLL_BUSY_MS = 3e4;
|
|
28170
28262
|
var POLL_IDLE_MS = 3e5;
|
|
28263
|
+
/** No two reads of the contact's pointer come closer than this, whatever asked for them. */
|
|
28264
|
+
var POLL_GAP_MS = 5e3;
|
|
28171
28265
|
/** The manifest and its addresses are signed again before they get this old (they live seven days). */
|
|
28172
28266
|
var RENEW_AFTER_MS = 3456e5;
|
|
28173
28267
|
/** My pointer is published again this often while something is held, in case a relay forgot it. */
|
|
@@ -28202,6 +28296,9 @@ var HoldEngine = class {
|
|
|
28202
28296
|
/** Chats whose pointer the relays' request budget held back: it goes out as soon as the budget frees a request. */
|
|
28203
28297
|
pointerDue = /* @__PURE__ */ new Set();
|
|
28204
28298
|
retryTimer = null;
|
|
28299
|
+
/** A read the contact's word asked for, one waiting per chat, and when the last such read went out. */
|
|
28300
|
+
peerPolls = /* @__PURE__ */ new Map();
|
|
28301
|
+
lastPeerPoll = /* @__PURE__ */ new Map();
|
|
28205
28302
|
constructor(host) {
|
|
28206
28303
|
this.host = host;
|
|
28207
28304
|
}
|
|
@@ -28222,6 +28319,8 @@ var HoldEngine = class {
|
|
|
28222
28319
|
if (this.timer) clearTimeout(this.timer);
|
|
28223
28320
|
if (this.retryTimer) clearTimeout(this.retryTimer);
|
|
28224
28321
|
this.timer = this.retryTimer = null;
|
|
28322
|
+
for (const timer of this.peerPolls.values()) clearTimeout(timer);
|
|
28323
|
+
this.peerPolls.clear();
|
|
28225
28324
|
await Promise.allSettled([...this.chains.values()]);
|
|
28226
28325
|
}
|
|
28227
28326
|
serialize(linkId, run) {
|
|
@@ -28303,7 +28402,24 @@ var HoldEngine = class {
|
|
|
28303
28402
|
if (said.peerTop !== void 0 && said.peerTop > hold.inSeq) this.expecting.set(linkId, said.peerTop);
|
|
28304
28403
|
});
|
|
28305
28404
|
this.host.changed();
|
|
28306
|
-
if (this.expecting.has(linkId)) this.
|
|
28405
|
+
if (this.expecting.has(linkId)) this.peerPoll(linkId);
|
|
28406
|
+
}
|
|
28407
|
+
/**
|
|
28408
|
+
* The contact says it holds items for this side: its pointer is read soon, but at the pace the chat's own reads keep.
|
|
28409
|
+
* Only this person's action (`wake`) skips the gap; the contact's word, however often it comes, makes one read wait
|
|
28410
|
+
* per chat, never within `POLL_GAP_MS` of the last read nor within `POLL_BUSY_MS` of the last read it asked for.
|
|
28411
|
+
*/
|
|
28412
|
+
peerPoll(linkId) {
|
|
28413
|
+
if (!this.running || this.peerPolls.has(linkId)) return;
|
|
28414
|
+
const at = Math.max((this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS, (this.lastPeerPoll.get(linkId) ?? -Infinity) + POLL_BUSY_MS);
|
|
28415
|
+
this.peerPolls.set(linkId, setTimeout(() => {
|
|
28416
|
+
this.peerPolls.delete(linkId);
|
|
28417
|
+
const hold = this.state(linkId);
|
|
28418
|
+
if (!this.running || !this.expecting.has(linkId) || !hold.enabled || !hold.peerAllows || !this.keysFor(linkId)) return;
|
|
28419
|
+
if ((this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS > this.now()) return this.peerPoll(linkId);
|
|
28420
|
+
this.lastPeerPoll.set(linkId, this.now());
|
|
28421
|
+
this.serialize(linkId, () => this.poll(linkId)).catch(() => {});
|
|
28422
|
+
}, Math.max(0, at - this.now())));
|
|
28307
28423
|
}
|
|
28308
28424
|
/** Ways of paying the contact allowed at the last session, whatever the hold settings; undefined before any. */
|
|
28309
28425
|
lastPeerMethods(linkId) {
|
|
@@ -28520,6 +28636,9 @@ var HoldEngine = class {
|
|
|
28520
28636
|
this.errors.delete(linkId);
|
|
28521
28637
|
this.chains.delete(linkId);
|
|
28522
28638
|
this.pointerDue.delete(linkId);
|
|
28639
|
+
clearTimeout(this.peerPolls.get(linkId));
|
|
28640
|
+
this.peerPolls.delete(linkId);
|
|
28641
|
+
this.lastPeerPoll.delete(linkId);
|
|
28523
28642
|
}
|
|
28524
28643
|
/**
|
|
28525
28644
|
* Publishes my pointer. One the relays' request budget held back is no failure: the item is stored, the pointer is
|
|
@@ -28621,7 +28740,7 @@ var HoldEngine = class {
|
|
|
28621
28740
|
await this.serialize(linkId, () => this.maintain(linkId)).catch(() => {});
|
|
28622
28741
|
const busy = hold.outbox.some((e) => e.state !== "failed") || this.expecting.has(linkId);
|
|
28623
28742
|
const due = (this.lastPoll.get(linkId) ?? 0) + (busy ? POLL_BUSY_MS : POLL_IDLE_MS) <= this.now();
|
|
28624
|
-
if (hold.peerAllows && (all || due) && (this.lastPoll.get(linkId) ?? 0) +
|
|
28743
|
+
if (hold.peerAllows && (all || due) && (this.lastPoll.get(linkId) ?? 0) + POLL_GAP_MS <= this.now()) await this.serialize(linkId, () => this.poll(linkId)).catch(() => {});
|
|
28625
28744
|
}
|
|
28626
28745
|
if (this.running) this.timer = setTimeout(() => void this.tick(), TICK_MS);
|
|
28627
28746
|
}
|
|
@@ -30801,6 +30920,9 @@ var CashuWallet = class CashuWallet {
|
|
|
30801
30920
|
});
|
|
30802
30921
|
const written = (await this.swapsAt(mint)).filter((s) => s.kind === "receive");
|
|
30803
30922
|
let swap = written.find((s) => s.token === token);
|
|
30923
|
+
const own = payment?.(0, mint);
|
|
30924
|
+
const sameRecord = (a, b) => a?.id === b?.id && a?.linkId === b?.linkId && a?.direction === b?.direction;
|
|
30925
|
+
if (swap && !sameRecord(swap.payment, own)) throw engineError("ecashBeingReceived");
|
|
30804
30926
|
if (swap?.finished) return {
|
|
30805
30927
|
amount: swap.tx?.amount ?? 0,
|
|
30806
30928
|
mint,
|
|
@@ -31581,6 +31703,18 @@ var METHOD_NAME = {
|
|
|
31581
31703
|
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;
|
|
31582
31704
|
/** Federation ecash is counted in msats; a chat counts whole sats. */
|
|
31583
31705
|
var fedimintSats = (msats) => Math.floor(msats / 1e3);
|
|
31706
|
+
/**
|
|
31707
|
+
* Which notes these are, whatever the spelling: the Fedimint client drops whitespace anywhere and reads URL-safe or
|
|
31708
|
+
* standard base64, so the digest is of the bytes. Text that is no base64 is digested without its whitespace.
|
|
31709
|
+
*/
|
|
31710
|
+
function fedimintNotesDigest(notes) {
|
|
31711
|
+
const text = notes.replace(/\s+/g, "");
|
|
31712
|
+
try {
|
|
31713
|
+
return digestHex(toBase64Url(fromBase64Url(text.replace(/=+$/, ""))));
|
|
31714
|
+
} catch {
|
|
31715
|
+
return digestHex(text);
|
|
31716
|
+
}
|
|
31717
|
+
}
|
|
31584
31718
|
/** The distinct wallets of a per-network set (one object may stand for both). */
|
|
31585
31719
|
var distinct = (each) => [...new Set(WALLET_NETWORKS.map((n) => each[n]))];
|
|
31586
31720
|
/**
|
|
@@ -32410,6 +32544,11 @@ var PaymentDesk = class {
|
|
|
32410
32544
|
return;
|
|
32411
32545
|
}
|
|
32412
32546
|
}
|
|
32547
|
+
if (target && request.network && request.network !== walletNetworkOf(target.network)) {
|
|
32548
|
+
if (!federations) return;
|
|
32549
|
+
federations = void 0;
|
|
32550
|
+
target = void 0;
|
|
32551
|
+
}
|
|
32413
32552
|
const network = request.network ?? paymentNetwork({
|
|
32414
32553
|
target,
|
|
32415
32554
|
mints: parseCashuRequestPayload(findEndpoint(request.endpoints, ENDPOINT.cashu) ?? ""),
|
|
@@ -32422,8 +32561,10 @@ var PaymentDesk = class {
|
|
|
32422
32561
|
}
|
|
32423
32562
|
const allowed = (method) => (held ? !!link?.paymentEnabled(method) : !!link?.allowsPayment(method)) && this.accepts(linkId, method, network);
|
|
32424
32563
|
const bolt11 = allowed("lightning") ? findEndpoint(request.endpoints, ENDPOINT.bolt11) : void 0;
|
|
32425
|
-
const
|
|
32426
|
-
const
|
|
32564
|
+
const decoded = bolt11 ? decodeBolt11(bolt11) : null;
|
|
32565
|
+
const chain = decoded?.network;
|
|
32566
|
+
const sameTarget = !(target?.method === "bitcoin" || target?.method === "arkade" || target?.method === "bark") || chain === "bitcoin" === (walletNetworkOf(target.network) === "mainnet");
|
|
32567
|
+
const invoice = bolt11 && decoded?.amountSat === amount && sameTarget && !(network === "mainnet" && chain && chain !== "bitcoin") ? bolt11 : void 0;
|
|
32427
32568
|
const mints = allowed("cashu") ? parseCashuRequestPayload(findEndpoint(request.endpoints, ENDPOINT.cashu) ?? "").filter((mint) => mintNetwork(mint) === network) : [];
|
|
32428
32569
|
if (!target && !invoice && !mints.length && !federations) return;
|
|
32429
32570
|
await this.save({
|
|
@@ -32518,6 +32659,14 @@ var PaymentDesk = class {
|
|
|
32518
32659
|
return;
|
|
32519
32660
|
}
|
|
32520
32661
|
const inspected = this.wallet.inspect?.(payment.endpoint[1]);
|
|
32662
|
+
if (payment.endpoint[0] === ENDPOINT.cashu && inspected !== void 0 && inspected?.kind !== "token") {
|
|
32663
|
+
link.sendPaymentResult({
|
|
32664
|
+
id: payment.id,
|
|
32665
|
+
ok: false,
|
|
32666
|
+
error: "That is not a valid ecash token"
|
|
32667
|
+
});
|
|
32668
|
+
return;
|
|
32669
|
+
}
|
|
32521
32670
|
if (inspected?.kind === "token" && !this.accepts(linkId, "cashu", mintNetwork(inspected.mint))) {
|
|
32522
32671
|
link.sendPaymentResult({
|
|
32523
32672
|
id: payment.id,
|
|
@@ -33506,7 +33655,7 @@ var PaymentDesk = class {
|
|
|
33506
33655
|
/**
|
|
33507
33656
|
* Notes from the contact. Redeemed only when they are of a federation we joined and this chat allows Fedimint;
|
|
33508
33657
|
* otherwise refused unredeemed, and the contact takes them back. Written down (with the notes) before redeeming:
|
|
33509
|
-
* an interrupted redeem is finished from the journal, never lost.
|
|
33658
|
+
* an interrupted redeem is finished from the journal, never lost. The chat says it once the federation answered.
|
|
33510
33659
|
*/
|
|
33511
33660
|
async receiveFedimint(linkId, payment) {
|
|
33512
33661
|
const link = this.host.getLink(linkId);
|
|
@@ -33579,6 +33728,17 @@ var PaymentDesk = class {
|
|
|
33579
33728
|
await refuse(`${networkLabel(walletNetworkOf(network))} Fedimint is off in this chat`);
|
|
33580
33729
|
return;
|
|
33581
33730
|
}
|
|
33731
|
+
const digest = fedimintNotesDigest(notes);
|
|
33732
|
+
const spelled = digestHex(notes.trim());
|
|
33733
|
+
const before = [...this.payments.values()].find((p) => (p.notesDigest === digest || p.notesDigest === spelled) && p.direction === "in" && p.kind === "payment");
|
|
33734
|
+
if (before) {
|
|
33735
|
+
link.sendPaymentResult({
|
|
33736
|
+
id: payment.id,
|
|
33737
|
+
ok: false,
|
|
33738
|
+
error: before.state === "failed" ? before.error ?? "These notes were already redeemed" : "These notes were already received"
|
|
33739
|
+
});
|
|
33740
|
+
return;
|
|
33741
|
+
}
|
|
33582
33742
|
await this.save({
|
|
33583
33743
|
id: payment.id,
|
|
33584
33744
|
linkId,
|
|
@@ -33591,16 +33751,8 @@ var PaymentDesk = class {
|
|
|
33591
33751
|
createdAt: payment.timestamp,
|
|
33592
33752
|
requestId: payment.requestId,
|
|
33593
33753
|
federation: found.federation,
|
|
33594
|
-
token: notes
|
|
33595
|
-
|
|
33596
|
-
await this.host.storeMessage({
|
|
33597
|
-
linkId,
|
|
33598
|
-
id: `peer_${payment.timestamp}`,
|
|
33599
|
-
text: `⚡ ${amount.toLocaleString()} ${network === "bitcoin" ? "sats" : "test sats"} on Fedimint`,
|
|
33600
|
-
sender: "peer",
|
|
33601
|
-
timestamp: payment.timestamp,
|
|
33602
|
-
via: "datalink",
|
|
33603
|
-
paymentId: payment.id
|
|
33754
|
+
token: notes,
|
|
33755
|
+
notesDigest: digest
|
|
33604
33756
|
});
|
|
33605
33757
|
await this.finishRedeem(this.payments.get(payment.id));
|
|
33606
33758
|
}
|
|
@@ -33648,8 +33800,30 @@ var PaymentDesk = class {
|
|
|
33648
33800
|
ok: false,
|
|
33649
33801
|
error: "These notes were already redeemed"
|
|
33650
33802
|
});
|
|
33803
|
+
try {
|
|
33804
|
+
await this.host.storeMessage({
|
|
33805
|
+
linkId: payment.linkId,
|
|
33806
|
+
id: `peer_${payment.createdAt}_refused`,
|
|
33807
|
+
text: "Could not receive Fedimint ecash: These notes were already redeemed",
|
|
33808
|
+
sender: "peer",
|
|
33809
|
+
timestamp: payment.createdAt,
|
|
33810
|
+
via: "datalink"
|
|
33811
|
+
});
|
|
33812
|
+
} catch {}
|
|
33651
33813
|
return;
|
|
33652
33814
|
}
|
|
33815
|
+
if (state) {
|
|
33816
|
+
const test = fedimint.federation(payment.federation)?.network !== "bitcoin";
|
|
33817
|
+
await this.host.storeMessage({
|
|
33818
|
+
linkId: payment.linkId,
|
|
33819
|
+
id: `peer_${payment.createdAt}`,
|
|
33820
|
+
text: `⚡ ${payment.amount.toLocaleString()} ${test ? "test sats" : "sats"} on Fedimint`,
|
|
33821
|
+
sender: "peer",
|
|
33822
|
+
timestamp: payment.createdAt,
|
|
33823
|
+
via: "datalink",
|
|
33824
|
+
paymentId: id
|
|
33825
|
+
});
|
|
33826
|
+
}
|
|
33653
33827
|
if (state !== "done") return;
|
|
33654
33828
|
await this.save({
|
|
33655
33829
|
...this.current(payment),
|
|
@@ -34432,6 +34606,11 @@ var DEFAULT_SETTINGS = {
|
|
|
34432
34606
|
var CARD_RESTORE_MOST = 50;
|
|
34433
34607
|
var CARD_RESTORE_MS = 6048e5;
|
|
34434
34608
|
/**
|
|
34609
|
+
* 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
|
|
34610
|
+
* contact that says `edit/1` again and again on a session gets one look now and one more after the gap, whatever the count.
|
|
34611
|
+
*/
|
|
34612
|
+
var CARD_RESTORE_EVERY_MS = 3e4;
|
|
34613
|
+
/**
|
|
34435
34614
|
* A round trip that moved is shown at once, and written to disk by itself (relaxed, no disk sync of its own) at most
|
|
34436
34615
|
* 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
|
|
34437
34616
|
* of the round trip's drift, never a row; any other change to the story writes the latest round trip with it.
|
|
@@ -34488,6 +34667,8 @@ var SPARE_INVITE_WARM_AFTER_TAKE_MS = 3e4;
|
|
|
34488
34667
|
* first 11 s, and read nothing more for the rest of the minute, the others' answers included (bug hunt r7a, 2026-09-29).
|
|
34489
34668
|
*/
|
|
34490
34669
|
var STARTUP_QUIET_MS = 15e3;
|
|
34670
|
+
/** At start, how long links start in one task before the page gets the thread back (`startNow`). */
|
|
34671
|
+
var START_SLICE_MS = 10;
|
|
34491
34672
|
var SPARE_INVITE_MAX_AGE_MS = 9e5;
|
|
34492
34673
|
/** How far before this clock a warm packet is dated (`warmKey`): further than a contact's clock is ever behind. */
|
|
34493
34674
|
var WARM_DATED_BACK_MS = 864e5;
|
|
@@ -34630,8 +34811,12 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34630
34811
|
/** Other profiles of this device, looked at for new messages (WISP 04 § Checking other profiles). */
|
|
34631
34812
|
profilePeek;
|
|
34632
34813
|
/** Whether this device's WebRTC attempts say direct connections are blocked on its network (`directPath.ts`). */
|
|
34633
|
-
directPath = new DirectPathWatch(() => {
|
|
34634
|
-
if (
|
|
34814
|
+
directPath = new DirectPathWatch((blocked) => {
|
|
34815
|
+
if (this.shuttingDown) return;
|
|
34816
|
+
this.emitState();
|
|
34817
|
+
if (blocked) {
|
|
34818
|
+
for (const [linkId, live] of this.links) if (live.stored.group && !live.link?.isDataLinkOpen) this.edgeWithoutRtc(linkId);
|
|
34819
|
+
}
|
|
34635
34820
|
});
|
|
34636
34821
|
/** Whether this device's clock seems to be off, from what the relays' answers and several contacts' packets say (`clockWatch.ts`). */
|
|
34637
34822
|
clock = new ClockWatch(() => {
|
|
@@ -34641,9 +34826,11 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34641
34826
|
/**
|
|
34642
34827
|
* Edges of groups whose WebRTC did not connect (`edgeWithoutRtc`): they go on as an app with no WebRTC does, over a
|
|
34643
34828
|
* native transport, until the member is seen online again after a packet said it was gone (`away`, `edgeRtcPresence`).
|
|
34644
|
-
* Not kept: the next start tries WebRTC first again.
|
|
34829
|
+
* Not kept: the next start tries WebRTC first again. `held`: it stays native on a return too, until the network changes.
|
|
34645
34830
|
*/
|
|
34646
34831
|
edgeRtcOff = /* @__PURE__ */ new Map();
|
|
34832
|
+
/** Edges put back on WebRTC by a return (`edgeRtcPresence`) since the network last changed: failing again holds them native. */
|
|
34833
|
+
edgeRtcRetried = /* @__PURE__ */ new Set();
|
|
34647
34834
|
pollIntervals;
|
|
34648
34835
|
localFetch;
|
|
34649
34836
|
links = /* @__PURE__ */ new Map();
|
|
@@ -34735,6 +34922,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
34735
34922
|
outboxes = /* @__PURE__ */ new Map();
|
|
34736
34923
|
/** My edits on their way, per 1:1 chat (WISP 400 § Edits). */
|
|
34737
34924
|
editQueues = /* @__PURE__ */ new Map();
|
|
34925
|
+
/** Per 1:1 chat, its look for cards to send again (`restoreCardsSoon`): when the last began, and what waits. */
|
|
34926
|
+
cardRestores = /* @__PURE__ */ new Map();
|
|
34738
34927
|
/** The contacts' edits of messages not here yet. */
|
|
34739
34928
|
editBuffer = new EditBuffer();
|
|
34740
34929
|
/** Received status card updates, applied at most once a second per message (WISP 405 · Status Cards). */
|
|
@@ -35301,7 +35490,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
35301
35490
|
subject
|
|
35302
35491
|
}),
|
|
35303
35492
|
publish: (seed, records) => this.transport.publish(identityFromSeed(seed), records),
|
|
35304
|
-
resolve: async (key) => (await this.transport.resolve(key))?.records ?? null
|
|
35493
|
+
resolve: async (key) => (await this.transport.resolve(key, { background: true }))?.records ?? null
|
|
35305
35494
|
});
|
|
35306
35495
|
/** The profile's did:dht: a key of its own, public, never tied to a chat (WISP 310-did-dht). */
|
|
35307
35496
|
did = new ProfileDid({
|
|
@@ -35856,7 +36045,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
35856
36045
|
const fresh = !this.walletFeedbackIds.has(tx.id);
|
|
35857
36046
|
this.walletFeedbackIds.add(tx.id);
|
|
35858
36047
|
if (this.walletFeedbackReady && fresh && tx.amount > 0 && tx.timestamp >= this.feedbackStartedAt) {
|
|
35859
|
-
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);
|
|
36048
|
+
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);
|
|
35860
36049
|
if (tx.kind === "lightning-out") this.feedback("confirmed", tx.id);
|
|
35861
36050
|
}
|
|
35862
36051
|
}
|
|
@@ -35995,12 +36184,16 @@ var GhostlyNode = class GhostlyNode {
|
|
|
35995
36184
|
if (note) this.reactionNotes.set(`group:${group.id}`, note);
|
|
35996
36185
|
}
|
|
35997
36186
|
this.publicProfiles.start();
|
|
36187
|
+
const pause = pacer(START_SLICE_MS);
|
|
35998
36188
|
if (this.networkOn) for (const linkId of this.nativeStartOrder([...history.keys()])) {
|
|
36189
|
+
if (!this.networkOn || this.shuttingDown) break;
|
|
35999
36190
|
const messages = history.get(linkId);
|
|
36000
36191
|
if (!this.links.has(linkId)) continue;
|
|
36001
36192
|
this.startLink(linkId, messages);
|
|
36002
36193
|
if (!this.links.get(linkId)?.stored.group) this.refreshPublicProfiles({ linkId }).catch(() => {});
|
|
36194
|
+
await pause();
|
|
36003
36195
|
}
|
|
36196
|
+
if (this.shuttingDown) return;
|
|
36004
36197
|
this.emitState();
|
|
36005
36198
|
if (this.networkOn) {
|
|
36006
36199
|
this.hold.start();
|
|
@@ -36433,6 +36626,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
36433
36626
|
this.publicProfiles.stop();
|
|
36434
36627
|
this.publicActivity.clear();
|
|
36435
36628
|
for (const queue of this.editQueues.values()) queue.stop();
|
|
36629
|
+
for (const restore of this.cardRestores.values()) clearTimeout(restore.timer);
|
|
36630
|
+
this.cardRestores.clear();
|
|
36436
36631
|
this.groupEdits.stop();
|
|
36437
36632
|
this.reactions.stop();
|
|
36438
36633
|
this.cardEdits.stop();
|
|
@@ -37389,11 +37584,13 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37389
37584
|
this.outboxes.delete(linkId);
|
|
37390
37585
|
this.editQueues.get(linkId)?.stop();
|
|
37391
37586
|
this.editQueues.delete(linkId);
|
|
37587
|
+
clearTimeout(this.cardRestores.get(linkId)?.timer);
|
|
37588
|
+
this.cardRestores.delete(linkId);
|
|
37392
37589
|
this.editBuffer.forget(linkId);
|
|
37393
37590
|
live.carried?.stop();
|
|
37591
|
+
this.links.delete(linkId);
|
|
37394
37592
|
live.link?.stop(true);
|
|
37395
37593
|
live.caps?.stop();
|
|
37396
|
-
this.links.delete(linkId);
|
|
37397
37594
|
this.identities.forget(linkId);
|
|
37398
37595
|
this.nostrSocial.forgetLink(linkId);
|
|
37399
37596
|
this.hold.forgetLink(linkId);
|
|
@@ -37408,9 +37605,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37408
37605
|
renameLink({ linkId, label }) {
|
|
37409
37606
|
const live = this.links.get(linkId);
|
|
37410
37607
|
if (!live) return;
|
|
37608
|
+
const clean = sanitizeDisplayText(label.trim().replace(/\s+/gu, " "), 48)?.replace(/ {2,}/g, " ");
|
|
37411
37609
|
live.stored = {
|
|
37412
37610
|
...live.stored,
|
|
37413
|
-
label:
|
|
37611
|
+
label: clean
|
|
37414
37612
|
};
|
|
37415
37613
|
db.patchLink(linkId, { label: live.stored.label });
|
|
37416
37614
|
this.emitState();
|
|
@@ -37440,6 +37638,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37440
37638
|
this.transport.networkChanged?.();
|
|
37441
37639
|
this.directPath.reset();
|
|
37442
37640
|
}
|
|
37641
|
+
if (params.network) {
|
|
37642
|
+
for (const off of this.edgeRtcOff.values()) off.held = false;
|
|
37643
|
+
this.edgeRtcRetried.clear();
|
|
37644
|
+
}
|
|
37443
37645
|
if (params.network) for (const failed of this.nativeFailed.values()) {
|
|
37444
37646
|
failed.at = 0;
|
|
37445
37647
|
failed.wait = 0;
|
|
@@ -37930,6 +38132,42 @@ var GhostlyNode = class GhostlyNode {
|
|
|
37930
38132
|
}
|
|
37931
38133
|
if (changed.length) await this.messagesChanged(linkId, changed);
|
|
37932
38134
|
}
|
|
38135
|
+
/**
|
|
38136
|
+
* `restoreCards`, then what waits goes. One look at a time per chat, at most once per `CARD_RESTORE_EVERY_MS`: asked
|
|
38137
|
+
* again while one runs or within the gap, one more look goes once it is over, and what waits still goes at once (the
|
|
38138
|
+
* edit queue reads the history once a session).
|
|
38139
|
+
*/
|
|
38140
|
+
restoreCardsSoon(linkId) {
|
|
38141
|
+
const flush = () => this.editsFor(linkId).flush().catch(() => {});
|
|
38142
|
+
let state = this.cardRestores.get(linkId);
|
|
38143
|
+
if (!state) this.cardRestores.set(linkId, state = {
|
|
38144
|
+
at: -Infinity,
|
|
38145
|
+
busy: false,
|
|
38146
|
+
again: false
|
|
38147
|
+
});
|
|
38148
|
+
if (state.busy) {
|
|
38149
|
+
state.again = true;
|
|
38150
|
+
return;
|
|
38151
|
+
}
|
|
38152
|
+
const wait = state.at + CARD_RESTORE_EVERY_MS - Date.now();
|
|
38153
|
+
if (wait > 0) {
|
|
38154
|
+
state.timer ??= setTimeout(() => {
|
|
38155
|
+
state.timer = void 0;
|
|
38156
|
+
if (this.cardRestores.get(linkId) === state) this.restoreCardsSoon(linkId);
|
|
38157
|
+
}, wait);
|
|
38158
|
+
flush();
|
|
38159
|
+
return;
|
|
38160
|
+
}
|
|
38161
|
+
state.busy = true;
|
|
38162
|
+
state.at = Date.now();
|
|
38163
|
+
this.restoreCards(linkId).catch(() => {}).then(flush).finally(() => {
|
|
38164
|
+
state.busy = false;
|
|
38165
|
+
if (state.again && this.cardRestores.get(linkId) === state) {
|
|
38166
|
+
state.again = false;
|
|
38167
|
+
this.restoreCardsSoon(linkId);
|
|
38168
|
+
}
|
|
38169
|
+
});
|
|
38170
|
+
}
|
|
37933
38171
|
/** My edits in one 1:1 chat on their way to the contact. */
|
|
37934
38172
|
editsFor(linkId) {
|
|
37935
38173
|
let queue = this.editQueues.get(linkId);
|
|
@@ -39883,8 +40121,15 @@ var GhostlyNode = class GhostlyNode {
|
|
|
39883
40121
|
if (typing === true && this.settings.sendTyping !== false) this.groups.setTyping(groupId, true, typingActivity(kind, status));
|
|
39884
40122
|
else this.groups.setTyping(groupId, false);
|
|
39885
40123
|
}
|
|
40124
|
+
/**
|
|
40125
|
+
* A call's signaling: read the contact's record fast, for its `_call`. A compatibility chat's only: a paired chat's
|
|
40126
|
+
* signals go only over its live session (WISP 601), so a read finds nothing for the call, and its data link keeps
|
|
40127
|
+
* its own fast reads (an offer's look would be cut short by a call's `fast: false`).
|
|
40128
|
+
*/
|
|
39886
40129
|
setFastPoll({ linkId, fast }) {
|
|
39887
|
-
this.links.get(linkId)
|
|
40130
|
+
const live = this.links.get(linkId);
|
|
40131
|
+
if (live?.stored.profile) return;
|
|
40132
|
+
live?.link?.session.setFastPoll(fast);
|
|
39888
40133
|
}
|
|
39889
40134
|
/** Used by the viewer: a request to a service some peer shares with us. */
|
|
39890
40135
|
async request(peerPubKeyZ32, serviceId, request) {
|
|
@@ -40145,7 +40390,8 @@ var GhostlyNode = class GhostlyNode {
|
|
|
40145
40390
|
for (const url of defaults) try {
|
|
40146
40391
|
answered.push((await this.wallet.checkMint(url)).url);
|
|
40147
40392
|
} catch (error) {
|
|
40148
|
-
|
|
40393
|
+
const unreachable = error instanceof Error ? parseEngineError(error.message) : null;
|
|
40394
|
+
last = unreachable?.code === "mintUnreachable" ? Object.assign(engineError("hostUnreachable", unreachable.values), { cause: error }) : error;
|
|
40149
40395
|
}
|
|
40150
40396
|
if (!answered.length) throw last instanceof Error ? last : /* @__PURE__ */ new Error("No mint answered");
|
|
40151
40397
|
await this.updateSettings({ settings: {
|
|
@@ -41823,6 +42069,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
41823
42069
|
if (!live?.stored.group) return;
|
|
41824
42070
|
this.links.delete(linkId);
|
|
41825
42071
|
this.edgeRtcOff.delete(linkId);
|
|
42072
|
+
this.edgeRtcRetried.delete(linkId);
|
|
41826
42073
|
this.groupWakeReceived.delete(linkId);
|
|
41827
42074
|
this.quietEdges.delete(linkId);
|
|
41828
42075
|
this.groupNativeWaiting.delete(linkId);
|
|
@@ -42103,15 +42350,19 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42103
42350
|
},
|
|
42104
42351
|
onDirectEvidence: (evidence) => {
|
|
42105
42352
|
this.directPath.note(peer, evidence);
|
|
42106
|
-
if (
|
|
42353
|
+
if (evidence !== "open" && evidence !== "closed") this.edgeWithoutRtc(linkId);
|
|
42107
42354
|
},
|
|
42108
42355
|
onAnswersRefused: () => {
|
|
42109
|
-
|
|
42356
|
+
this.edgeWithoutRtc(linkId);
|
|
42110
42357
|
},
|
|
42111
42358
|
onDataLinkState: (state) => {
|
|
42112
42359
|
traceJoin(group, `link.${state}`, { role });
|
|
42113
42360
|
if (state === "open" || live.dataLink === "open") live.lastSyncAt = Date.now();
|
|
42114
42361
|
if (state === "open" && !entry) this.groups.edgeOpen(group, peer);
|
|
42362
|
+
if (state === "open") {
|
|
42363
|
+
const off = this.edgeRtcOff.get(linkId);
|
|
42364
|
+
if (off) off.held = true;
|
|
42365
|
+
}
|
|
42115
42366
|
if (state === "open" && !entry && member()) this.desk.replay(linkId).catch(() => {});
|
|
42116
42367
|
live.dataLink = state;
|
|
42117
42368
|
if (entry && state !== "open" && live.entryDone) this.closeGroupLink(linkId).catch(() => {});
|
|
@@ -42153,13 +42404,19 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42153
42404
|
* app with no WebRTC (WISP 902 § Transports): it runs its native endpoints and says so in its packet (`_tr`, with no
|
|
42154
42405
|
* `webrtc/1`), the member's app starts its own for it as it does for a Linux Desktop, and the two meet over Iroh
|
|
42155
42406
|
* through its relay. Until the member comes back (`edgeRtcPresence`), or for this run of the app.
|
|
42407
|
+
* An entry session of a group's link too: there, the admin's packet was seen and the session never went live, and the
|
|
42408
|
+
* join stayed at "Let in: getting the group's keys" for as long as the joiner waited (2026-10-16).
|
|
42156
42409
|
*/
|
|
42157
42410
|
async edgeWithoutRtc(linkId) {
|
|
42158
42411
|
const live = this.links.get(linkId);
|
|
42159
|
-
if (!live?.link || !live.stored.group ||
|
|
42412
|
+
if (!live?.link || !live.stored.group || this.shuttingDown || this.options.webrtcGroupLinks) return;
|
|
42160
42413
|
if (this.edgeRtcOff.has(linkId) || this.keepsGroupNative(live.stored) || !Object.keys(this.nativeFactories).length) return;
|
|
42161
|
-
this.edgeRtcOff.set(linkId, {
|
|
42414
|
+
this.edgeRtcOff.set(linkId, {
|
|
42415
|
+
away: false,
|
|
42416
|
+
held: this.edgeRtcRetried.has(linkId)
|
|
42417
|
+
});
|
|
42162
42418
|
traceLink(live.myPubKeyZ32, "edge-rtc-off", {});
|
|
42419
|
+
if (live.stored.groupEntry) traceJoin(live.stored.group, "link.native", { role: live.stored.groupEntry });
|
|
42163
42420
|
await this.restartEdge(linkId);
|
|
42164
42421
|
}
|
|
42165
42422
|
/**
|
|
@@ -42168,7 +42425,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42168
42425
|
* not a network that blocks direct connections. Held native for this whole run, the edge said so in its packet, the
|
|
42169
42426
|
* member's app followed on its next starts, and past the group links' native slots members stayed unreachable for as
|
|
42170
42427
|
* long as this app ran (2026-10-09). The edge tries WebRTC again, its `_tr` with `webrtc/1` again (WISP 902 §
|
|
42171
|
-
* Transports)
|
|
42428
|
+
* Transports). Not an edge held native (`held`: it failed again after a return, or went live natively), nor while
|
|
42429
|
+
* this device's attempts say its network blocks direct connections: a member's packet that carries a WebRTC signal
|
|
42430
|
+
* 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
|
|
42431
|
+
* a WebRTC that died again (2026-10-16). A network that really blocks it costs one more failed attempt per network.
|
|
42172
42432
|
*/
|
|
42173
42433
|
edgeRtcPresence(linkId, presence) {
|
|
42174
42434
|
const off = this.edgeRtcOff.get(linkId);
|
|
@@ -42177,9 +42437,10 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42177
42437
|
off.away = true;
|
|
42178
42438
|
return;
|
|
42179
42439
|
}
|
|
42180
|
-
if (!off.away) return;
|
|
42440
|
+
if (!off.away || off.held || this.directPath.blocked) return;
|
|
42181
42441
|
const live = this.links.get(linkId);
|
|
42182
42442
|
this.edgeRtcOff.delete(linkId);
|
|
42443
|
+
this.edgeRtcRetried.add(linkId);
|
|
42183
42444
|
if (live) traceLink(live.myPubKeyZ32, "edge-rtc-back", {});
|
|
42184
42445
|
this.groupNativeWaiting.delete(linkId);
|
|
42185
42446
|
this.nativeFailed.delete(linkId);
|
|
@@ -42194,6 +42455,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42194
42455
|
await link.stop(false).catch(() => {});
|
|
42195
42456
|
if (this.links.get(linkId) !== live || live.link || this.shuttingDown || !this.networkOn) return;
|
|
42196
42457
|
this.startEdge(linkId);
|
|
42458
|
+
if (live.stored.groupEntry) this.links.get(linkId)?.link?.expectPeer();
|
|
42197
42459
|
}
|
|
42198
42460
|
startLink(linkId, messages) {
|
|
42199
42461
|
const live = this.links.get(linkId);
|
|
@@ -42431,7 +42693,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42431
42693
|
onMessageEdit: stored.profile && !stored.group ? (edit) => this.receiveEdit(linkId, edit) : void 0,
|
|
42432
42694
|
onEditReceipt: stored.profile && !stored.group ? (id, e) => this.editsFor(linkId).received(id, e) : void 0,
|
|
42433
42695
|
onEditSupport: (supported) => {
|
|
42434
|
-
if (supported && stored.profile && !stored.group) this.
|
|
42696
|
+
if (supported && stored.profile && !stored.group) this.restoreCardsSoon(linkId);
|
|
42435
42697
|
},
|
|
42436
42698
|
onWakeSupport: (supported) => {
|
|
42437
42699
|
if (supported && stored.profile && !stored.group) this.shareWake(linkId);
|
|
@@ -42457,6 +42719,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42457
42719
|
if (peer && !live.stored.group) this.clock.peer(peer, packetAt, readBefore, readAt);
|
|
42458
42720
|
},
|
|
42459
42721
|
onDataLinkState: (state) => {
|
|
42722
|
+
if (this.links.get(linkId) !== live) return;
|
|
42460
42723
|
const was = live.dataLink;
|
|
42461
42724
|
live.dataLink = state;
|
|
42462
42725
|
if (state === "open") {
|
|
@@ -42570,6 +42833,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42570
42833
|
onFileComplete: (id, direction) => this.fileSettled(this.localFileId(linkId, id, direction, { failed: false }), void 0, linkId),
|
|
42571
42834
|
onFilesFrame: (frame) => this.fileDesk.handle(linkId, frame),
|
|
42572
42835
|
onFilesSession: (open) => {
|
|
42836
|
+
if (this.links.get(linkId) !== live) return;
|
|
42573
42837
|
this.fileDesk.session(linkId, open);
|
|
42574
42838
|
if (open) this.sayWithdrawnFiles(linkId);
|
|
42575
42839
|
},
|
|
@@ -42703,7 +42967,7 @@ var GhostlyNode = class GhostlyNode {
|
|
|
42703
42967
|
get nativeFactories() {
|
|
42704
42968
|
const relay = this.relaysHyperdht ? this.hyperdhtRelay : "";
|
|
42705
42969
|
return {
|
|
42706
|
-
...relay ? { "hyperdht/1": async (seedB64) => (await import("./hyperdhtRelay-
|
|
42970
|
+
...relay ? { "hyperdht/1": async (seedB64) => (await import("./hyperdhtRelay-CrgYQN-g.js")).createRelayedHyperEndpoint(seedB64, relay) } : {},
|
|
42707
42971
|
...this.options.nativeTransports,
|
|
42708
42972
|
...this.ownIrohRelays ? { "iroh/1": (seedB64) => this.options.nativeTransports["iroh/1"](seedB64, this.settings.irohRelays?.length ? { relays: [...this.settings.irohRelays] } : {}) } : {},
|
|
42709
42973
|
...this.options.irohWeb ? { "iroh/1": (seedB64) => createIrohWebEndpoint(seedB64, { relays: this.irohRelays }) } : {}
|
|
@@ -43552,4 +43816,4 @@ function signalKind(signal) {
|
|
|
43552
43816
|
//#endregion
|
|
43553
43817
|
export { EngineServer };
|
|
43554
43818
|
|
|
43555
|
-
//# sourceMappingURL=server-
|
|
43819
|
+
//# sourceMappingURL=server-Bx3RGkBC.js.map
|