@solarpunkltd/swarm-chat-js 9.0.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -252
- package/dist/index.cjs +1 -1
- package/dist/index.js +27 -57
- package/dist/message/binding.d.ts +7 -7
- package/dist/message/message.d.ts +7 -6
- package/dist/message/personalSign.d.ts +1 -1
- package/dist/message/walletLink.d.ts +5 -5
- package/dist/{message-DQda4_Ge.js → message-BUFAxjtN.js} +16 -20
- package/dist/message-BjeTRy2F.cjs +4 -0
- package/dist/message.cjs +1 -1
- package/dist/message.js +1 -2
- package/dist/pacer.d.ts +1 -1
- package/package.json +3 -3
- package/dist/message-DBi9VeRs.cjs +0 -4
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./message-DBi9VeRs.cjs");let t=require("@ethersphere/bee-js");var n={LOADING_INIT:`loadingInit`,LOADING_PREVIOUS_MESSAGES:`loadingPreviousMessages`,MESSAGE_RECEIVED:`messageReceived`,MESSAGE_REQUEST_INITIATED:`messageRequestInitiated`,MESSAGE_REQUEST_UPLOADED:`messageRequestUploaded`,MESSAGE_REQUEST_ERROR:`messageRequestError`,CRITICAL_ERROR:`criticalError`,STATUS:`status`,MESSAGE_SKIPPED:`messageSkipped`,ERROR:`error`};function r(e){return a(e,-1,e.ts)}function i(e){return a(e.msg,e.seq,e.at)}function a(e,t,n){return{id:e.id,type:e.type,message:e.text,username:e.name,address:e.addr,timestamp:n,...e.target?{targetMessageId:e.target}:{},index:t,signedMessage:e}}var o=class{constructor(){this.listeners=new Map,this.on=(e,t)=>{this.listeners.set(e,[...this.listeners.get(e)??[],t])},this.off=(e,t)=>{this.listeners.set(e,(this.listeners.get(e)??[]).filter(e=>e!==t))},this.cleanAll=()=>{this.listeners.clear()}}emit(e,t){for(let n of this.listeners.get(e)??[])try{n(t)}catch(t){console.error(`a listener for ${e} threw`,t)}}},s=2e4,c=class{constructor(e,t){this.spacingMs=e,this.now=t,this.missedAt=new Map}readableAt(e,t=this.now()){let n=this.missedAt.get(e);return n===void 0||this.expired(n,t)?-1/0:n+this.spacingMs}mayRead(e,t=this.now()){return t>=this.readableAt(e,t)}missed(e,t=this.now()){for(let[e,n]of this.missedAt)this.expired(n,t)&&this.missedAt.delete(e);this.missedAt.set(e,t)}found(e){this.missedAt.delete(e)}clear(){this.missedAt.clear()}expired(e,t){return e>t||t-e>=this.spacingMs}},l=class extends Error{constructor(e){super(`the feed head lookup did not answer in time`,e),this.name=`HeadLookupTimeoutError`}},u=class extends Error{constructor(e,t){super(`feed slot ${e} was served but could not be read`,t),this.index=e,this.name=`UnreadableSlotError`}};function d(e){return e instanceof t.BeeResponseError&&(e.status===404||e.status===500)}async function f(e,n){try{return await n()}catch(n){if(d(n))return null;throw n instanceof t.BeeResponseError?n:new u(e,{cause:n})}}function p(n,r,i,a,o=e.n){let s=t.Topic.fromString(i),c=e=>n.feed.makeReader(s,r,m(e));return{readNote:t=>f(t,async()=>(await n.soc.makeReader(r,m(a.slotReadMs)).download(e.s(i,o,t))).payload.toUint8Array()),readSlot:e=>f(e,async()=>(await c(a.slotReadMs).downloadPayload({index:e})).payload.toUint8Array()),async readHead(){let e=m(a.feedReadMs);try{let{payload:t,feedIndex:i}=await n.feed.makeReader(s,r,e).downloadPayload();return{index:Number(i.toBigInt()),payload:t.toUint8Array()}}catch(t){if(d(t))return null;throw e.signal?.aborted?new l({cause:t}):t}},async readFile(e){return(await n.data.download(e,void 0,m(a.feedReadMs))).toUint8Array()}}}function m(e){return{signal:AbortSignal.timeout(e)}}var h=`0123456789abcdef`.repeat(4);function g(e,n,r,i,a){let o=new t.PrivateKey(r),s=t.Identifier.fromString(i);return async t=>{await e.messaging.gsocSend(n,o,s,t,{deferred:!1},m(a.writeMs))}}var _={LIVE:`live`,RECONNECTING:`reconnecting`,STALLED:`stalled`},v={pollIntervalMs:1e3,missingReadSpacingMs:s,maxSlotsPerPoll:16,unservedPollsBeforeProbe:3,unreadablePollsBeforeFailure:3,probeIntervalCapMs:6e4,probeDistances:[1,2,4,8],missedLimit:32,missedReadsPerPoll:4,missedExpiryMs:3e5,backoffCapMs:8e3,stallAfterMs:8e3,random:Math.random,now:Date.now},y=class extends Error{constructor(e){super(`the gateway keeps answering feed slot ${e} with something that is not a chunk`),this.index=e,this.name=`UnreadableGatewayError`}},b=class{constructor(e,t,n,r={},i=null){this.source=e,this.topic=t,this.events=n,this.notes=i,this.next=0,this.ceiling=null,this.nextNoteSlot=0,this.lastNoteFoundAt=0,this.unservedPolls=0,this.nextProbeAt=0,this.unreadablePolls=0,this.gatewayFailures=0,this.missed=new Map,this.timer=null,this.generation=0,this.running=!1,this.status=null,this.settings={...v,...r},this.pacer=new c(this.settings.missingReadSpacingMs,this.settings.now)}get nextIndex(){return this.next}get missedIndices(){return[...this.missed.keys()]}get ledByNotes(){return this.ceiling!==null}start(e,t=null){this.stop(),this.next=e,this.ceiling=t?.newest??null,this.nextNoteSlot=t?.nextNoteSlot??(this.notes?this.notes.lastReadableSlot()+1:0),this.lastNoteFoundAt=this.settings.now(),this.resetRefusals(),this.unreadablePolls=0,this.gatewayFailures=0,this.missed.clear(),this.pacer.clear(),this.status=null,this.running=!0,this.schedule(0)}stop(){this.running=!1,this.generation++,this.timer&&=(clearTimeout(this.timer),null)}schedule(e){let t=this.generation;this.timer=setTimeout(()=>{this.timer=null,this.poll(t)},e)}async poll(e){let t=0,n=!1;try{this.notes!==null&&await this.readDueNotes(this.notes,e),t=await this.walk(e),await this.readMissed(e)}catch(t){n=!0,e===this.generation&&this.gatewayFailed(t)}if(e===this.generation&&this.running){if(n){this.schedule(this.backoffMs());return}this.gatewayAnswered(),this.schedule(t>=this.settings.maxSlotsPerPoll?0:this.untilNextRead())}}untilNextRead(){let e=this.settings.now(),t=t=>{let n=this.pacer.readableAt(t);return n>e?n:e+this.settings.pollIntervalMs},n=[...this.missed.keys()].map(t);return this.notes!==null&&n.push(this.notes.readableAt(this.nextNoteSlot)),this.ceiling===null&&n.push(t(this.next)),Math.max(0,Math.min(...n)-e)}async readDueNotes(e,t){let n=this.settings.now(),r=e.lastReadableSlot(n);if(r<this.nextNoteSlot)return;let i=Math.max(this.nextNoteSlot,r-e.lookBackSlots+1),a=await e.scan(r,i);if(t===this.generation){if(this.nextNoteSlot=r+1,a){this.lastNoteFoundAt=n,this.ceiling=Math.max(this.ceiling??-1,a.note.newest,this.next-1);return}n-this.lastNoteFoundAt>=e.silenceMs&&(this.lastNoteFoundAt=n,e.clock.distrust(),this.nextNoteSlot=Math.min(this.nextNoteSlot,e.lastReadableSlot(n)+1))}}async read(e){let t;try{t=await this.source.readSlot(e)}catch(e){if(e instanceof u)return`unreadable`;throw e}return t===null?this.pacer.missed(e):this.pacer.found(e),t}async readUnnamed(e){return this.pacer.mayRead(e)?this.read(e):`held`}async walk(e){for(let t=0;t<this.settings.maxSlotsPerPoll;t++){let n=this.next;if(this.ceiling!==null&&n>this.ceiling)return t;let r=this.ceiling===null?await this.readUnnamed(n):await this.read(n);if(e!==this.generation||r===`held`)return t;if(this.ceiling!==null&&(r===null||r===`unreadable`)){this.remember(n),this.next=n+1;continue}if(r===null||r===`unreadable`){if(t===0){if(this.unservedPolls++,this.unreadablePolls=r===`unreadable`?this.unreadablePolls+1:0,this.shouldProbe()&&await this.probePast(n,e)){this.unreadablePolls=0;continue}if(this.unreadablePolls>=this.settings.unreadablePollsBeforeFailure)throw new y(n)}return t}this.resetRefusals(),this.unreadablePolls=0,this.next=n+1,this.accept(n,r)}return this.settings.maxSlotsPerPoll}shouldProbe(){if(this.unservedPolls!==this.nextProbeAt)return!1;let{probeIntervalCapMs:e,pollIntervalMs:t,missingReadSpacingMs:n}=this.settings,r=Math.max(1,Math.ceil(e/Math.max(t,n)));return this.nextProbeAt+=Math.min(this.nextProbeAt,r),!0}resetRefusals(){this.unservedPolls=0,this.nextProbeAt=this.settings.unservedPollsBeforeProbe}async probePast(e,t){let n=new Set([e]);for(let r of this.settings.probeDistances){let i=e+r,a=await this.readUnnamed(i);if(t!==this.generation)return!1;if(a===null||a===`unreadable`||a===`held`){n.add(i);continue}this.resetRefusals(),this.remember(e);for(let r=e+1;r<i;r++){let e=n.has(r)?null:await this.readUnnamed(r);if(t!==this.generation)return!1;e===null||e===`unreadable`||e===`held`?this.remember(r):this.accept(r,e)}return this.next=i+1,this.accept(i,a),!0}return!1}remember(e){if(!this.missed.has(e)){if(this.missed.size>=this.settings.missedLimit){this.events.skipped(e,`unreachable`,`stepped past with the retry list full`);return}this.missed.set(e,this.settings.now())}}async readMissed(e){let t=this.settings.now();for(let[e,n]of this.missed)t-n>=this.settings.missedExpiryMs&&(this.missed.delete(e),this.events.skipped(e,`unreachable`,`not served within the time a stepped-past slot is kept`));let n=[...this.missed.keys()].filter(e=>this.pacer.mayRead(e,t)).slice(0,this.settings.missedReadsPerPoll);for(let t of n){let n=await this.read(t);if(e!==this.generation)return;let r=this.missed.get(t);this.missed.delete(t),n!==null&&n!==`unreadable`?this.accept(t,n):r!==void 0&&this.missed.set(t,r)}}accept(t,n){let r=e.v(n,t,this.topic);r.ok?(this.notes?.clock.observe(r.value.at,this.settings.now()),this.events.entry(r.value)):this.events.skipped(t,r.reason,r.detail)}gatewayFailed(e){this.gatewayFailures++,this.setStatus(_.RECONNECTING),this.events.error(e)}gatewayAnswered(){this.gatewayFailures=0;let e=this.settings.now(),t=[...this.missed.values()].some(t=>e-t>=this.settings.stallAfterMs);this.setStatus(t?_.STALLED:_.LIVE)}backoffMs(){let{pollIntervalMs:e,backoffCapMs:t,random:n}=this.settings,r=Math.min(t,e*2**this.gatewayFailures);return r/2+n()*r/2}setStatus(e){e!==this.status&&(this.status=e,this.events.status(e))}},x=16,S=class{constructor(e,t,n,r=null){this.source=e,this.topic=t,this.events=n,this.notes=r,this.older=null,this.loading=null}async open(){this.older=null;let e=await this.newestNote();if(e!==null)return this.openAt(e.newest,e);let t=await this.readHead();return t===null?{startAt:0,rows:[],notes:null}:this.openAt(t.index,null,t.payload)}async newestNote(){if(this.notes===null)return null;let e=this.notes.lastReadableSlot(),t=await this.notes.scan(e,e-this.notes.lookBackSlots+1);return t===null?null:{newest:t.note.newest,nextNoteSlot:e+1}}async openAt(e,t,n){let r=e<0?null:await this.newestLink(e,n);if(r===null)return{startAt:0,rows:[],notes:t};let i=await this.readFile(r);return i===`refused`?{startAt:0,rows:[],notes:t}:{startAt:r.toSeq+1,rows:i??[],notes:t}}async readHead(){try{return await this.source.readHead()}catch(e){if(e instanceof l)return this.events.error(e),null;throw e}}hasOlder(){return this.older!==null}loadOlder(){return this.loading??=this.loadOlderOnce().finally(()=>{this.loading=null}),this.loading}async loadOlderOnce(){let t=this.older;if(t===null)return[];let n=await this.source.readFile(t.ref),r=e.y(n,this.topic,t);if(!r.ok)throw this.older=null,Error(`history file ${t.ref} refused (${r.reason}): ${r.detail}`);return this.report(r.value.skipped),this.older=r.value.prev,r.value.rows}async newestLink(t,n){let r=n===void 0?t:t-1;if(n!==void 0){let r=e.v(n,t,this.topic);if(r.ok)return r.value.history}for(let n=r;n>=Math.max(0,t-x);n--){let t=await this.source.readSlot(n).catch(e=>{if(e instanceof u)return null;throw e});if(t===null)continue;let r=e.v(t,n,this.topic);if(r.ok)return r.value.history}return null}async readFile(t){try{let n=e.y(await this.source.readFile(t.ref),this.topic,t);return n.ok?(this.report(n.value.skipped),this.older=n.value.prev,n.value.rows):(this.events.error(Error(`history file ${t.ref} refused (${n.reason}): ${n.detail}`)),`refused`)}catch(e){return this.events.error(e),this.older=t,null}}report(e){e>0&&this.events.skipped(e)}},C={slotMs:e.n,heartbeatMs:e.t,marginMs:1e3,scanBatch:4,clockLimitMs:3e5,missingReadSpacingMs:s};function w(e){return typeof e.readNote==`function`}var T=class{constructor(e){this.limitMs=e,this.aheadAtMost=1/0,this.trusted=!0}observe(e,t){this.aheadAtMost=Math.min(this.aheadAtMost,t-e)}distrust(){this.trusted=!1}get isTrusted(){return this.trusted}get ms(){let e=Number.isFinite(this.aheadAtMost),t=this.trusted||!e?Math.min(0,this.aheadAtMost):this.aheadAtMost;return Math.max(-this.limitMs,Math.min(this.limitMs,t))}},E=class{constructor(e,t,n){this.source=e,this.now=n,this.counts={found:0,empty:0},this.settings={...C,...t},this.clock=new T(this.settings.clockLimitMs),this.pacer=new c(this.settings.missingReadSpacingMs,n)}lastReadableSlot(t=this.now()){return e.u(t-this.settings.marginMs-this.clock.ms,this.settings.slotMs)-1}readableAt(t){return e.l(t,this.settings.slotMs)+this.settings.marginMs+this.clock.ms}get lookBackSlots(){return Math.ceil(this.settings.heartbeatMs/this.settings.slotMs)+2}get silenceMs(){return this.settings.heartbeatMs+2*this.settings.slotMs+this.settings.marginMs}async read(t){if(!this.pacer.mayRead(t))return null;let n;try{n=await this.source.readNote(t),n===null&&this.pacer.missed(t)}catch(e){if(!(e instanceof u))throw e;n=null}let r=n===null?null:e.d(n);return r===null?(this.counts.empty++,null):(this.counts.found++,this.clock.observe(r.writtenAt,this.now()),r)}async scan(e,t){for(let n=e;n>=t;n-=this.settings.scanBatch){let e=[];for(let r=n;r>n-this.settings.scanBatch&&r>=t;r--)e.push(r);let r=await Promise.all(e.map(e=>this.read(e))),i=r.findIndex(e=>e!==null);if(i>=0)return{slot:e[i],note:r[i]}}return null}},D={resendAfterMs:1e4,maxResends:5,reactionWindowMs:1e3,isLive:()=>!0},O=class{constructor(e,t,n,r,i=D){this.key=e,this.profile=t,this.write=n,this.events=r,this.settings=i,this.outgoing=new Map,this.reactions=new Map,this.stopped=!1}get address(){return this.key.publicKey().address().toHex()}send(t){let{message:n,bytes:r}=e.M(this.key,{...t,...this.profile}),i={message:n,bytes:r,writes:0,written:!1,inFlight:!1,timer:null,lastError:null};return this.outgoing.set(n.id,i),this.events.pending(n),this.attempt(i),n}react(t,n,r){let i=JSON.stringify([t,n,r]),a=this.reactions.get(i);if(a){a.taps++;return}let o=setTimeout(()=>{let a=this.reactions.get(i);this.reactions.delete(i),a&&a.taps%2==1&&!this.stopped&&this.send({topic:t,type:e.O.REACTION,target:n,text:r})},this.settings.reactionWindowMs);this.reactions.set(i,{taps:1,timer:o})}confirm(e){if(e.addr!==this.address)return;let t=this.outgoing.get(e.id);t&&(this.clearTimer(t),this.outgoing.delete(e.id),this.events.confirmed(t.message))}retry(e){let t=this.outgoing.get(e);return!t||this.stopped?!1:(this.clearTimer(t),t.writes=0,t.inFlight||this.attempt(t),!0)}isPending(e){return this.outgoing.has(e)}stop(){this.stopped=!0;for(let e of this.outgoing.values())this.clearTimer(e);for(let{timer:e}of this.reactions.values())clearTimeout(e);this.reactions.clear()}attempt(e){!this.stopped&&this.outgoing.has(e.message.id)&&(e.writes++,e.inFlight=!0,this.write(e.bytes).then(()=>{e.inFlight=!1,!e.written&&this.outgoing.has(e.message.id)&&(e.written=!0,this.events.written(e.message)),this.scheduleNext(e)},t=>{e.inFlight=!1,e.lastError=t,this.scheduleNext(e)}))}scheduleNext(e){!this.stopped&&this.outgoing.has(e.message.id)&&(e.timer=setTimeout(()=>{if(e.timer=null,!this.settings.isLive()){this.scheduleNext(e);return}if(e.writes>this.settings.maxResends){this.events.failed(e.message,e.lastError??Error(`never seen on the chat feed`));return}this.attempt(e)},this.settings.resendAfterMs))}clearTimer(e){e.timer&&=(clearTimeout(e.timer),null)}},k=[1e3,2e3,4e3,8e3],A=3;function j(e){return(e.startsWith(`0x`)?e.slice(2):e).toLowerCase()}var M=class{constructor(e,r={}){this.emitter=new o,this.seen=new Set,this.status=null,this.generation=0,this.running=!1,this.starting=null,this.openTimer=null,this.wakeOpen=null;let{user:i,infra:a}=e;this.key=new t.PrivateKey(j(i.privateKey)),this.topic=a.chatTopic,this.profile={name:i.nickname,via:a.via,...i.binding?{idb:i.binding}:{},...i.walletLink?{wl:i.walletLink}:{}},this.openRetryMs=r.openRetryMs??k,this.senderSettings={...D,isLive:()=>this.status===_.LIVE,...r.sender};let s={slotReadMs:a.socReadTimeout??5e3,feedReadMs:a.feedReadTimeout??15e3,writeMs:a.gsocWriteTimeout??1e4},c={...a.noteSlotMs===void 0?{}:{slotMs:a.noteSlotMs},...a.noteHeartbeatMs===void 0?{}:{heartbeatMs:a.noteHeartbeatMs},...r.notes};this.source=r.source??p(new t.Bee(a.beeUrl),j(a.chatAddress),a.chatTopic,s,c.slotMs),this.write=r.write??g(new t.Bee(a.writeUrl??a.beeUrl),a.stamp?j(a.stamp):h,j(a.gsocResourceId),a.gsocTopic,s);let l=r.follower?.now??(()=>Date.now()),u={pollIntervalMs:a.pollingInterval??1e3,...r.follower,now:l},d=this.source;this.notes=w(d)?new E(d,c,l):null,this.follower=new b(this.source,this.topic,{entry:e=>this.show(e),skipped:(e,t,r)=>this.emitter.emit(n.MESSAGE_SKIPPED,{index:e,reason:t,detail:r}),status:e=>this.setStatus(e),error:e=>this.emitter.emit(n.ERROR,e)},u,this.notes),this.history=new S(this.source,this.topic,{skipped:e=>this.emitter.emit(n.MESSAGE_SKIPPED,{index:-1,reason:`history-row`,detail:`${e} rows of a history file`}),error:e=>this.emitter.emit(n.ERROR,e)},this.notes),this.sender=this.makeSender()}getEmitter(){return this.emitter}getStatus(){return this.status}getAddress(){return this.key.publicKey().address().toHex()}start(){if(this.running)return this.starting??Promise.resolve();this.running=!0,this.generation++,this.seen.clear(),this.sender=this.makeSender();let e=this.open(this.generation).finally(()=>{this.starting===e&&(this.starting=null)});return this.starting=e,e}async stop(){this.running=!1,this.generation++,this.openTimer&&=(clearTimeout(this.openTimer),null),this.wakeOpen?.(),this.follower.stop(),this.sender.stop()}async sendMessage(t,n,i){if(n===e.O.REACTION){if(!i)throw Error(`a reaction names the message it reacts to`);return this.sender.react(this.topic,i,t),null}return r(this.sender.send({topic:this.topic,type:n,target:i??``,text:t}))}retrySendMessage(e){return this.sender.retry(typeof e==`string`?e:e.id)}async fetchPreviousMessages(){this.emitter.emit(n.LOADING_PREVIOUS_MESSAGES,!0);try{let e=this.generation,t=await this.history.loadOlder();return e===this.generation?this.showRows(t):[]}finally{this.emitter.emit(n.LOADING_PREVIOUS_MESSAGES,!1)}}hasPreviousMessages(){return this.history.hasOlder()}orderMessages(e){return[...e].sort((e,t)=>e.index>=0&&t.index>=0?e.index-t.index:e.index>=0||t.index>=0?e.index>=0?-1:1:e.timestamp-t.timestamp)}async open(e){this.emitter.emit(n.LOADING_INIT,!0);let t=0;for(;e===this.generation;)try{let t=await this.history.open();if(e!==this.generation)return;this.showRows(t.rows),this.follower.start(t.startAt,t.notes),this.emitter.emit(n.LOADING_INIT,!1);return}catch(r){if(e!==this.generation)return;t++,this.emitter.emit(n.ERROR,r),this.setStatus(_.RECONNECTING),t===A&&this.emitter.emit(n.CRITICAL_ERROR,r),await this.waitToOpen(this.openRetryMs[Math.min(t,this.openRetryMs.length)-1]??8e3)}}waitToOpen(e){return new Promise(t=>{this.wakeOpen=()=>{this.wakeOpen=null,t()},this.openTimer=setTimeout(()=>{this.openTimer=null,this.wakeOpen?.()},e)})}makeSender(){return new O(this.key,this.profile,this.write,{pending:e=>this.emitter.emit(n.MESSAGE_REQUEST_INITIATED,r(e)),written:e=>this.emitter.emit(n.MESSAGE_REQUEST_UPLOADED,r(e)),failed:(e,t)=>{this.emitter.emit(n.ERROR,t),this.emitter.emit(n.MESSAGE_REQUEST_ERROR,r(e))},confirmed:()=>{}},this.senderSettings)}show(e){this.seen.has(e.seq)||(this.seen.add(e.seq),this.sender.confirm(e.msg),this.emitter.emit(n.MESSAGE_RECEIVED,i(e)))}showRows(e){let t=[];for(let r of e){if(this.seen.has(r.seq))continue;this.seen.add(r.seq),this.sender.confirm(r.msg);let e=i(r);t.push(e),this.emitter.emit(n.MESSAGE_RECEIVED,e)}return t}setStatus(e){e!==this.status&&(this.status=e,this.emitter.emit(n.STATUS,e))}};exports.CHAT_BINDING_TITLE=e.G,exports.ChatEmitter=o,exports.ChatMessageError=e.S,exports.DEFAULT_NOTE_HEARTBEAT_MS=e.t,exports.DEFAULT_NOTE_SLOT_MS=e.n,exports.EVENTS=n,exports.FeedStatus=_,exports.HeadLookupTimeoutError=l,exports.MAX_BINDING_CHARACTERS=e.K,exports.MAX_ENTRY_BYTES=e.p,exports.MAX_MESSAGE_BYTES=e.C,exports.MAX_NAME_CHARACTERS=e.w,exports.MAX_NOTE_BYTES=e.r,exports.MAX_TEXT_CHARACTERS=e.T,exports.MAX_TOPIC_CHARACTERS=e.E,exports.MAX_WALLET_LINK_CHARACTERS=e.B,exports.MESSAGE_VERSION=e.D,exports.MessageType=e.O,exports.MessageVia=e.k,exports.NOTE_VERSION=e.i,exports.OWN_FEED_TOPIC_PREFIX=e.b,exports.SwarmChat=M,exports.UnreadableGatewayError=y,exports.UnreadableSlotError=u,exports.WALLET_LINK_STATEMENT=e.V,exports.WALLET_LINK_TITLE=e.H,exports.chatBindingSchema=e.q,exports.chatMessageSchema=e.A,exports.checkChatBinding=e.J,exports.checkWalletLink=e.U,exports.countCharacters=e.j,exports.createChatMessage=e.M,exports.displayNameProblem=e.N,exports.encodeChatMessage=e.P,exports.encodeSlotNote=e.a,exports.feedEntrySchema=e.m,exports.hasValidSignature=e.F,exports.historyFileSchema=e.h,exports.historyLinkSchema=e.g,exports.historyRowSchema=e._,exports.newMessageId=e.I,exports.noteAddress=e.o,exports.noteIdentifier=e.s,exports.noteIdentifierText=e.c,exports.noteSlotEnd=e.l,exports.noteSlotOf=e.u,exports.ownFeedTopic=e.x,exports.parseChatMessage=e.L,exports.parseFeedEntry=e.v,exports.parseHistoryFile=e.y,exports.parseSlotNote=e.d,exports.signedBytes=e.R,exports.slotNoteSchema=e.f,exports.verifyChatMessage=e.z,exports.walletLinkSchema=e.W;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./message-BjeTRy2F.cjs");let t=require("@ethersphere/bee-js");var n={LOADING_INIT:`loadingInit`,LOADING_PREVIOUS_MESSAGES:`loadingPreviousMessages`,MESSAGE_RECEIVED:`messageReceived`,MESSAGE_REQUEST_INITIATED:`messageRequestInitiated`,MESSAGE_REQUEST_UPLOADED:`messageRequestUploaded`,MESSAGE_REQUEST_ERROR:`messageRequestError`,CRITICAL_ERROR:`criticalError`,STATUS:`status`,MESSAGE_SKIPPED:`messageSkipped`,ERROR:`error`};function r(e){return a(e,-1,e.ts)}function i(e){return a(e.msg,e.seq,e.at)}function a(e,t,n){return{id:e.id,type:e.type,message:e.text,username:e.name,address:e.addr,timestamp:n,...e.target?{targetMessageId:e.target}:{},index:t,signedMessage:e}}var o=class{constructor(){this.listeners=new Map,this.on=(e,t)=>{this.listeners.set(e,[...this.listeners.get(e)??[],t])},this.off=(e,t)=>{this.listeners.set(e,(this.listeners.get(e)??[]).filter(e=>e!==t))},this.cleanAll=()=>{this.listeners.clear()}}emit(e,t){for(let n of this.listeners.get(e)??[])try{n(t)}catch(t){console.error(`a listener for ${e} threw`,t)}}},s=2e4,c=class{constructor(e,t){this.spacingMs=e,this.now=t,this.missedAt=new Map}readableAt(e,t=this.now()){let n=this.missedAt.get(e);return n===void 0||this.expired(n,t)?-1/0:n+this.spacingMs}mayRead(e,t=this.now()){return t>=this.readableAt(e,t)}missed(e,t=this.now()){for(let[e,n]of this.missedAt)this.expired(n,t)&&this.missedAt.delete(e);this.missedAt.set(e,t)}found(e){this.missedAt.delete(e)}clear(){this.missedAt.clear()}expired(e,t){return e>t||t-e>=this.spacingMs}},l=class extends Error{constructor(e){super(`the feed head lookup did not answer in time`,e),this.name=`HeadLookupTimeoutError`}},u=class extends Error{constructor(e,t){super(`feed slot ${e} was served but could not be read`,t),this.index=e,this.name=`UnreadableSlotError`}};function d(e){return e instanceof t.BeeResponseError&&(e.status===404||e.status===500)}async function f(e,n){try{return await n()}catch(n){if(d(n))return null;throw n instanceof t.BeeResponseError?n:new u(e,{cause:n})}}function p(n,r,i,a,o=e.n){let s=t.Topic.fromString(i),c=e=>n.feed.makeReader(s,r,m(e));return{readNote:t=>f(t,async()=>(await n.soc.makeReader(r,m(a.slotReadMs)).download(e.s(i,o,t))).payload.toUint8Array()),readSlot:e=>f(e,async()=>(await c(a.slotReadMs).downloadPayload({index:e})).payload.toUint8Array()),async readHead(){let e=m(a.feedReadMs);try{let{payload:t,feedIndex:i}=await n.feed.makeReader(s,r,e).downloadPayload();return{index:Number(i.toBigInt()),payload:t.toUint8Array()}}catch(t){if(d(t))return null;throw e.signal?.aborted?new l({cause:t}):t}},async readFile(e){return(await n.data.download(e,void 0,m(a.feedReadMs))).toUint8Array()}}}function m(e){return{signal:AbortSignal.timeout(e)}}var h=`0123456789abcdef`.repeat(4);function g(e,n,r,i,a){let o=new t.PrivateKey(r),s=t.Identifier.fromString(i);return async t=>{await e.messaging.gsocSend(n,o,s,t,{deferred:!1},m(a.writeMs))}}var _={LIVE:`live`,RECONNECTING:`reconnecting`,STALLED:`stalled`},v={pollIntervalMs:1e3,missingReadSpacingMs:s,maxSlotsPerPoll:16,unservedPollsBeforeProbe:3,unreadablePollsBeforeFailure:3,probeIntervalCapMs:6e4,probeDistances:[1,2,4,8],missedLimit:32,missedReadsPerPoll:4,missedExpiryMs:3e5,backoffCapMs:8e3,stallAfterMs:8e3,random:Math.random,now:Date.now},y=class extends Error{constructor(e){super(`the gateway keeps answering feed slot ${e} with something that is not a chunk`),this.index=e,this.name=`UnreadableGatewayError`}},b=class{constructor(e,t,n,r={},i=null){this.source=e,this.topic=t,this.events=n,this.notes=i,this.next=0,this.ceiling=null,this.nextNoteSlot=0,this.lastNoteFoundAt=0,this.unservedPolls=0,this.nextProbeAt=0,this.unreadablePolls=0,this.gatewayFailures=0,this.missed=new Map,this.timer=null,this.generation=0,this.running=!1,this.status=null,this.settings={...v,...r},this.pacer=new c(this.settings.missingReadSpacingMs,this.settings.now)}get nextIndex(){return this.next}get missedIndices(){return[...this.missed.keys()]}get ledByNotes(){return this.ceiling!==null}start(e,t=null){this.stop(),this.next=e,this.ceiling=t?.newest??null,this.nextNoteSlot=t?.nextNoteSlot??(this.notes?this.notes.lastReadableSlot()+1:0),this.lastNoteFoundAt=this.settings.now(),this.resetRefusals(),this.unreadablePolls=0,this.gatewayFailures=0,this.missed.clear(),this.pacer.clear(),this.status=null,this.running=!0,this.schedule(0)}stop(){this.running=!1,this.generation++,this.timer&&=(clearTimeout(this.timer),null)}schedule(e){let t=this.generation;this.timer=setTimeout(()=>{this.timer=null,this.poll(t)},e)}async poll(e){let t=0,n=!1;try{this.notes!==null&&await this.readDueNotes(this.notes,e),t=await this.walk(e),await this.readMissed(e)}catch(t){n=!0,e===this.generation&&this.gatewayFailed(t)}e===this.generation&&this.running&&(n?this.schedule(this.backoffMs()):(this.gatewayAnswered(),this.schedule(t>=this.settings.maxSlotsPerPoll?0:this.untilNextRead())))}untilNextRead(){let e=this.settings.now(),t=t=>{let n=this.pacer.readableAt(t);return n>e?n:e+this.settings.pollIntervalMs},n=[...this.missed.keys()].map(t);return this.notes!==null&&n.push(this.notes.readableAt(this.nextNoteSlot)),this.ceiling===null&&n.push(t(this.next)),Math.max(0,Math.min(...n)-e)}async readDueNotes(e,t){let n=this.settings.now(),r=e.lastReadableSlot(n);if(r<this.nextNoteSlot)return;let i=Math.max(this.nextNoteSlot,r-e.lookBackSlots+1),a=await e.scan(r,i);t===this.generation&&(this.nextNoteSlot=r+1,a?(this.lastNoteFoundAt=n,this.ceiling=Math.max(this.ceiling??-1,a.note.newest,this.next-1)):n-this.lastNoteFoundAt>=e.silenceMs&&(this.lastNoteFoundAt=n,e.clock.distrust(),this.nextNoteSlot=Math.min(this.nextNoteSlot,e.lastReadableSlot(n)+1)))}async read(e){let t;try{t=await this.source.readSlot(e)}catch(e){if(e instanceof u)return`unreadable`;throw e}return t===null?this.pacer.missed(e):this.pacer.found(e),t}async readUnnamed(e){return this.pacer.mayRead(e)?this.read(e):`held`}async walk(e){for(let t=0;t<this.settings.maxSlotsPerPoll;t++){let n=this.next;if(this.ceiling!==null&&n>this.ceiling)return t;let r=this.ceiling===null?await this.readUnnamed(n):await this.read(n);if(e!==this.generation||r===`held`)return t;if(this.ceiling!==null&&(r===null||r===`unreadable`))this.remember(n),this.next=n+1;else{if(r===null||r===`unreadable`){if(t===0){if(this.unservedPolls++,this.unreadablePolls=r===`unreadable`?this.unreadablePolls+1:0,this.shouldProbe()&&await this.probePast(n,e)){this.unreadablePolls=0;continue}if(this.unreadablePolls>=this.settings.unreadablePollsBeforeFailure)throw new y(n)}return t}this.resetRefusals(),this.unreadablePolls=0,this.next=n+1,this.accept(n,r)}}return this.settings.maxSlotsPerPoll}shouldProbe(){if(this.unservedPolls!==this.nextProbeAt)return!1;let{probeIntervalCapMs:e,pollIntervalMs:t,missingReadSpacingMs:n}=this.settings,r=Math.max(1,Math.ceil(e/Math.max(t,n)));return this.nextProbeAt+=Math.min(this.nextProbeAt,r),!0}resetRefusals(){this.unservedPolls=0,this.nextProbeAt=this.settings.unservedPollsBeforeProbe}async probePast(e,t){let n=new Set([e]);for(let r of this.settings.probeDistances){let i=e+r,a=await this.readUnnamed(i);if(t!==this.generation)return!1;if(a===null||a===`unreadable`||a===`held`)n.add(i);else{this.resetRefusals(),this.remember(e);for(let r=e+1;r<i;r++){let e=n.has(r)?null:await this.readUnnamed(r);if(t!==this.generation)return!1;e===null||e===`unreadable`||e===`held`?this.remember(r):this.accept(r,e)}return this.next=i+1,this.accept(i,a),!0}}return!1}remember(e){this.missed.has(e)||(this.missed.size>=this.settings.missedLimit?this.events.skipped(e,`unreachable`,`stepped past with the retry list full`):this.missed.set(e,this.settings.now()))}async readMissed(e){let t=this.settings.now();for(let[e,n]of this.missed)t-n>=this.settings.missedExpiryMs&&(this.missed.delete(e),this.events.skipped(e,`unreachable`,`not served within the time a stepped-past slot is kept`));let n=[...this.missed.keys()].filter(e=>this.pacer.mayRead(e,t)).slice(0,this.settings.missedReadsPerPoll);for(let t of n){let n=await this.read(t);if(e!==this.generation)return;let r=this.missed.get(t);this.missed.delete(t),n!==null&&n!==`unreadable`?this.accept(t,n):r!==void 0&&this.missed.set(t,r)}}accept(t,n){let r=e.v(n,t,this.topic);r.ok?(this.notes?.clock.observe(r.value.at,this.settings.now()),this.events.entry(r.value)):this.events.skipped(t,r.reason,r.detail)}gatewayFailed(e){this.gatewayFailures++,this.setStatus(_.RECONNECTING),this.events.error(e)}gatewayAnswered(){this.gatewayFailures=0;let e=this.settings.now(),t=[...this.missed.values()].some(t=>e-t>=this.settings.stallAfterMs);this.setStatus(t?_.STALLED:_.LIVE)}backoffMs(){let{pollIntervalMs:e,backoffCapMs:t,random:n}=this.settings,r=Math.min(t,e*2**this.gatewayFailures);return r/2+n()*r/2}setStatus(e){e!==this.status&&(this.status=e,this.events.status(e))}},x=16,S=class{constructor(e,t,n,r=null){this.source=e,this.topic=t,this.events=n,this.notes=r,this.older=null,this.loading=null}async open(){this.older=null;let e=await this.newestNote();if(e!==null)return this.openAt(e.newest,e);let t=await this.readHead();return t===null?{startAt:0,rows:[],notes:null}:this.openAt(t.index,null,t.payload)}async newestNote(){if(this.notes===null)return null;let e=this.notes.lastReadableSlot(),t=await this.notes.scan(e,e-this.notes.lookBackSlots+1);return t===null?null:{newest:t.note.newest,nextNoteSlot:e+1}}async openAt(e,t,n){let r=e<0?null:await this.newestLink(e,n);if(r===null)return{startAt:0,rows:[],notes:t};let i=await this.readFile(r);return i===`refused`?{startAt:0,rows:[],notes:t}:{startAt:r.toSeq+1,rows:i??[],notes:t}}async readHead(){try{return await this.source.readHead()}catch(e){if(e instanceof l)return this.events.error(e),null;throw e}}hasOlder(){return this.older!==null}loadOlder(){return this.loading??=this.loadOlderOnce().finally(()=>{this.loading=null}),this.loading}async loadOlderOnce(){let t=this.older;if(t===null)return[];let n=await this.source.readFile(t.ref),r=e.y(n,this.topic,t);if(!r.ok)throw this.older=null,Error(`history file ${t.ref} refused (${r.reason}): ${r.detail}`);return this.report(r.value.skipped),this.older=r.value.prev,r.value.rows}async newestLink(t,n){let r=n===void 0?t:t-1;if(n!==void 0){let r=e.v(n,t,this.topic);if(r.ok)return r.value.history}for(let n=r;n>=Math.max(0,t-x);n--){let t=await this.source.readSlot(n).catch(e=>{if(e instanceof u)return null;throw e});if(t===null)continue;let r=e.v(t,n,this.topic);if(r.ok)return r.value.history}return null}async readFile(t){try{let n=e.y(await this.source.readFile(t.ref),this.topic,t);return n.ok?(this.report(n.value.skipped),this.older=n.value.prev,n.value.rows):(this.events.error(Error(`history file ${t.ref} refused (${n.reason}): ${n.detail}`)),`refused`)}catch(e){return this.events.error(e),this.older=t,null}}report(e){e>0&&this.events.skipped(e)}},C={slotMs:e.n,heartbeatMs:e.t,marginMs:1e3,scanBatch:4,clockLimitMs:3e5,missingReadSpacingMs:s};function w(e){return typeof e.readNote==`function`}var T=class{constructor(e){this.limitMs=e,this.aheadAtMost=1/0,this.trusted=!0}observe(e,t){this.aheadAtMost=Math.min(this.aheadAtMost,t-e)}distrust(){this.trusted=!1}get isTrusted(){return this.trusted}get ms(){let e=Number.isFinite(this.aheadAtMost),t=this.trusted||!e?Math.min(0,this.aheadAtMost):this.aheadAtMost;return Math.max(-this.limitMs,Math.min(this.limitMs,t))}},E=class{constructor(e,t,n){this.source=e,this.now=n,this.counts={found:0,empty:0},this.settings={...C,...t},this.clock=new T(this.settings.clockLimitMs),this.pacer=new c(this.settings.missingReadSpacingMs,n)}lastReadableSlot(t=this.now()){return e.u(t-this.settings.marginMs-this.clock.ms,this.settings.slotMs)-1}readableAt(t){return e.l(t,this.settings.slotMs)+this.settings.marginMs+this.clock.ms}get lookBackSlots(){return Math.ceil(this.settings.heartbeatMs/this.settings.slotMs)+2}get silenceMs(){return this.settings.heartbeatMs+2*this.settings.slotMs+this.settings.marginMs}async read(t){if(!this.pacer.mayRead(t))return null;let n;try{n=await this.source.readNote(t),n===null&&this.pacer.missed(t)}catch(e){if(!(e instanceof u))throw e;n=null}let r=n===null?null:e.d(n);return r===null?(this.counts.empty++,null):(this.counts.found++,this.clock.observe(r.writtenAt,this.now()),r)}async scan(e,t){for(let n=e;n>=t;n-=this.settings.scanBatch){let e=[];for(let r=n;r>n-this.settings.scanBatch&&r>=t;r--)e.push(r);let r=await Promise.all(e.map(e=>this.read(e))),i=r.findIndex(e=>e!==null);if(i>=0)return{slot:e[i],note:r[i]}}return null}},D={resendAfterMs:1e4,maxResends:5,reactionWindowMs:1e3,isLive:()=>!0},O=class{constructor(e,t,n,r,i=D){this.key=e,this.profile=t,this.write=n,this.events=r,this.settings=i,this.outgoing=new Map,this.reactions=new Map,this.stopped=!1}get address(){return this.key.publicKey().address().toHex()}send(t){let{message:n,bytes:r}=e.M(this.key,{...t,...this.profile}),i={message:n,bytes:r,writes:0,written:!1,inFlight:!1,timer:null,lastError:null};return this.outgoing.set(n.id,i),this.events.pending(n),this.attempt(i),n}react(t,n,r){let i=JSON.stringify([t,n,r]),a=this.reactions.get(i);if(a){a.taps++;return}let o=setTimeout(()=>{let a=this.reactions.get(i);this.reactions.delete(i),a&&a.taps%2==1&&!this.stopped&&this.send({topic:t,type:e.O.REACTION,target:n,text:r})},this.settings.reactionWindowMs);this.reactions.set(i,{taps:1,timer:o})}confirm(e){if(e.addr!==this.address)return;let t=this.outgoing.get(e.id);t&&(this.clearTimer(t),this.outgoing.delete(e.id),this.events.confirmed(t.message))}retry(e){let t=this.outgoing.get(e);return!t||this.stopped?!1:(this.clearTimer(t),t.writes=0,t.inFlight||this.attempt(t),!0)}isPending(e){return this.outgoing.has(e)}stop(){this.stopped=!0;for(let e of this.outgoing.values())this.clearTimer(e);for(let{timer:e}of this.reactions.values())clearTimeout(e);this.reactions.clear()}attempt(e){!this.stopped&&this.outgoing.has(e.message.id)&&(e.writes++,e.inFlight=!0,this.write(e.bytes).then(()=>{e.inFlight=!1,!e.written&&this.outgoing.has(e.message.id)&&(e.written=!0,this.events.written(e.message)),this.scheduleNext(e)},t=>{e.inFlight=!1,e.lastError=t,this.scheduleNext(e)}))}scheduleNext(e){!this.stopped&&this.outgoing.has(e.message.id)&&(e.timer=setTimeout(()=>{e.timer=null,this.settings.isLive()?e.writes>this.settings.maxResends?this.events.failed(e.message,e.lastError??Error(`never seen on the chat feed`)):this.attempt(e):this.scheduleNext(e)},this.settings.resendAfterMs))}clearTimer(e){e.timer&&=(clearTimeout(e.timer),null)}},k=[1e3,2e3,4e3,8e3],A=3;function j(e){return(e.startsWith(`0x`)?e.slice(2):e).toLowerCase()}var M=class{constructor(e,r={}){this.emitter=new o,this.seen=new Set,this.status=null,this.generation=0,this.running=!1,this.starting=null,this.openTimer=null,this.wakeOpen=null;let{user:i,infra:a}=e;this.key=new t.PrivateKey(j(i.privateKey)),this.topic=a.chatTopic,this.profile={name:i.nickname,via:a.via,...i.binding?{idb:i.binding}:{},...i.walletLink?{wl:i.walletLink}:{}},this.openRetryMs=r.openRetryMs??k,this.senderSettings={...D,isLive:()=>this.status===_.LIVE,...r.sender};let s={slotReadMs:a.socReadTimeout??5e3,feedReadMs:a.feedReadTimeout??15e3,writeMs:a.gsocWriteTimeout??1e4},c={...a.noteSlotMs===void 0?{}:{slotMs:a.noteSlotMs},...a.noteHeartbeatMs===void 0?{}:{heartbeatMs:a.noteHeartbeatMs},...r.notes};this.source=r.source??p(new t.Bee(a.beeUrl),j(a.chatAddress),a.chatTopic,s,c.slotMs),this.write=r.write??g(new t.Bee(a.writeUrl??a.beeUrl),a.stamp?j(a.stamp):h,j(a.gsocResourceId),a.gsocTopic,s);let l=r.follower?.now??(()=>Date.now()),u={pollIntervalMs:a.pollingInterval??1e3,...r.follower,now:l},d=this.source;this.notes=w(d)?new E(d,c,l):null,this.follower=new b(this.source,this.topic,{entry:e=>this.show(e),skipped:(e,t,r)=>this.emitter.emit(n.MESSAGE_SKIPPED,{index:e,reason:t,detail:r}),status:e=>this.setStatus(e),error:e=>this.emitter.emit(n.ERROR,e)},u,this.notes),this.history=new S(this.source,this.topic,{skipped:e=>this.emitter.emit(n.MESSAGE_SKIPPED,{index:-1,reason:`history-row`,detail:`${e} rows of a history file`}),error:e=>this.emitter.emit(n.ERROR,e)},this.notes),this.sender=this.makeSender()}getEmitter(){return this.emitter}getStatus(){return this.status}getAddress(){return this.key.publicKey().address().toHex()}start(){if(this.running)return this.starting??Promise.resolve();this.running=!0,this.generation++,this.seen.clear(),this.sender=this.makeSender();let e=this.open(this.generation).finally(()=>{this.starting===e&&(this.starting=null)});return this.starting=e,e}async stop(){this.running=!1,this.generation++,this.openTimer&&=(clearTimeout(this.openTimer),null),this.wakeOpen?.(),this.follower.stop(),this.sender.stop()}async sendMessage(t,n,i){if(n===e.O.REACTION){if(!i)throw Error(`a reaction names the message it reacts to`);return this.sender.react(this.topic,i,t),null}return r(this.sender.send({topic:this.topic,type:n,target:i??``,text:t}))}retrySendMessage(e){return this.sender.retry(typeof e==`string`?e:e.id)}async fetchPreviousMessages(){this.emitter.emit(n.LOADING_PREVIOUS_MESSAGES,!0);try{let e=this.generation,t=await this.history.loadOlder();return e===this.generation?this.showRows(t):[]}finally{this.emitter.emit(n.LOADING_PREVIOUS_MESSAGES,!1)}}hasPreviousMessages(){return this.history.hasOlder()}orderMessages(e){return[...e].sort((e,t)=>e.index>=0&&t.index>=0?e.index-t.index:e.index>=0||t.index>=0?e.index>=0?-1:1:e.timestamp-t.timestamp)}async open(e){this.emitter.emit(n.LOADING_INIT,!0);let t=0;for(;e===this.generation;)try{let t=await this.history.open();if(e!==this.generation)return;this.showRows(t.rows),this.follower.start(t.startAt,t.notes),this.emitter.emit(n.LOADING_INIT,!1);return}catch(r){if(e!==this.generation)return;t++,this.emitter.emit(n.ERROR,r),this.setStatus(_.RECONNECTING),t===A&&this.emitter.emit(n.CRITICAL_ERROR,r),await this.waitToOpen(this.openRetryMs[Math.min(t,this.openRetryMs.length)-1]??8e3)}}waitToOpen(e){return new Promise(t=>{this.wakeOpen=()=>{this.wakeOpen=null,t()},this.openTimer=setTimeout(()=>{this.openTimer=null,this.wakeOpen?.()},e)})}makeSender(){return new O(this.key,this.profile,this.write,{pending:e=>this.emitter.emit(n.MESSAGE_REQUEST_INITIATED,r(e)),written:e=>this.emitter.emit(n.MESSAGE_REQUEST_UPLOADED,r(e)),failed:(e,t)=>{this.emitter.emit(n.ERROR,t),this.emitter.emit(n.MESSAGE_REQUEST_ERROR,r(e))},confirmed:()=>{}},this.senderSettings)}show(e){this.seen.has(e.seq)||(this.seen.add(e.seq),this.sender.confirm(e.msg),this.emitter.emit(n.MESSAGE_RECEIVED,i(e)))}showRows(e){let t=[];for(let r of e){if(this.seen.has(r.seq))continue;this.seen.add(r.seq),this.sender.confirm(r.msg);let e=i(r);t.push(e),this.emitter.emit(n.MESSAGE_RECEIVED,e)}return t}setStatus(e){e!==this.status&&(this.status=e,this.emitter.emit(n.STATUS,e))}};exports.CHAT_BINDING_TITLE=e.G,exports.ChatEmitter=o,exports.ChatMessageError=e.S,exports.DEFAULT_NOTE_HEARTBEAT_MS=e.t,exports.DEFAULT_NOTE_SLOT_MS=e.n,exports.EVENTS=n,exports.FeedStatus=_,exports.HeadLookupTimeoutError=l,exports.MAX_BINDING_CHARACTERS=e.K,exports.MAX_ENTRY_BYTES=e.p,exports.MAX_MESSAGE_BYTES=e.C,exports.MAX_NAME_CHARACTERS=e.w,exports.MAX_NOTE_BYTES=e.r,exports.MAX_TEXT_CHARACTERS=e.T,exports.MAX_TOPIC_CHARACTERS=e.E,exports.MAX_WALLET_LINK_CHARACTERS=e.B,exports.MESSAGE_VERSION=e.D,exports.MessageType=e.O,exports.MessageVia=e.k,exports.NOTE_VERSION=e.i,exports.OWN_FEED_TOPIC_PREFIX=e.b,exports.SwarmChat=M,exports.UnreadableGatewayError=y,exports.UnreadableSlotError=u,exports.WALLET_LINK_STATEMENT=e.V,exports.WALLET_LINK_TITLE=e.H,exports.chatBindingSchema=e.q,exports.chatMessageSchema=e.A,exports.checkChatBinding=e.J,exports.checkWalletLink=e.U,exports.countCharacters=e.j,exports.createChatMessage=e.M,exports.displayNameProblem=e.N,exports.encodeChatMessage=e.P,exports.encodeSlotNote=e.a,exports.feedEntrySchema=e.m,exports.hasValidSignature=e.F,exports.historyFileSchema=e.h,exports.historyLinkSchema=e.g,exports.historyRowSchema=e._,exports.newMessageId=e.I,exports.noteAddress=e.o,exports.noteIdentifier=e.s,exports.noteIdentifierText=e.c,exports.noteSlotEnd=e.l,exports.noteSlotOf=e.u,exports.ownFeedTopic=e.x,exports.parseChatMessage=e.L,exports.parseFeedEntry=e.v,exports.parseHistoryFile=e.y,exports.parseSlotNote=e.d,exports.signedBytes=e.R,exports.slotNoteSchema=e.f,exports.verifyChatMessage=e.z,exports.walletLinkSchema=e.W;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as e, B as t, C as n, D as r, E as i, F as a, G as o, H as s, I as c, J as ee, K as l, L as te, M as u, N as ne, O as d, P as f, R as p, S as m, T as h, U as g, V as _, W as v, _ as y, a as b, b as re, c as ie, d as x, f as ae, g as oe, h as se, i as ce, j as le, k as ue, l as S, m as de, n as C, o as fe, p as pe, q as me, r as he, s as w, t as T, u as E, v as D, w as O, x as k, y as A, z as j } from "./message-
|
|
1
|
+
import { A as e, B as t, C as n, D as r, E as i, F as a, G as o, H as s, I as c, J as ee, K as l, L as te, M as u, N as ne, O as d, P as f, R as p, S as m, T as h, U as g, V as _, W as v, _ as y, a as b, b as re, c as ie, d as x, f as ae, g as oe, h as se, i as ce, j as le, k as ue, l as S, m as de, n as C, o as fe, p as pe, q as me, r as he, s as w, t as T, u as E, v as D, w as O, x as k, y as A, z as j } from "./message-BUFAxjtN.js";
|
|
2
2
|
import { Bee as M, BeeResponseError as N, Identifier as P, PrivateKey as F, Topic as I } from "@ethersphere/bee-js";
|
|
3
|
-
|
|
3
|
+
// src/events.ts
|
|
4
4
|
var L = {
|
|
5
5
|
LOADING_INIT: "loadingInit",
|
|
6
6
|
LOADING_PREVIOUS_MESSAGES: "loadingPreviousMessages",
|
|
@@ -126,8 +126,7 @@ function ve(e, t, n, r, i) {
|
|
|
126
126
|
await e.messaging.gsocSend(t, a, o, n, { deferred: !1 }, J(i.writeMs));
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
//#region src/follower.ts
|
|
129
|
+
// src/follower.ts
|
|
131
130
|
var Y = {
|
|
132
131
|
LIVE: "live",
|
|
133
132
|
RECONNECTING: "reconnecting",
|
|
@@ -191,13 +190,7 @@ var Y = {
|
|
|
191
190
|
} catch (t) {
|
|
192
191
|
n = !0, e === this.generation && this.gatewayFailed(t);
|
|
193
192
|
}
|
|
194
|
-
|
|
195
|
-
if (n) {
|
|
196
|
-
this.schedule(this.backoffMs());
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
this.gatewayAnswered(), this.schedule(t >= this.settings.maxSlotsPerPoll ? 0 : this.untilNextRead());
|
|
200
|
-
}
|
|
193
|
+
e === this.generation && this.running && (n ? this.schedule(this.backoffMs()) : (this.gatewayAnswered(), this.schedule(t >= this.settings.maxSlotsPerPoll ? 0 : this.untilNextRead())));
|
|
201
194
|
}
|
|
202
195
|
untilNextRead() {
|
|
203
196
|
let e = this.settings.now(), t = (t) => {
|
|
@@ -210,13 +203,7 @@ var Y = {
|
|
|
210
203
|
let n = this.settings.now(), r = e.lastReadableSlot(n);
|
|
211
204
|
if (r < this.nextNoteSlot) return;
|
|
212
205
|
let i = Math.max(this.nextNoteSlot, r - e.lookBackSlots + 1), a = await e.scan(r, i);
|
|
213
|
-
|
|
214
|
-
if (this.nextNoteSlot = r + 1, a) {
|
|
215
|
-
this.lastNoteFoundAt = n, this.ceiling = Math.max(this.ceiling ?? -1, a.note.newest, this.next - 1);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
n - this.lastNoteFoundAt >= e.silenceMs && (this.lastNoteFoundAt = n, e.clock.distrust(), this.nextNoteSlot = Math.min(this.nextNoteSlot, e.lastReadableSlot(n) + 1));
|
|
219
|
-
}
|
|
206
|
+
t === this.generation && (this.nextNoteSlot = r + 1, a ? (this.lastNoteFoundAt = n, this.ceiling = Math.max(this.ceiling ?? -1, a.note.newest, this.next - 1)) : n - this.lastNoteFoundAt >= e.silenceMs && (this.lastNoteFoundAt = n, e.clock.distrust(), this.nextNoteSlot = Math.min(this.nextNoteSlot, e.lastReadableSlot(n) + 1)));
|
|
220
207
|
}
|
|
221
208
|
async read(e) {
|
|
222
209
|
let t;
|
|
@@ -237,21 +224,20 @@ var Y = {
|
|
|
237
224
|
if (this.ceiling !== null && n > this.ceiling) return t;
|
|
238
225
|
let r = this.ceiling === null ? await this.readUnnamed(n) : await this.read(n);
|
|
239
226
|
if (e !== this.generation || r === "held") return t;
|
|
240
|
-
if (this.ceiling !== null && (r === null || r === "unreadable"))
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
227
|
+
if (this.ceiling !== null && (r === null || r === "unreadable")) this.remember(n), this.next = n + 1;
|
|
228
|
+
else {
|
|
229
|
+
if (r === null || r === "unreadable") {
|
|
230
|
+
if (t === 0) {
|
|
231
|
+
if (this.unservedPolls++, this.unreadablePolls = r === "unreadable" ? this.unreadablePolls + 1 : 0, this.shouldProbe() && await this.probePast(n, e)) {
|
|
232
|
+
this.unreadablePolls = 0;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (this.unreadablePolls >= this.settings.unreadablePollsBeforeFailure) throw new X(n);
|
|
249
236
|
}
|
|
250
|
-
|
|
237
|
+
return t;
|
|
251
238
|
}
|
|
252
|
-
|
|
239
|
+
this.resetRefusals(), this.unreadablePolls = 0, this.next = n + 1, this.accept(n, r);
|
|
253
240
|
}
|
|
254
|
-
this.resetRefusals(), this.unreadablePolls = 0, this.next = n + 1, this.accept(n, r);
|
|
255
241
|
}
|
|
256
242
|
return this.settings.maxSlotsPerPoll;
|
|
257
243
|
}
|
|
@@ -268,28 +254,21 @@ var Y = {
|
|
|
268
254
|
for (let r of this.settings.probeDistances) {
|
|
269
255
|
let i = e + r, a = await this.readUnnamed(i);
|
|
270
256
|
if (t !== this.generation) return !1;
|
|
271
|
-
if (a === null || a === "unreadable" || a === "held")
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
257
|
+
if (a === null || a === "unreadable" || a === "held") n.add(i);
|
|
258
|
+
else {
|
|
259
|
+
this.resetRefusals(), this.remember(e);
|
|
260
|
+
for (let r = e + 1; r < i; r++) {
|
|
261
|
+
let e = n.has(r) ? null : await this.readUnnamed(r);
|
|
262
|
+
if (t !== this.generation) return !1;
|
|
263
|
+
e === null || e === "unreadable" || e === "held" ? this.remember(r) : this.accept(r, e);
|
|
264
|
+
}
|
|
265
|
+
return this.next = i + 1, this.accept(i, a), !0;
|
|
280
266
|
}
|
|
281
|
-
return this.next = i + 1, this.accept(i, a), !0;
|
|
282
267
|
}
|
|
283
268
|
return !1;
|
|
284
269
|
}
|
|
285
270
|
remember(e) {
|
|
286
|
-
|
|
287
|
-
if (this.missed.size >= this.settings.missedLimit) {
|
|
288
|
-
this.events.skipped(e, "unreachable", "stepped past with the retry list full");
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
this.missed.set(e, this.settings.now());
|
|
292
|
-
}
|
|
271
|
+
this.missed.has(e) || (this.missed.size >= this.settings.missedLimit ? this.events.skipped(e, "unreachable", "stepped past with the retry list full") : this.missed.set(e, this.settings.now()));
|
|
293
272
|
}
|
|
294
273
|
async readMissed(e) {
|
|
295
274
|
let t = this.settings.now();
|
|
@@ -565,15 +544,7 @@ var Te = class {
|
|
|
565
544
|
}
|
|
566
545
|
scheduleNext(e) {
|
|
567
546
|
!this.stopped && this.outgoing.has(e.message.id) && (e.timer = setTimeout(() => {
|
|
568
|
-
|
|
569
|
-
this.scheduleNext(e);
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
if (e.writes > this.settings.maxResends) {
|
|
573
|
-
this.events.failed(e.message, e.lastError ?? /* @__PURE__ */ Error("never seen on the chat feed"));
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
this.attempt(e);
|
|
547
|
+
e.timer = null, this.settings.isLive() ? e.writes > this.settings.maxResends ? this.events.failed(e.message, e.lastError ?? /* @__PURE__ */ Error("never seen on the chat feed")) : this.attempt(e) : this.scheduleNext(e);
|
|
577
548
|
}, this.settings.resendAfterMs));
|
|
578
549
|
}
|
|
579
550
|
clearTimer(e) {
|
|
@@ -734,5 +705,4 @@ var ke = class {
|
|
|
734
705
|
e !== this.status && (this.status = e, this.emitter.emit(L.STATUS, e));
|
|
735
706
|
}
|
|
736
707
|
};
|
|
737
|
-
//#endregion
|
|
738
708
|
export { o as CHAT_BINDING_TITLE, V as ChatEmitter, m as ChatMessageError, T as DEFAULT_NOTE_HEARTBEAT_MS, C as DEFAULT_NOTE_SLOT_MS, L as EVENTS, Y as FeedStatus, W as HeadLookupTimeoutError, l as MAX_BINDING_CHARACTERS, pe as MAX_ENTRY_BYTES, n as MAX_MESSAGE_BYTES, O as MAX_NAME_CHARACTERS, he as MAX_NOTE_BYTES, h as MAX_TEXT_CHARACTERS, i as MAX_TOPIC_CHARACTERS, t as MAX_WALLET_LINK_CHARACTERS, r as MESSAGE_VERSION, d as MessageType, ue as MessageVia, ce as NOTE_VERSION, re as OWN_FEED_TOPIC_PREFIX, ke as SwarmChat, X as UnreadableGatewayError, G as UnreadableSlotError, _ as WALLET_LINK_STATEMENT, s as WALLET_LINK_TITLE, me as chatBindingSchema, e as chatMessageSchema, ee as checkChatBinding, g as checkWalletLink, le as countCharacters, u as createChatMessage, ne as displayNameProblem, f as encodeChatMessage, b as encodeSlotNote, de as feedEntrySchema, a as hasValidSignature, se as historyFileSchema, oe as historyLinkSchema, y as historyRowSchema, c as newMessageId, fe as noteAddress, w as noteIdentifier, ie as noteIdentifierText, S as noteSlotEnd, E as noteSlotOf, k as ownFeedTopic, te as parseChatMessage, D as parseFeedEntry, A as parseHistoryFile, x as parseSlotNote, p as signedBytes, ae as slotNoteSchema, j as verifyChatMessage, v as walletLinkSchema };
|
|
@@ -2,15 +2,15 @@ import { z } from 'zod';
|
|
|
2
2
|
/**
|
|
3
3
|
* The Swarm ID chat binding: the account's statement, signed with its own key, that a chat address on one site is its
|
|
4
4
|
* own. The Swarm ID fork (solarpunk-id, `lib/src/utils/chat-binding.ts`) makes it, and this module reads it exactly as
|
|
5
|
-
*
|
|
5
|
+
* Swarm ID's `verifyChatBinding` does, without importing Swarm ID: the same four lines, the same clean site origin,
|
|
6
6
|
* the same EIP-191 personal_sign recovery with v 27 or 28 and a low s.
|
|
7
7
|
*/
|
|
8
8
|
/** The first line, which also versions the binding format. */
|
|
9
9
|
export declare const CHAT_BINDING_TITLE = "Swarm ID chat binding v1";
|
|
10
|
-
/**
|
|
10
|
+
/** Swarm ID's own bound on a binding's text. */
|
|
11
11
|
export declare const MAX_BINDING_CHARACTERS = 512;
|
|
12
12
|
/**
|
|
13
|
-
* A binding as a message carries it. `sig` is spelled as
|
|
13
|
+
* A binding as a message carries it. `sig` is spelled as Swarm ID writes it, `0x` and 130 lowercase hex characters
|
|
14
14
|
* of r, s and v, so one binding has one spelling inside the signed bytes.
|
|
15
15
|
*/
|
|
16
16
|
export declare const chatBindingSchema: z.ZodObject<{
|
|
@@ -29,13 +29,13 @@ export interface ChatIdentity {
|
|
|
29
29
|
/**
|
|
30
30
|
* The wallet the message's Swarm ID wallet link names, `0x` and 40 lowercase hex characters, present only when the
|
|
31
31
|
* message carries a link both the wallet and this account signed. A reader looks its ENS name up itself, and the
|
|
32
|
-
*
|
|
32
|
+
* Swarm ID's `resolveVerifiedEnsName` does that with both the reverse and the forward record.
|
|
33
33
|
*/
|
|
34
34
|
wallet?: string;
|
|
35
35
|
}
|
|
36
36
|
export interface BindingOptions {
|
|
37
|
-
/** The
|
|
38
|
-
|
|
37
|
+
/** The origins the reader runs on, each bare. When given, a binding for a site not among them is refused. */
|
|
38
|
+
origins?: readonly string[];
|
|
39
39
|
/** Accept a binding for `http://localhost`, `http://127.0.0.1` or `http://[::1]`, as only a development build signs. */
|
|
40
40
|
allowLocalHttp?: boolean;
|
|
41
41
|
}
|
|
@@ -48,7 +48,7 @@ export type BindingCheck = {
|
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
50
|
* Reads a binding for the chat address `addr` (40 lowercase hex characters, no `0x`). Refuses every text but the four
|
|
51
|
-
* lines
|
|
51
|
+
* lines Swarm ID writes, a binding for another chat address, one for a site not in `origins` when that is given,
|
|
52
52
|
* and a signature nothing recovers an account from. Never throws.
|
|
53
53
|
*/
|
|
54
54
|
export declare function checkChatBinding(binding: ChatBinding, addr: string, options?: BindingOptions): BindingCheck;
|
|
@@ -88,11 +88,12 @@ export type ChatMessageCheck = {
|
|
|
88
88
|
detail: string;
|
|
89
89
|
};
|
|
90
90
|
/**
|
|
91
|
-
* `
|
|
92
|
-
* any other site is refused, so a binding signed for one site never passes in
|
|
91
|
+
* `origins` are the sites the chat runs on, each a bare origin such as `https://example.com`, and are required: a
|
|
92
|
+
* binding for any other site is refused, so a binding signed for one site never passes in a chat that site is not
|
|
93
|
+
* part of. A chat served from several pages, such as one domain and a copy on Swarm under an ENS name, lists each.
|
|
93
94
|
*/
|
|
94
95
|
export interface VerifyOptions {
|
|
95
|
-
|
|
96
|
+
origins: readonly string[];
|
|
96
97
|
/** Accept a binding for `http://localhost`, `http://127.0.0.1` or `http://[::1]`, as only a development build signs. */
|
|
97
98
|
allowLocalHttp?: boolean;
|
|
98
99
|
}
|
|
@@ -139,10 +140,10 @@ export declare function createChatMessage(privateKey: PrivateKey | Uint8Array |
|
|
|
139
140
|
export declare function hasValidSignature(message: ChatMessage): boolean;
|
|
140
141
|
/**
|
|
141
142
|
* Verifies a message that arrived as an object: its shape, its signature, and, when it carries a binding, that the
|
|
142
|
-
* binding is
|
|
143
|
-
* carries a wallet link, the link must be
|
|
143
|
+
* binding is Swarm ID's four lines for this `addr` and for one of `options.origins`, and recovers an account. When it also
|
|
144
|
+
* carries a wallet link, the link must be Swarm ID's five lines for that account, signed by its wallet and by the
|
|
144
145
|
* account, and the identity then names the wallet. A message whose binding or link fails is refused as `binding`,
|
|
145
|
-
* never passed as a guest, and so is a bound message checked with no
|
|
146
|
+
* never passed as a guest, and so is a bound message checked with no origins.
|
|
146
147
|
* Never throws, and touches no DOM and no Node API, so a page runs it in a Web Worker as the server runs it.
|
|
147
148
|
*/
|
|
148
149
|
export declare function verifyChatMessage(value: unknown, options: VerifyOptions): ChatMessageCheck;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The address that made `sig` over `text`, `0x` and 40 lowercase hex characters, or null for a signature
|
|
2
|
+
* The address that made `sig` over `text`, `0x` and 40 lowercase hex characters, or null for a signature Swarm ID
|
|
3
3
|
* would refuse or nothing recovers from. `sig` is `0x` and 130 hex characters of r, s and v, already shape-checked.
|
|
4
4
|
*/
|
|
5
5
|
export declare function recoverPersonalSigner(text: string, sig: string): string | null;
|
|
@@ -4,18 +4,18 @@ import { z } from 'zod';
|
|
|
4
4
|
* that the two belong to the same person, which lets a reader show the wallet's ENS name. The Swarm ID fork makes it
|
|
5
5
|
* while the person has "Show my ENS name on sites" on, and its canonical description is `docs/Wallet-Link.md` in the
|
|
6
6
|
* fork (solarpunk-id), with `verifyWalletLink` in its `lib/src/utils/wallet-link.ts`. This module reads it exactly as
|
|
7
|
-
* that function does, without importing
|
|
7
|
+
* that function does, without importing Swarm ID: the same five lines, the second of them read exactly, and both
|
|
8
8
|
* EIP-191 personal_sign signatures with v 27 or 28 and a low s. It looks nothing up: a reader takes the checked wallet to its own ENS lookup.
|
|
9
9
|
*/
|
|
10
10
|
/** The first line, which also versions the wallet link format. */
|
|
11
11
|
export declare const WALLET_LINK_TITLE = "Swarm ID wallet link v1";
|
|
12
12
|
/** The second line, what the wallet's owner agrees to, which a wallet shows them before they sign. */
|
|
13
13
|
export declare const WALLET_LINK_STATEMENT = "I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.";
|
|
14
|
-
/**
|
|
14
|
+
/** Swarm ID's own bound on a wallet link's text, which is 258 characters in the format it writes. */
|
|
15
15
|
export declare const MAX_WALLET_LINK_CHARACTERS = 320;
|
|
16
16
|
/**
|
|
17
|
-
* A wallet link as a message carries it:
|
|
18
|
-
* and `asig`. Each signature is spelled as
|
|
17
|
+
* A wallet link as a message carries it: Swarm ID's `{ message, walletSignature, accountSignature }` as `msg`, `wsig`
|
|
18
|
+
* and `asig`. Each signature is spelled as Swarm ID writes it, `0x` and 130 lowercase hex characters of r, s and v, so
|
|
19
19
|
* one link has one spelling inside the signed bytes.
|
|
20
20
|
*/
|
|
21
21
|
export declare const walletLinkSchema: z.ZodObject<{
|
|
@@ -38,7 +38,7 @@ export type WalletLinkCheck = {
|
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
40
|
* Reads a wallet link for `account` (`0x` and 40 lowercase hex characters), the account a verified chat binding
|
|
41
|
-
* named. Refuses every text but the five lines
|
|
41
|
+
* named. Refuses every text but the five lines Swarm ID writes, its statement included, a wallet signature that does not recover the wallet
|
|
42
42
|
* the link names, an account signature that does not recover the account it names, and a link naming any other
|
|
43
43
|
* account. Never throws.
|
|
44
44
|
*/
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Bytes as e, EthAddress as t, Identifier as n, PrivateKey as r, Reference as i, Signature as a } from "@ethersphere/bee-js";
|
|
2
2
|
import { z as o } from "zod";
|
|
3
3
|
import { publicKeyToAddress as s, recoverPublicKey as c } from "@ethersphere/core-sdk/crypto";
|
|
4
|
-
|
|
4
|
+
// src/message/canonicalSignature.ts
|
|
5
5
|
var l = 115792089237316195423570985008687907852837564279074904382605163141518161494337n, ee = l / 2n;
|
|
6
6
|
function te(e, t) {
|
|
7
7
|
let n = BigInt(`0x${e}`), r = BigInt(`0x${t}`);
|
|
8
8
|
return n > 0n && n < l && r > 0n && r <= ee;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
//#region src/message/personalSign.ts
|
|
10
|
+
// src/message/personalSign.ts
|
|
12
11
|
var ne = "Ethereum Signed Message:\n", re = /* @__PURE__ */ new Set([27, 28]), ie = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/, u = new TextEncoder();
|
|
13
12
|
function ae(e) {
|
|
14
13
|
let t = u.encode(e), n = u.encode(`${ne}${t.length}`), r = new Uint8Array(n.length + t.length);
|
|
@@ -32,8 +31,7 @@ function f(e) {
|
|
|
32
31
|
let t = Date.parse(e);
|
|
33
32
|
return !Number.isNaN(t) && new Date(t).toISOString() === e;
|
|
34
33
|
}
|
|
35
|
-
|
|
36
|
-
//#region src/message/binding.ts
|
|
34
|
+
// src/message/binding.ts
|
|
37
35
|
var p = "Swarm ID chat binding v1", se = 512, ce = "Site: ", le = "Chat address: ", ue = "Date: ", de = "\n", fe = 4, pe = /^0x[0-9a-f]{40}$/, me = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/, he = /* @__PURE__ */ new Set([
|
|
38
36
|
"localhost",
|
|
39
37
|
"127.0.0.1",
|
|
@@ -82,9 +80,13 @@ function g(e, t, n = {}) {
|
|
|
82
80
|
ok: !1,
|
|
83
81
|
detail: "the binding is for another chat address than addr"
|
|
84
82
|
};
|
|
85
|
-
if (n.
|
|
83
|
+
if (n.origins !== void 0 && !Array.isArray(n.origins)) return {
|
|
86
84
|
ok: !1,
|
|
87
|
-
detail:
|
|
85
|
+
detail: "origins is not a list of sites"
|
|
86
|
+
};
|
|
87
|
+
if (n.origins !== void 0 && !n.origins.includes(i)) return {
|
|
88
|
+
ok: !1,
|
|
89
|
+
detail: `the binding is for ${i}, not for ${n.origins.join(" or ") || "any site"}`
|
|
88
90
|
};
|
|
89
91
|
let s = d(e.msg, e.sig);
|
|
90
92
|
return s === null ? {
|
|
@@ -99,8 +101,7 @@ function g(e, t, n = {}) {
|
|
|
99
101
|
}
|
|
100
102
|
};
|
|
101
103
|
}
|
|
102
|
-
|
|
103
|
-
//#region src/message/walletLink.ts
|
|
104
|
+
// src/message/walletLink.ts
|
|
104
105
|
var _ = "Swarm ID wallet link v1", _e = "I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.", ve = 320, ye = "Account: ", be = "Wallet: ", xe = "Date: ", Se = "\n", v = 5, y = /^0x[0-9a-f]{40}$/, b = o.string().regex(/^0x[0-9a-f]{130}$/, "expected 0x and 130 lowercase hex characters"), x = o.strictObject({
|
|
105
106
|
msg: o.string().max(320),
|
|
106
107
|
wsig: b,
|
|
@@ -149,8 +150,7 @@ function C(e, t) {
|
|
|
149
150
|
detail: `the wallet link is for ${r}, not the binding's account ${t}`
|
|
150
151
|
};
|
|
151
152
|
}
|
|
152
|
-
|
|
153
|
-
//#region src/message/message.ts
|
|
153
|
+
// src/message/message.ts
|
|
154
154
|
var Ce = 9, w = 3072, we = 128, Te = 500, Ee = 20, T = {
|
|
155
155
|
TEXT: "text",
|
|
156
156
|
THREAD: "thread",
|
|
@@ -338,10 +338,10 @@ function U(e, t) {
|
|
|
338
338
|
message: r,
|
|
339
339
|
identity: null
|
|
340
340
|
};
|
|
341
|
-
if (
|
|
341
|
+
if (!Array.isArray(t?.origins)) return {
|
|
342
342
|
ok: !1,
|
|
343
343
|
reason: "binding",
|
|
344
|
-
detail: "no
|
|
344
|
+
detail: "no origins were given to check the binding against"
|
|
345
345
|
};
|
|
346
346
|
let i = g(r.idb, r.addr, t);
|
|
347
347
|
if (!i.ok) return {
|
|
@@ -396,14 +396,12 @@ function Re(e, t) {
|
|
|
396
396
|
}
|
|
397
397
|
return U(r, t);
|
|
398
398
|
}
|
|
399
|
-
|
|
400
|
-
//#region src/message/ownFeed.ts
|
|
399
|
+
// src/message/ownFeed.ts
|
|
401
400
|
var W = "swarm-chat-own-feed-v1:";
|
|
402
401
|
function ze(e) {
|
|
403
402
|
return `${W}${e}`;
|
|
404
403
|
}
|
|
405
|
-
|
|
406
|
-
//#region src/message/entry.ts
|
|
404
|
+
// src/message/entry.ts
|
|
407
405
|
var Be = 4096, Ve = o.string().regex(/^[0-9a-f]{64}([0-9a-f]{64})?$/, "expected a 64 or 128 hex character reference"), G = o.number().int().nonnegative().max(2 ** 53 - 1), K = o.strictObject({
|
|
408
406
|
ref: Ve,
|
|
409
407
|
toSeq: G
|
|
@@ -507,8 +505,7 @@ function We(e, t, n) {
|
|
|
507
505
|
}
|
|
508
506
|
};
|
|
509
507
|
}
|
|
510
|
-
|
|
511
|
-
//#region src/message/note.ts
|
|
508
|
+
// src/message/note.ts
|
|
512
509
|
var Ge = 1, Ke = 2e3, qe = 3e4, Je = 256, Ye = o.strictObject({
|
|
513
510
|
v: o.literal(1),
|
|
514
511
|
newest: o.number().int().min(-1).max(2 ** 53 - 1),
|
|
@@ -551,5 +548,4 @@ function rt(e) {
|
|
|
551
548
|
return null;
|
|
552
549
|
}
|
|
553
550
|
}
|
|
554
|
-
//#endregion
|
|
555
551
|
export { F as A, ve as B, w as C, Ce as D, we as E, H as F, p as G, _ as H, B as I, g as J, se as K, Re as L, Le as M, Ne as N, T as O, z as P, R, I as S, Te as T, C as U, _e as V, x as W, J as _, nt as a, W as b, Qe as c, rt as d, Ye as f, K as g, Y as h, Ge as i, D as j, E as k, Ze as l, q as m, Ke as n, $e as o, Be as p, m as q, Je as r, $ as s, qe as t, Xe as u, Ue as v, Ee as w, ze as x, We as y, U as z };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
let e=require("@ethersphere/bee-js"),t=require("zod"),n=require("@ethersphere/core-sdk/crypto");var r=115792089237316195423570985008687907852837564279074904382605163141518161494337n,i=r/2n;function a(e,t){let n=BigInt(`0x${e}`),a=BigInt(`0x${t}`);return n>0n&&n<r&&a>0n&&a<=i}var o=`Ethereum Signed Message:
|
|
2
|
+
`,s=new Set([27,28]),c=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/,l=new TextEncoder;function ee(e){let t=l.encode(e),n=l.encode(`${o}${t.length}`),r=new Uint8Array(n.length+t.length);return r.set(n),r.set(t,n.length),r}function te(e){return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function u(e,t){let r=t.slice(2,66),i=t.slice(66,130),o=parseInt(t.slice(130),16);if(!s.has(o)||!a(r,i))return null;try{let t=(0,n.recoverPublicKey)(ee(e),BigInt(`0x${r}`),BigInt(`0x${i}`),BigInt(o));return`0x${te((0,n.publicKeyToAddress)(t))}`}catch{return null}}function d(e){if(!c.test(e))return!1;let t=Date.parse(e);return!Number.isNaN(t)&&new Date(t).toISOString()===e}var f=`Swarm ID chat binding v1`,ne=512,re=`Site: `,ie=`Chat address: `,ae=`Date: `,oe=`
|
|
3
|
+
`,p=4,se=/^0x[0-9a-f]{40}$/,ce=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,le=new Set([`localhost`,`127.0.0.1`,`[::1]`]),m=t.z.strictObject({msg:t.z.string().max(512),sig:t.z.string().regex(/^0x[0-9a-f]{130}$/,`expected 0x and 130 lowercase hex characters`)});function ue(e,t){let n;try{n=new URL(e)}catch{return!1}let r=n.protocol===`https:`,i=t&&n.protocol===`http:`&&le.has(n.hostname);return!r&&!i||!i&&!ce.test(n.hostname)?!1:n.host!==``&&n.username===``&&n.password===``&&n.origin===e}function h(e,t){return e.startsWith(t)?e.slice(t.length):null}function g(e,t,n={}){if(!m.safeParse(e).success)return{ok:!1,detail:`not a binding of a text and a 65 byte signature`};let r=e.msg.split(oe);if(r.length!==p||r[0]!==`Swarm ID chat binding v1`)return{ok:!1,detail:`not the ${p} lines of a ${f}`};let i=h(r[1],re),a=h(r[2],ie),o=h(r[3],ae);if(i===null||!ue(i,n.allowLocalHttp===!0))return{ok:!1,detail:`the binding does not name a clean site origin`};if(a===null||!se.test(a))return{ok:!1,detail:`the binding does not name a chat address as 0x and 40 lowercase hex characters`};if(o===null||!d(o))return{ok:!1,detail:`the binding date is not ISO 8601 UTC with milliseconds`};if(a!==`0x${t}`)return{ok:!1,detail:`the binding is for another chat address than addr`};if(n.origins!==void 0&&!Array.isArray(n.origins))return{ok:!1,detail:`origins is not a list of sites`};if(n.origins!==void 0&&!n.origins.includes(i))return{ok:!1,detail:`the binding is for ${i}, not for ${n.origins.join(` or `)||`any site`}`};let s=u(e.msg,e.sig);return s===null?{ok:!1,detail:`the binding signature recovers no account`}:{ok:!0,identity:{account:s,site:i,date:o}}}var _=`Swarm ID wallet link v1`,de=`I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.`,fe=320,pe=`Account: `,me=`Wallet: `,he=`Date: `,ge=`
|
|
4
|
+
`,v=5,y=/^0x[0-9a-f]{40}$/,b=t.z.string().regex(/^0x[0-9a-f]{130}$/,`expected 0x and 130 lowercase hex characters`),x=t.z.strictObject({msg:t.z.string().max(320),wsig:b,asig:b});function S(e,t){return e.startsWith(t)?e.slice(t.length):null}function C(e,t){if(!x.safeParse(e).success)return{ok:!1,detail:`not a wallet link of a text and two 65 byte signatures`};let n=e.msg.split(ge);if(n.length!==v||n[0]!==`Swarm ID wallet link v1`)return{ok:!1,detail:`not the ${v} lines of a ${_}`};if(n[1]!==`I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.`)return{ok:!1,detail:`the wallet link's second line is not the ${_} statement`};let r=S(n[2],pe),i=S(n[3],me),a=S(n[4],he);return r===null||!y.test(r)?{ok:!1,detail:`the wallet link does not name an account as 0x and 40 lowercase hex characters`}:i===null||!y.test(i)?{ok:!1,detail:`the wallet link does not name a wallet as 0x and 40 lowercase hex characters`}:a===null||!d(a)?{ok:!1,detail:`the wallet link date is not ISO 8601 UTC with milliseconds`}:r===t?u(e.msg,e.wsig)===i?u(e.msg,e.asig)===r?{ok:!0,wallet:i,account:r,date:a}:{ok:!1,detail:`the account signature does not recover the account the link names`}:{ok:!1,detail:`the wallet signature does not recover the wallet the link names`}:{ok:!1,detail:`the wallet link is for ${r}, not the binding's account ${t}`}}var _e=9,w=3072,ve=128,ye=500,be=20,T={TEXT:`text`,THREAD:`thread`,REACTION:`reaction`},E={GATEWAY:`gateway`,OWN_STAMP:`own-stamp`};function D(e){let t=0;for(let n of e)t++;return t}function O(e){return t.z.string().regex(RegExp(`^[0-9a-f]{${e}}$`),`expected ${e} lowercase hex characters`)}function k(e,n){return t.z.string().refine(t=>{let r=D(t);return r>=e&&r<=n},`expected ${e} to ${n} characters`)}var A=/(?![\u200c\u200d])[\p{Cf}\p{Cc}\u2800\u115f\u1160\u3164\uffa0]|\u034f|\u17b4|\u17b5/u,xe=/[\p{Default_Ignorable_Code_Point}\p{Mn}\p{Me}\u2800]/gu,j=Object.fromEntries([...[...`℮ꬲеҽ⋿ΕЕⴹᎬꗋꓰ𑢦𑢮𐊆`].map(e=>[e,`e`]),...[...`⊤⟙🝨𝍳ΤⲦТтߠᎢꔋㄒꓔ𖼊𑢼𐊗𐊱𐌕丅`].map(e=>[e,`t`]),...[...`һҺႹհᏂΗⲎНнᎻᕼꓧ𐋏`].map(e=>[e,`h`])]),Se=RegExp(`[${Object.keys(j).join(``)}]`,`gu`),Ce=/[\u3002\u0660\u06f0\u0701\u0702\ua4f8\ua60e\uabec\u{10a50}\u{1d16d}\u{1ecae}]/gu,we=/[\p{Z}.]+$/u,M=`.eth`;function Te(e){return e.normalize(`NFKD`).replace(Ce,`.`).replace(xe,``).replace(Se,e=>j[e]??e).toLowerCase().trim().replace(we,``)}function N(e){return Te(e).endsWith(M)}function Ee(e,t){return k(e,t).refine(e=>!A.test(e),`expected no format or control characters`).refine(e=>!N(e),`expected a name not ending in ${M}, which ENS names keep`)}function De(e){let t=D(e);return t<1||t>20?`length`:A.test(e)?`invisible`:N(e)?`ens-like`:null}var P=O(32),F=t.z.strictObject({v:t.z.literal(9),topic:k(1,128),id:P,type:t.z.enum([T.TEXT,T.THREAD,T.REACTION]),target:t.z.union([t.z.literal(``),P]),text:k(1,500),name:Ee(1,20),addr:O(40),ts:t.z.number().int().nonnegative().max(2**53-1),via:t.z.enum([E.GATEWAY,E.OWN_STAMP]),idb:m.optional(),wl:x.optional(),sig:O(130)}).refine(e=>e.type===T.TEXT==(e.target===``),{message:`a text message has no target, a thread reply or a reaction names one`,path:[`target`]}).refine(e=>e.wl===void 0||e.idb!==void 0,{message:`a wallet link is carried only beside a chat binding, whose account it names`,path:[`wl`]}),I=class extends Error{constructor(e,t){super(`chat message refused (${e}): ${t}`),this.reason=e,this.name=`ChatMessageError`}},L=new TextEncoder,Oe=`1b`,ke=`1c`,Ae=new TextDecoder(`utf-8`,{fatal:!0});function R(e){return L.encode(JSON.stringify([e.v,e.topic,e.id,e.type,e.target,e.text,e.name,e.addr,e.ts,e.via,e.idb?.msg??``,e.idb?.sig??``,...e.wl?[e.wl.msg,e.wl.wsig,e.wl.asig]:[]]))}function z(e){let t={v:e.v,topic:e.topic,id:e.id,type:e.type,target:e.target,text:e.text,name:e.name,addr:e.addr,ts:e.ts,via:e.via,...e.idb?{idb:{msg:e.idb.msg,sig:e.idb.sig}}:{},...e.wl?{wl:{msg:e.wl.msg,wsig:e.wl.wsig,asig:e.wl.asig}}:{},sig:e.sig};return L.encode(JSON.stringify(t))}function B(){let e=crypto.getRandomValues(new Uint8Array(16));return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function V(e){return e.issues.map(e=>`${e.path.join(`.`)||`message`}: ${e.message}`).join(`, `)}function je(t,n){let r=t instanceof e.PrivateKey?t:new e.PrivateKey(t),i={v:9,topic:n.topic,id:n.id??B(),type:n.type,target:n.target??``,text:n.text,name:n.name,addr:r.publicKey().address().toHex(),ts:n.ts??Date.now(),via:n.via,...n.idb?{idb:n.idb}:{},...n.wl?{wl:n.wl}:{}},a={...i,sig:`0`.repeat(130)},o=F.safeParse(a);if(!o.success)throw new I(`shape`,V(o.error));let s=z(a).byteLength;if(s>3072)throw new I(`too-large`,`${s} bytes, the cap is ${w}`);if(i.idb){let e=g(i.idb,i.addr,{allowLocalHttp:!0});if(!e.ok)throw new I(`binding`,e.detail);if(i.wl){let t=C(i.wl,e.identity.account);if(!t.ok)throw new I(`binding`,`wallet link: ${t.detail}`)}}let c={...i,sig:r.sign(R(i)).toHex()};return{message:c,bytes:z(c)}}function H(t){let n=t.sig.slice(128);if(n!==Oe&&n!==ke||!a(t.sig.slice(0,64),t.sig.slice(64,128)))return!1;try{return new e.Signature(t.sig).recoverPublicKey(R(t)).address().toHex()===t.addr}catch{return!1}}function U(e,t){let n=F.safeParse(e);if(!n.success)return{ok:!1,reason:`shape`,detail:V(n.error)};let r=n.data;if(!H(r))return{ok:!1,reason:`signature`,detail:`the signature was not made by addr over these fields`};if(!r.idb)return{ok:!0,message:r,identity:null};if(!Array.isArray(t?.origins))return{ok:!1,reason:`binding`,detail:`no origins were given to check the binding against`};let i=g(r.idb,r.addr,t);if(!i.ok)return{ok:!1,reason:`binding`,detail:i.detail};if(!r.wl)return{ok:!0,message:r,identity:i.identity};let a=C(r.wl,i.identity.account);return a.ok?{ok:!0,message:r,identity:{...i.identity,wallet:a.wallet}}:{ok:!1,reason:`binding`,detail:`wallet link: ${a.detail}`}}function Me(e,t){if(e.byteLength>3072)return{ok:!1,reason:`too-large`,detail:`${e.byteLength} bytes, the cap is ${w}`};let n;try{n=Ae.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}let r;try{r=JSON.parse(n)}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}return U(r,t)}var W=`swarm-chat-own-feed-v1:`;function Ne(e){return`${W}${e}`}var Pe=4096,Fe=t.z.string().regex(/^[0-9a-f]{64}([0-9a-f]{64})?$/,`expected a 64 or 128 hex character reference`),G=t.z.number().int().nonnegative().max(2**53-1),K=t.z.strictObject({ref:Fe,toSeq:G}),q=t.z.strictObject({v:t.z.literal(9),seq:G,at:G,msg:F,history:K.nullable()}),J=t.z.strictObject({seq:G,at:G,msg:F}),Y=t.z.strictObject({v:t.z.literal(9),topic:t.z.string().min(1),fromSeq:G,toSeq:G,messages:t.z.array(t.z.unknown()),prev:K.nullable()}).refine(e=>e.fromSeq<=e.toSeq,{message:`fromSeq is after toSeq`,path:[`fromSeq`]}),Ie=new TextDecoder(`utf-8`,{fatal:!0});function X(e){let t;try{t=Ie.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}try{return{ok:!0,value:JSON.parse(t)}}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}}function Z(e){return e.issues.map(e=>`${e.path.join(`.`)||`value`}: ${e.message}`).join(`, `)}function Le(e,t,n){let r=X(e);if(!r.ok)return r;let i=q.safeParse(r.value);return i.success?i.data.seq===t?i.data.msg.topic===n?{ok:!0,value:i.data}:{ok:!1,reason:`mismatch`,detail:`the message belongs to another chat`}:{ok:!1,reason:`mismatch`,detail:`seq ${i.data.seq} at index ${t}`}:{ok:!1,reason:`shape`,detail:Z(i.error)}}function Re(e,t,n){let r=X(e);if(!r.ok)return r;let i=Y.safeParse(r.value);if(!i.success)return{ok:!1,reason:`shape`,detail:Z(i.error)};if(i.data.topic!==t||i.data.toSeq!==n.toSeq)return{ok:!1,reason:`mismatch`,detail:`the file is not the one its link names`};let{fromSeq:a,toSeq:o,prev:s}=i.data,c=[],l=0;for(let e of i.data.messages){let n=J.safeParse(e);n.success&&n.data.seq>=a&&n.data.seq<=o&&n.data.msg.topic===t?c.push(n.data):l++}return{ok:!0,value:{topic:t,fromSeq:a,toSeq:o,rows:c,prev:s,skipped:l}}}var ze=1,Be=2e3,Ve=3e4,He=256,Q=t.z.strictObject({v:t.z.literal(1),newest:t.z.number().int().min(-1).max(2**53-1),writtenAt:t.z.number().int().nonnegative().max(2**53-1)});function $(e){if(!Number.isInteger(e)||e<=0)throw RangeError(`a note slot is a positive whole number of milliseconds, not ${e}`)}function Ue(e,t){return $(t),Math.floor(e/t)}function We(e,t){return $(t),(e+1)*t}function Ge(e,t,n){return`${e}/note/${t}/${n}`}function Ke(t,n,r){return e.Identifier.fromString(Ge(t,n,r))}function qe(t,n,r,i){let a=Ke(t,n,r);return new e.Reference(e.Bytes.keccak256(e.Bytes.concat(a.toUint8Array(),new e.EthAddress(i).toUint8Array())))}var Je=new TextEncoder,Ye=new TextDecoder(`utf-8`,{fatal:!0});function Xe(e){let t={v:1,newest:e.newest,writtenAt:e.writtenAt};return Je.encode(JSON.stringify(t))}function Ze(e){if(e.length>256)return null;try{let t=Q.safeParse(JSON.parse(Ye.decode(e)));return t.success?t.data:null}catch{return null}}Object.defineProperty(exports,"A",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"B",{enumerable:!0,get:function(){return fe}}),Object.defineProperty(exports,"C",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"D",{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,"E",{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,"F",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"G",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"H",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"I",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"J",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"K",{enumerable:!0,get:function(){return ne}}),Object.defineProperty(exports,"L",{enumerable:!0,get:function(){return Me}}),Object.defineProperty(exports,"M",{enumerable:!0,get:function(){return je}}),Object.defineProperty(exports,"N",{enumerable:!0,get:function(){return De}}),Object.defineProperty(exports,"O",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"P",{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,"R",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"S",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"T",{enumerable:!0,get:function(){return ye}}),Object.defineProperty(exports,"U",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"V",{enumerable:!0,get:function(){return de}}),Object.defineProperty(exports,"W",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return Xe}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return Ge}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return Ze}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return ze}}),Object.defineProperty(exports,"j",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"k",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return We}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Be}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return qe}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return Pe}}),Object.defineProperty(exports,"q",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return He}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return Ke}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return Ve}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return Ue}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return Le}}),Object.defineProperty(exports,"w",{enumerable:!0,get:function(){return be}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return Ne}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return Re}}),Object.defineProperty(exports,"z",{enumerable:!0,get:function(){return U}});
|
package/dist/message.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./message-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./message-BjeTRy2F.cjs");exports.CHAT_BINDING_TITLE=e.G,exports.ChatMessageError=e.S,exports.DEFAULT_NOTE_HEARTBEAT_MS=e.t,exports.DEFAULT_NOTE_SLOT_MS=e.n,exports.MAX_BINDING_CHARACTERS=e.K,exports.MAX_ENTRY_BYTES=e.p,exports.MAX_MESSAGE_BYTES=e.C,exports.MAX_NAME_CHARACTERS=e.w,exports.MAX_NOTE_BYTES=e.r,exports.MAX_TEXT_CHARACTERS=e.T,exports.MAX_TOPIC_CHARACTERS=e.E,exports.MAX_WALLET_LINK_CHARACTERS=e.B,exports.MESSAGE_VERSION=e.D,exports.MessageType=e.O,exports.MessageVia=e.k,exports.NOTE_VERSION=e.i,exports.OWN_FEED_TOPIC_PREFIX=e.b,exports.WALLET_LINK_STATEMENT=e.V,exports.WALLET_LINK_TITLE=e.H,exports.chatBindingSchema=e.q,exports.chatMessageSchema=e.A,exports.checkChatBinding=e.J,exports.checkWalletLink=e.U,exports.countCharacters=e.j,exports.createChatMessage=e.M,exports.displayNameProblem=e.N,exports.encodeChatMessage=e.P,exports.encodeSlotNote=e.a,exports.feedEntrySchema=e.m,exports.hasValidSignature=e.F,exports.historyFileSchema=e.h,exports.historyLinkSchema=e.g,exports.historyRowSchema=e._,exports.newMessageId=e.I,exports.noteAddress=e.o,exports.noteIdentifier=e.s,exports.noteIdentifierText=e.c,exports.noteSlotEnd=e.l,exports.noteSlotOf=e.u,exports.ownFeedTopic=e.x,exports.parseChatMessage=e.L,exports.parseFeedEntry=e.v,exports.parseHistoryFile=e.y,exports.parseSlotNote=e.d,exports.signedBytes=e.R,exports.slotNoteSchema=e.f,exports.verifyChatMessage=e.z,exports.walletLinkSchema=e.W;
|
package/dist/message.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { o as CHAT_BINDING_TITLE, _ as ChatMessageError, V as DEFAULT_NOTE_HEARTBEAT_MS, F as DEFAULT_NOTE_SLOT_MS, u as MAX_BINDING_CHARACTERS, L as MAX_ENTRY_BYTES, n as MAX_MESSAGE_BYTES, W as MAX_NAME_CHARACTERS, z as MAX_NOTE_BYTES, v as MAX_TEXT_CHARACTERS, i as MAX_TOPIC_CHARACTERS, t as MAX_WALLET_LINK_CHARACTERS, r as MESSAGE_VERSION, m as MessageType, M as MessageVia, A as NOTE_VERSION, w as OWN_FEED_TOPIC_PREFIX, b as WALLET_LINK_STATEMENT, s as WALLET_LINK_TITLE, R as chatBindingSchema, e as chatMessageSchema, l as checkChatBinding, y as checkWalletLink, j as countCharacters, f as createChatMessage, p as displayNameProblem, h as encodeChatMessage, C as encodeSlotNote, P as feedEntrySchema, a as hasValidSignature, k as historyFileSchema, O as historyLinkSchema, S as historyRowSchema, c as newMessageId, I as noteAddress, B as noteIdentifier, T as noteIdentifierText, N as noteSlotEnd, H as noteSlotOf, G as ownFeedTopic, d as parseChatMessage, U as parseFeedEntry, K as parseHistoryFile, E as parseSlotNote, g as signedBytes, D as slotNoteSchema, q as verifyChatMessage, x as walletLinkSchema };
|
|
1
|
+
export { G as CHAT_BINDING_TITLE, S as ChatMessageError, t as DEFAULT_NOTE_HEARTBEAT_MS, n as DEFAULT_NOTE_SLOT_MS, K as MAX_BINDING_CHARACTERS, p as MAX_ENTRY_BYTES, C as MAX_MESSAGE_BYTES, w as MAX_NAME_CHARACTERS, r as MAX_NOTE_BYTES, T as MAX_TEXT_CHARACTERS, E as MAX_TOPIC_CHARACTERS, B as MAX_WALLET_LINK_CHARACTERS, D as MESSAGE_VERSION, O as MessageType, k as MessageVia, i as NOTE_VERSION, b as OWN_FEED_TOPIC_PREFIX, V as WALLET_LINK_STATEMENT, H as WALLET_LINK_TITLE, q as chatBindingSchema, A as chatMessageSchema, J as checkChatBinding, U as checkWalletLink, j as countCharacters, M as createChatMessage, N as displayNameProblem, P as encodeChatMessage, a as encodeSlotNote, m as feedEntrySchema, F as hasValidSignature, h as historyFileSchema, g as historyLinkSchema, _ as historyRowSchema, I as newMessageId, o as noteAddress, s as noteIdentifier, c as noteIdentifierText, l as noteSlotEnd, u as noteSlotOf, x as ownFeedTopic, L as parseChatMessage, v as parseFeedEntry, y as parseHistoryFile, d as parseSlotNote, R as signedBytes, f as slotNoteSchema, z as verifyChatMessage, W as walletLinkSchema } from "./message-BUFAxjtN.js";
|
package/dist/pacer.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* chunk for a minute (`ethersphere/bee`, `pkg/retrieval/retrieval.go`, `errSkip` and `skiplistDur = time.Minute`).
|
|
6
6
|
* Once no peer is left it answers 500 at once, because "no peer left" is not `storage.ErrNotFound`
|
|
7
7
|
* (`pkg/api/chunk.go`). A chunk written while its address is on that list stays unreadable on that node for up to a
|
|
8
|
-
* minute. Measured on
|
|
8
|
+
* minute. Measured on a test node on 2026-10-12: an address read every second for 20 s and then written was readable
|
|
9
9
|
* after 33 to 36 s, one nobody had asked for at once. About four reads of a missing address exhaust the list, so one
|
|
10
10
|
* read every twenty seconds stays under it.
|
|
11
11
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solarpunkltd/swarm-chat-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "JS library for chatting on Swarm",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chat",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://github.com/Solar-Punk-Ltd/swarm-chat-js/issues"
|
|
12
12
|
},
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
|
-
"author": "
|
|
14
|
+
"author": "Solar Punk Ltd",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git+https://github.com/Solar-Punk-Ltd/swarm-chat-js"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"oxlint": "1.83.0",
|
|
57
57
|
"oxlint-tsgolint": "7.0.2001",
|
|
58
58
|
"typescript": "7.0.2",
|
|
59
|
-
"vite": "8.3.
|
|
59
|
+
"vite": "8.3.3",
|
|
60
60
|
"vitest": "5.0.1"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
let e=require("@ethersphere/bee-js"),t=require("zod"),n=require("@ethersphere/core-sdk/crypto");var r=115792089237316195423570985008687907852837564279074904382605163141518161494337n,i=r/2n;function a(e,t){let n=BigInt(`0x${e}`),a=BigInt(`0x${t}`);return n>0n&&n<r&&a>0n&&a<=i}var o=`Ethereum Signed Message:
|
|
2
|
-
`,s=new Set([27,28]),c=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/,l=new TextEncoder;function ee(e){let t=l.encode(e),n=l.encode(`${o}${t.length}`),r=new Uint8Array(n.length+t.length);return r.set(n),r.set(t,n.length),r}function te(e){return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function u(e,t){let r=t.slice(2,66),i=t.slice(66,130),o=parseInt(t.slice(130),16);if(!s.has(o)||!a(r,i))return null;try{let t=(0,n.recoverPublicKey)(ee(e),BigInt(`0x${r}`),BigInt(`0x${i}`),BigInt(o));return`0x${te((0,n.publicKeyToAddress)(t))}`}catch{return null}}function d(e){if(!c.test(e))return!1;let t=Date.parse(e);return!Number.isNaN(t)&&new Date(t).toISOString()===e}var f=`Swarm ID chat binding v1`,ne=512,re=`Site: `,ie=`Chat address: `,ae=`Date: `,oe=`
|
|
3
|
-
`,p=4,se=/^0x[0-9a-f]{40}$/,ce=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,le=new Set([`localhost`,`127.0.0.1`,`[::1]`]),m=t.z.strictObject({msg:t.z.string().max(512),sig:t.z.string().regex(/^0x[0-9a-f]{130}$/,`expected 0x and 130 lowercase hex characters`)});function ue(e,t){let n;try{n=new URL(e)}catch{return!1}let r=n.protocol===`https:`,i=t&&n.protocol===`http:`&&le.has(n.hostname);return!r&&!i||!i&&!ce.test(n.hostname)?!1:n.host!==``&&n.username===``&&n.password===``&&n.origin===e}function h(e,t){return e.startsWith(t)?e.slice(t.length):null}function g(e,t,n={}){if(!m.safeParse(e).success)return{ok:!1,detail:`not a binding of a text and a 65 byte signature`};let r=e.msg.split(oe);if(r.length!==p||r[0]!==`Swarm ID chat binding v1`)return{ok:!1,detail:`not the ${p} lines of a ${f}`};let i=h(r[1],re),a=h(r[2],ie),o=h(r[3],ae);if(i===null||!ue(i,n.allowLocalHttp===!0))return{ok:!1,detail:`the binding does not name a clean site origin`};if(a===null||!se.test(a))return{ok:!1,detail:`the binding does not name a chat address as 0x and 40 lowercase hex characters`};if(o===null||!d(o))return{ok:!1,detail:`the binding date is not ISO 8601 UTC with milliseconds`};if(a!==`0x${t}`)return{ok:!1,detail:`the binding is for another chat address than addr`};if(n.origin!==void 0&&i!==n.origin)return{ok:!1,detail:`the binding is for ${i}, not ${n.origin}`};let s=u(e.msg,e.sig);return s===null?{ok:!1,detail:`the binding signature recovers no account`}:{ok:!0,identity:{account:s,site:i,date:o}}}var _=`Swarm ID wallet link v1`,de=`I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.`,fe=320,pe=`Account: `,me=`Wallet: `,he=`Date: `,ge=`
|
|
4
|
-
`,v=5,y=/^0x[0-9a-f]{40}$/,b=t.z.string().regex(/^0x[0-9a-f]{130}$/,`expected 0x and 130 lowercase hex characters`),x=t.z.strictObject({msg:t.z.string().max(320),wsig:b,asig:b});function S(e,t){return e.startsWith(t)?e.slice(t.length):null}function C(e,t){if(!x.safeParse(e).success)return{ok:!1,detail:`not a wallet link of a text and two 65 byte signatures`};let n=e.msg.split(ge);if(n.length!==v||n[0]!==`Swarm ID wallet link v1`)return{ok:!1,detail:`not the ${v} lines of a ${_}`};if(n[1]!==`I link this wallet to the Swarm ID account below, so sites may show my ENS name beside its messages.`)return{ok:!1,detail:`the wallet link's second line is not the ${_} statement`};let r=S(n[2],pe),i=S(n[3],me),a=S(n[4],he);return r===null||!y.test(r)?{ok:!1,detail:`the wallet link does not name an account as 0x and 40 lowercase hex characters`}:i===null||!y.test(i)?{ok:!1,detail:`the wallet link does not name a wallet as 0x and 40 lowercase hex characters`}:a===null||!d(a)?{ok:!1,detail:`the wallet link date is not ISO 8601 UTC with milliseconds`}:r===t?u(e.msg,e.wsig)===i?u(e.msg,e.asig)===r?{ok:!0,wallet:i,account:r,date:a}:{ok:!1,detail:`the account signature does not recover the account the link names`}:{ok:!1,detail:`the wallet signature does not recover the wallet the link names`}:{ok:!1,detail:`the wallet link is for ${r}, not the binding's account ${t}`}}var _e=9,w=3072,ve=128,ye=500,be=20,T={TEXT:`text`,THREAD:`thread`,REACTION:`reaction`},E={GATEWAY:`gateway`,OWN_STAMP:`own-stamp`};function D(e){let t=0;for(let n of e)t++;return t}function O(e){return t.z.string().regex(RegExp(`^[0-9a-f]{${e}}$`),`expected ${e} lowercase hex characters`)}function k(e,n){return t.z.string().refine(t=>{let r=D(t);return r>=e&&r<=n},`expected ${e} to ${n} characters`)}var A=/(?![\u200c\u200d])[\p{Cf}\p{Cc}\u2800\u115f\u1160\u3164\uffa0]|\u034f|\u17b4|\u17b5/u,xe=/[\p{Default_Ignorable_Code_Point}\p{Mn}\p{Me}\u2800]/gu,j=Object.fromEntries([...[...`℮ꬲеҽ⋿ΕЕⴹᎬꗋꓰ𑢦𑢮𐊆`].map(e=>[e,`e`]),...[...`⊤⟙🝨𝍳ΤⲦТтߠᎢꔋㄒꓔ𖼊𑢼𐊗𐊱𐌕丅`].map(e=>[e,`t`]),...[...`һҺႹհᏂΗⲎНнᎻᕼꓧ𐋏`].map(e=>[e,`h`])]),Se=RegExp(`[${Object.keys(j).join(``)}]`,`gu`),Ce=/[\u3002\u0660\u06f0\u0701\u0702\ua4f8\ua60e\uabec\u{10a50}\u{1d16d}\u{1ecae}]/gu,we=/[\p{Z}.]+$/u,M=`.eth`;function Te(e){return e.normalize(`NFKD`).replace(Ce,`.`).replace(xe,``).replace(Se,e=>j[e]??e).toLowerCase().trim().replace(we,``)}function N(e){return Te(e).endsWith(M)}function Ee(e,t){return k(e,t).refine(e=>!A.test(e),`expected no format or control characters`).refine(e=>!N(e),`expected a name not ending in ${M}, which ENS names keep`)}function De(e){let t=D(e);return t<1||t>20?`length`:A.test(e)?`invisible`:N(e)?`ens-like`:null}var P=O(32),F=t.z.strictObject({v:t.z.literal(9),topic:k(1,128),id:P,type:t.z.enum([T.TEXT,T.THREAD,T.REACTION]),target:t.z.union([t.z.literal(``),P]),text:k(1,500),name:Ee(1,20),addr:O(40),ts:t.z.number().int().nonnegative().max(2**53-1),via:t.z.enum([E.GATEWAY,E.OWN_STAMP]),idb:m.optional(),wl:x.optional(),sig:O(130)}).refine(e=>e.type===T.TEXT==(e.target===``),{message:`a text message has no target, a thread reply or a reaction names one`,path:[`target`]}).refine(e=>e.wl===void 0||e.idb!==void 0,{message:`a wallet link is carried only beside a chat binding, whose account it names`,path:[`wl`]}),I=class extends Error{constructor(e,t){super(`chat message refused (${e}): ${t}`),this.reason=e,this.name=`ChatMessageError`}},L=new TextEncoder,Oe=`1b`,ke=`1c`,Ae=new TextDecoder(`utf-8`,{fatal:!0});function R(e){return L.encode(JSON.stringify([e.v,e.topic,e.id,e.type,e.target,e.text,e.name,e.addr,e.ts,e.via,e.idb?.msg??``,e.idb?.sig??``,...e.wl?[e.wl.msg,e.wl.wsig,e.wl.asig]:[]]))}function z(e){let t={v:e.v,topic:e.topic,id:e.id,type:e.type,target:e.target,text:e.text,name:e.name,addr:e.addr,ts:e.ts,via:e.via,...e.idb?{idb:{msg:e.idb.msg,sig:e.idb.sig}}:{},...e.wl?{wl:{msg:e.wl.msg,wsig:e.wl.wsig,asig:e.wl.asig}}:{},sig:e.sig};return L.encode(JSON.stringify(t))}function B(){let e=crypto.getRandomValues(new Uint8Array(16));return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function V(e){return e.issues.map(e=>`${e.path.join(`.`)||`message`}: ${e.message}`).join(`, `)}function je(t,n){let r=t instanceof e.PrivateKey?t:new e.PrivateKey(t),i={v:9,topic:n.topic,id:n.id??B(),type:n.type,target:n.target??``,text:n.text,name:n.name,addr:r.publicKey().address().toHex(),ts:n.ts??Date.now(),via:n.via,...n.idb?{idb:n.idb}:{},...n.wl?{wl:n.wl}:{}},a={...i,sig:`0`.repeat(130)},o=F.safeParse(a);if(!o.success)throw new I(`shape`,V(o.error));let s=z(a).byteLength;if(s>3072)throw new I(`too-large`,`${s} bytes, the cap is ${w}`);if(i.idb){let e=g(i.idb,i.addr,{allowLocalHttp:!0});if(!e.ok)throw new I(`binding`,e.detail);if(i.wl){let t=C(i.wl,e.identity.account);if(!t.ok)throw new I(`binding`,`wallet link: ${t.detail}`)}}let c={...i,sig:r.sign(R(i)).toHex()};return{message:c,bytes:z(c)}}function H(t){let n=t.sig.slice(128);if(n!==Oe&&n!==ke||!a(t.sig.slice(0,64),t.sig.slice(64,128)))return!1;try{return new e.Signature(t.sig).recoverPublicKey(R(t)).address().toHex()===t.addr}catch{return!1}}function U(e,t){let n=F.safeParse(e);if(!n.success)return{ok:!1,reason:`shape`,detail:V(n.error)};let r=n.data;if(!H(r))return{ok:!1,reason:`signature`,detail:`the signature was not made by addr over these fields`};if(!r.idb)return{ok:!0,message:r,identity:null};if(typeof t?.origin!=`string`)return{ok:!1,reason:`binding`,detail:`no origin was given to check the binding against`};let i=g(r.idb,r.addr,t);if(!i.ok)return{ok:!1,reason:`binding`,detail:i.detail};if(!r.wl)return{ok:!0,message:r,identity:i.identity};let a=C(r.wl,i.identity.account);return a.ok?{ok:!0,message:r,identity:{...i.identity,wallet:a.wallet}}:{ok:!1,reason:`binding`,detail:`wallet link: ${a.detail}`}}function Me(e,t){if(e.byteLength>3072)return{ok:!1,reason:`too-large`,detail:`${e.byteLength} bytes, the cap is ${w}`};let n;try{n=Ae.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}let r;try{r=JSON.parse(n)}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}return U(r,t)}var W=`swarm-chat-own-feed-v1:`;function Ne(e){return`${W}${e}`}var Pe=4096,Fe=t.z.string().regex(/^[0-9a-f]{64}([0-9a-f]{64})?$/,`expected a 64 or 128 hex character reference`),G=t.z.number().int().nonnegative().max(2**53-1),K=t.z.strictObject({ref:Fe,toSeq:G}),q=t.z.strictObject({v:t.z.literal(9),seq:G,at:G,msg:F,history:K.nullable()}),J=t.z.strictObject({seq:G,at:G,msg:F}),Y=t.z.strictObject({v:t.z.literal(9),topic:t.z.string().min(1),fromSeq:G,toSeq:G,messages:t.z.array(t.z.unknown()),prev:K.nullable()}).refine(e=>e.fromSeq<=e.toSeq,{message:`fromSeq is after toSeq`,path:[`fromSeq`]}),Ie=new TextDecoder(`utf-8`,{fatal:!0});function X(e){let t;try{t=Ie.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}try{return{ok:!0,value:JSON.parse(t)}}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}}function Z(e){return e.issues.map(e=>`${e.path.join(`.`)||`value`}: ${e.message}`).join(`, `)}function Le(e,t,n){let r=X(e);if(!r.ok)return r;let i=q.safeParse(r.value);return i.success?i.data.seq===t?i.data.msg.topic===n?{ok:!0,value:i.data}:{ok:!1,reason:`mismatch`,detail:`the message belongs to another chat`}:{ok:!1,reason:`mismatch`,detail:`seq ${i.data.seq} at index ${t}`}:{ok:!1,reason:`shape`,detail:Z(i.error)}}function Re(e,t,n){let r=X(e);if(!r.ok)return r;let i=Y.safeParse(r.value);if(!i.success)return{ok:!1,reason:`shape`,detail:Z(i.error)};if(i.data.topic!==t||i.data.toSeq!==n.toSeq)return{ok:!1,reason:`mismatch`,detail:`the file is not the one its link names`};let{fromSeq:a,toSeq:o,prev:s}=i.data,c=[],l=0;for(let e of i.data.messages){let n=J.safeParse(e);n.success&&n.data.seq>=a&&n.data.seq<=o&&n.data.msg.topic===t?c.push(n.data):l++}return{ok:!0,value:{topic:t,fromSeq:a,toSeq:o,rows:c,prev:s,skipped:l}}}var ze=1,Be=2e3,Ve=3e4,He=256,Q=t.z.strictObject({v:t.z.literal(1),newest:t.z.number().int().min(-1).max(2**53-1),writtenAt:t.z.number().int().nonnegative().max(2**53-1)});function $(e){if(!Number.isInteger(e)||e<=0)throw RangeError(`a note slot is a positive whole number of milliseconds, not ${e}`)}function Ue(e,t){return $(t),Math.floor(e/t)}function We(e,t){return $(t),(e+1)*t}function Ge(e,t,n){return`${e}/note/${t}/${n}`}function Ke(t,n,r){return e.Identifier.fromString(Ge(t,n,r))}function qe(t,n,r,i){let a=Ke(t,n,r);return new e.Reference(e.Bytes.keccak256(e.Bytes.concat(a.toUint8Array(),new e.EthAddress(i).toUint8Array())))}var Je=new TextEncoder,Ye=new TextDecoder(`utf-8`,{fatal:!0});function Xe(e){let t={v:1,newest:e.newest,writtenAt:e.writtenAt};return Je.encode(JSON.stringify(t))}function Ze(e){if(e.length>256)return null;try{let t=Q.safeParse(JSON.parse(Ye.decode(e)));return t.success?t.data:null}catch{return null}}Object.defineProperty(exports,"A",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"B",{enumerable:!0,get:function(){return fe}}),Object.defineProperty(exports,"C",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"D",{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,"E",{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,"F",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"G",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"H",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"I",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"J",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"K",{enumerable:!0,get:function(){return ne}}),Object.defineProperty(exports,"L",{enumerable:!0,get:function(){return Me}}),Object.defineProperty(exports,"M",{enumerable:!0,get:function(){return je}}),Object.defineProperty(exports,"N",{enumerable:!0,get:function(){return De}}),Object.defineProperty(exports,"O",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"P",{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,"R",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"S",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"T",{enumerable:!0,get:function(){return ye}}),Object.defineProperty(exports,"U",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"V",{enumerable:!0,get:function(){return de}}),Object.defineProperty(exports,"W",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return Xe}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return Ge}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return Ze}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return ze}}),Object.defineProperty(exports,"j",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"k",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return We}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Be}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return qe}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return Pe}}),Object.defineProperty(exports,"q",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return He}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return Ke}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return Ve}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return Ue}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return Le}}),Object.defineProperty(exports,"w",{enumerable:!0,get:function(){return be}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return Ne}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return Re}}),Object.defineProperty(exports,"z",{enumerable:!0,get:function(){return U}});
|