hive-p2p 1.0.12 → 1.0.14
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/core/config.mjs +1 -1
- package/libs/hive-p2p.min.js +10 -0
- package/package.json +10 -5
- package/services/clock-v2.mjs +196 -0
- package/services/clock.mjs +5 -31
package/core/config.mjs
CHANGED
|
@@ -109,7 +109,7 @@ export const TRANSPORTS = {
|
|
|
109
109
|
|
|
110
110
|
WS_CLIENT: WebSocket,
|
|
111
111
|
WS_SERVER: isNode ? (await import('ws')).WebSocketServer : null,
|
|
112
|
-
PEER: isNode ? (await import('simple-peer')).default : SimplePeer
|
|
112
|
+
PEER: isNode ? (await import('simple-peer')).default : window.SimplePeer
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
export const DISCOVERY = {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var Qs=Object.create;var Ht=Object.defineProperty;var us=Object.getOwnPropertyDescriptor;var ls=Object.getOwnPropertyNames;var ds=Object.getPrototypeOf,ps=Object.prototype.hasOwnProperty;var hA=(i,A)=>()=>(i&&(A=i(i=0)),A);var ys=(i,A)=>()=>(A||i((A={exports:{}}).exports,A),A.exports),et=(i,A)=>{for(var t in A)Ht(i,t,{get:A[t],enumerable:!0})},Ss=(i,A,t,e)=>{if(A&&typeof A=="object"||typeof A=="function")for(let s of ls(A))!ps.call(i,s)&&s!==t&&Ht(i,s,{get:()=>A[s],enumerable:!(e=us(A,s))||e.enumerable});return i};var Ds=(i,A,t)=>(t=i!=null?Qs(ds(i)):{},Ss(A||!i||!i.__esModule?Ht(t,"default",{value:i,enumerable:!0}):t,i));var st,Ce=hA(()=>{st=class i{verbose;mockMode;static#t=null;#A=null;#e=!1;#s=0;#n=["time.google.com","time.cloudflare.com","pool.ntp.org"];constructor(A=0,t=!1){if(this.verbose=A,this.mockMode=t,i.#t)return i.#t;i.#t=this}static get instance(){return i.#t||new i}static get time(){return i.instance.time}get time(){return this.mockMode?Date.now():this.#A===null?null:Date.now()+Math.round(this.#A)}async sync(A){if(A!==void 0&&(this.verbose=A),this.mockMode)return Date.now();if(this.#e){for(;this.#e;)await new Promise(t=>setTimeout(t,50));return this.time}this.#e=!0;try{let t=await this.#i();return t.length===0?(console.warn("[Clock] All NTP sources failed, using local time"),this.#A=0,this.time):(this.#A=this.#r(t),this.#s=Date.now(),t.length<this.#n.length&&setTimeout(()=>this.#g(),100),this.time)}catch(t){return console.error("[Clock] Sync failed:",t),this.#A=0,this.time}finally{this.#e=!1}}get status(){return this.mockMode?{synchronized:!0,syncing:!1,offset:0,lastSync:Date.now(),age:0}:{synchronized:this.#A!==null,syncing:this.#e,offset:this.#A,lastSync:this.#s,age:this.#s?Date.now()-this.#s:null}}async#i(){let A=this.#n.map(s=>this.#o(s)),t=await Promise.allSettled(A),e=[];for(let s of t)s.status==="fulfilled"&&e.push(s.value);return e}async#o(A){let t=new AbortController,e=setTimeout(()=>t.abort(),2e3);try{let s=Date.now(),n=await fetch(`https://${A}`,{method:"HEAD",signal:t.signal,cache:"no-cache"}),o=(Date.now()-s)/2;if(!n.ok)throw new Error(`HTTP ${n.status}`);let g=new Date(n.headers.get("date")).getTime();if(isNaN(g))throw new Error("Invalid date header");return{source:A,serverTime:g+o,localTime:Date.now(),latency:o*2}}finally{clearTimeout(e)}}#r(A){if(A.length===1)return A[0].serverTime-A[0].localTime;A.sort((s,n)=>s.latency-n.latency);let t=[];for(let s of A)t.push(s.serverTime-s.localTime);t.sort((s,n)=>s-n);let e=Math.floor(t.length/2);return t.length%2===0?(t[e-1]+t[e])/2:t[e]}async#g(){if(!this.#e)try{let A=await this.#i();if(A.length===0)return;let t=this.#r(A);Math.abs(t-this.#A)>100&&(this.#A=t)}catch(A){this.verbose&&console.warn("[Clock] Background refine failed:",A)}}}});var ue=ys((Qn,Qe)=>{"use strict";Qe.exports=function(){throw new Error("ws does not work in the browser. Browser clients must use the native WebSocket object")}});var le,F,q,P,EA,w,X,R,_,v,U,de,sA=hA(async()=>{Ce();le=typeof window>"u",F=st.instance,q={AVOID_INTERVALS:!1,USE_TEST_TRANSPORTS:!1,ICE_DELAY:{min:250,max:3e3},ICE_OFFER_FAILURE_RATE:.2,ICE_ANSWER_FAILURE_RATE:.15,AVOID_FOLLOWERS_NODES:!1,AUTO_START:!0,PUBLIC_PEERS_COUNT:100,PEERS_COUNT:1860,BOOTSTRAPS_PER_PEER:10,DELAY_BETWEEN_INIT:10,RANDOM_UNICAST_PER_SEC:0,RANDOM_GOSSIP_PER_SEC:0,DIFFUSION_TEST_DELAY:1e4},P={DEFAULT_VERBOSE:1,CONNECTION_UPGRADE_TIMEOUT:15e3,IS_BROWSER:!le},EA={PORT:8080,AUTO_KICK_DELAY:6e4,AUTO_KICK_DURATION:3e4,MAX_WS_IN_CONNS:20},w={DIFFICULTY:0,ARGON2_MEM:2**16,ARE_IDS_HEX:!0,PUBLIC_PREFIX:"0",STANDARD_PREFIX:"1",ID_LENGTH:16,PUBKEY_LENGTH:32,PRIVATEKEY_LENGTH:32,SIGNATURE_LENGTH:64},X={MAX_SDP_OFFERS:2,ICE_COMPLETE_TIMEOUT:1e3,SIGNAL_CREATION_TIMEOUT:8e3,SDP_OFFER_EXPIRATION:4e4,WS_CLIENT:WebSocket,WS_SERVER:le?(await Promise.resolve().then(()=>Ds(ue(),1))).WebSocketServer:null,PEER:(await import("simple-peer")).default},R={PEER_LINK_DELAY:1e4,PEER_LINK_EXPIRATION:6e4,LOOP_DELAY:2500,TARGET_NEIGHBORS_COUNT:5,ON_CONNECT_DISPATCH:{DELAY:0,BROADCAST_EVENT:!1,OVER_NEIGHBORED:!0,SHARE_HISTORY:!1},ON_DISCONNECT_DISPATCH:{DELAY:0,BROADCAST_EVENT:!1},ON_UNICAST:{DIGEST_TRAVELED_ROUTE:!0}},_={MAX_HOPS:8,MAX_NODES:256,MAX_ROUTES:5,MARKERS_BYTES:{message:0,0:"message",handshake:1,1:"handshake",signal_answer:2,2:"signal_answer",signal_offer:3,3:"signal_offer"}},v={EXPIRATION:1e4,CACHE_DURATION:2e4,HOPS:{default:20,signal_offer:6,diffusion_test:100,over_neighbored:6},TRANSMISSION_RATE:{MIN_NEIGHBOURS_TO_APPLY_PONDERATION:2,NEIGHBOURS_PONDERATION:5,Default:1,signal_offer:.618},MARKERS_BYTES:{gossip:128,128:"gossip",signal_offer:129,129:"signal_offer",peer_connected:130,130:"peer_connected",peer_disconnected:131,131:"peer_disconnected",diffusion_test:132,132:"diffusion_test",over_neighbored:133,133:"over_neighbored"}},U={SIMULATOR:"color: yellow; font-weight: bold;",ARBITER:"color: white;",CRYPTO_CODEX:"color: green;",GOSSIP:"color: fuchsia;",UNICAST:"color: cyan;",PEER_STORE:"color: orange;",SERVICE:"color: teal;",PUNISHER:{BAN:"color: red; font-weight: bold;",KICK:"color: darkorange; font-weight: bold;"}},de={CLOCK:F,SIMULATION:q,NODE:P,TRANSPORTS:X,DISCOVERY:R,IDENTITY:w,UNICAST:_,GOSSIP:v,LOG_CSS:U}});var rt,gt,ye=hA(async()=>{await sA();rt=class{sandbox;SIGNAL_OFFER_TIMEOUT=3e4;SIGNAL_ANSWER_TIMEOUT=1e4;PENDING_OFFERS={};PENDING_ANSWERS={};sdpToBuild=[];signalsToDigest=[];constructor(A){this.sandbox=A}tick(){let A=Date.now();this.#t(A);let t=this.sdpToBuild;this.sdpToBuild=[];for(let{transportId:s,type:n,time:o}of t){if(o>A){this.sdpToBuild.push({transportId:s,type:n,time:o});continue}let g=this.sandbox.transportInstances[s];if(!g||g.destroying||g.destroyed)continue;let{success:c,signalData:r,reason:I}=this.#A(s,n);!c||!r?g.dispatchError(I||`Failed to build SDP for peer: ${this.id}`):g.callbacks.signal?.forEach(a=>a(r))}let e=this.signalsToDigest;this.signalsToDigest=[];for(let{signalData:s,receiverId:n}of e){let o=this.sandbox.transportInstances[n];if(!o||o.destroying||o.destroyed)continue;let{success:g,reason:c}=this.#e(s,n);g||o.dispatchError(c||`Failed to digest signal for peer: ${this.id}`)}}#t(A=Date.now()){for(let t in this.PENDING_OFFERS)for(let e in this.PENDING_OFFERS[t])A>this.PENDING_OFFERS[t][e].expiration&&delete this.PENDING_OFFERS[t][e];for(let t in this.PENDING_ANSWERS){let e=this.PENDING_ANSWERS[t];A>e.expiration&&delete this.PENDING_ANSWERS[t]}}#A(A,t){if(t!=="offer"&&t!=="answer")return{success:!1,signalData:null,reason:`Invalid signal type: ${t}.`};if(t==="answer"&&this.PENDING_ANSWERS[A])return{success:!1,signalData:null,reason:`There is already a pending answer for transport ID: ${A}`};let e=t==="offer"?this.SIGNAL_OFFER_TIMEOUT:this.SIGNAL_ANSWER_TIMEOUT||1e4,s=Math.random().toString(36).substring(2),n={transportId:A,expiration:Date.now()+e,type:t,sdp:{id:s,v:"0",o:`- ${Math.random().toString(36).substring(2)} ${Math.floor(Math.random()*1e6)} 2 IN IP4 127.0.0.1\r
|
|
2
|
+
`,s:"-",t:"0 0",a:["group:BUNDLE..."]}};return t==="offer"&&this.PENDING_OFFERS[A]?.[s]?{success:!1,signalData:null,reason:`There is already a pending offer with the same SDP ID for transport ID: ${A} (extreme case)`}:(t==="offer"&&!this.PENDING_OFFERS[A]&&(this.PENDING_OFFERS[A]={}),t==="offer"&&(this.PENDING_OFFERS[A][s]=n),t==="answer"&&(this.PENDING_ANSWERS[A]=n),{success:!0,signalData:n,reason:"na"})}#e(A,t){let{transportId:e,type:s,sdp:n}=A;if(e===void 0)return{success:!1,reason:"Missing transportId in signal data."};if(s!=="offer"&&s!=="answer")return{success:!1,reason:`Invalid signal type: ${s}.`};if(s==="offer"&&(!this.PENDING_OFFERS[e]||!this.PENDING_OFFERS[e][n.id]))return{success:!1,reason:`No pending offer found for transport ID: ${e} with SDP ID: ${n.id}`};if(s==="answer"&&(!this.PENDING_ANSWERS[e]||this.PENDING_ANSWERS[e].sdp.id!==n.id))return{success:!1,reason:`No pending answer found for transport ID: ${e} with SDP ID: ${n.id}`};if(s==="offer"&&Math.random()<q.ICE_OFFER_FAILURE_RATE)return{success:!1,reason:`Simulated failure for 'offer' signal from ${e} to ${t}`};if(s==="answer"&&Math.random()<q.ICE_ANSWER_FAILURE_RATE)return{success:!1,reason:`Simulated failure for 'answer' signal from ${e} to ${t}`};if(s==="offer")return this.buildSDP(t,"answer"),{success:!0,reason:"na"};delete this.PENDING_OFFERS[t],delete this.PENDING_ANSWERS[e];let o=this.sandbox.linkInstances(t,e);return{success:!o,reason:o||"na"}}buildSDP(A,t){let e={min:q.ICE_DELAY.min,max:q.ICE_DELAY.max},s=Math.floor(Math.random()*(e.max-e.min+1))+e.min;this.sdpToBuild.push({transportId:A,type:t,time:Date.now()+s})}digestSignal(A,t){this.signalsToDigest.push({signalData:A,receiverId:t})}},gt=class{verbose=P.DEFAULT_VERBOSE;wsGlobalIndex=1;tGlobalIndex=1;transportInstances={};wsConnections={};publicWsServers={};inscribeWebSocketServer(A,t){this.publicWsServers[A]=t}removeWebSocketServer(A){delete this.publicWsServers[A]}inscribeWsConnection(A){let t=(this.wsGlobalIndex++).toString();A.id=t,this.wsConnections[t]=A,this.verbose>3&&console.log(`[SANDBOX] Inscribed wsConnection: ${A.id}`)}connectToWebSocketServer(A,t,e){let s=this.wsConnections[t],n=this.publicWsServers[A];if(!s||!n||n.closing||n.clients.size>=n.maxClients)return;let o=new e(n,t);n.clients.add(o),o.init(s.id),n.callbacks.connection.forEach(g=>g(o)),s.init(o.id)}inscribeInstance(A){let t=(this.tGlobalIndex++).toString();A.id=t,this.transportInstances[t]=A,this.verbose>3&&console.log(`[SANDBOX] Inscribed transport: ${t}`)}linkInstances(A,t){let[e,s]=[this.transportInstances[A],this.transportInstances[t]];if(!e||!s)return`Missing transport instances: ${A}=>${!!e}, ${t}=>${!!s}`;if(e.initiator&&s.initiator)return`Both transport instances cannot be initiators: ${A}, ${t}`;if(e.destroying||s.destroying)return`One of the transport instances is destroying: ${A}=>${e.destroying}, ${t}=>${s.destroying}`;if(e.destroyed||s.destroyed)return`One of the transport instances is destroyed: ${A}=>${e.destroyed}, ${t}=>${s.destroyed}`;if(e.remoteId)return`Transport instance tA: ${A} is already linked to remoteId: ${e.remoteId}`;if(s.remoteId)return`Transport instance tB: ${t} is already linked to remoteId: ${s.remoteId}`;e.remoteId=t,s.remoteId=A,this.verbose>2&&console.log(`[SANDBOX] Linked transports: ${A} <-> ${t}`),e.callbacks.connect.forEach(n=>n()),s.callbacks.connect.forEach(n=>n())}sendData(A,t,e){if(A===void 0)return{success:!1,reason:`Cannot send message from id: ${A}`};if(t===void 0)return{success:!1,reason:`Cannot send message to id: ${t}`};let s=this.transportInstances[A];if(!s)return{success:!1,reason:`No transport instance found for id: ${A}`};if(!s.remoteId)return{success:!1,reason:`Transport instance ${A} is not linked to any remoteId`};if(s.id!==A)return{success:!1,reason:`Wrong id for senderInstance ${A} !== ${s.id}`};if(s.remoteId!==t)return{success:!1,reason:`Transport instance ${A} is not linked to remoteId: ${t}`};let n=this.transportInstances[t];return n?n.remoteId?n.id!==t?{success:!1,reason:`Wrong id for remoteInstance ${A} !== ${t}`}:n.remoteId!==A?{success:!1,reason:`Transport instance ${A} is not linked to remoteId: ${t}`}:(this.enqueueTransportData(A,t,e),{success:!0,reason:"na"}):{success:!1,reason:`Transport instance ${t} is not linked to any remoteId`}:{success:!1,reason:`No transport instance found for id: ${t}`}}destroyTransportAndAssociatedTransport(A){let t=this.transportInstances[A];if(!t)return;let e=t.remoteId,s=e?this.transportInstances[e]:null;this.verbose>3&&console.log(`[SANDBOX] Destroying transports: ${A}`),t&&s&&(this.verbose>2&&console.log(`[SANDBOX] Destroying linked transports: ${A} & ${e}`),delete this.transportInstances[e],s.destroy(`Remote transport instance ${A} closed the connection.`)),delete this.transportInstances[A],t.close()}batchSize=2500;messageQueueSync=[];queueIndex=0;messageQueue=new Array(1e5);queueStart=0;queueEnd=0;queueCount=0;processMessageQueueSync(){let A=this.messageQueueSync.length;if(A===0)return;let t=this.batchSize;A>this.batchSize*3&&(t=this.batchSize*1.5),A>this.batchSize*5&&(t=this.batchSize*2),A>this.batchSize*10&&(t=this.batchSize*3),A>this.batchSize*20&&(t=this.batchSize*5),t=Math.round(t);let e=Math.min(this.queueIndex+t,A);for(let n=this.queueIndex;n<e;n++){let[o,g,c,r]=this.messageQueueSync[n];o==="transport_data"?this.#t(g,c,r):o==="ws_message"&&this.#A(g,c,r)}if(this.queueIndex=e,this.queueIndex<5e3)return;let s=this.messageQueueSync.length>5e4;s&&console.warn(`[SANDBOX] Message queue is very long: ${this.messageQueueSync.length} messages pending.`),s&&(this.queueIndex+=this.batchSize),this.messageQueueSync=this.messageQueueSync.slice(this.queueIndex),this.queueIndex=0}async processMessageQueue(){if(this.queueCount===0)return;let A=this.batchSize;this.queueCount>this.batchSize*3&&(A=this.batchSize*1.5),this.queueCount>this.batchSize*5&&(A=this.batchSize*2),this.queueCount>this.batchSize*10&&(A=this.batchSize*3),this.queueCount>this.batchSize*20&&(A=this.batchSize*5);let t=Math.min(A,this.queueCount);for(let e=0;e<t;e++){let s=this.messageQueue[this.queueStart];this.queueStart=(this.queueStart+1)%this.messageQueue.length;let[n,o,g,c]=s;n==="transport_data"?this.#t(o,g,c):n==="ws_message"&&this.#A(o,g,c)}await new Promise(e=>setTimeout(e,0)),this.queueCount-=t}#t(A,t,e){let[s,n]=[this.transportInstances[A],this.transportInstances[t]];if(!s||!n||s.destroying||n.destroying){s?.close(),n?.close();return}if(s.destroyed){n.close();return}if(n.destroyed){s.close();return}for(let o of n.callbacks.data)o(e)}#A(A,t,e){let[s,n]=[this.wsConnections[A],this.wsConnections[t]];if(!n||!s||n.readyState!==1||s.readyState!==1){n?.close(),s?.close();return}if(n.onmessage)n.onmessage({data:e});else for(let o of n.callbacks.message)o(e)}enqueueTransportDataSync(A,t,e){this.messageQueueSync.push(["transport_data",A,t,e])}enqueueWsMessageSync(A,t,e){this.messageQueueSync.push(["ws_message",A,t,e])}enqueueTransportData(A,t,e){this.messageQueue[this.queueEnd]=["transport_data",A,t,e],this.queueEnd=(this.queueEnd+1)%this.messageQueue.length,this.queueCount++,this.queueCount===this.messageQueue.length&&(console.error("[SANDBOX] Message queue overflow, dropping oldest messages."),this.queueStart=(this.queueStart+this.batchSize)%this.messageQueue.length,this.queueCount-=this.batchSize)}enqueueWsMessage(A,t,e){this.messageQueue[this.queueEnd]=["ws_message",A,t,e],this.queueEnd=(this.queueEnd+1)%this.messageQueue.length,this.queueCount++,this.queueCount===this.messageQueue.length&&(console.error("[SANDBOX] Message queue overflow, dropping oldest messages."),this.queueStart=(this.queueStart+this.batchSize)%this.messageQueue.length,this.queueCount-=this.batchSize)}}});var It={};et(It,{ICE_CANDIDATE_EMITTER:()=>Pt,SANDBOX:()=>V,TEST_WS_EVENT_MANAGER:()=>ct,TestTransport:()=>Ot,TestWsConnection:()=>at,TestWsServer:()=>Yt});var Lt,at,Yt,Ot,V,Pt,ct,ht=hA(async()=>{await sA();await ye();Lt=class{toInit=[];toClose=[];toError=[];initTick(){if(this.toInit.length<=0)return;let A=Date.now(),t=this.toInit;this.toInit=[];for(let{connId:e,time:s}of t)s>A?this.toInit.push({connId:e,time:s}):this.#t(e)}closeTick(){if(this.toClose.length<=0)return;let A=Date.now(),t=this.toClose;this.toClose=[];for(let{wsId:e,remoteWsId:s,time:n}of t)n>A?this.toClose.push({wsId:e,remoteWsId:s,time:n}):this.#A(e,s)}cleanerTick(){let A=Date.now();for(let t of Object.values(V.publicWsServers))for(let e of t.clients)e.readyState===3&&t.clients.delete(e)}errorTick(){if(this.toError.length<=0)return;let A=Date.now(),t=this.toError;this.toError=[];for(let{wsId:e,error:s,time:n}of t)n>A?this.toError.push({wsId:e,error:s,time:n}):V.wsConnections[e]?.dispatchError(s)}#t(A){let t=V.wsConnections[A];t&&V.connectToWebSocketServer(t.url,t.id,at)}#A(A,t){let e=V.wsConnections[A],s=V.wsConnections[t];e?.onclose?.(),s?.onclose?.();for(let n of e?.callbacks?.close||[])n();for(let n of s?.callbacks?.close||[])n()}scheduleInit(A,t=500){this.toInit.push({connId:A,time:Date.now()+t})}scheduleClose(A,t,e=100){this.toClose.push({wsId:A,remoteWsId:t,time:Date.now()+e})}scheduleError(A,t,e=100){this.toError.push({wsId:A,error:t,time:Date.now()+e})}},at=class{id;isTestTransport=!0;remoteWsId=null;remoteId=!1;delayBeforeConnectionTry=500;readyState=0;url;callbacks={message:[],close:[],error:[]};onmessage;onopen;onclose;onerror;constructor(A="ws://...",t){V.inscribeWsConnection(this),!t&&(this.url=A,ct.scheduleInit(this.id,this.delayBeforeConnectionTry))}init(A){if(!this.readyState===3||this.remoteWsId){this.close(),console.error(`WebSocket instance already closed or connected: ${this.id}`),ct.scheduleError(this.id,`Failed to connect to WebSocket server at ${this.url}`,1e3);return}this.remoteWsId=A,this.readyState=1,this.onopen&&this.onopen()}on(A,t){if(!this.callbacks[A])return console.error(`Unknown event: ${A}`);this.callbacks[A].push(t)}close(){if(this.readyState===3)return;this.readyState=3;let A=V.wsConnections[this.remoteWsId];A&&(A.readyState=3),this.remoteWsId&&ct.scheduleClose(this.id,this.remoteWsId,100)}send(A){if(!this.remoteWsId){console.error(`No WebSocket server found for URL: ${this.url}`),this.close();return}V.enqueueWsMessage(this.id,this.remoteWsId,A)}dispatchError(A){this.callbacks.error.forEach(t=>t(A)),this.onerror&&this.onerror(A)}},Yt=class{url;clients=new Set;maxClients=EA.MAX_WS_IN_CONNS||20;callbacks={connection:[],close:[],error:[]};constructor(A={port,host:domain}){this.url=`ws://${A.host}:${A.port}`,V.inscribeWebSocketServer(this.url,this)}on(A,t){if(!this.callbacks[A])return console.error(`Unknown event: ${A}`);this.callbacks[A].push(t)}close(){if(!this.closing){this.closing=!0,V.removeWebSocketServer(this.url);for(let A of this.callbacks.close)A()}}},Ot=class{destroying;destroyed;id=null;isTestTransport=!0;remoteId=null;remoteWsId=!1;callbacks={connect:[],close:[],data:[],signal:[],error:[]};initiator;trickle;wrtc;constructor(A={initiator:!1,trickle:!0,wrtc:null,timeout:5e3}){V.inscribeInstance(this),this.initiator=A.initiator,this.trickle=A.trickle,this.wrtc=A.wrtc,this.initiator&&Pt.buildSDP(this.id,"offer")}on(A,t){this.callbacks[A]&&this.callbacks[A].push(t)}dispatchError(A){this.callbacks.error.forEach(t=>t(new Error(A)))}signal(A){if(!this.destroying){if(this.destroyed)throw new Error(`Transport instance already destroyed: ${this.id}`);if(this.remoteId)return this.dispatchError(`Transport instance already connected to a remote ID: ${this.remoteId}`);if(!A.sdp||!A.sdp.id)return this.dispatchError("Invalid remote SDP:",A);if(A.type==="answer"&&!this.initiator)return this.dispatchError("Invalid remote SDP type: expecting an answer.");if(A.type==="offer"&&this.initiator)return this.dispatchError("Invalid remote SDP type: expecting an offer.");Pt.digestSignal(A,this.id)}}send(A){let{success:t,reason:e}=V.sendData(this.id,this.remoteId,A);t||this.destroy(e)}close(){this.destroy()}destroy(A=null){this.destroying||(this.destroying=!0,A&&this.dispatchError(A),this.callbacks.close?.forEach(t=>t()),V.destroyTransportAndAssociatedTransport(this.id),this.destroyed=!0,this.destroying=!1)}},V=new gt,Pt=new rt(V),ct=new Lt});var We={};et(We,{Point:()=>QA,etc:()=>Js,getPublicKey:()=>Ye,getPublicKeyAsync:()=>Le,hash:()=>_s,hashes:()=>ne,keygen:()=>Ks,keygenAsync:()=>Ws,sign:()=>Os,signAsync:()=>Ys,utils:()=>qs,verify:()=>vs,verifyAsync:()=>Ps});var xe,$,lt,Se,De,Kt,Wt,Gs,CA,qA,ms,H,Us,Ts,Ms,oA,St,Fe,Ge,$t,yA,we,jt,me,ks,TA,Ue,dt,UA,l,Te,Me,ke,_s,qt,Xt,QA,wA,PA,_e,Zt,fA,Hs,be,Ls,pt,zt,Ae,He,te,ee,Le,Ye,Oe,Pe,ve,Ys,Os,se,Je,Ps,vs,Js,ne,ie,Ks,Ws,qs,yt,Xs,Ke,Vt,Vs,Ne,Re,$s,qe=hA(()=>{xe={p:0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,n:0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,h:8n,a:0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,d:0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,Gx:0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,Gy:0x6666666666666666666666666666666666666666666666666666666666666658n},{p:$,n:lt,Gx:Se,Gy:De,a:Kt,d:Wt,h:Gs}=xe,CA=32,qA=64,ms=(...i)=>{"captureStackTrace"in Error&&typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(...i)},H=(i="")=>{let A=new Error(i);throw ms(A,H),A},Us=i=>typeof i=="bigint",Ts=i=>typeof i=="string",Ms=i=>i instanceof Uint8Array||ArrayBuffer.isView(i)&&i.constructor.name==="Uint8Array",oA=(i,A,t="")=>{let e=Ms(i),s=i?.length,n=A!==void 0;if(!e||n&&s!==A){let o=t&&`"${t}" `,g=n?` of length ${A}`:"",c=e?`length=${s}`:`type=${typeof i}`;H(o+"expected Uint8Array"+g+", got "+c)}return i},St=i=>new Uint8Array(i),Fe=i=>Uint8Array.from(i),Ge=(i,A)=>i.toString(16).padStart(A,"0"),$t=i=>Array.from(oA(i)).map(A=>Ge(A,2)).join(""),yA={_0:48,_9:57,A:65,F:70,a:97,f:102},we=i=>{if(i>=yA._0&&i<=yA._9)return i-yA._0;if(i>=yA.A&&i<=yA.F)return i-(yA.A-10);if(i>=yA.a&&i<=yA.f)return i-(yA.a-10)},jt=i=>{let A="hex invalid";if(!Ts(i))return H(A);let t=i.length,e=t/2;if(t%2)return H(A);let s=St(e);for(let n=0,o=0;n<e;n++,o+=2){let g=we(i.charCodeAt(o)),c=we(i.charCodeAt(o+1));if(g===void 0||c===void 0)return H(A);s[n]=g*16+c}return s},me=()=>globalThis?.crypto,ks=()=>me()?.subtle??H("crypto.subtle must be defined, consider polyfill"),TA=(...i)=>{let A=St(i.reduce((e,s)=>e+oA(s).length,0)),t=0;return i.forEach(e=>{A.set(e,t),t+=e.length}),A},Ue=(i=CA)=>me().getRandomValues(St(i)),dt=BigInt,UA=(i,A,t,e="bad number: out of range")=>Us(i)&&A<=i&&i<t?i:H(e),l=(i,A=$)=>{let t=i%A;return t>=0n?t:A+t},Te=i=>l(i,lt),Me=(i,A)=>{(i===0n||A<=0n)&&H("no inverse n="+i+" mod="+A);let t=l(i,A),e=A,s=0n,n=1n,o=1n,g=0n;for(;t!==0n;){let c=e/t,r=e%t,I=s-o*c,a=n-g*c;e=t,t=r,s=o,n=g,o=I,g=a}return e===1n?l(s,A):H("no inverse")},ke=i=>{let A=ne[i];return typeof A!="function"&&H("hashes."+i+" not set"),A},_s=i=>ke("sha512")(i),qt=i=>i instanceof QA?i:H("Point expected"),Xt=2n**256n,QA=class i{static BASE;static ZERO;X;Y;Z;T;constructor(A,t,e,s){let n=Xt;this.X=UA(A,0n,n),this.Y=UA(t,0n,n),this.Z=UA(e,1n,n),this.T=UA(s,0n,n),Object.freeze(this)}static CURVE(){return xe}static fromAffine(A){return new i(A.x,A.y,1n,l(A.x*A.y))}static fromBytes(A,t=!1){let e=Wt,s=Fe(oA(A,CA)),n=A[31];s[31]=n&-129;let o=Zt(s);UA(o,0n,t?Xt:$);let c=l(o*o),r=l(c-1n),I=l(e*c+1n),{isValid:a,value:h}=Ls(r,I);a||H("bad point: y not sqrt");let E=(h&1n)===1n,C=(n&128)!==0;return!t&&h===0n&&C&&H("bad point: x==0, isLastByteOdd"),C!==E&&(h=l(-h)),new i(h,o,1n,l(h*o))}static fromHex(A,t){return i.fromBytes(jt(A),t)}get x(){return this.toAffine().x}get y(){return this.toAffine().y}assertValidity(){let A=Kt,t=Wt,e=this;if(e.is0())return H("bad point: ZERO");let{X:s,Y:n,Z:o,T:g}=e,c=l(s*s),r=l(n*n),I=l(o*o),a=l(I*I),h=l(c*A),E=l(I*l(h+r)),C=l(a+l(t*l(c*r)));if(E!==C)return H("bad point: equation left != right (1)");let u=l(s*n),p=l(o*g);return u!==p?H("bad point: equation left != right (2)"):this}equals(A){let{X:t,Y:e,Z:s}=this,{X:n,Y:o,Z:g}=qt(A),c=l(t*g),r=l(n*s),I=l(e*g),a=l(o*s);return c===r&&I===a}is0(){return this.equals(PA)}negate(){return new i(l(-this.X),this.Y,this.Z,l(-this.T))}double(){let{X:A,Y:t,Z:e}=this,s=Kt,n=l(A*A),o=l(t*t),g=l(2n*l(e*e)),c=l(s*n),r=A+t,I=l(l(r*r)-n-o),a=c+o,h=a-g,E=c-o,C=l(I*h),u=l(a*E),p=l(I*E),f=l(h*a);return new i(C,u,f,p)}add(A){let{X:t,Y:e,Z:s,T:n}=this,{X:o,Y:g,Z:c,T:r}=qt(A),I=Kt,a=Wt,h=l(t*o),E=l(e*g),C=l(n*a*r),u=l(s*c),p=l((t+e)*(o+g)-h-E),f=l(u-C),S=l(u+C),Q=l(E-I*h),N=l(p*f),D=l(S*Q),G=l(p*Q),m=l(f*S);return new i(N,D,m,G)}subtract(A){return this.add(qt(A).negate())}multiply(A,t=!0){if(!t&&(A===0n||this.is0()))return PA;if(UA(A,1n,lt),A===1n)return this;if(this.equals(wA))return $s(A).p;let e=PA,s=wA;for(let n=this;A>0n;n=n.double(),A>>=1n)A&1n?e=e.add(n):t&&(s=s.add(n));return e}multiplyUnsafe(A){return this.multiply(A,!1)}toAffine(){let{X:A,Y:t,Z:e}=this;if(this.equals(PA))return{x:0n,y:1n};let s=Me(e,$);l(e*s)!==1n&&H("invalid inverse");let n=l(A*s),o=l(t*s);return{x:n,y:o}}toBytes(){let{x:A,y:t}=this.assertValidity().toAffine(),e=_e(t);return e[31]|=A&1n?128:0,e}toHex(){return $t(this.toBytes())}clearCofactor(){return this.multiply(dt(Gs),!1)}isSmallOrder(){return this.clearCofactor().is0()}isTorsionFree(){let A=this.multiply(lt/2n,!1).double();return lt%2n&&(A=A.add(this)),A.is0()}},wA=new QA(Se,De,1n,l(Se*De)),PA=new QA(0n,1n,1n,0n);QA.BASE=wA;QA.ZERO=PA;_e=i=>jt(Ge(UA(i,0n,Xt),qA)).reverse(),Zt=i=>dt("0x"+$t(Fe(oA(i)).reverse())),fA=(i,A)=>{let t=i;for(;A-- >0n;)t*=t,t%=$;return t},Hs=i=>{let t=i*i%$*i%$,e=fA(t,2n)*t%$,s=fA(e,1n)*i%$,n=fA(s,5n)*s%$,o=fA(n,10n)*n%$,g=fA(o,20n)*o%$,c=fA(g,40n)*g%$,r=fA(c,80n)*c%$,I=fA(r,80n)*c%$,a=fA(I,10n)*n%$;return{pow_p_5_8:fA(a,2n)*i%$,b2:t}},be=0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n,Ls=(i,A)=>{let t=l(A*A*A),e=l(t*t*A),s=Hs(i*e).pow_p_5_8,n=l(i*t*s),o=l(A*n*n),g=n,c=l(n*be),r=o===i,I=o===l(-i),a=o===l(-i*be);return r&&(n=g),(I||a)&&(n=c),(l(n)&1n)===1n&&(n=l(-n)),{isValid:r||I,value:n}},pt=i=>Te(Zt(i)),zt=(...i)=>ne.sha512Async(TA(...i)),Ae=(...i)=>ke("sha512")(TA(...i)),He=i=>{let A=i.slice(0,CA);A[0]&=248,A[31]&=127,A[31]|=64;let t=i.slice(CA,qA),e=pt(A),s=wA.multiply(e),n=s.toBytes();return{head:A,prefix:t,scalar:e,point:s,pointBytes:n}},te=i=>zt(oA(i,CA)).then(He),ee=i=>He(Ae(oA(i,CA))),Le=i=>te(i).then(A=>A.pointBytes),Ye=i=>ee(i).pointBytes,Oe=i=>zt(i.hashable).then(i.finish),Pe=i=>i.finish(Ae(i.hashable)),ve=(i,A,t)=>{let{pointBytes:e,scalar:s}=i,n=pt(A),o=wA.multiply(n).toBytes();return{hashable:TA(o,e,t),finish:r=>{let I=Te(n+pt(r)*s);return oA(TA(o,_e(I)),qA)}}},Ys=async(i,A)=>{let t=oA(i),e=await te(A),s=await zt(e.prefix,t);return Oe(ve(e,s,t))},Os=(i,A)=>{let t=oA(i),e=ee(A),s=Ae(e.prefix,t);return Pe(ve(e,s,t))},se={zip215:!0},Je=(i,A,t,e=se)=>{i=oA(i,qA),A=oA(A),t=oA(t,CA);let{zip215:s}=e,n,o,g,c,r=Uint8Array.of();try{n=QA.fromBytes(t,s),o=QA.fromBytes(i.slice(0,CA),s),g=Zt(i.slice(CA,qA)),c=wA.multiply(g,!1),r=TA(o.toBytes(),n.toBytes(),A)}catch{}return{hashable:r,finish:a=>{if(c==null||!s&&n.isSmallOrder())return!1;let h=pt(a);return o.add(n.multiply(h,!1)).add(c.negate()).clearCofactor().is0()}}},Ps=async(i,A,t,e=se)=>Oe(Je(i,A,t,e)),vs=(i,A,t,e=se)=>Pe(Je(i,A,t,e)),Js={bytesToHex:$t,hexToBytes:jt,concatBytes:TA,mod:l,invert:Me,randomBytes:Ue},ne={sha512Async:async i=>{let A=ks(),t=TA(i);return St(await A.digest("SHA-512",t.buffer))},sha512:void 0},ie=(i=Ue(CA))=>i,Ks=i=>{let A=ie(i),t=Ye(A);return{secretKey:A,publicKey:t}},Ws=async i=>{let A=ie(i),t=await Le(A);return{secretKey:A,publicKey:t}},qs={getExtendedPublicKeyAsync:te,getExtendedPublicKey:ee,randomSecretKey:ie},yt=8,Xs=256,Ke=Math.ceil(Xs/yt)+1,Vt=2**(yt-1),Vs=()=>{let i=[],A=wA,t=A;for(let e=0;e<Ke;e++){t=A,i.push(t);for(let s=1;s<Vt;s++)t=t.add(A),i.push(t);A=t.double()}return i},Re=(i,A)=>{let t=A.negate();return i?t:A},$s=i=>{let A=Ne||(Ne=Vs()),t=PA,e=wA,s=2**yt,n=s,o=dt(s-1),g=dt(yt);for(let c=0;c<Ke;c++){let r=Number(i&o);i>>=g,r>Vt&&(r-=n,i+=1n);let I=c*Vt,a=I,h=I+Math.abs(r)-1,E=c%2!==0,C=r<0;r===0?e=e.add(Re(E,A[a])):t=t.add(Re(C,A[h]))}return i!==0n&&H("invalid wnaf"),{p:t,f:e}}});function js(i){return i instanceof Uint8Array||ArrayBuffer.isView(i)&&i.constructor.name==="Uint8Array"}function oe(i,A,t=""){let e=js(i),s=i?.length,n=A!==void 0;if(!e||n&&s!==A){let o=t&&`"${t}" `,g=n?` of length ${A}`:"",c=e?`length=${s}`:`type=${typeof i}`;throw new Error(o+"expected Uint8Array"+g+", got "+c)}return i}function re(i,A=!0){if(i.destroyed)throw new Error("Hash instance has been destroyed");if(A&&i.finished)throw new Error("Hash#digest() has already been called")}function Xe(i,A){oe(i,void 0,"digestInto() output");let t=A.outputLen;if(i.length<t)throw new Error('"digestInto() output" expected to be of length >='+t)}function MA(...i){for(let A=0;A<i.length;A++)i[A].fill(0)}function Dt(i){return new DataView(i.buffer,i.byteOffset,i.byteLength)}function cA(i,A){return i<<32-A|i>>>A}function kA(i,A={}){let t=(s,n)=>i(n).update(s).digest(),e=i(void 0);return t.outputLen=e.outputLen,t.blockLen=e.blockLen,t.create=s=>i(s),Object.assign(t,A),Object.freeze(t)}var _A,ge=hA(()=>{_A=i=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,i])})});function Ve(i,A,t){return i&A^~i&t}function $e(i,A,t){return i&A^i&t^A&t}var XA,SA,DA,K,W,je=hA(()=>{ge();XA=class{blockLen;outputLen;padOffset;isLE;buffer;view;finished=!1;length=0;pos=0;destroyed=!1;constructor(A,t,e,s){this.blockLen=A,this.outputLen=t,this.padOffset=e,this.isLE=s,this.buffer=new Uint8Array(A),this.view=Dt(this.buffer)}update(A){re(this),oe(A);let{view:t,buffer:e,blockLen:s}=this,n=A.length;for(let o=0;o<n;){let g=Math.min(s-this.pos,n-o);if(g===s){let c=Dt(A);for(;s<=n-o;o+=s)this.process(c,o);continue}e.set(A.subarray(o,o+g),this.pos),this.pos+=g,o+=g,this.pos===s&&(this.process(t,0),this.pos=0)}return this.length+=A.length,this.roundClean(),this}digestInto(A){re(this),Xe(A,this),this.finished=!0;let{buffer:t,view:e,blockLen:s,isLE:n}=this,{pos:o}=this;t[o++]=128,MA(this.buffer.subarray(o)),this.padOffset>s-o&&(this.process(e,0),o=0);for(let a=o;a<s;a++)t[a]=0;e.setBigUint64(s-8,BigInt(this.length*8),n),this.process(e,0);let g=Dt(A),c=this.outputLen;if(c%4)throw new Error("_sha2: outputLen must be aligned to 32bit");let r=c/4,I=this.get();if(r>I.length)throw new Error("_sha2: outputLen bigger than state");for(let a=0;a<r;a++)g.setUint32(4*a,I[a],n)}digest(){let{buffer:A,outputLen:t}=this;this.digestInto(A);let e=A.slice(0,t);return this.destroy(),e}_cloneInto(A){A||=new this.constructor,A.set(...this.get());let{blockLen:t,buffer:e,length:s,finished:n,destroyed:o,pos:g}=this;return A.destroyed=o,A.finished=n,A.length=s,A.pos=g,s%t&&A.buffer.set(e),A}clone(){return this._cloneInto()}},SA=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),DA=Uint32Array.from([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428]),K=Uint32Array.from([3418070365,3238371032,1654270250,914150663,2438529370,812702999,355462360,4144912697,1731405415,4290775857,2394180231,1750603025,3675008525,1694076839,1203062813,3204075428]),W=Uint32Array.from([1779033703,4089235720,3144134277,2227873595,1013904242,4271175723,2773480762,1595750129,1359893119,2917565137,2600822924,725511199,528734635,4215389547,1541459225,327033209])});function Zs(i,A=!1){return A?{h:Number(i&wt),l:Number(i>>Ze&wt)}:{h:Number(i>>Ze&wt)|0,l:Number(i&wt)|0}}function ze(i,A=!1){let t=i.length,e=new Uint32Array(t),s=new Uint32Array(t);for(let n=0;n<t;n++){let{h:o,l:g}=Zs(i[n],A);[e[n],s[n]]=[o,g]}return[e,s]}function uA(i,A,t,e){let s=(A>>>0)+(e>>>0);return{h:i+t+(s/2**32|0)|0,l:s|0}}var wt,Ze,ce,ae,HA,LA,VA,$A,As,ts,es,ss,ns,is,os=hA(()=>{wt=BigInt(4294967295),Ze=BigInt(32);ce=(i,A,t)=>i>>>t,ae=(i,A,t)=>i<<32-t|A>>>t,HA=(i,A,t)=>i>>>t|A<<32-t,LA=(i,A,t)=>i<<32-t|A>>>t,VA=(i,A,t)=>i<<64-t|A>>>t-32,$A=(i,A,t)=>i>>>t-32|A<<64-t;As=(i,A,t)=>(i>>>0)+(A>>>0)+(t>>>0),ts=(i,A,t,e)=>A+t+e+(i/2**32|0)|0,es=(i,A,t,e)=>(i>>>0)+(A>>>0)+(t>>>0)+(e>>>0),ss=(i,A,t,e,s)=>A+t+e+s+(i/2**32|0)|0,ns=(i,A,t,e,s)=>(i>>>0)+(A>>>0)+(t>>>0)+(e>>>0)+(s>>>0),is=(i,A,t,e,s,n)=>A+t+e+s+n+(i/2**32|0)|0});var gs={};et(gs,{_SHA224:()=>Rt,_SHA256:()=>Nt,_SHA384:()=>Ft,_SHA512:()=>xt,_SHA512_224:()=>Gt,_SHA512_256:()=>mt,sha224:()=>nn,sha256:()=>sn,sha384:()=>rn,sha512:()=>on,sha512_224:()=>cn,sha512_256:()=>gn});var An,bA,bt,Nt,Rt,rs,tn,en,NA,RA,vA,xt,Ft,j,Z,Gt,mt,sn,nn,on,rn,gn,cn,cs=hA(()=>{je();os();ge();An=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),bA=new Uint32Array(64),bt=class extends XA{constructor(A){super(64,A,8,!1)}get(){let{A,B:t,C:e,D:s,E:n,F:o,G:g,H:c}=this;return[A,t,e,s,n,o,g,c]}set(A,t,e,s,n,o,g,c){this.A=A|0,this.B=t|0,this.C=e|0,this.D=s|0,this.E=n|0,this.F=o|0,this.G=g|0,this.H=c|0}process(A,t){for(let a=0;a<16;a++,t+=4)bA[a]=A.getUint32(t,!1);for(let a=16;a<64;a++){let h=bA[a-15],E=bA[a-2],C=cA(h,7)^cA(h,18)^h>>>3,u=cA(E,17)^cA(E,19)^E>>>10;bA[a]=u+bA[a-7]+C+bA[a-16]|0}let{A:e,B:s,C:n,D:o,E:g,F:c,G:r,H:I}=this;for(let a=0;a<64;a++){let h=cA(g,6)^cA(g,11)^cA(g,25),E=I+h+Ve(g,c,r)+An[a]+bA[a]|0,u=(cA(e,2)^cA(e,13)^cA(e,22))+$e(e,s,n)|0;I=r,r=c,c=g,g=o+E|0,o=n,n=s,s=e,e=E+u|0}e=e+this.A|0,s=s+this.B|0,n=n+this.C|0,o=o+this.D|0,g=g+this.E|0,c=c+this.F|0,r=r+this.G|0,I=I+this.H|0,this.set(e,s,n,o,g,c,r,I)}roundClean(){MA(bA)}destroy(){this.set(0,0,0,0,0,0,0,0),MA(this.buffer)}},Nt=class extends bt{A=SA[0]|0;B=SA[1]|0;C=SA[2]|0;D=SA[3]|0;E=SA[4]|0;F=SA[5]|0;G=SA[6]|0;H=SA[7]|0;constructor(){super(32)}},Rt=class extends bt{A=DA[0]|0;B=DA[1]|0;C=DA[2]|0;D=DA[3]|0;E=DA[4]|0;F=DA[5]|0;G=DA[6]|0;H=DA[7]|0;constructor(){super(28)}},rs=ze(["0x428a2f98d728ae22","0x7137449123ef65cd","0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc","0x3956c25bf348b538","0x59f111f1b605d019","0x923f82a4af194f9b","0xab1c5ed5da6d8118","0xd807aa98a3030242","0x12835b0145706fbe","0x243185be4ee4b28c","0x550c7dc3d5ffb4e2","0x72be5d74f27b896f","0x80deb1fe3b1696b1","0x9bdc06a725c71235","0xc19bf174cf692694","0xe49b69c19ef14ad2","0xefbe4786384f25e3","0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65","0x2de92c6f592b0275","0x4a7484aa6ea6e483","0x5cb0a9dcbd41fbd4","0x76f988da831153b5","0x983e5152ee66dfab","0xa831c66d2db43210","0xb00327c898fb213f","0xbf597fc7beef0ee4","0xc6e00bf33da88fc2","0xd5a79147930aa725","0x06ca6351e003826f","0x142929670a0e6e70","0x27b70a8546d22ffc","0x2e1b21385c26c926","0x4d2c6dfc5ac42aed","0x53380d139d95b3df","0x650a73548baf63de","0x766a0abb3c77b2a8","0x81c2c92e47edaee6","0x92722c851482353b","0xa2bfe8a14cf10364","0xa81a664bbc423001","0xc24b8b70d0f89791","0xc76c51a30654be30","0xd192e819d6ef5218","0xd69906245565a910","0xf40e35855771202a","0x106aa07032bbd1b8","0x19a4c116b8d2d0c8","0x1e376c085141ab53","0x2748774cdf8eeb99","0x34b0bcb5e19b48a8","0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb","0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3","0x748f82ee5defb2fc","0x78a5636f43172f60","0x84c87814a1f0ab72","0x8cc702081a6439ec","0x90befffa23631e28","0xa4506cebde82bde9","0xbef9a3f7b2c67915","0xc67178f2e372532b","0xca273eceea26619c","0xd186b8c721c0c207","0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178","0x06f067aa72176fba","0x0a637dc5a2c898a6","0x113f9804bef90dae","0x1b710b35131c471b","0x28db77f523047d84","0x32caab7b40c72493","0x3c9ebe0a15c9bebc","0x431d67c49c100d4c","0x4cc5d4becb3e42b6","0x597f299cfc657e2a","0x5fcb6fab3ad6faec","0x6c44198c4a475817"].map(i=>BigInt(i))),tn=rs[0],en=rs[1],NA=new Uint32Array(80),RA=new Uint32Array(80),vA=class extends XA{constructor(A){super(128,A,16,!1)}get(){let{Ah:A,Al:t,Bh:e,Bl:s,Ch:n,Cl:o,Dh:g,Dl:c,Eh:r,El:I,Fh:a,Fl:h,Gh:E,Gl:C,Hh:u,Hl:p}=this;return[A,t,e,s,n,o,g,c,r,I,a,h,E,C,u,p]}set(A,t,e,s,n,o,g,c,r,I,a,h,E,C,u,p){this.Ah=A|0,this.Al=t|0,this.Bh=e|0,this.Bl=s|0,this.Ch=n|0,this.Cl=o|0,this.Dh=g|0,this.Dl=c|0,this.Eh=r|0,this.El=I|0,this.Fh=a|0,this.Fl=h|0,this.Gh=E|0,this.Gl=C|0,this.Hh=u|0,this.Hl=p|0}process(A,t){for(let Q=0;Q<16;Q++,t+=4)NA[Q]=A.getUint32(t),RA[Q]=A.getUint32(t+=4);for(let Q=16;Q<80;Q++){let N=NA[Q-15]|0,D=RA[Q-15]|0,G=HA(N,D,1)^HA(N,D,8)^ce(N,D,7),m=LA(N,D,1)^LA(N,D,8)^ae(N,D,7),M=NA[Q-2]|0,L=RA[Q-2]|0,eA=HA(M,L,19)^VA(M,L,61)^ce(M,L,6),Y=LA(M,L,19)^$A(M,L,61)^ae(M,L,6),T=es(m,Y,RA[Q-7],RA[Q-16]),AA=ss(T,G,eA,NA[Q-7],NA[Q-16]);NA[Q]=AA|0,RA[Q]=T|0}let{Ah:e,Al:s,Bh:n,Bl:o,Ch:g,Cl:c,Dh:r,Dl:I,Eh:a,El:h,Fh:E,Fl:C,Gh:u,Gl:p,Hh:f,Hl:S}=this;for(let Q=0;Q<80;Q++){let N=HA(a,h,14)^HA(a,h,18)^VA(a,h,41),D=LA(a,h,14)^LA(a,h,18)^$A(a,h,41),G=a&E^~a&u,m=h&C^~h&p,M=ns(S,D,m,en[Q],RA[Q]),L=is(M,f,N,G,tn[Q],NA[Q]),eA=M|0,Y=HA(e,s,28)^VA(e,s,34)^VA(e,s,39),T=LA(e,s,28)^$A(e,s,34)^$A(e,s,39),AA=e&n^e&g^n&g,nA=s&o^s&c^o&c;f=u|0,S=p|0,u=E|0,p=C|0,E=a|0,C=h|0,{h:a,l:h}=uA(r|0,I|0,L|0,eA|0),r=g|0,I=c|0,g=n|0,c=o|0,n=e|0,o=s|0;let O=As(eA,T,nA);e=ts(O,L,Y,AA),s=O|0}({h:e,l:s}=uA(this.Ah|0,this.Al|0,e|0,s|0)),{h:n,l:o}=uA(this.Bh|0,this.Bl|0,n|0,o|0),{h:g,l:c}=uA(this.Ch|0,this.Cl|0,g|0,c|0),{h:r,l:I}=uA(this.Dh|0,this.Dl|0,r|0,I|0),{h:a,l:h}=uA(this.Eh|0,this.El|0,a|0,h|0),{h:E,l:C}=uA(this.Fh|0,this.Fl|0,E|0,C|0),{h:u,l:p}=uA(this.Gh|0,this.Gl|0,u|0,p|0),{h:f,l:S}=uA(this.Hh|0,this.Hl|0,f|0,S|0),this.set(e,s,n,o,g,c,r,I,a,h,E,C,u,p,f,S)}roundClean(){MA(NA,RA)}destroy(){MA(this.buffer),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},xt=class extends vA{Ah=W[0]|0;Al=W[1]|0;Bh=W[2]|0;Bl=W[3]|0;Ch=W[4]|0;Cl=W[5]|0;Dh=W[6]|0;Dl=W[7]|0;Eh=W[8]|0;El=W[9]|0;Fh=W[10]|0;Fl=W[11]|0;Gh=W[12]|0;Gl=W[13]|0;Hh=W[14]|0;Hl=W[15]|0;constructor(){super(64)}},Ft=class extends vA{Ah=K[0]|0;Al=K[1]|0;Bh=K[2]|0;Bl=K[3]|0;Ch=K[4]|0;Cl=K[5]|0;Dh=K[6]|0;Dl=K[7]|0;Eh=K[8]|0;El=K[9]|0;Fh=K[10]|0;Fl=K[11]|0;Gh=K[12]|0;Gl=K[13]|0;Hh=K[14]|0;Hl=K[15]|0;constructor(){super(48)}},j=Uint32Array.from([2352822216,424955298,1944164710,2312950998,502970286,855612546,1738396948,1479516111,258812777,2077511080,2011393907,79989058,1067287976,1780299464,286451373,2446758561]),Z=Uint32Array.from([573645204,4230739756,2673172387,3360449730,596883563,1867755857,2520282905,1497426621,2519219938,2827943907,3193839141,1401305490,721525244,746961066,246885852,2177182882]),Gt=class extends vA{Ah=j[0]|0;Al=j[1]|0;Bh=j[2]|0;Bl=j[3]|0;Ch=j[4]|0;Cl=j[5]|0;Dh=j[6]|0;Dl=j[7]|0;Eh=j[8]|0;El=j[9]|0;Fh=j[10]|0;Fl=j[11]|0;Gh=j[12]|0;Gl=j[13]|0;Hh=j[14]|0;Hl=j[15]|0;constructor(){super(28)}},mt=class extends vA{Ah=Z[0]|0;Al=Z[1]|0;Bh=Z[2]|0;Bl=Z[3]|0;Ch=Z[4]|0;Cl=Z[5]|0;Dh=Z[6]|0;Dl=Z[7]|0;Eh=Z[8]|0;El=Z[9]|0;Fh=Z[10]|0;Fl=Z[11]|0;Gh=Z[12]|0;Gl=Z[13]|0;Hh=Z[14]|0;Hl=Z[15]|0;constructor(){super(32)}},sn=kA(()=>new Nt,_A(1)),nn=kA(()=>new Rt,_A(4)),on=kA(()=>new xt,_A(3)),rn=kA(()=>new Ft,_A(2)),gn=kA(()=>new mt,_A(6)),cn=kA(()=>new Gt,_A(5))});var as={};et(as,{default:()=>In});var an,In,Is=hA(()=>{an=(()=>{var i,A,t={773(n,o,g){var c,r=typeof self<"u"&&self.Module!==void 0?self.Module:{},I={};for(c in r)r.hasOwnProperty(c)&&(I[c]=r[c]);var a,h,E,C,u=[];a=typeof window=="object",h=typeof importScripts=="function",E=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string",C=!a&&!E&&!h;var p,f,S,Q,N,D="";E?(D=h?g(967).dirname(D)+"/":"//",p=function(B,y){return Q||(Q=g(145)),N||(N=g(967)),B=N.normalize(B),Q.readFileSync(B,y?null:"utf8")},S=function(B){var y=p(B,!0);return y.buffer||(y=new Uint8Array(y)),eA(y.buffer),y},process.argv.length>1&&process.argv[1].replace(/\\/g,"/"),u=process.argv.slice(2),n.exports=r,process.on("uncaughtException",function(B){if(!(B instanceof Cs))throw B}),process.on("unhandledRejection",IA),r.inspect=function(){return"[Emscripten Module object]"}):C?(typeof read<"u"&&(p=function(B){return read(B)}),S=function(B){var y;return typeof readbuffer=="function"?new Uint8Array(readbuffer(B)):(eA(typeof(y=read(B,"binary"))=="object"),y)},typeof scriptArgs<"u"?u=scriptArgs:arguments!==void 0&&(u=arguments),typeof print<"u"&&(typeof console>"u"&&(console={}),console.log=print,console.warn=console.error=typeof printErr<"u"?printErr:print)):(a||h)&&(h?D=self.location.href:typeof document<"u"&&document.currentScript&&(D=document.currentScript.src),D=D.indexOf("blob:")!==0?D.substr(0,D.lastIndexOf("/")+1):"",p=function(B){var y=new XMLHttpRequest;return y.open("GET",B,!1),y.send(null),y.responseText},h&&(S=function(B){var y=new XMLHttpRequest;return y.open("GET",B,!1),y.responseType="arraybuffer",y.send(null),new Uint8Array(y.response)}),f=function(B,y,b){var x=new XMLHttpRequest;x.open("GET",B,!0),x.responseType="arraybuffer",x.onload=function(){x.status==200||x.status==0&&x.response?y(x.response):b()},x.onerror=b,x.send(null)}),r.print||console.log.bind(console);var G,m,M=r.printErr||console.warn.bind(console);for(c in I)I.hasOwnProperty(c)&&(r[c]=I[c]);I=null,r.arguments&&(u=r.arguments),r.thisProgram&&r.thisProgram,r.quit&&r.quit,r.wasmBinary&&(G=r.wasmBinary),r.noExitRuntime,typeof WebAssembly!="object"&&IA("no native wasm support detected");var L=!1;function eA(B,y){B||IA("Assertion failed: "+y)}var Y,T,AA=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0;function nA(B){Y=B,r.HEAP8=new Int8Array(B),r.HEAP16=new Int16Array(B),r.HEAP32=new Int32Array(B),r.HEAPU8=T=new Uint8Array(B),r.HEAPU16=new Uint16Array(B),r.HEAPU32=new Uint32Array(B),r.HEAPF32=new Float32Array(B),r.HEAPF64=new Float64Array(B)}r.INITIAL_MEMORY;var O,YA=[],At=[],xA=[],aA=0,FA=null,iA=null;function IA(B){throw r.onAbort&&r.onAbort(B),M(B+=""),L=!0,B="abort("+B+"). Build with -s ASSERTIONS=1 for more info.",new WebAssembly.RuntimeError(B)}function GA(B){return B.startsWith("data:application/octet-stream;base64,")}function dA(B){return B.startsWith("file://")}r.preloadedImages={},r.preloadedAudios={};var OA,k="argon2.wasm";function JA(B){try{if(B==k&&G)return new Uint8Array(G);if(S)return S(B);throw"both async and sync fetching of the wasm failed"}catch(y){IA(y)}}function kt(B){for(;B.length>0;){var y=B.shift();if(typeof y!="function"){var b=y.func;typeof b=="number"?y.arg===void 0?O.get(b)():O.get(b)(y.arg):b(y.arg===void 0?null:y.arg)}else y(r)}}function Bs(B){try{return m.grow(B-Y.byteLength+65535>>>16),nA(m.buffer),1}catch{}}GA(k)||(OA=k,k=r.locateFile?r.locateFile(OA,D):D+OA);var tt,fs={a:function(B,y,b){T.copyWithin(B,y,y+b)},b:function(B){var y,b=T.length;if((B>>>=0)>2147418112)return!1;for(var x=1;x<=4;x*=2){var z=b*(1+.2/x);if(z=Math.min(z,B+100663296),Bs(Math.min(2147418112,((y=Math.max(B,z))%65536>0&&(y+=65536-y%65536),y))))return!0}return!1}},he=((function(){var B={a:fs};function y(z,tA){var rA,pA=z.exports;r.asm=pA,nA((m=r.asm.c).buffer),O=r.asm.k,rA=r.asm.d,At.unshift(rA),(function(gA){if(aA--,r.monitorRunDependencies&&r.monitorRunDependencies(aA),aA==0&&(FA!==null&&(clearInterval(FA),FA=null),iA)){var KA=iA;iA=null,KA()}})()}function b(z){y(z.instance)}function x(z){return(function(){if(!G&&(a||h)){if(typeof fetch=="function"&&!dA(k))return fetch(k,{credentials:"same-origin"}).then(function(tA){if(!tA.ok)throw"failed to load wasm binary file at '"+k+"'";return tA.arrayBuffer()}).catch(function(){return JA(k)});if(f)return new Promise(function(tA,rA){f(k,function(pA){tA(new Uint8Array(pA))},rA)})}return Promise.resolve().then(function(){return JA(k)})})().then(function(tA){return WebAssembly.instantiate(tA,B)}).then(z,function(tA){M("failed to asynchronously prepare wasm: "+tA),IA(tA)})}if(aA++,r.monitorRunDependencies&&r.monitorRunDependencies(aA),r.instantiateWasm)try{return r.instantiateWasm(B,y)}catch(z){return M("Module.instantiateWasm callback failed with error: "+z),!1}G||typeof WebAssembly.instantiateStreaming!="function"||GA(k)||dA(k)||typeof fetch!="function"?x(b):fetch(k,{credentials:"same-origin"}).then(function(z){return WebAssembly.instantiateStreaming(z,B).then(b,function(tA){return M("wasm streaming compile failed: "+tA),M("falling back to ArrayBuffer instantiation"),x(b)})})})(),r.___wasm_call_ctors=function(){return(r.___wasm_call_ctors=r.asm.d).apply(null,arguments)},r._argon2_hash=function(){return(r._argon2_hash=r.asm.e).apply(null,arguments)},r._malloc=function(){return(he=r._malloc=r.asm.f).apply(null,arguments)}),Ee=(r._free=function(){return(r._free=r.asm.g).apply(null,arguments)},r._argon2_verify=function(){return(r._argon2_verify=r.asm.h).apply(null,arguments)},r._argon2_error_message=function(){return(r._argon2_error_message=r.asm.i).apply(null,arguments)},r._argon2_encodedlen=function(){return(r._argon2_encodedlen=r.asm.j).apply(null,arguments)},r._argon2_hash_ext=function(){return(r._argon2_hash_ext=r.asm.l).apply(null,arguments)},r._argon2_verify_ext=function(){return(r._argon2_verify_ext=r.asm.m).apply(null,arguments)},r.stackAlloc=function(){return(Ee=r.stackAlloc=r.asm.n).apply(null,arguments)});function Cs(B){this.name="ExitStatus",this.message="Program terminated with exit("+B+")",this.status=B}function _t(B){function y(){tt||(tt=!0,r.calledRun=!0,L||(kt(At),r.onRuntimeInitialized&&r.onRuntimeInitialized(),(function(){var b;if(r.postRun)for(typeof r.postRun=="function"&&(r.postRun=[r.postRun]);r.postRun.length;)b=r.postRun.shift(),xA.unshift(b);kt(xA)})()))}B=B||u,aA>0||((function(){var b;if(r.preRun)for(typeof r.preRun=="function"&&(r.preRun=[r.preRun]);r.preRun.length;)b=r.preRun.shift(),YA.unshift(b);kt(YA)})(),aA>0||(r.setStatus?(r.setStatus("Running..."),setTimeout(function(){setTimeout(function(){r.setStatus("")},1),y()},1)):y()))}if(r.allocate=function(B,y){var b;return b=y==1?Ee(B.length):he(B.length),B.subarray||B.slice?T.set(B,b):T.set(new Uint8Array(B),b),b},r.UTF8ToString=function(B,y){return B?(function(b,x,z){for(var tA=x+z,rA=x;b[rA]&&!(rA>=tA);)++rA;if(rA-x>16&&b.subarray&&AA)return AA.decode(b.subarray(x,rA));for(var pA="";x<rA;){var gA=b[x++];if(128&gA){var KA=63&b[x++];if((224&gA)!=192){var Be=63&b[x++];if((gA=(240&gA)==224?(15&gA)<<12|KA<<6|Be:(7&gA)<<18|KA<<12|Be<<6|63&b[x++])<65536)pA+=String.fromCharCode(gA);else{var fe=gA-65536;pA+=String.fromCharCode(55296|fe>>10,56320|1023&fe)}}else pA+=String.fromCharCode((31&gA)<<6|KA)}else pA+=String.fromCharCode(gA)}return pA})(T,B,y):""},r.ALLOC_NORMAL=0,iA=function B(){tt||_t(),tt||(iA=B)},r.run=_t,r.preInit)for(typeof r.preInit=="function"&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();_t(),n.exports=r,r.unloadRuntime=function(){typeof self<"u"&&delete self.Module,r=m=O=Y=T=void 0,delete n.exports}},631:function(n,o,g){var c,r;typeof self<"u",(r=typeof(c=function(){let I=typeof self<"u"?self:this,a={Argon2d:0,Argon2i:1,Argon2id:2};function h(f){if(h._promise)return h._promise;if(h._module)return Promise.resolve(h._module);let S;return S=I.process&&I.process.versions&&I.process.versions.node?E().then(Q=>new Promise(N=>{Q.postRun=()=>N(Q)})):(I.loadArgon2WasmBinary?I.loadArgon2WasmBinary():Promise.resolve(g(721)).then(Q=>(function(N){let D=atob(N),G=new Uint8Array(new ArrayBuffer(D.length));for(let m=0;m<D.length;m++)G[m]=D.charCodeAt(m);return G})(Q))).then(Q=>{var N,D;return N=Q,D=f?(function(G){let m=32767;return new WebAssembly.Memory({initial:Math.min(Math.max(Math.ceil(1024*G/65536),256)+256,m),maximum:m})})(f):void 0,new Promise(G=>(I.Module={wasmBinary:N,wasmMemory:D,postRun(){G(Module)}},E()))}),h._promise=S,S.then(Q=>(h._module=Q,delete h._promise,Q))}function E(){return I.loadArgon2WasmModule?I.loadArgon2WasmModule():Promise.resolve(g(773))}function C(f,S){return f.allocate(S,"i8",f.ALLOC_NORMAL)}function u(f,S){return C(f,new Uint8Array([...S,0]))}function p(f){if(typeof f!="string")return f;if(typeof TextEncoder=="function")return new TextEncoder().encode(f);if(typeof Buffer=="function")return Buffer.from(f);throw Error("Don't know how to encode UTF8")}return{ArgonType:a,hash:function(f){let S=f.mem||1024;return h(S).then(Q=>{let N=f.time||1,D=f.parallelism||1,G=p(f.pass),m=u(Q,G),M=G.length,L=p(f.salt),eA=u(Q,L),Y=L.length,T=f.type||a.Argon2d,AA=Q.allocate(Array(f.hashLen||24),"i8",Q.ALLOC_NORMAL),nA=f.secret?C(Q,f.secret):0,O=f.secret?f.secret.byteLength:0,YA=f.ad?C(Q,f.ad):0,At=f.ad?f.ad.byteLength:0,xA=f.hashLen||24,aA=Q._argon2_encodedlen(N,S,D,Y,xA,T),FA=Q.allocate(Array(aA+1),"i8",Q.ALLOC_NORMAL),iA,IA,GA;try{IA=Q._argon2_hash_ext(N,S,D,m,M,eA,Y,AA,xA,FA,aA,T,nA,O,YA,At,19)}catch(dA){iA=dA}if(IA!==0||iA){try{iA||(iA=Q.UTF8ToString(Q._argon2_error_message(IA)))}catch{}GA={message:iA,code:IA}}else{let dA="",OA=new Uint8Array(xA);for(let k=0;k<xA;k++){let JA=Q.HEAP8[AA+k];OA[k]=JA,dA+=("0"+(255&JA).toString(16)).slice(-2)}GA={hash:OA,hashHex:dA,encoded:Q.UTF8ToString(FA)}}try{Q._free(m),Q._free(eA),Q._free(AA),Q._free(FA),YA&&Q._free(YA),nA&&Q._free(nA)}catch{}if(iA)throw GA;return GA})},verify:function(f){return h().then(S=>{let Q=p(f.pass),N=u(S,Q),D=Q.length,G=f.secret?C(S,f.secret):0,m=f.secret?f.secret.byteLength:0,M=f.ad?C(S,f.ad):0,L=f.ad?f.ad.byteLength:0,eA=u(S,p(f.encoded)),Y,T,AA,nA=f.type;if(nA===void 0){let O=f.encoded.split("$")[1];O&&(nA=a[O=O.replace("a","A")]||a.Argon2d)}try{T=S._argon2_verify_ext(eA,N,D,G,m,M,L,nA)}catch(O){Y=O}if(T||Y){try{Y||(Y=S.UTF8ToString(S._argon2_error_message(T)))}catch{}AA={message:Y,code:T}}try{S._free(N),S._free(eA)}catch{}if(Y)throw AA;return AA})},unloadRuntime:function(){h._module&&(h._module.unloadRuntime(),delete h._promise,delete h._module)}}})=="function"?c.apply(o,[]):c)===void 0||(n.exports=r)},721:function(n,o){n.exports="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DwtBixEPC0GeEyEBCyABC48DAQF/IwBBgANrIgQkACAEQQA2AowBIARBjAFqIAEQBwJAIAFBwABNBEAgBEGQAWogARAYQQBIDQEgBEGQAWogBEGMAWpBBBAGQQBIDQEgBEGQAWogAiADEAZBAEgNASAEQZABaiAAIAEQEhoMAQsgBEGQAWpBwAAQGEEASA0AIARBkAFqIARBjAFqQQQQBkEASA0AIARBkAFqIAIgAxAGQQBIDQAgBEGQAWogBEFAa0HAABASQQBIDQAgACAEKQNANwAAIAAgBCkDSDcACCAAIAQpA1g3ABggACAEKQNQNwAQIABBIGohACABQSBrIgJBwQBPBEADQCAEIARBQGtBwAAQBSIBQUBrQcAAIAEQMUEASA0CIAAgASkDQDcAACAAIAEpA0g3AAggACAEKQNYNwAYIAAgBCkDUDcAECAAQSBqIQAgAkEgayICQcAASw0ACwsgBCAEQUBrQcAAEAUiAUFAayACIAEQMUEASA0AIAAgAUFAayACEAUaCyAEQZABakHwARAEIARBgANqJAALAwABC5kCACAARQRAQQAPCwJ/AkAgAAR/IAFB/wBNDQECQEGgHigCACgCAEUEQCABQYB/cUGAvwNGDQMMAQsgAUH/D00EQCAAIAFBP3FBgAFyOgABIAAgAUEGdkHAAXI6AABBAgwECyABQYCwA09BACABQYBAcUGAwANHG0UEQCAAIAFBP3FBgAFyOgACIAAgAUEMdkHgAXI6AAAgACABQQZ2QT9xQYABcjoAAUEDDAQLIAFBgIAEa0H//z9NBEAgACABQT9xQYABcjoAAyAAIAFBEnZB8AFyOgAAIAAgAUEGdkE/cUGAAXI6AAIgACABQQx2QT9xQYABcjoAAUEEDAQLC0HcHkEZNgIAQX8FQQELDAELIAAgAToAAEEBCwtQAQN/AkAgACgCACwAABAPRQRADAELA0AgACgCACICLAAAIQMgACACQQFqNgIAIAEgA2pBMGshASACLAABEA9FDQEgAUEKbCEBDAALAAsgAQu7AgACQCABQRRLDQACQAJAAkACQAJAAkACQAJAAkACQCABQQlrDgoAAQIDBAUGBwgJCgsgAiACKAIAIgFBBGo2AgAgACABKAIANgIADwsgAiACKAIAIgFBBGo2AgAgACABNAIANwMADwsgAiACKAIAIgFB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AUHjFEEDEBANACABQQNqIANBDGoQFSIBRQ0AIAAgAygCDDYCKCABQecUQQMQEA0AIAFBA2ogA0EMahAVIgFFDQAgACADKAIMIgQ2AjAgACAENgI0IAEtAABBJEcNACADIAc2AgwgACgCECADQQxqIAFBAWoQLCIBRQ0AIAAgAygCDDYCFCABLQAAQSRHDQAgAyAGNgIMIAAoAgAgA0EMaiABQQFqECwiAUUNACAAIAMoAgw2AgQgAEEANgJEIABCADcCPCAAQgA3AhggAEIANwIgIAAQHCICDQBBYEEAIAEtAAAbIQILIANBEGokACACCykBAn8DQCAAIAJBA3QiA2ogASADaikAADcDACACQQFqIgJBgAFHDQALCwwAIABBAEGACBALGgtlAQJ/IAAgAhAeIgIEfyACBUFdQQACfyAAKAIAIQRBACECIAAoAgQiAAR/A0AgAyACIARqLQAAIAEgAmotAABzciEDIAJBAWoiAiAARw0ACyADQQFrQQh2QQFxQQFrBUEACwsbCwtdAQJ/IwBB8AFrIgMkAEF/IQQCQCACRSAARSABRXJyIAFBwABLcg0AIAMgARAYQQBIDQAgAyACQcAAEAZBAEgNACADIAAgARASIQQLIANB8AEQBCADQfABaiQAIAQLCQAgACABNwAACxAAIwAgAGtBcHEiACQAIAALMwEBfyAAKAIUIgMgASACIAAoAhAgA2siASABIAJLGyIBEAUaIAAgACgCFCABajYCFCACC9oBAQR/IwBB0ABrIggkAAJAIABFBEBBYCEADAELIAggABAKIgk2AgwgCCAJNgIcIAggCRAJIgo2AhggCCAJEAkiCzYCCEEAIQkCQAJAIApFIAtFcg0AIAggAjYCFCAIIAE2AhAgCEEIaiAAIAcQLSIADQEgCCgCCCEJIAggCCgCDBAJIgA2AgggAEUNACAIIAY2AiwgCCAFNgIoIAggBDYCJCAIIAM2AiAgCEEIaiAJIAcQMCEADAELQWohAAsgCCgCGBAIIAgoAggQCCAJEAgLIAhB0ABqJAAgAAuQAgEDfyMAQdAAayIRJABBfiETAkAgCEEESQ0AIAgQCSISRQRAQWohEwwBCyARQQA2AkwgEUIANwJEIBEgAjYCPCARIAI2AjggESABNgI0IBEgADYCMCARIA82AiwgESAONgIoIBEgDTYCJCAR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IGxvbmcgb3IgdG9vIHNob3J0AE1pc3NpbmcgYXJndW1lbnRzAFRvbyBtYW55IGxhbmVzAFRvbyBmZXcgbGFuZXMAVG9vIG1hbnkgdGhyZWFkcwBOb3QgZW5vdWdoIHRocmVhZHMATWVtb3J5IGFsbG9jYXRpb24gZXJyb3IATWVtb3J5IGNvc3QgaXMgdG9vIHNtYWxsAFRpbWUgY29zdCBpcyB0b28gc21hbGwAYXJnb24yaQBBcmdvbjJpAFRoZSBwYXNzd29yZCBkb2VzIG5vdCBtYXRjaCB0aGUgc3VwcGxpZWQgaGFzaABPdXRwdXQgcG9pbnRlciBtaXNtYXRjaABPdXRwdXQgaXMgdG9vIGxvbmcAU2FsdCBpcyB0b28gbG9uZwBTZWNyZXQgaXMgdG9vIGxvbmcAUGFzc3dvcmQgaXMgdG9vIGxvbmcAQXNzb2NpYXRlZCBkYXRhIGlzIHRvbyBsb25nAFRocmVhZGluZyBmYWlsdXJlAE1lbW9yeSBjb3N0IGlzIHRvbyBsYXJnZQBUaW1lIGNvc3QgaXMgdG9vIGxhcmdlAFVua25vd24gZXJyb3IgY29kZQBhcmdvbjJpZABBcmdvbjJpZABFbmNvZGluZyBmYWlsZWQARGVjb2RpbmcgZmFpbGVkAGFyZ29uMmQAQXJnb24yZABBcmdvbjJfQ29udGV4dCBjb250ZXh0IGlzIE5VTEwAT3V0cHV0IHBvaW50ZXIgaXMgTlVMTABUaGUgYWxsb2NhdGUgbWVtb3J5IGNhbGxiYWNrIGlzIE5VTEwAVGhlIGZyZWUgbWVtb3J5IGNhbGxiYWNrIGlzIE5VTEwAT0sAJHY9ACx0PQAscD0AJG09AFRoZXJlIGlzIG5vIHN1Y2ggdmVyc2lvbiBvZiBBcmdvbjIAU2FsdCBwb2ludGVyIGlzIE5VTEwsIGJ1dCBzYWx0IGxlbmd0aCBpcyBub3QgMABTZWNyZXQgcG9pbnRlciBpcyBOVUxMLCBidXQgc2VjcmV0IGxlbmd0aCBpcyBub3QgMABQYXNzd29yZCBwb2ludGVyIGlzIE5VTEwsIGJ1dCBwYXNzd29yZCBsZW5ndGggaXMgbm90IDAAQXNzb2NpYXRlZCBkYXRhIHBvaW50ZXIgaXMgTlVMTCwgYnV0IGFkIGxlbmd0aCBpcyBub3QgMAAobnVsbCkAAACbCAAAuwcAAEkJAADACQAAsAkAAPAHAAAfCAAAMAgAAMkIAABvCgAA4AkAABYKAAA7CgAAQwgAACsLAADBCgAAkgoAAPQKAAACCAAAEQgAAFsJAABbCAAAdAkAAHQIAAAFCQAAdAcAAC0JAACeBwAA9AgAAGIHAAAYCQAAiAcAAOEIAABOBwAA/wkAAFwKAAABAEGkGAsBAgBByxgLBf//////AEGQGQtBEQAKABEREQAAAAAFAAAAAAAACQAAAAALAAAAAAAAAAARAA8KERERAwoHAAEACQsLAAAJBgsAAAsABhEAAAAREREAQeEZCyELAAAAAAAAAAARAAoKERERAAoAAAIACQsAAAAJAAsAAAsAQZsaCwEMAEGnGgsVDAAAAAAMAAAAAAkMAAAAAAAMAAAMAEHVGgsBDgBB4RoLFQ0AAAAEDQAAAAAJDgAAAAAADgAADgBBjxsLARAAQZsbCx4PAAAAAA8AAAAACRAAAAAAABAAABAAABIAAAASEhIAQdIbCw4SAAAAEhISAAAAAAAACQBBgxwLAQsAQY8cCxUKAAAAAAoAAAAACQsAAAAAAAsAAAsAQb0cCwEMAEHJHAsnDAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAwMTIzNDU2Nzg5QUJDREVGAEHwHAsBAQBBoB4LAogPAEHYHgsDkBFQ"},145(){},967(){}},e={};function s(n){var o=e[n];if(o!==void 0)return o.exports;var g=e[n]={exports:{}};return t[n].call(g.exports,g,g.exports,s),g.exports}return s(631)})(),In=an});await sA();await sA();var ws=1e4,bs=1e6,Ns=36e5,J={VALID_SIGNATURE:1e4,VALID_POW:3e5,UNICAST_RELAYED:5e3,WRONG_SIGNATURE:-6e5,WRONG_POW:-1e8,WRONG_SERIALIZATION:-6e4,GOSSIP_FLOOD:-6e4,UNICAST_FLOOD:-3e4,HOPS_EXCEEDED:-3e5,UNICAST_INVALID_ROUTE:-6e4,FAILED_HANDSHAKE:-6e5,WRONG_LENGTH:-6e5},nt=class{id;cryptoCodex;verbose;trustBalances={};bytesCounters={gossip:0,unicast:0};bytesCounterResetIn=0;constructor(A,t,e=0){this.id=A,this.cryptoCodex=t,this.verbose=e}tick(){for(let A in this.trustBalances){let t=this.trustBalances[A];t!==0&&(t=t<0?Math.min(0,t+1e3):Math.max(0,t-100))}this.bytesCounterResetIn-1e3>0||(this.bytesCounterResetIn=ws,this.bytesCounters={gossip:0,unicast:0})}countPeerAction(A,t){if(J[t])return this.adjustTrust(A,J[t])}adjustTrust(A,t,e="na"){A!==this.id&&(t&&(this.trustBalances[A]=Math.min(Ns,(this.trustBalances[A]||0)+t)),t&&this.verbose>2&&console.log(`%c(Arbiter: ${this.id}) ${A} +${t}ms (${e}). Updated: ${this.trustBalances[A]}ms.`,U.ARBITER),this.isBanished(A)&&this.verbose>1&&console.log(`%c(Arbiter: ${this.id}) Peer ${A} is now banished.`,U.ARBITER))}isBanished(A="toto"){return(this.trustBalances[A]||0)<0}countMessageBytes(A,t,e){return this.bytesCounters[e]||(this.bytesCounters[e]=0),this.bytesCounters[e]+=t,this.bytesCounters[e]<bs?!0:this.adjustTrust(A,e==="gossip"?J.GOSSIP_FLOOD:J.UNICAST_FLOOD,"Message flood detected")}async digestMessage(A,t,e,s=.01){let{senderId:n,pubkey:o,topic:g,expectedEnd:c}=t;this.#A(A,t,e),this.#t(g?"gossip":"unicast",e,c)&&(g?this.#e(A,t):this.#s(A,t),!(this.isBanished(A)||this.isBanished(n))&&(this.trustBalances[n]>J.VALID_POW||Math.random()<s&&await this.#n(n,o)))}#t(A,t,e){if(!e||t.length===e)return!0;this.adjustTrust(from,J.WRONG_LENGTH,`${A} message length mismatch`)}#A(A,t,e){let{pubkey:s,signature:n,signatureStart:o}=t,g=e.subarray(0,o);this.cryptoCodex.verifySignature(s,n,g)?this.adjustTrust(A,J.VALID_SIGNATURE,"Gossip signature valid"):this.adjustTrust(A,J.WRONG_SIGNATURE,"Gossip signature invalid")}#e(A,t){t.HOPS<=(v.HOPS[t.topic]||v.HOPS.default)||this.adjustTrust(A,J.HOPS_EXCEEDED,"Gossip HOPS exceeded")}#s(A,t){t.route.length<=_.MAX_HOPS||this.adjustTrust(A,J.HOPS_EXCEEDED,"Unicast HOPS exceeded")}async#n(A,t){await this.cryptoCodex.pubkeyDifficultyCheck(t)?this.adjustTrust(A,J.VALID_POW,"Gossip PoW valid"):this.adjustTrust(A,J.WRONG_POW,"Gossip PoW invalid")}};await sA();var Rs;function it(i,A=0){let t=typeof i=="string"?(Rs??=new TextEncoder).encode(i):i,e=t,s=A+374761393&4294967295,n=0;if(e.length>=16){let g=[A+2654435761+2246822519&4294967295,A+2246822519&4294967295,A+0&4294967295,A-2654435761&4294967295],c=t,r=c.length-16,I=0;for(n=0;(n&4294967280)<=r;n+=4){let a=n,h=c[a+0]+(c[a+1]<<8),E=c[a+2]+(c[a+3]<<8),C=h*2246822519+(E*2246822519<<16),u=g[I]+C&4294967295;u=u<<13|u>>>19;let p=u&65535,f=u>>>16;g[I]=p*2654435761+(f*2654435761<<16)&4294967295,I=I+1&3}s=(g[0]<<1|g[0]>>>31)+(g[1]<<7|g[1]>>>25)+(g[2]<<12|g[2]>>>20)+(g[3]<<18|g[3]>>>14)&4294967295}s=s+t.length&4294967295;let o=t.length-4;for(;n<=o;n+=4){let g=n,c=e[g+0]+(e[g+1]<<8),r=e[g+2]+(e[g+3]<<8),I=c*3266489917+(r*3266489917<<16);s=s+I&4294967295,s=s<<17|s>>>15,s=(s&65535)*668265263+((s>>>16)*668265263<<16)&4294967295}for(;n<e.length;++n){let g=e[n];s=s+g*374761393,s=s<<11|s>>>21,s=(s&65535)*2654435761+((s>>>16)*2654435761<<16)&4294967295}return s=s^s>>>15,s=((s&65535)*2246822519&4294967295)+((s>>>16)*2246822519<<16),s=s^s>>>13,s=((s&65535)*3266489917&4294967295)+((s>>>16)*3266489917<<16),s=s^s>>>16,s<0?s+4294967296:s}async function xs(){if(!(typeof globalThis.RTCPeerConnection<"u"))return(await import("wrtc")).default}var pe=await xs(),ot=class{id;verbose;stunUrls;constructor(A,t,e=0){this.id=A,this.verbose=e,this.stunUrls=t}onSignalAnswer=null;onConnect=null;offerInstanceByExpiration={};creatingOffer=!1;offerCreationTimeout=null;offersToCreate=X.MAX_SDP_OFFERS;offers={};tick(){let A=F.time;for(let n in this.offerInstanceByExpiration){let o=this.offerInstanceByExpiration[n];A<n||(o?.destroy(),delete this.offerInstanceByExpiration[n],this.creatingOffer=!1)}for(let n in this.offers){let o=this.offers[n];if(o.offererInstance.destroyed){delete this.offers[n];continue}if(o.isUsed){delete this.offers[n];continue}o.timestamp+X.SDP_OFFER_EXPIRATION>A||(o.offererInstance?.destroy(),delete this.offers[n])}let t=0;for(let n in this.offers){t++;let o=this.offers[n];if(o.isDigestingOneAnswer){o.isDigestingOneAnswer=!1;continue}if(o.offererInstance.destroyed)continue;let g=o.answers.filter(I=>!I.used);if(!g.length)continue;let c=g.reduce((I,a)=>I.timestamp>a.timestamp?I:a);if(!c)continue;c.used=!0;let r=A-c.timestamp;r>P.CONNECTION_UPGRADE_TIMEOUT/2||(o.offererInstance.signal(c.signal),o.isDigestingOneAnswer=!0,this.verbose>2&&console.log(`(${this.id}) Using answer from ${c.peerId} for offer ${n} (received since ${r} ms)`))}if(this.creatingOffer||t>=this.offersToCreate)return;this.creatingOffer=!0;let e=A+(X.SIGNAL_CREATION_TIMEOUT||8e3),s=this.#t(e);this.offerInstanceByExpiration[e]=s}#t(A){let t=X.ICE_COMPLETE_TIMEOUT||1e3,e=new X.PEER({initiator:!0,trickle:!1,iceCompleteTimeout:t,wrtc:pe,config:{iceServers:this.stunUrls}});return e.on("error",s=>this.#e(s)),e.on("signal",s=>{let{candidate:n,type:o}=s;if(!s||n)throw new Error("Unexpected signal data from offerer instance: "+JSON.stringify(s));if(o!=="offer")throw new Error("Unexpected signal type from offerer instance: "+o);delete this.offerInstanceByExpiration[A];let g=it(JSON.stringify(s));e.on("connect",()=>{this.offers[g]&&(this.offers[g].isUsed=!0),this.onConnect(void 0,e)}),this.offers[g]={timestamp:F.time,sentCounter:0,signal:s,offererInstance:e,answers:[],answerers:{},isUsed:!1},this.creatingOffer=!1}),e}#A(A,t="",e=2,s="includes"){return s[0]==="i"&&!A.message.includes(t)?!1:A.message.startsWith(t)?(this.verbose>=e&&console.info(`%cOfferManager => ${A.message}`,U.PEER_STORE),!0):!1}#e=A=>{this.verbose<1||this.#A(A,"Ice connection failed",2)||this.#A(A,"Connection failed",2)||this.#A(A,"Remote transport instance",3,"startsWith")||this.#A(A,"Simulated failure",4,"startsWith")||this.#A(A,"No peer found",4,"startsWith")||this.#A(A,"Missing transport instance",2,"startsWith")||this.#A(A,"Failed to create answer",2,"startsWith")||this.#A(A,"Transport instance",3,"startsWith")||this.#A(A,"cannot signal after peer is destroyed",3,"startsWith")||this.#A(A,"No pending",3)||this.#A(A,"is already linked",3)||this.#A(A,"There is already a pending",3)||this.#A(A,"closed the connection",3)||this.#A(A,"No transport instance found for id:",3)||this.verbose>0&&console.error("transportInstance ERROR => ",A.stack)};addSignalAnswer(A,t,e,s){!t||t.type!=="answer"||!e||!this.offers[e]||this.offers[e].answerers[A]||(this.offers[e].answerers[A]=!0,this.offers[e].answers.push({peerId:A,signal:t,timestamp:s}),this.verbose>3&&console.log(`(OfferManager) Added answer from ${A} for offer ${e}`))}getTransportInstanceForSignal(A,t,e){try{if(!t||!t.type||!t.sdp)throw new Error("Wrong remote SDP provided");let{type:s,sdp:n}=t;if(s!=="offer"&&s!=="answer")throw new Error("Invalid remote SDP type");if(s==="offer"&&!n)throw new Error("No SDP in the remote SDP offer");if(s==="answer"&&!n)throw new Error("No SDP in the remote SDP answer");if(s==="answer"){let c=e?this.offers[e]?.offererInstance:null;if(!c)throw new Error("No pending offer found for the given offer hash to accept the answer");return c}let o=X.ICE_COMPLETE_TIMEOUT||1e3,g=new X.PEER({initiator:!1,trickle:!1,iceCompleteTimeout:o,wrtc:pe,config:{iceServers:this.stunUrls}});return g.on("error",c=>this.#e(c)),g.on("signal",c=>this.onSignalAnswer(A,c,e)),g.on("connect",()=>this.onConnect(A,g)),g}catch(s){if(s.message.startsWith("No pending offer found")&&this.verbose<2)return null;if(this.verbose>1&&s.message.startsWith("No pending offer found"))return console.info(`%c${s.message}`,U.PEER_STORE);this.verbose>0&&console.error(s.stack)}}destroy(){for(let A in this.offers)this.offers[A].offererInstance?.destroy()}};await sA();var{SANDBOX:Un,ICE_CANDIDATE_EMITTER:Tn,TEST_WS_EVENT_MANAGER:Mn}=q.ENABLED?await ht().then(()=>It):{},vt=class{neighbors;connectionsCount;constructor(A={}){this.neighbors=A,this.connectionsCount=Object.keys(A).length}setNeighbor(A,t=F.time){this.neighbors[A]||this.connectionsCount++,this.neighbors[A]=t}unsetNeighbor(A){this.neighbors[A]&&this.connectionsCount--,delete this.neighbors[A]}},mA=class{peerId;transportInstance;isWebSocket;direction;pendingUntil;connStartTime;constructor(A,t,e,s=!1){this.peerId=A,this.transportInstance=t,this.isWebSocket=s,this.direction=e,this.pendingUntil=F.time+P.CONNECTION_UPGRADE_TIMEOUT}setConnected(){this.connStartTime=F.time,this.pendingUntil=0}getConnectionDuration(){return this.connStartTime?F.time-this.connStartTime:0}close(){this.isWebSocket?this.transportInstance?.close():this.transportInstance?.destroy()}},Et=class{id;cryptoCodex;offerManager;arbiter;verbose;isDestroy=!1;neighborsList=[];connecting={};connected={};known={};knownCount=0;kick={};callbacks={connect:[(A,t)=>this.#t(A,t)],disconnect:[(A,t)=>this.#A(A,t)],signal:[],data:[]};constructor(A,t,e,s,n=0){this.id=A,this.cryptoCodex=t,this.offerManager=e,this.arbiter=s,this.verbose=n,this.offerManager.onSignalAnswer=(o,g,c)=>{if(!(this.isDestroy||this.isKicked(o)||this.arbiter.isBanished(o)))for(let r of this.callbacks.signal)r(o,{signal:g,offerHash:c})},this.offerManager.onConnect=(o,g)=>{if(this.isDestroy)return g?.destroy();if(o===this.id)throw new Error(`Refusing to connect to self (${this.id}).`);let c=o;if(g.on("close",()=>{if(c)for(let r of this.callbacks.disconnect)r(c,g.initiator?"out":"in")}),g.on("data",r=>{if(c)for(let I of this.callbacks.data)I(c,r);else{let I=new Uint8Array(r);if(I[0]>127)return;let{route:a,type:h,neighborsList:E}=t.readUnicastMessage(I)||{};if(h!=="handshake"||a.length!==2||a[1]!==this.id)return;c=a[0],this.digestPeerNeighbors(c,E);for(let C of this.callbacks.connect)C(c,"out")}}),o)for(let r of this.callbacks.connect)r(o,"in")}}get publicNeighborsList(){return this.neighborsList.filter(A=>this.cryptoCodex.isPublicNode(A))}get standardNeighborsList(){return this.neighborsList.filter(A=>!this.cryptoCodex.isPublicNode(A))}#t(A,t){if(!this.connecting[A]?.[t])return this.verbose>=3?console.info(`%cPeer with ID ${A} is not connecting.`,U.PEER_STORE):null;let e=this.connecting[A][t];if(this.#e(A,"connecting",t),this.isKicked(A))return this.verbose>=3&&console.info(`%c(${this.id}) Connect => Peer with ID ${A} is kicked. => close()`,U.PEER_STORE),e.close();if(this.connected[A])return this.verbose>1&&console.warn(`%c(${this.id}) Connect => Peer with ID ${A} is already connected. => close()`,U.PEER_STORE),e.close();e.setConnected(),this.connected[A]=e,this.neighborsList.push(A),this.#s(this.id,A)}#A(A,t){this.#e(A,"connected",t)}#e(A,t="both",e="both"){if(!A&&A===this.id)return;let[s,n]=[this.connecting[A],this.connected[A]];if(!s&&!n||(t!=="connecting"&&(n?.direction===e||e==="both")&&(n?.close(),delete this.connected[A],this.neighborsList=Object.keys(this.connected),this.#n(this.id,A)),t==="connected"))return;let o=e==="both"?["out","in"]:[e];for(let g of o)delete s?.[g];this.connecting[A]?.in||this.connecting[A]?.out||delete this.connecting[A]}#s(A="toto",t="tutu"){for(let e of[A,t])this.known[e]||(this.known[e]=new vt,this.knownCount++),this.known[e].setNeighbor(e===A?t:A)}#n(A="toto",t="tutu"){for(let e of[A,t])this.known[e]&&(this.known[e].unsetNeighbor(e===A?t:A),!(this.known[e].connectionsCount>0)&&(delete this.known[e],this.knownCount--))}cleanupExpired(A=!0){let t=F.time;for(let e of["in","out"])for(let s in this.connecting){if(!this.connecting[s][e])continue;let n=this.connected[s]?1e4:0;this.connecting[s][e].pendingUntil+n>t||(this.verbose>=4&&!this.connected[s]&&console.info(`%c(${this.id}) Pending ${e} connection to peer ${s} expired.`,U.PEER_STORE),this.verbose>0&&this.connected[s]?.direction===e&&console.info(`%c(${this.id}) Pending ${e} connection to peer ${s} expired (already connected WARNING!).`,"color: white;"),this.connecting[s]?.out?.isWebSocket&&this.connecting[s].out.close(),this.connecting[s]?.in?.close(),this.#e(s,"connecting",e))}A&&(this.neighborsList=Object.keys(this.connected),this.digestPeerNeighbors(this.id,this.neighborsList))}on(A,t){if(!this.callbacks[A])throw new Error(`Unknown callback type: ${A}`);this.callbacks[A].push(t)}getUpdatedPeerConnectionsCount(A,t=!0){let e=F.time,s=0,n=this.known[A]?.neighbors||{};for(let o in n){if(o!==this.id&&e-n[o]>R.PEER_LINK_EXPIRATION){this.#n(A,o);continue}t?s++:this.cryptoCodex.isPublicNode(o)||s++}return s}addConnectingPeer(A,t,e){if(A===this.id)throw new Error(`Refusing to connect to self (${this.id}).`);let s=t.type==="offer"?"in":"out";if(this.connecting[A]?.[s])return;let n=this.offerManager.getTransportInstanceForSignal(A,t,e);return n?(this.connecting[A]||(this.connecting[A]={}),this.connecting[A][s]=new mA(A,n,s),!0):this.verbose>3?console.info(`%cFailed to get transport instance for signal from ${A}.`,U.PEER_STORE):null}assignSignal(A,t,e,s){let n=this.connecting[A]?.[t.type==="offer"?"in":"out"];try{if(n?.isWebSocket)throw new Error(`Cannot assign signal for ID ${A}. (WebSocket)`);t.type==="answer"?this.offerManager.addSignalAnswer(A,t,e,s):n.transportInstance.signal(t)}catch(o){console.error(`Error signaling ${t?.type} for ${A}:`,o.stack)}}kickPeer(A,t=6e4,e){t&&(this.kick[A]=F.time+t),this.#e(A,"both"),this.verbose>1&&console.log(`%c(${this.id}) Kicked peer ${A} for ${t/1e3}s. ${e?"| Reason: "+e:""}`,"color: green;")}isKicked(A){return this.kick[A]&&this.kick[A]>F.time}digestValidRoute(A=[]){for(let t=1;t<A.length;t++)this.#s(A[t-1],A[t])}digestPeerNeighbors(A,t=[]){if(!(!A||!Array.isArray(t))){for(let e in this.known[A]?.neighbors||{})t.includes(e)||this.#n(A,e);for(let e of t)this.#s(A,e)}}destroy(){this.isDestroy=!0;for(let[A,t]of Object.entries(this.connected))this.#e(A),t.close();for(let[A,t]of Object.entries(this.connecting))this.#e(A),t.in?.close(),t.out?.close();this.offerManager.destroy()}};await sA();var Bt=class{cache={};peerStore;constructor(A,t){this.id=A,this.peerStore=t}buildRoutes(A,t=5,e=3,s=1728,n=!0,o=3){if(this.id===A)throw new Error("Cannot build route to self");if(this.peerStore.connected[A])return{routes:[{path:[this.id,A]}],success:!0,nodesExplored:1};if(!this.peerStore.known[A])return this.#e(A);if(this.cache[A]&&this.#t(this.cache[A]))return{routes:this.cache[A],success:!0,nodesExplored:0};let g=this.#s(A,e,s,o);if(!g.success)return{routes:[],success:!1,nodesExplored:g.nodesExplored};let r=this.#A(g.paths,n).slice(0,t);return this.cache[A]=r,{routes:r,success:!0,nodesExplored:g.nodesExplored}}#t(A){for(let{path:t}of A)for(let e=1;e<t.length;e++){let s=t[e-1],n=t[e];if(s===this.id){if(!this.peerStore.connected[n])return!1}else if(!this.peerStore.known[s]?.neighbors?.[n])return!1}return!0}#A(A,t){let e=[];for(let s of A)e.push({path:s,hops:s.length-1});return t&&e.sort((s,n)=>s.hops-n.hops),e}#e(A){let t=[],e=this.peerStore.neighborsList,s=[...Array(e.length).keys()].sort(()=>Math.random()-.5);for(let n of s)t.push({path:[this.id,e[n],A],hops:0,score:0});return t.length===0?{routes:[],success:!1,nodesExplored:0}:{routes:t,success:"blind",nodesExplored:t.length}}#s(A,t,e,s){let n=[],o=0,g=[{node:this.id,path:[this.id],pathSet:new Set([this.id]),depth:0}],c=new Map;c.set(this.id,[this.id]);let r=[{node:A,path:[A],pathSet:new Set([A]),depth:0}],I=new Map;I.set(A,[A]);let a=Math.ceil(t/2);for(;(g.length>0||r.length>0)&&o<e;){if(g.length>0){let h=this.#n(g,c,I,a);for(let E of h){let C=this.#i(c.get(E),I.get(E));if(n.push(C),!(C.length-1>s))return{success:!0,paths:n,nodesExplored:o}}o++}if(r.length>0){let h=this.#n(r,I,c,a);for(let E of h){let C=this.#i(c.get(E),I.get(E));if(n.push(C),!(C.length-1>s))return{success:!0,paths:n,nodesExplored:o}}o++}}return{success:n.length>0,paths:n,nodesExplored:o}}#n(A,t,e,s){if(A.length===0)return[];let{node:n,path:o,pathSet:g,depth:c}=A.shift();if(c>=s)return[];let r=[];function I(a){if(g.has(a))return;let h=c+1;if(e.has(a)&&r.push(a),t.has(a))return;let E=[...o,a],C=new Set(g).add(a);t.set(a,E),A.push({node:a,path:E,pathSet:C,depth:h})}if(n===this.id)for(let a of this.peerStore.neighborsList)I(a);else for(let a in this.peerStore.known[n]?.neighbors||{})I(a);return r}#i(A,t){let e=A.length+t.length-1,s=new Array(e),n=0;for(let o of A)s[n++]=o;for(let o=t.length-2;o>=0;o--)s[n++]=t[o];return s}};var{SANDBOX:On,ICE_CANDIDATE_EMITTER:Pn,TEST_WS_EVENT_MANAGER:vn}=q.ENABLED?await ht().then(()=>It):{},Fs=Bt,WA=class{type="message";timestamp;neighborsList;route;pubkey;data;signature;signatureStart;expectedEnd;constructor(A,t,e,s,n,o,g,c,r){this.type=A,this.timestamp=t,this.neighborsList=e,this.route=s,this.pubkey=n,this.data=o,this.signature=g,this.signatureStart=c,this.expectedEnd=r}getSenderId(){return this.route[0]}getTargetId(){return this.route[this.route.length-1]}extractRouteInfo(A="toto"){let t=this.newRoute||this.route,e=[],s=-1;for(let r=0;r<t.length;r++)if(e.push(t[r]),t[r]===A){s=r;break}let n=t[0],o=t[t.length-1],g=s>0?t[s-1]:null,c=s!==-1?t[s+1]:null;return{traveledRoute:e,selfPosition:s,senderId:n,targetId:o,prevId:g,nextId:c,routeLength:t.length}}},ft=class extends WA{rerouterPubkey;newRoute;rerouterSignature;constructor(A,t,e,s,n,o,g,c,r){super(A,t,e,s,n,o),this.rerouterPubkey=g,this.newRoute=c,this.rerouterSignature=r}getRerouterId(){return this.newRoute[0]}},Ct=class{callbacks={message_handle:[]};id;cryptoCodex;arbiter;peerStore;verbose;pathFinder;maxHops=_.MAX_HOPS;maxRoutes=_.MAX_ROUTES;maxNodes=_.MAX_NODES;constructor(A,t,e,s,n=0){this.id=A,this.cryptoCodex=t,this.arbiter=e,this.peerStore=s,this.verbose=n,this.pathFinder=new Fs(this.id,this.peerStore)}on(A,t){this.callbacks[A]?this.callbacks[A].push(t):this.callbacks[A]=[t]}sendUnicast(A,t,e="message",s=1){if(A===this.id)return!1;let n=this.pathFinder.buildRoutes(A,this.maxRoutes,this.maxHops,this.maxNodes,!0);if(!n.success)return!1;let o=n.success==="blind"?1:s;for(let g=0;g<Math.min(o,n.routes.length);g++){let c=n.routes[g].path;if(c.length>_.MAX_HOPS){this.verbose>1&&console.warn(`Cannot send unicast message to ${A} as route exceeds maxHops (${_.MAX_HOPS}). BFS incurred.`);continue}let r=this.cryptoCodex.createUnicastMessage(e,t,c,this.peerStore.neighborsList);this.#t(c[1],r)}return!0}#t(A,t){if(this.id===A)return{success:!1,reason:"Cannot send message to self."};let e=this.peerStore.connected[A]?.transportInstance;if(!e)return{success:!1,reason:`Transport instance is not available for peer ${A}.`};try{return e.send(t),{success:!0}}catch(s){this.peerStore.kickPeer(A,0,"send-error"),this.verbose>0&&console.error(`Error sending message to ${A}:`,s.message)}return{success:!1,reason:`Error sending message to ${A}.`}}async handleDirectMessage(A,t){if(this.arbiter.isBanished(A))return this.verbose>=3?console.info(`%cReceived direct message from banned peer ${A}, ignoring.`,"color: red;"):null;if(!this.arbiter.countMessageBytes(A,t.byteLength,"unicast"))return;let e=this.cryptoCodex.readUnicastMessage(t);if(!e)return this.arbiter.countPeerAction(A,"WRONG_SERIALIZATION");if(await this.arbiter.digestMessage(A,e,t),this.arbiter.isBanished(A)||this.arbiter.isBanished(e.senderId))return;let{traveledRoute:s,selfPosition:n,senderId:o,targetId:g,prevId:c,nextId:r}=e.extractRouteInfo(this.id);if(A===o&&A===this.id)throw new Error("DirectMessage senderId and from are both self id !!");for(let h of this.callbacks.message_handle||[])h();if(n===-1)return this.arbiter.adjustTrust(A,J.UNICAST_INVALID_ROUTE,"Self not in route");if(c&&A!==c)return this.arbiter.adjustTrust(A,J.UNICAST_INVALID_ROUTE,"Previous hop id does not match actual from id");if(o===this.id)return this.arbiter.adjustTrust(A,J.UNICAST_INVALID_ROUTE,"SenderId is self id");if(this.verbose>3&&console.log(o===A?`(${this.id}) Direct ${e.type} from ${o}: ${e.data}`:`(${this.id}) Direct ${e.type} from ${o} (lastRelay: ${A}): ${e.data}`),this.peerStore.digestPeerNeighbors(o,e.neighborsList),A!==o&&this.arbiter.adjustTrust(A,J.UNICAST_RELAYED,"Relayed unicast message"),R.ON_UNICAST.DIGEST_TRAVELED_ROUTE&&this.peerStore.digestValidRoute(s),this.id===g){for(let h of this.callbacks[e.type]||[])h(o,e.data);return}let{success:I,reason:a}=this.#t(r,t);if(!I&&!e.rerouterSignature){let h=this.pathFinder.buildRoutes(g,this.maxRoutes,this.maxHops,this.maxNodes,!0);if(!h.success)return;let E=h.routes[0].path;if(E.length>_.MAX_HOPS){this.verbose>1&&console.warn(`Cannot re-route unicast message to ${g} as new route exceeds maxHops (${_.MAX_HOPS}).`);return}let C=this.cryptoCodex.createReroutedUnicastMessage(t,E),u=E[n+1];this.#t(u,C)}}};await sA();var Qt=class{topic="gossip";timestamp;neighborsList;HOPS;senderId;pubkey;data;signature;signatureStart;expectedEnd;constructor(A,t,e,s,n,o,g,c,r,I){this.topic=A,this.timestamp=t,this.neighborsList=e,this.HOPS=s,this.senderId=n,this.pubkey=o,this.data=g,this.signature=c,this.signatureStart=r,this.expectedEnd=I}},Jt=class{cryptoCodex;xxHash32UsageCount=0;seenTimeouts={};cache=[];cleanupFrequency=100;cleanupIn=100;cleanupDurationWarning=10;constructor(A){this.cryptoCodex=A}getGossipHistoryByTime(A="asc"){let t=this.cache.map(e=>({senderId:e.senderId,topic:e.topic,data:e.serializedMessage}));return A==="asc"?t:t.reverse()}addMessage(A){let t=F.time,{marker:e,neighLength:s,timestamp:n,dataLength:o,pubkey:g,associatedId:c}=this.cryptoCodex.readBufferHeader(A);if(t-n>v.EXPIRATION)return;let r=A.subarray(0,47+s+o),I=it(r);if(this.xxHash32UsageCount++,this.seenTimeouts[I])return;let a=v.MARKERS_BYTES[e],h=c,E=t+v.CACHE_DURATION;return this.cache.push({hash:I,senderId:h,topic:a,serializedMessage:A,timestamp:n,expiration:E}),this.seenTimeouts[I]=E,--this.cleanupIn<=0&&this.#t(t),{hash:I,isNew:!this.seenTimeouts[I]}}#t(A=F.time){let t=-1;for(let e=0;e<this.cache.length;e++)this.cache[e].expiration<=A?delete this.seenTimeouts[this.cache[e].hash]:t===-1&&(t=e);t>0?this.cache=this.cache.slice(t):t===-1&&(this.cache=[]),this.cleanupIn=this.cleanupFrequency}},ut=class{callbacks={message_handle:[]};id;cryptoCodex;arbiter;peerStore;verbose;bloomFilter;constructor(A,t,e,s,n=0){this.id=A,this.cryptoCodex=t,this.arbiter=e,this.peerStore=s,this.verbose=n,this.bloomFilter=new Jt(t)}on(A,t){this.callbacks[A]?this.callbacks[A].push(t):this.callbacks[A]=[t]}broadcastToAll(A,t="gossip",e){let s=e||v.HOPS[t]||v.HOPS.default,n=this.cryptoCodex.createGossipMessage(t,A,s,this.peerStore.neighborsList);if(this.bloomFilter.addMessage(n)){this.verbose>3&&console.log(`(${this.id}) Gossip ${t}, to ${JSON.stringify(this.peerStore.neighborsList)}: ${A}`);for(let o of this.peerStore.neighborsList)this.#t(o,n)}}#t(A,t){if(A===this.id)throw new Error(`Refusing to send a gossip message to self (${this.id}).`);let e=this.peerStore.connected[A]?.transportInstance;if(!e)return{success:!1,reason:`Transport instance is not available for peer ${A}.`};try{e.send(t)}catch{this.peerStore.connected[A]?.close()}}sendGossipHistoryToPeer(A){let t=this.bloomFilter.getGossipHistoryByTime("asc");for(let e of t)this.#t(A,e.data)}async handleGossipMessage(A,t){if(this.arbiter.isBanished(A))return this.verbose>=3?console.info(`%cReceived gossip message from banned peer ${A}, ignoring.`,"color: red;"):null;if(!this.arbiter.countMessageBytes(A,t.byteLength,"gossip"))return;for(let p of this.callbacks.message_handle||[])p(t);if(!this.bloomFilter.addMessage(t))return;let e=this.cryptoCodex.readGossipMessage(t);if(!e)return this.arbiter.countPeerAction(A,"WRONG_SERIALIZATION");if(await this.arbiter.digestMessage(A,e,t),this.arbiter.isBanished(A)||this.arbiter.isBanished(e.senderId))return;let{topic:s,timestamp:n,neighborsList:o,HOPS:g,senderId:c,data:r}=e;if(c===this.id)throw new Error(`#${this.id}#${A}# Received our own message back from peer ${A}.`);this.verbose>3&&console.log(c===A?`(${this.id}) Gossip ${s} from ${c}: ${r}`:`(${this.id}) Gossip ${s} from ${c} (by: ${A}): ${r}`),this.peerStore.digestPeerNeighbors(c,o);for(let p of this.callbacks[s]||[])p(c,r,g,e);if(g<1)return;let I=this.peerStore.neighborsList.length,a=Math.max(1,I/v.TRANSMISSION_RATE.NEIGHBOURS_PONDERATION),h=v.TRANSMISSION_RATE[s]||v.TRANSMISSION_RATE.default,E=Math.pow(h,a),C=I<v.TRANSMISSION_RATE.MIN_NEIGHBOURS_TO_APPLY_PONDERATION,u=this.cryptoCodex.decrementGossipHops(t);for(let p of this.peerStore.neighborsList)if(p!==A){if(!C&&Math.random()>E)continue;this.#t(p,u)}}};await sA();await sA();var BA=class i{IS_BROWSER=typeof window<"u";FROMBASE64_AVAILABLE=typeof Uint8Array.fromBase64=="function";textEncoder=new TextEncoder;textDecoder=new TextDecoder;buffer2=new ArrayBuffer(2);view2=new DataView(this.buffer2);buffer4=new ArrayBuffer(4);view4=new DataView(this.buffer4);buffer8=new ArrayBuffer(8);view8=new DataView(this.buffer8);hexMap={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15};numberTo2Bytes(A){return this.view2.setUint16(0,A,!0),new Uint8Array(this.buffer2)}numberTo4Bytes(A){return this.view4.setUint32(0,A,!0),new Uint8Array(this.buffer4)}numberTo8Bytes(A){return this.view8.setBigUint64(0,BigInt(A),!0),new Uint8Array(this.buffer8)}stringToBytes(A="toto"){return this.textEncoder.encode(A)}hexToBytes(A){let t=A.length/2,e=new Uint8Array(t);for(let s=0,n=0;s<t;++s,n+=2)e[s]=(this.hexMap[A[n]]<<4)+this.hexMap[A[n+1]];return e}base64toBytes(A){if(!this.IS_BROWSER)return new Uint8Array(Buffer.from(A,"base64"));if(this.FROMBASE64_AVAILABLE)return Uint8Array.fromBase64(A);let t=atob(A),e=new Uint8Array(t.length);for(let s=0;s<t.length;s++)e[s]=t.charCodeAt(s);return e}bytes2ToNumber(A){for(let t=0;t<2;t++)this.view2.setUint8(t,A[t]);return this.view2.getUint16(0,!0)}bytes4ToNumber(A){for(let t=0;t<4;t++)this.view4.setUint8(t,A[t]);return this.view4.getUint32(0,!0)}bytes8ToNumber(A){for(let t=0;t<8;t++)this.view8.setUint8(t,A[t]);return Number(this.view8.getBigUint64(0,!0))}bytesToString(A){return this.textDecoder.decode(A)}static bytesToHex(A,t=0){let e="";for(let s of A)e+=s<16?`0${s.toString(16)}`:s.toString(16);return t>0&&(e=e.padStart(t,"0")),e}bytesToHex(A,t=0){return i.bytesToHex(A,t)}static hexToBits(A="ffffff",t="string"){let e=[];if(t==="arrayOfNumbers")for(let s=0;s<A.length;s++)e.push(...parseInt(A[s],16).toString(2).padStart(4,"0").split("").map(n=>parseInt(n,10)));else for(let s=0;s<A.length;s++)e.push(parseInt(A[s],16).toString(2).padStart(4,"0"));return t==="string"?e.join(""):e}static bytesToBits(A,t="string"){return this.hexToBits(this.bytesToHex(A),t)}static ipToInt(A="192.168.0.1"){return A.split(".").reduce((t,e)=>(t<<8)+parseInt(e,10),0)}};var jA=typeof window<"u",[hn,{sha512:En}]=await Promise.all([jA?import("https://unpkg.com/@noble/ed25519@3.0.0/index.js"):Promise.resolve().then(()=>(qe(),We)),jA?import("https://unpkg.com/@noble/hashes@2.0.0/sha2.js"):Promise.resolve().then(()=>(cs(),gs))]),ZA=hn;ZA.hashes.sha512=En;var Ut=class{converter=new BA;argon2;hash=async(A,t,e=2**16,s=1,n=1,o=2,g=32)=>{let c=this.#t(A,t,s,e,n,o,g),r=await this.getArgon2Lib(),I=jA?await r.hash(c):await r.hash(A,c);if(!I)return!1;let a=I.encoded||I,h=this.#A(a);return h||!1};async getArgon2Lib(){if(this.argon2)return this.argon2;if(!jA)try{let t=await import("argon2");this.argon2=t}catch{throw new Error("Please install argon2 package: npm install argon2")}if(this.argon2)return this.argon2;try{if(argon2)return console.log("Argon2 loaded as a global variable"),this.argon2=argon2,this.argon2}catch{}if(this.argon2)return this.argon2;console.log("trying import argon2 ES6 and inject in window");let A=await Promise.resolve().then(()=>(Is(),as));return window.argon2=A.default,this.argon2=A.default,this.argon2}#t(A="averylongpassword123456",t="saltsaltsaltsaltsalt",e=1,s=2**10,n=1,o=2,g=32){let c=t.padEnd(20,"0").substring(0,16);return{type:o,pass:A,parallelism:n,time:e,timeCost:e,mem:s,memoryCost:s,hashLen:g,hashLength:g,salt:jA?c:Buffer.from(c)}}#A(A="$argon2id$v=19$m=1048576,t=1,p=1$c2FsdHNhbHRzYWx0c2FsdHNhbHQ$UamPN/XTTX4quPewQNw4/s3y1JJeS22cRroh5l7OTMM"){let t=A.split("$").pop(),e=this.converter.base64toBytes(t),s=this.converter.bytesToHex(e),n=BA.hexToBits(s,"string");return n?{encoded:A,hash:e,hex:s,bitsString:n}:!1}};var lA=class i{argon2=new Ut;converter=new BA;AVOID_CRYPTO=!1;verbose=P.DEFAULT_VERBOSE;id;publicKey;privateKey;constructor(A,t=P.DEFAULT_VERBOSE){if(this.verbose=t,!A)return;this.AVOID_CRYPTO=!0,this.id=A.padEnd(w.ID_LENGTH," ").slice(0,w.ID_LENGTH),this.privateKey=new Uint8Array(32).fill(0),this.publicKey=new Uint8Array(32).fill(0);let e=new TextEncoder().encode(this.id);for(let s=0;s<w.ID_LENGTH;s++)this.publicKey[s]=e[s]}static async createCryptoCodex(A,t){let e=new i(void 0,this.verbose);return await e.generate(A,t),e}static isPublicNode(A){return(w.ARE_IDS_HEX?BA.hexToBits(A[0]):A).startsWith(w.PUBLIC_PREFIX)}get idLength(){return w.ARE_IDS_HEX?w.ID_LENGTH/2:w.ID_LENGTH}isPublicNode(A){return i.isPublicNode(A)}async generate(A,t){if(!this.nodeId&&(await this.#A(t,A),!this.id))throw new Error("Failed to generate identity")}async pubkeyDifficultyCheck(A){if(this.AVOID_CRYPTO||!w.DIFFICULTY)return!0;let{bitsString:t}=await this.argon2.hash(A,"HiveP2P",w.ARGON2_MEM)||{};if(t&&t.startsWith("0".repeat(w.DIFFICULTY)))return!0}#t(A){return w.ARE_IDS_HEX?this.converter.bytesToHex(A.slice(0,this.idLength),w.ID_LENGTH):this.converter.bytesToString(A.slice(0,w.ID_LENGTH))}async#A(A,t){let e=2**w.DIFFICULTY*100;for(let s=0;s<e;s++){let{secretKey:n,publicKey:o}=ZA.keygen(A),g=this.#t(o);if(!(t&&!this.isPublicNode(g))&&!(!t&&this.isPublicNode(g))&&await this.pubkeyDifficultyCheck(o)){this.id=g,this.privateKey=n,this.publicKey=o,this.verbose>2&&console.log(`%cNode generated id: ${this.id} (isPublic: ${t}, difficulty: ${w.DIFFICULTY}) after ${((s+1)/2).toFixed(1)} iterations`,U.CRYPTO_CODEX);return}}this.verbose>0&&console.log(`%cFAILED to generate id after ${e} iterations. Try lowering the difficulty.`,U.CRYPTO_CODEX)}signBufferViewAndAppendSignature(A,t,e=A.length-w.SIGNATURE_LENGTH){if(this.AVOID_CRYPTO)return;let s=A.subarray(0,e);A.set(ZA.sign(s,t),e)}createGossipMessage(A,t,e=3,s=[],n=F.time){let o=v.MARKERS_BYTES[A];if(o===void 0)throw new Error(`Failed to create gossip message: unknown topic '${A}'.`);let g=this.#e(s),{dataCode:c,dataBytes:r}=this.#s(t),I=47+g.length+r.length+w.SIGNATURE_LENGTH+1,a=new ArrayBuffer(I),h=new Uint8Array(a);return this.#n(h,o,c,s.length,n,r,this.publicKey),h.set(g,47),h.set(r,47+g.length),h.set([Math.min(255,e)],I-1),this.signBufferViewAndAppendSignature(h,this.privateKey,I-w.SIGNATURE_LENGTH-1),h}decrementGossipHops(A){let t=new Uint8Array(A),e=A[A.length-1];return t[A.length-1]=Math.max(0,e-1),t}createUnicastMessage(A,t,e,s=[],n=F.time){let o=_.MARKERS_BYTES[A];if(o===void 0)throw new Error(`Failed to create unicast message: unknown type '${A}'.`);if(e.length<2)throw new Error("Failed to create unicast message: route must have at least 2 nodes (next hop and target).");if(e.length>_.MAX_HOPS)throw new Error(`Failed to create unicast message: route exceeds max hops (${_.MAX_HOPS}).`);let g=this.#e(s),{dataCode:c,dataBytes:r}=this.#s(t),I=this.#e(e),a=47+g.length+1+I.length+r.length+w.SIGNATURE_LENGTH,h=new ArrayBuffer(a),E=new Uint8Array(h);this.#n(E,o,c,s.length,n,r,this.publicKey);let C=g.length+r.length;return E.set(g,47),E.set(r,47+g.length),E.set([e.length],47+C),E.set(I,48+C),this.signBufferViewAndAppendSignature(E,this.privateKey,a-w.SIGNATURE_LENGTH),E}createReroutedUnicastMessage(A,t){if(t.length<2)throw new Error("Failed to create rerouted unicast message: route must have at least 2 nodes (next hop and target).");if(t.length>_.MAX_HOPS)throw new Error(`Failed to create rerouted unicast message: route exceeds max hops (${_.MAX_HOPS}).`);let e=t.map(g=>this.converter.stringToBytes(g)),s=A.length+32+w.ID_LENGTH*e.length+w.SIGNATURE_LENGTH,n=new ArrayBuffer(s),o=new Uint8Array(n);o.set(A,0),o.set(this.publicKey,A.length);for(let g=0;g<e.length;g++)o.set(e[g],A.length+32+g*w.ID_LENGTH);return this.signBufferViewAndAppendSignature(o,this.privateKey,s-w.SIGNATURE_LENGTH),o}#e(A){return w.ARE_IDS_HEX?this.converter.hexToBytes(A.join(""),w.ID_LENGTH*A.length):this.converter.stringToBytes(A.join(""))}#s(A){return typeof A=="string"?{dataCode:1,dataBytes:this.converter.stringToBytes(A)}:A instanceof Uint8Array?{dataCode:2,dataBytes:A}:{dataCode:3,dataBytes:this.converter.stringToBytes(JSON.stringify(A))}}#n(A,t,e,s,n,o,g){let c=this.converter.numberTo8Bytes(n),r=this.converter.numberTo4Bytes(o.length);A.set([t],0),A.set([e],1),A.set([s],2),A.set(c,3),A.set(r,11),A.set(g,15)}verifySignature(A,t,e){return this.AVOID_CRYPTO?!0:ZA.verify(t,e,A)}readBufferHeader(A,t=!0){let e=A[0],s=A[1],n=A[2],o=A.slice(3,11),g=A.slice(11,15),c=A.slice(15,47),r=t?this.#t(c):null,I=n*this.idLength,a=this.converter.bytes8ToNumber(o),h=this.converter.bytes4ToNumber(g);return{marker:e,dataCode:s,neighLength:I,timestamp:a,dataLength:h,pubkey:c,associatedId:r}}readGossipMessage(A){this.verbose>3&&console.log(`%creadGossipMessage ${A.byteLength} bytes`,U.CRYPTO_CODEX),this.verbose>3&&console.log(`%c${A}`,U.CRYPTO_CODEX);try{let{marker:t,dataCode:e,neighLength:s,timestamp:n,dataLength:o,pubkey:g,associatedId:c}=this.readBufferHeader(A),r=v.MARKERS_BYTES[t];if(r===void 0)throw new Error(`Failed to deserialize gossip message: unknown marker byte ${d[0]}.`);let I=s+o,a=this.#i(A.slice(47,47+s)),h=this.#o(e,A.slice(47+s,47+I)),E=47+I,C=A.slice(E,E+w.SIGNATURE_LENGTH),u=A[A.length-1],p=E+w.SIGNATURE_LENGTH+1,f=c;return new Qt(r,n,a,u,f,g,h,C,E,p)}catch(t){this.verbose>1&&console.warn(`Error deserializing ${topic||"unknown"} gossip message:`,t.stack)}return null}readUnicastMessage(A){this.verbose>3&&console.log(`%creadUnicastMessage ${A.byteLength} bytes`,U.CRYPTO_CODEX),this.verbose>3&&console.log(`%c${A}`,U.CRYPTO_CODEX);try{let{marker:t,dataCode:e,neighLength:s,timestamp:n,dataLength:o,pubkey:g}=this.readBufferHeader(A,!1),c=_.MARKERS_BYTES[t];if(c===void 0)throw new Error(`Failed to deserialize unicast message: unknown marker byte ${d[0]}.`);let r=s+o,I=this.#i(A.slice(47,47+s)),a=this.#o(e,A.slice(47+s,47+r)),E=A[47+r]*this.idLength,C=47+r+1+E,u=A.slice(47+r+1,C),p=this.#i(u),f=C+w.SIGNATURE_LENGTH,S=A.slice(C,f);if(!(A.length>f))return new WA(c,n,I,p,g,a,S,C,f);let N=A.slice(f,f+32),D=this.#i(A.slice(f+32,A.length-w.SIGNATURE_LENGTH)),G=A.slice(A.length-w.SIGNATURE_LENGTH);return new ft(c,n,I,p,g,a,S,N,D,G,A.length)}catch(t){this.verbose>1&&console.warn(`Error deserializing ${type||"unknown"} unicast message:`,t.stack)}return null}#i(A){let t=[],e=this.idLength;if(A.length%e!==0)throw new Error("Failed to parse ids: invalid serialized length.");for(let s=0;s<A.length/e;s++){let n=A.slice(s*e,(s+1)*e);w.ARE_IDS_HEX?t.push(this.converter.bytesToHex(n,w.ID_LENGTH)):t.push(this.converter.bytesToString(n))}return t}#o(A,t){if(A===1)return this.converter.bytesToString(t);if(A===2)return t;if(A===3)return JSON.parse(this.converter.bytesToString(t));throw new Error(`Failed to parse data: unknown data code '${A}'.`)}};var{SANDBOX:Bi,ICE_CANDIDATE_EMITTER:fi,TEST_WS_EVENT_MANAGER:Ci}=q.ENABLED?await ht().then(()=>It):{},Ie=class{maxOffers=30;offers=[];orderingBy="neighborsCount";get size(){return this.offers.length}updateOrderingBy(A=!1){this.orderingBy=A?"overlap":"neighborsCount"}removeOlderThan(A=1e3){this.offers=this.offers.filter(t=>t.timestamp+A>=F.time)}get bestOfferInfo(){let{senderId:A,overlap:t,neighborsCount:e,data:s,timestamp:n}=this.offers.shift()||{};return{senderId:A,data:s,timestamp:n,value:this.orderingBy==="overlap"?t:e}}pushSortTrim(A,t={min:.2,max:.8}){let{min:e,max:s}=t;Math.random()<Math.min(e,this.offers.size/this.maxOffers*s)||(this.offers.push(A),this.offers.length!==1&&(this.offers.sort((n,o)=>this.orderingBy==="overlap"?n.overlap-o.overlap:o.neighborsCount-n.neighborsCount),this.size>this.maxOffers&&this.offers.pop()))}},Tt=class{id;gossip;messager;peerStore;bootstraps;halfTarget=Math.ceil(R.TARGET_NEIGHBORS_COUNT/2);twiceTarget=R.TARGET_NEIGHBORS_COUNT*2;bootstrapsIds=new Set;get isPublicNode(){return!!this.services?.publicUrl}services;phase=0;nextBootstrapIndex=0;offersQueue=new Ie;maxBonus=P.CONNECTION_UPGRADE_TIMEOUT*.2;constructor(A,t,e,s,n){this.id=A,this.gossip=t,this.messager=e,this.peerStore=s;for(let o of n)this.bootstrapsIds.add(o.id);this.bootstraps=[...n].sort(()=>Math.random()-.5),this.nextBootstrapIndex=Math.random()*this.bootstrapsIds.size|0}tick(){let{neighborsCount:A,nonPublicNeighborsCount:t,isEnough:e,isTooMany:s,isHalfReached:n}=this.#t,o=t>=R.TARGET_NEIGHBORS_COUNT/3?1:X.MAX_SDP_OFFERS;if(this.peerStore.offerManager.offersToCreate=e?0:o,this.isPublicNode){this.services.freePublicNodeByKickingPeers();return}if(s)return Math.random()>.05?this.#o():null;e?Math.random()>.05&&this.#i():this.#i(),this.phase=this.phase?0:1,this.phase===0&&this.tryConnectNextBootstrap(A,t),this.phase===1&&this.#n(t,n)}handleIncomingSignal(A,t,e){if(this.isPublicNode||!A||this.peerStore.isKicked(A)||t.signal?.type!=="offer"&&t.signal?.type!=="answer")return;let{signal:s,offerHash:n}=t||{},{connected:o,nonPublicNeighborsCount:g,isTooMany:c,isHalfReached:r}=this.#t;if(c||o[A])return;if(s.type==="answer"){if(this.peerStore.addConnectingPeer(A,s,n)!==!0)return;let E=Math.abs(g-this.#A(A).nonPublicCount),C=this.maxBonus/R.TARGET_NEIGHBORS_COUNT,u=Math.round(Math.min(this.maxBonus,E*C));return this.peerStore.assignSignal(A,s,n,F.time+u)}if(g>this.twiceTarget)return;let{overlap:I,nonPublicCount:a}=this.#A(A);if(a>this.twiceTarget)return;let h={senderId:A,data:t,overlap:I,neighborsCount:a,timestamp:F.time};this.offersQueue.updateOrderingBy(r),this.offersQueue.pushSortTrim(h)}tryConnectNextBootstrap(A=0,t=0){if(this.bootstrapsIds.size===0)return;let e=A-t,[s,n]=[0,0];for(let c in this.peerStore.connecting)this.bootstrapsIds.has(c)?n++:s++;if(e+n>=this.halfTarget||A>=R.TARGET_NEIGHBORS_COUNT||s+t>this.twiceTarget)return;let{id:o,publicUrl:g}=this.bootstraps[this.nextBootstrapIndex++%this.bootstrapsIds.size];o&&g&&(this.peerStore.connected[o]||this.peerStore.connecting[o])||this.#s(o,g)}get#t(){return{connected:this.peerStore.connected,neighborsCount:this.peerStore.neighborsList.length,nonPublicNeighborsCount:this.peerStore.standardNeighborsList.length,isEnough:this.peerStore.standardNeighborsList.length>=R.TARGET_NEIGHBORS_COUNT,isTooMany:this.peerStore.standardNeighborsList.length>R.TARGET_NEIGHBORS_COUNT,isHalfReached:this.peerStore.standardNeighborsList.length>=this.halfTarget}}#A(A="toto"){let t=this.peerStore.known[A]?.neighbors||{},e={overlap:0,nonPublicCount:0,p1nCount:this.peerStore.getUpdatedPeerConnectionsCount(A)};for(let s in t)lA.isPublicNode(s)||e.nonPublicCount++;for(let s of this.peerStore.standardNeighborsList)t[s]&&e.overlap++;return e}#e(A=[]){return A.map(t=>({id:t,...this.#A(t)}))}#s(A="toto",t="localhost:8080"){if(!lA.isPublicNode(A))return this.verbose<1?null:console.warn(`Topologist: trying to connect to a non-public node (${A})`);let e=new X.WS_CLIENT(t);e.binaryType="arraybuffer",this.peerStore.connecting[A]||(this.peerStore.connecting[A]={}),this.peerStore.connecting[A].out=new mA(A,e,"out",!0),e.onerror=s=>console.error("WebSocket error:",s.stack),e.onopen=()=>{e.onclose=()=>{for(let s of this.peerStore.callbacks.disconnect)s(A,"out")},e.onmessage=s=>{for(let n of this.peerStore.callbacks.data)n(A,s.data)};for(let s of this.peerStore.callbacks.connect)s(A,"out")}}#n(A=0,t=!1){let s=Object.keys(this.peerStore.connecting).length+A,[n,o,g]=[null,null,null];for(let u in this.peerStore.offerManager.offers){let p=this.peerStore.offerManager.offers[u],{isUsed:f,sentCounter:S,signal:Q,timestamp:N}=p;if(f||S>0)continue;let D=F.time-N;if(!(D>X.SDP_OFFER_EXPIRATION/2)&&!(g&&D>g)){o=p,n=u,g=D;break}}if(!n||!o)return;if(!t&&s<=this.twiceTarget){this.gossip.broadcastToAll({signal:o.signal,offerHash:n},"signal_offer"),o.sentCounter++;return}let c=null;for(let u of this.#e(this.peerStore.standardNeighborsList)){let p=u[t?"overlap":"nonPublicCount"];c===null&&(c=p),t&&p<c&&(c=p),!t&&p<=c&&(c=p)}let r=100,I=1e3,a=this.peerStore.knownCount,h=Math.max(Math.min(I/a,a/I),.127),E=[];for(let u in this.peerStore.known){if(Math.random()>h)continue;if(--I<=0)break;if(u===this.id||lA.isPublicNode(u)||this.peerStore.isKicked(u))continue;if(this.peerStore.connected[u]||this.peerStore.connecting[u])continue;let{overlap:p,nonPublicCount:f}=this.#A(u);if(!(f>R.TARGET_NEIGHBORS_COUNT)&&(c===null&&(c=t?p:f),!(t&&p>c)&&!(!t&&f<c)&&(E.push(u),--r<=0)))break}if(!E.length)return;let C=new Map;for(let u=0;u<Math.min(E.length,100);u++){let p=E[Math.floor(Math.random()*E.length)];if(!C.has(p)&&(C.size===0&&o.sentCounter++,C.set(p,!0),this.messager.sendUnicast(p,{signal:o.signal,offerHash:n},"signal_offer",1),C.size>=12))break}}#i(){let A=null,t=Object.keys(this.peerStore.connecting).length;this.offersQueue.updateOrderingBy(this.#t.isHalfReached),this.offersQueue.removeOlderThan(X.SDP_OFFER_EXPIRATION/2);for(let e=0;e<this.offersQueue.size;e++){let{senderId:s,data:n,timestamp:o,value:g}=this.offersQueue.bestOfferInfo;if(!s||!n||!o)break;if(!(this.peerStore.connected[s]||this.peerStore.isKicked(s))&&!this.peerStore.connecting[s]?.in){if(A=A===null?g:A,A!==g)break;this.peerStore.addConnectingPeer(s,n.signal,n.offerHash)===!0&&(this.peerStore.assignSignal(s,n.signal,n.offerHash,o),t++)}}}#o(){let t=this.#e(this.peerStore.standardNeighborsList).sort((e,s)=>s.overlap-e.overlap||s.nonPublicCount-e.nonPublicCount);this.peerStore.kickPeer(t[0].id,6e4,"improveTopology")}};await sA();var Bn=P.IS_BROWSER?null:await import("dgram"),Mt=class{id;verbose;maxKick;peerStore;cryptoCodex;publicUrl;constructor(A,t,e=3,s=1){this.id=A.id,this.verbose=s,this.maxKick=e,this.peerStore=t,this.cryptoCodex=A}start(A="localhost",t=EA.PORT){this.publicUrl=`ws://${A}:${t}`,this.#t(A,t),q.USE_TEST_TRANSPORTS||this.#A(A,t+1)}freePublicNodeByKickingPeers(){let A=Math.min(this.maxKick,this.peerStore.neighborsList.length-R.TARGET_NEIGHBORS_COUNT);if(A<=0)return;let t=0,e=EA.AUTO_KICK_DELAY;for(let s in this.peerStore.connected){let n=this.peerStore.connected[s],o=this.peerStore.getUpdatedPeerConnectionsCount(s,!1);if(o>R.TARGET_NEIGHBORS_COUNT){if(this.peerStore.kickPeer(s,EA.AUTO_KICK_DURATION,"freePublicNode"),this.peerStore.neighborsList.length<=R.TARGET_NEIGHBORS_COUNT)break;continue}if(!(n.getConnectionDuration()<(o>2?e:e*2))&&(this.peerStore.kickPeer(s,EA.AUTO_KICK_DURATION,"freePublicNode"),++t>=A))break}}#t(A="localhost",t=EA.PORT){this.wsServer=new X.WS_SERVER({port:t,host:A}),this.wsServer.on("error",e=>console.error(`WebSocket error on Node #${this.id}:`,e)),this.wsServer.on("connection",e=>{e.on("close",()=>{if(s)for(let n of this.peerStore.callbacks.disconnect)n(s,"in")}),e.on("error",n=>console.error(`WebSocket error on Node #${this.id} with peer ${s}:`,n.stack));let s;e.on("message",n=>{if(s)for(let o of this.peerStore.callbacks.data)o(s,n);else{let o=new Uint8Array(n);if(o[0]>127)return;let{route:g,type:c,neighborsList:r}=this.cryptoCodex.readUnicastMessage(o)||{};if(c!=="handshake"||g.length!==2||g[1]!==this.id)return;s=g[0],this.peerStore.digestPeerNeighbors(s,r),this.peerStore.connecting[s]?.out?.close(),this.peerStore.connecting[s]||(this.peerStore.connecting[s]={}),this.peerStore.connecting[s].in=new mA(s,e,"in",!0);for(let I of this.peerStore.callbacks.connect)I(s,"in")}})})}#A(A="localhost",t=EA.PORT+1){this.stunServer=Bn.createSocket("udp4"),this.stunServer.on("message",(e,s)=>{this.verbose>2&&console.log(`%cSTUN message from ${s.address}:${s.port} - ${e.toString("hex")}`,U.SERVICE),this.#e(e)&&this.stunServer.send(this.#s(e,s),s.port,s.address)}),this.stunServer.bind(t,A)}#e(A){if(A.length<20)return!1;let t=A.readUInt16BE(0),e=A.readUInt32BE(4);return t===1&&e===554869826}#s(A,t){let e=A.subarray(8,20),s=Buffer.allocUnsafe(32);return s.writeUInt16BE(257,0),s.writeUInt16BE(12,2),s.writeUInt32BE(554869826,4),e.copy(s,8),s.writeUInt16BE(1,20),s.writeUInt16BE(8,22),s.writeUInt16BE(1,24),s.writeUInt16BE(t.port,26),s.writeUInt32BE(BA.ipToInt(t.address),28),this.verbose>2&&console.log(`%cSTUN Response: client will discover IP ${t.address}:${t.port}`,"color: green;"),s}static deriveSTUNServers(A,t=!1){let e=[];for(let s of A){let n=s.publicUrl.split(":")[1].replace("//",""),o=parseInt(s.publicUrl.split(":")[2])+1;e.push({urls:`stun:${n}:${o}`})}return t&&(this.stunUrls.push({urls:"stun:stun.l.google.com:5349"}),this.stunUrls.push({urls:"stun:stun.l.google.com:19302"}),this.stunUrls.push({urls:"stun:stun1.l.google.com:3478"}),this.stunUrls.push({urls:"stun:stun1.l.google.com:5349"})),e}};async function hs(i={}){let A=i.verbose!==void 0?i.verbose:P.DEFAULT_VERBOSE,t=i.cryptoCodex||new lA(void 0,A);t.publicKey||await t.generate(!1);let e=new zA(t,i.bootstraps||[],A);return i.autoStart!==!1&&await e.start(),e}var zA=class{started=!1;id;cryptoCodex;verbose;arbiter;offerManager;peerStore;messager;gossip;topologist;services;constructor(A,t=[],e=P.DEFAULT_VERBOSE){this.verbose=e,this.topologist?.services&&(this.topologist.services.verbose=e),this.cryptoCodex=A,this.id=this.cryptoCodex.id;let s=Mt.deriveSTUNServers(t||[]);this.offerManager=new ot(this.id,s,e),this.arbiter=new nt(this.id,A,e),this.peerStore=new Et(this.id,this.cryptoCodex,this.offerManager,this.arbiter,e),this.messager=new Ct(this.id,this.cryptoCodex,this.arbiter,this.peerStore,e),this.gossip=new ut(this.id,this.cryptoCodex,this.arbiter,this.peerStore,e),this.topologist=new Tt(this.id,this.gossip,this.messager,this.peerStore,t||[]);let{arbiter:n,peerStore:o,messager:g,gossip:c,topologist:r}=this;o.on("signal",(I,a)=>this.sendMessage(I,a,"signal_answer")),o.on("connect",(I,a)=>this.#t(I,a)),o.on("disconnect",(I,a)=>this.#A(I,a)),o.on("data",(I,a)=>this.#e(I,a)),g.on("signal_answer",(I,a)=>r.handleIncomingSignal(I,a)),g.on("signal_offer",(I,a)=>r.handleIncomingSignal(I,a)),c.on("signal_offer",(I,a,h)=>r.handleIncomingSignal(I,a,h)),e>2&&console.log(`Node initialized: ${this.id}`)}#t=(A,t)=>{let e=this.cryptoCodex.isPublicNode(A);if(this.publicUrl)return;this.verbose>(this.publicUrl||e?3:2)&&console.log(`(${this.id}) ${t==="in"?"Incoming":"Outgoing"} connection established with peer ${A}`),(e||t==="in")&&this.sendMessage(A,this.id,"handshake");let n=this.peerStore.neighborsList.length>=R.TARGET_NEIGHBORS_COUNT+this.halfTarget,o=()=>{R.ON_CONNECT_DISPATCH.OVER_NEIGHBORED&&n&&this.broadcast([],"over_neighbored"),R.ON_CONNECT_DISPATCH.SHARE_HISTORY&&this.peerStore.getUpdatedPeerConnectionsCount(A)<=1&&this.gossip.sendGossipHistoryToPeer(A)};R.ON_CONNECT_DISPATCH.DELAY?setTimeout(o,R.ON_CONNECT_DISPATCH.DELAY):o()};#A=(A,t)=>{if(!this.peerStore.neighborsList.length){for(let n in this.peerStore.connecting)this.peerStore.kickPeer(n,0,"no_neighbors_left");for(let n in this.offerManager.offers)this.offerManager.offers[n].timestamp=0}let e=this.cryptoCodex.isPublicNode(A);if(this.peerStore.connected[A])return;this.verbose>(this.publicUrl||e?3:2)&&console.log(`(${this.id}) ${t==="in"?"Incoming":"Outgoing"} connection closed with peer ${A}`)};#e=(A,t)=>{let e=new Uint8Array(t);e[0]>127?this.gossip.handleGossipMessage(A,e):this.messager.handleDirectMessage(A,e)};get publicUrl(){return this.services?.publicUrl}get publicIdentity(){return{id:this.id,publicUrl:this.publicUrl}}onMessageData(A){this.messager.on("message",A)}onGossipData(A){this.gossip.on("gossip",A)}async start(){return await F.sync(this.verbose),this.started=!0,q.AVOID_INTERVALS||(this.topologist.tryConnectNextBootstrap(),this.arbiterInterval=setInterval(()=>this.arbiter.tick(),1e3),this.enhancerInterval=setInterval(()=>this.topologist.tick(),R.LOOP_DELAY),this.peerStoreInterval=setInterval(()=>{this.peerStore.cleanupExpired(),this.peerStore.offerManager.tick()},2500)),!0}broadcast(A,t,e){this.gossip.broadcastToAll(A,t,e)}sendMessage(A,t,e,s=1){this.messager.sendUnicast(A,t,e,s)}async tryConnectToPeer(A="toto",t=5){console.info("FUNCTION DISABLED FOR NOW")}destroy(){this.enhancerInterval&&clearInterval(this.enhancerInterval),this.enhancerInterval=null,this.peerStoreInterval&&clearInterval(this.peerStoreInterval),this.peerStoreInterval=null,this.peerStore.destroy(),this.wsServer&&this.wsServer.close(),this.stunServer&&this.stunServer.close()}};await sA();var Es={Node:zA,createNode:hs,CryptoCodex:lA,CONFIG:de};var Mi=Es;typeof window<"u"&&(window.HiveP2P=Es);export{de as CONFIG,lA as CryptoCodex,zA as Node,hs as createNode,Mi as default};
|
|
3
|
+
/*! Bundled license information:
|
|
4
|
+
|
|
5
|
+
@noble/ed25519/index.js:
|
|
6
|
+
(*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
|
|
7
|
+
|
|
8
|
+
@noble/hashes/utils.js:
|
|
9
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
10
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hive-p2p",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"description": "P2P networking library for Node.js with WebRTC - Full featured package",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "./packages/full/index.mjs",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build:server": "node resources/build-prepare.mjs server",
|
|
12
|
+
"build:browser": "node resources/build-prepare.mjs browser",
|
|
13
|
+
"build:min": "cd packages/browser-min && npm run build"
|
|
14
|
+
},
|
|
10
15
|
"files": [
|
|
11
16
|
"packages/full/",
|
|
12
17
|
"core/",
|
|
@@ -27,6 +32,9 @@
|
|
|
27
32
|
"wrtc": "~0.4.7",
|
|
28
33
|
"ws": "~8.18.3"
|
|
29
34
|
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"esbuild": "^0.25.10"
|
|
37
|
+
},
|
|
30
38
|
"repository": {
|
|
31
39
|
"type": "git",
|
|
32
40
|
"url": "https://github.com/Seigneur-Machiavel/hive-p2p.git"
|
|
@@ -41,8 +49,5 @@
|
|
|
41
49
|
"simulation"
|
|
42
50
|
],
|
|
43
51
|
"author": "PinkParrot",
|
|
44
|
-
"license": "GPL-3.0"
|
|
45
|
-
"scripts": {
|
|
46
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
47
|
-
}
|
|
52
|
+
"license": "GPL-3.0"
|
|
48
53
|
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronized Network Clock
|
|
3
|
+
* Simple, efficient NTP-based time synchronization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class Clock {
|
|
7
|
+
verbose;
|
|
8
|
+
mockMode; // if true, use local time without sync
|
|
9
|
+
static #instance = null;
|
|
10
|
+
|
|
11
|
+
#offset = null; // ms difference from local time
|
|
12
|
+
#syncing = false;
|
|
13
|
+
#lastSync = 0;
|
|
14
|
+
#sources = ['time.google.com', 'time.cloudflare.com', 'pool.ntp.org'];
|
|
15
|
+
#browserSources = [
|
|
16
|
+
'worldtimeapi.org/api/timezone/UTC',
|
|
17
|
+
'timeapi.io/api/Time/current/zone?timeZone=UTC',
|
|
18
|
+
'api.github.com'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
constructor(verbose = 0, mockMode = false) {
|
|
22
|
+
this.verbose = verbose;
|
|
23
|
+
this.mockMode = mockMode;
|
|
24
|
+
if (Clock.#instance) return Clock.#instance;
|
|
25
|
+
else Clock.#instance = this;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// PUBLIC API
|
|
29
|
+
static get instance() { return Clock.#instance || new Clock(); }
|
|
30
|
+
static get time() { return Clock.instance.time; }
|
|
31
|
+
get time() {
|
|
32
|
+
if (this.mockMode) return Date.now();
|
|
33
|
+
if (this.#offset === null) return null;
|
|
34
|
+
return Date.now() + Math.round(this.#offset);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async sync(verbose) {
|
|
38
|
+
if (verbose !== undefined) this.verbose = verbose;
|
|
39
|
+
if (this.mockMode) return Date.now();
|
|
40
|
+
|
|
41
|
+
if (this.#syncing) {
|
|
42
|
+
while (this.#syncing) await new Promise(resolve => setTimeout(resolve, 50));
|
|
43
|
+
return this.time;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.#syncing = true;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const samples = await this.#fetchTimeSamples();
|
|
50
|
+
if (samples.length === 0) {
|
|
51
|
+
console.warn('[Clock] All NTP sources failed, using local time');
|
|
52
|
+
this.#offset = 0;
|
|
53
|
+
return this.time;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.#offset = this.#calculateOffset(samples);
|
|
57
|
+
this.#lastSync = Date.now();
|
|
58
|
+
|
|
59
|
+
if (samples.length < this.#sources.length)
|
|
60
|
+
setTimeout(() => this.#backgroundRefine(), 100);
|
|
61
|
+
return this.time;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('[Clock] Sync failed:', error);
|
|
64
|
+
this.#offset = 0;
|
|
65
|
+
return this.time;
|
|
66
|
+
} finally {
|
|
67
|
+
this.#syncing = false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get status() {
|
|
72
|
+
if (this.mockMode) return {
|
|
73
|
+
synchronized: true, syncing: false, offset: 0,
|
|
74
|
+
lastSync: Date.now(), age: 0
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
synchronized: this.#offset !== null,
|
|
78
|
+
syncing: this.#syncing,
|
|
79
|
+
offset: this.#offset,
|
|
80
|
+
lastSync: this.#lastSync,
|
|
81
|
+
age: this.#lastSync ? Date.now() - this.#lastSync : null
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// PRIVATE METHODS
|
|
86
|
+
async #fetchTimeSamples() {
|
|
87
|
+
const sources = (typeof window !== 'undefined') ? this.#browserSources : this.#sources;
|
|
88
|
+
const promises = sources.map(source => this.#fetchTimeFromSource(source));
|
|
89
|
+
const results = await Promise.allSettled(promises);
|
|
90
|
+
|
|
91
|
+
const samples = [];
|
|
92
|
+
for (const result of results) {
|
|
93
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
94
|
+
samples.push(result.value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return samples;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async #fetchTimeFromSource(source) {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000); // Plus de timeout
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
const url = source.startsWith('http') ? source : `https://${source}`;
|
|
107
|
+
|
|
108
|
+
const response = await fetch(url, {
|
|
109
|
+
method: source.includes('api.github.com') ? 'HEAD' : 'GET',
|
|
110
|
+
signal: controller.signal,
|
|
111
|
+
cache: 'no-cache',
|
|
112
|
+
mode: 'cors' // Explicit CORS
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const networkLatency = (Date.now() - startTime) / 2;
|
|
116
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
117
|
+
|
|
118
|
+
let serverTime;
|
|
119
|
+
|
|
120
|
+
if (source.includes('worldtimeapi')) {
|
|
121
|
+
const data = await response.json();
|
|
122
|
+
serverTime = new Date(data.utc_datetime).getTime();
|
|
123
|
+
} else if (source.includes('timeapi')) {
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
serverTime = new Date(data.dateTime).getTime();
|
|
126
|
+
} else {
|
|
127
|
+
const dateHeader = response.headers.get('date');
|
|
128
|
+
if (!dateHeader) throw new Error('No date header');
|
|
129
|
+
serverTime = new Date(dateHeader).getTime();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (isNaN(serverTime)) throw new Error('Invalid time data');
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
source,
|
|
136
|
+
serverTime: serverTime + networkLatency,
|
|
137
|
+
localTime: Date.now(),
|
|
138
|
+
latency: networkLatency * 2
|
|
139
|
+
};
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (this.verbose) console.warn(`[Clock] Failed to fetch time from ${source}:`, error.message);
|
|
142
|
+
return null; // Retourne explicitement null au lieu d'undefined
|
|
143
|
+
} finally {
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#calculateOffset(samples) {
|
|
149
|
+
// Filter out null samples (au cas où)
|
|
150
|
+
const validSamples = samples.filter(sample => sample !== null);
|
|
151
|
+
if (validSamples.length === 0) return 0;
|
|
152
|
+
if (validSamples.length === 1) return validSamples[0].serverTime - validSamples[0].localTime;
|
|
153
|
+
|
|
154
|
+
validSamples.sort((a, b) => a.latency - b.latency);
|
|
155
|
+
|
|
156
|
+
const offsets = [];
|
|
157
|
+
for (const sample of validSamples)
|
|
158
|
+
offsets.push(sample.serverTime - sample.localTime);
|
|
159
|
+
|
|
160
|
+
offsets.sort((a, b) => a - b);
|
|
161
|
+
const mid = Math.floor(offsets.length / 2);
|
|
162
|
+
|
|
163
|
+
if (offsets.length % 2 === 0)
|
|
164
|
+
return (offsets[mid - 1] + offsets[mid]) / 2;
|
|
165
|
+
return offsets[mid];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async #backgroundRefine() {
|
|
169
|
+
if (this.#syncing) return;
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const samples = await this.#fetchTimeSamples();
|
|
173
|
+
if (samples.length === 0) return;
|
|
174
|
+
|
|
175
|
+
const newOffset = this.#calculateOffset(samples);
|
|
176
|
+
if (Math.abs(newOffset - this.#offset) > 100)
|
|
177
|
+
this.#offset = newOffset;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (this.verbose) console.warn('[Clock] Background refine failed:', error);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function CLOCK_TEST() {
|
|
185
|
+
const startTime = Date.now();
|
|
186
|
+
const clock = new Clock(1); // Verbose pour debug
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
await clock.sync();
|
|
190
|
+
console.log('Synchronized in:', Date.now() - startTime, 'ms');
|
|
191
|
+
console.log('Synchronized time:', new Date(clock.time).toISOString());
|
|
192
|
+
console.log('Clock status:', clock.status);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error('Sync failed:', error);
|
|
195
|
+
}
|
|
196
|
+
}
|
package/services/clock.mjs
CHANGED
|
@@ -12,11 +12,6 @@ export class Clock {
|
|
|
12
12
|
#syncing = false;
|
|
13
13
|
#lastSync = 0;
|
|
14
14
|
#sources = ['time.google.com', 'time.cloudflare.com', 'pool.ntp.org'];
|
|
15
|
-
#browserSources = [
|
|
16
|
-
'https://worldtimeapi.org/api/timezone/UTC',
|
|
17
|
-
'https://timeapi.io/api/Time/current/zone?timeZone=UTC',
|
|
18
|
-
'https://api.github.com'
|
|
19
|
-
];
|
|
20
15
|
|
|
21
16
|
constructor(verbose = 0, mockMode = false) {
|
|
22
17
|
this.verbose = verbose;
|
|
@@ -77,9 +72,7 @@ export class Clock {
|
|
|
77
72
|
|
|
78
73
|
// PRIVATE METHODS
|
|
79
74
|
async #fetchTimeSamples() { // Fetch time samples from all sources in parallel
|
|
80
|
-
const
|
|
81
|
-
console.log(sources);
|
|
82
|
-
const promises = sources.map(source => this.#fetchTimeFromSource(source));
|
|
75
|
+
const promises = this.#sources.map(source => this.#fetchTimeFromSource(source));
|
|
83
76
|
const results = await Promise.allSettled(promises);
|
|
84
77
|
const samples = [];
|
|
85
78
|
for (const result of results) if (result.status === 'fulfilled') samples.push(result.value);
|
|
@@ -92,29 +85,12 @@ export class Clock {
|
|
|
92
85
|
|
|
93
86
|
try {
|
|
94
87
|
const startTime = Date.now();
|
|
95
|
-
const response = await fetch(`https://${source}`, {
|
|
96
|
-
|
|
97
|
-
signal: controller.signal,
|
|
98
|
-
cache: 'no-cache'
|
|
99
|
-
});
|
|
100
|
-
const networkLatency = (Date.now() - startTime) / 2;
|
|
88
|
+
const response = await fetch(`https://${source}`, { method: 'HEAD', signal: controller.signal, cache: 'no-cache' });
|
|
89
|
+
const networkLatency = (Date.now() - startTime) / 2; // Rough RTT/2
|
|
101
90
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
102
91
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// Browser APIs retournent du JSON
|
|
106
|
-
if (source.includes('worldtimeapi')) {
|
|
107
|
-
const data = await response.json();
|
|
108
|
-
serverTime = new Date(data.utc_datetime).getTime();
|
|
109
|
-
} else if (source.includes('timeapi')) {
|
|
110
|
-
const data = await response.json();
|
|
111
|
-
serverTime = new Date(data.dateTime).getTime();
|
|
112
|
-
} else {
|
|
113
|
-
// GitHub ou NTP classique - header Date
|
|
114
|
-
serverTime = new Date(response.headers.get('date')).getTime();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (isNaN(serverTime)) throw new Error('Invalid time data');
|
|
92
|
+
const serverTime = new Date(response.headers.get('date')).getTime();
|
|
93
|
+
if (isNaN(serverTime)) throw new Error('Invalid date header');
|
|
118
94
|
|
|
119
95
|
return {
|
|
120
96
|
source,
|
|
@@ -122,8 +98,6 @@ export class Clock {
|
|
|
122
98
|
localTime: Date.now(),
|
|
123
99
|
latency: networkLatency * 2
|
|
124
100
|
};
|
|
125
|
-
} catch (error) {
|
|
126
|
-
if (this.verbose) console.warn(`[Clock] Failed to fetch time from ${source}:`, error.message);
|
|
127
101
|
} finally { clearTimeout(timeoutId); }
|
|
128
102
|
}
|
|
129
103
|
/** @param {Array<{serverTime: number, localTime: number, latency: number}>} samples */
|