@wowok/wowok 2.2.14 → 2.2.16
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/LICENSE +19 -131
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/jsonRpc/client.d.ts +2 -2
- package/dist/cjs/jsonRpc/types/chain.d.ts +3 -3
- package/dist/cjs/jsonRpc/types/generated.d.ts +249 -271
- package/dist/cjs/jsonRpc/types/generated_old.d.ts +954 -0
- package/dist/cjs/jsonRpc/types/generated_old.js +1 -0
- package/dist/cjs/jsonRpc/types/params.d.ts +2 -2
- package/dist/cjs/w/call/arbitration.js +1 -1
- package/dist/cjs/w/call/base.d.ts +1 -0
- package/dist/cjs/w/call/base.js +1 -1
- package/dist/cjs/w/call/contact.js +1 -1
- package/dist/cjs/w/call/demand.js +1 -1
- package/dist/cjs/w/call/guard.js +1 -1
- package/dist/cjs/w/call/machine.js +1 -1
- package/dist/cjs/w/call/personal.js +1 -1
- package/dist/cjs/w/call/repository.js +1 -1
- package/dist/cjs/w/call/reward.js +1 -1
- package/dist/cjs/w/call/service.js +1 -1
- package/dist/cjs/w/call/treasury.js +1 -1
- package/dist/cjs/w/local/account.d.ts +2 -0
- package/dist/cjs/w/local/account.js +1 -1
- package/dist/cjs/w/local/cache.js +1 -1
- package/dist/cjs/w/local/index.js +1 -1
- package/dist/cjs/w/local/local.d.ts +3 -0
- package/dist/cjs/w/local/local.js +1 -1
- package/dist/cjs/w/local/storage.js +1 -1
- package/dist/cjs/w/local/util.js +1 -1
- package/dist/cjs/w/local/wip.js +1 -1
- package/dist/cjs/w/messenger/messenger-api.js +1 -1
- package/dist/cjs/w/messenger/messenger.js +1 -1
- package/dist/cjs/w/messenger/pq/crypto.js +1 -1
- package/dist/cjs/w/messenger/storage.js +1 -1
- package/dist/cjs/w/query/object.js +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/jsonRpc/client.d.ts +2 -2
- package/dist/esm/jsonRpc/types/chain.d.ts +3 -3
- package/dist/esm/jsonRpc/types/generated.d.ts +249 -271
- package/dist/esm/jsonRpc/types/generated_old.d.ts +954 -0
- package/dist/esm/jsonRpc/types/generated_old.js +1 -0
- package/dist/esm/jsonRpc/types/params.d.ts +2 -2
- package/dist/esm/w/call/arbitration.js +1 -1
- package/dist/esm/w/call/base.d.ts +1 -0
- package/dist/esm/w/call/base.js +1 -1
- package/dist/esm/w/call/contact.js +1 -1
- package/dist/esm/w/call/demand.js +1 -1
- package/dist/esm/w/call/guard.js +1 -1
- package/dist/esm/w/call/machine.js +1 -1
- package/dist/esm/w/call/personal.js +1 -1
- package/dist/esm/w/call/repository.js +1 -1
- package/dist/esm/w/call/reward.js +1 -1
- package/dist/esm/w/call/service.js +1 -1
- package/dist/esm/w/call/treasury.js +1 -1
- package/dist/esm/w/local/account.d.ts +2 -0
- package/dist/esm/w/local/account.js +1 -1
- package/dist/esm/w/local/cache.js +1 -1
- package/dist/esm/w/local/index.js +1 -1
- package/dist/esm/w/local/local.d.ts +3 -0
- package/dist/esm/w/local/local.js +1 -1
- package/dist/esm/w/local/storage.js +1 -1
- package/dist/esm/w/local/util.js +1 -1
- package/dist/esm/w/local/wip.js +1 -1
- package/dist/esm/w/messenger/messenger-api.js +1 -1
- package/dist/esm/w/messenger/messenger.js +1 -1
- package/dist/esm/w/messenger/pq/crypto.js +1 -1
- package/dist/esm/w/messenger/storage.js +1 -1
- package/dist/esm/w/query/object.js +1 -1
- package/package.json +1 -3
- package/NOTICE +0 -114
- package/THIRD_PARTY_LICENSES/APACHE_LICENSE.txt +0 -196
- package/THIRD_PARTY_LICENSES/MIT_LICENSE.txt +0 -58
package/dist/cjs/w/local/wip.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sha256}from'@noble/hashes/sha256';import{bytesToHex}from'@noble/hashes/utils';import*as a179a from'fs';import*as a179b from'path';import*as a179c from'https';import*as a179d from'http';const WIP_SCHEMA_URL='https://github.com/wowok-ai/docs/blob/main/WIP.md',WIP_VERSION='1.0.0';export const DEFAULT_LIMITS={'maxImageSize':0x2*0x400*0x400,'maxTotalSize':0xa*0x400*0x400,'maxImageCount':0xa,'maxTextLength':0x2710};export class WipError extends Error{constructor(a){super(a),this['name']='WipError';}}export class WipValidationError extends WipError{constructor(a){super(a),this['name']='WipValidationError';}}export class WipSizeError extends WipError{constructor(a){super(a),this['name']='WipSizeError';}}function detectMimeType(a){if(a['length']>=0x4&&a[0x0]===0x89&&a[0x1]===0x50&&a[0x2]===0x4e&&a[0x3]===0x47)return'image/png';if(a['length']>=0x3&&a[0x0]===0xff&&a[0x1]===0xd8&&a[0x2]===0xff)return'image/jpeg';if(a['length']>=0x6&&a[0x0]===0x47&&a[0x1]===0x49&&a[0x2]===0x46)return'image/gif';if(a['length']>=0xc&&a[0x0]===0x52&&a[0x1]===0x49&&a[0x2]===0x46&&a[0x3]===0x46&&a[0x8]===0x57&&a[0x9]===0x45&&a[0xa]===0x42&&a[0xb]===0x50)return'image/webp';return null;}function uint8ArrayToBase64(a){let b='';const c=a['length'];for(let d=0x0;d<c;d++){b+=String['fromCharCode'](a[d]);}return btoa(b);}function base64ToUint8Array(a){const b=atob(a),c=b['length'],d=new Uint8Array(c);for(let e=0x0;e<c;e++){d[e]=b['charCodeAt'](e);}return d;}function canonicalizeJson(a){if(a===null||typeof a!=='object')return JSON['stringify'](a);if(Array['isArray'](a))return'['+a['map'](canonicalizeJson)['join'](',')+']';const b=a,c=Object['keys'](b)['sort'](),d=c['map'](e=>'\x22'+e+'\x22:'+canonicalizeJson(b[e]));return'{'+d['join'](',')+'}';}function computeHash(a){const b=sha256(new TextEncoder()['encode'](a));return bytesToHex(b);}function generateId(a){const b=Date['now']()['toString'](0x24),c=Math['random']()['toString'](0x24)['substring'](0x2,0x8);return a+'-'+b+'-'+c;}function getExtensionFromMimeType(a){const b={'image/png':'png','image/jpeg':'jpg','image/gif':'gif','image/webp':'webp'};return b[a]||'bin';}class ResourceLoader{['maxSize'];constructor(a){this['maxSize']=a;}async['load'](a){if(!a||a['trim']()==='')throw new WipError('WIP\x20file\x20path\x20cannot\x20be\x20empty');if(a['startsWith']('data:'))return this['loadFromDataUrl'](a);if(a['startsWith']('http://')||a['startsWith']('https://'))return this['loadFromNetwork'](a);return this['loadFromFile'](a);}['loadFromDataUrl'](a){const b=a['match'](/^data:image\/(\w+);base64,(.+)$/);if(!b)throw new WipValidationError('Invalid\x20data\x20URL\x20format:\x20'+a['substring'](0x0,0x32)+'...');const c=b[0x2];try{return base64ToUint8Array(c);}catch(d){throw new WipError('Failed\x20to\x20decode\x20data\x20URL:\x20'+d);}}async['loadFromNetwork'](a){return new Promise((b,c)=>{const d=setTimeout(()=>{c(new WipError('Network\x20timeout\x20while\x20fetching:\x20'+a));},0x7530),e=a['startsWith']('https:'),f=e?a179c:a179d,g={'headers':{'Accept':'application/json,*/*'}};e&&(g['rejectUnauthorized']=![]);const h=f['get'](a,g,i=>{clearTimeout(d);if(i['statusCode']!==0xc8){c(new WipError('Failed\x20to\x20fetch:\x20'+i['statusCode']+'\x20'+i['statusMessage']));return;}const j=i['headers']['content-length'];if(j&&parseInt(j)>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+j+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}const k=[];i['on']('data',l=>{k['push'](l);}),i['on']('end',()=>{const l=Buffer['concat'](k);if(l['length']>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+l['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}b(new Uint8Array(l));}),i['on']('error',l=>{c(new WipError('Network\x20error:\x20'+l['message']));});});h['on']('error',i=>{clearTimeout(d),c(new WipError('Network\x20error:\x20'+i['message']));});});}['loadFromFile'](a){const b=a179b['resolve'](a);if(!a179a['existsSync'](b))throw new WipError('File\x20not\x20found:\x20'+b);const c=a179a['statSync'](b);if(!c['isFile']())throw new WipError('Path\x20is\x20not\x20a\x20file:\x20'+b);if(c['size']>this['maxSize'])throw new WipSizeError('File\x20'+b+'\x20size\x20('+c['size']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)');const d=a179a['readFileSync'](b);return new Uint8Array(d);}}export class WIP{['limits'];['resourceLoader'];constructor(a={}){this['limits']={...DEFAULT_LIMITS,...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}async['create'](a){if(a['text']['length']>this['limits']['maxTextLength'])throw new WipSizeError('Text\x20length\x20('+a['text']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxTextLength']+')');const b=[];if(a['images']&&a['images']['length']>0x0){if(a['images']['length']>this['limits']['maxImageCount'])throw new WipSizeError('Image\x20count\x20('+a['images']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxImageCount']+')');for(let j=0x0;j<a['images']['length'];j++){const k=await this['processImage'](a['images'][j],j);b['push'](k);}}const c={'content':{'text':a['text'],'format':a['textFormat']||'plain'},'media':b},d={'wip':WIP_SCHEMA_URL,'payload':c},e=computeHash(canonicalizeJson(d)),f={'type':'wip','version':WIP_VERSION,'created':new Date()['toISOString'](),'hash':e,'algorithm':'sha256'};if(a['signKeyPair']){const {signature:l,...m}=f,n=computeHash(canonicalizeJson(m)),o=await this['sign'](n,a['signKeyPair']['privateKey'],a['signAlgorithm']||'Falcon512');f['signature']={'value':o,'publicKey':a['signKeyPair']['publicKey'],'algorithm':a['signAlgorithm']||'Falcon512'};}const g={'wip':WIP_SCHEMA_URL,'payload':c,'meta':f},h=JSON['stringify'](g);if(h['length']>this['limits']['maxTotalSize'])throw new WipSizeError('Total\x20WIP\x20file\x20size\x20('+h['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['limits']['maxTotalSize']+'\x20bytes)');return g;}async['processImage'](a,b){const c=await this['resourceLoader']['load'](a['source']),d=detectMimeType(c);if(!d)throw new WipValidationError('Unsupported\x20image\x20format:\x20'+a['source']);let e=a['filename'];if(!e){if(a['source']['startsWith']('http')){const f=new URL(a['source']),g=f['pathname'];e=g['substring'](g['lastIndexOf']('/')+0x1)||'image-'+b;}else e=a['source']['substring'](a['source']['lastIndexOf']('/')+0x1)||'image-'+b;}return{'id':a['id']||generateId('img'),'type':d,'data':uint8ArrayToBase64(c),'filename':e};}async['sign'](a,b,c){if(c!=='Falcon512')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+c);const {Falcon512Keypair:d}=await import('../../keypairs/falcon512/index.js'),e=d['fromSecretKey'](b),f=await e['sign'](new TextEncoder()['encode'](a));return uint8ArrayToBase64(f);}async['verify'](a){try{if(!a['wip']||!a['payload']||!a['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure'};if(a['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+a['meta']['type']};const b={'wip':a['wip'],'payload':a['payload']},c=computeHash(canonicalizeJson(b));if(c!==a['meta']['hash'])return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered'};const d=[];if(a['meta']['signature']){const {signature:e,...f}=a['meta'],g=computeHash(canonicalizeJson(f)),h=Array['isArray'](a['meta']['signature'])?a['meta']['signature']:[a['meta']['signature']];for(const i of h){const j=await this['verifySignature'](g,i['value'],i['publicKey'],i['algorithm']);d['push']({'address':i['address'],'valid':j});if(!j)return{'valid':![],'error':'Invalid\x20signature','signatures':d};}}return{'valid':!![],'signatures':d};}catch(k){return{'valid':![],'error':'Verification\x20error:\x20'+k};}}async['verifySignature'](a,b,c,d){if(d!=='Falcon512')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+d);try{const {Falcon512PublicKey:e}=await import('../../keypairs/falcon512/publickey.js');let f;if(c['startsWith']('0x')){const i=Buffer['from'](c['slice'](0x2),'hex');if(i['length']===0x382)f=i['slice'](0x1);else i['length']===0x381?f=i:f=i;}else try{const j=Buffer['from'](c,'base64');j['length']===0x382?f=j['slice'](0x1):f=j;}catch{f=Buffer['from'](c,'base64');}const g=new e(f),h=Uint8Array['from'](Buffer['from'](b,'base64'));return await g['verify'](new TextEncoder()['encode'](a),h);}catch(k){return console['error']('Signature\x20verification\x20error:',k),![];}}async['toHtml'](a,b={}){const {title:title='WIP\x20Document',theme:theme='light'}=b,{payload:c,meta:d}=a,e=o=>{return o['replace'](/&/g,'&')['replace'](/</g,'<')['replace'](/>/g,'>')['replace'](/"/g,'"')['replace'](/'/g,''');},f=(o,p)=>{switch(p){case'html':return o;case'markdown':return o['replace'](/\*\*(.+?)\*\*/g,'<strong>$1</strong>')['replace'](/\*(.+?)\*/g,'<em>$1</em>')['replace'](/\n/g,'<br>');case'plain':default:return e(o)['replace'](/\n/g,'<br>');}},g=theme==='dark'?'#1a1a1a':'#ffffff',h=theme==='dark'?'#e0e0e0':'#333333',i=theme==='dark'?'#444444':'#e0e0e0',j='#4caf50',k='#ff9800',l=await this['verify'](a),m=l['valid']?'<span\x20style=\x22background:\x20'+j+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>✓\x20Verified</span>':'<span\x20style=\x22background:\x20'+k+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>⚠\x20Tampered</span>',n=c['media']['map'](o=>'\x0a\x09\x09\x09\x09<div\x20style=\x22margin:\x2016px\x200;\x20border:\x201px\x20solid\x20'+i+';\x20border-radius:\x208px;\x20overflow:\x20hidden;\x22>\x0a\x09\x09\x09\x09\x09<img\x20src=\x22data:'+o['type']+';base64,'+o['data']+'\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20style=\x22max-width:\x20100%;\x20height:\x20auto;\x20display:\x20block;\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20alt=\x22'+e(o['filename']||o['id'])+'\x22\x20/>\x0a\x09\x09\x09\x09\x09'+(o['filename']?'<div\x20style=\x22padding:\x208px;\x20font-size:\x2012px;\x20color:\x20#666;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-top:\x201px\x20solid\x20'+i+';\x22>'+e(o['filename'])+'</div>':'')+'\x0a\x09\x09\x09\x09</div>\x0a\x09\x09\x09')['join']('');return'<!DOCTYPE\x20html>\x0a<html\x20lang=\x22en\x22>\x0a<head>\x0a\x20\x20\x20\x20<meta\x20charset=\x22UTF-8\x22>\x0a\x20\x20\x20\x20<meta\x20name=\x22viewport\x22\x20content=\x22width=device-width,\x20initial-scale=1.0\x22>\x0a\x20\x20\x20\x20<title>'+e(title)+'</title>\x0a</head>\x0a<body\x20style=\x22margin:\x200;\x20padding:\x2020px;\x20font-family:\x20-apple-system,\x20BlinkMacSystemFont,\x20\x27Segoe\x20UI\x27,\x20Roboto,\x20sans-serif;\x20background:\x20'+g+';\x20color:\x20'+h+';\x20line-height:\x201.6;\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22max-width:\x20800px;\x20margin:\x200\x20auto;\x20background:\x20'+(theme==='dark'?'#252525':'#ffffff')+';\x20border-radius:\x2012px;\x20box-shadow:\x200\x202px\x208px\x20rgba(0,0,0,0.1);\x20overflow:\x20hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2020px\x2024px;\x20border-bottom:\x201px\x20solid\x20'+i+';\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<h1\x20style=\x22margin:\x200;\x20font-size:\x2020px;\x20font-weight:\x20600;\x22>'+e(title)+'</h1>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2012px;\x20color:\x20#666;\x20margin-top:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20WIP\x20v'+d['version']+'\x20•\x20'+new Date(d['created'])['toLocaleString']()+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+m+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20#999;\x20margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-radius:\x204px;\x20font-style:\x20italic;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Important\x20Note:\x20This\x20page\x20is\x20for\x20document\x20browsing\x20and\x20verification\x20reference\x20only.\x20Please\x20verify\x20the\x20document\x20integrity\x20through\x20the\x20API\x20using\x20the\x20WIP\x20file.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['signatures']&&l['signatures']['length']>0x0?'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a3f2a':'#e8f5e9')+';\x20border-radius:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20'+(theme==='dark'?'#81c784':'#2e7d32')+';\x20margin-bottom:\x204px;\x22>✓\x20Signature\x20Verification\x20('+l['signatures']['length']+'\x20signature'+(l['signatures']['length']>0x1?'s':'')+')</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+l['signatures']['map']((o,p)=>'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2010px;\x20color:\x20'+h+';\x20margin-left:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(p+0x1)+'.\x20'+(o['address']?e(o['address']['slice'](0x0,0x14))+'...':'Unknown')+':\x20'+(o['valid']?'<span\x20style=\x22color:\x20#4caf50;\x22>✓\x20Valid</span>':'<span\x20style=\x22color:\x20#f44336;\x22>✗\x20Invalid</span>')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20')['join']('')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2016px;\x20line-height:\x201.8;\x20margin-bottom:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+f(c['content']['text'],c['content']['format'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+n+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2016px\x2024px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f8f9fa')+';\x20border-top:\x201px\x20solid\x20'+i+';\x20font-size:\x2011px;\x20color:\x20#666;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x20flex-wrap:\x20wrap;\x20gap:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<strong>Hash:</strong>\x20<code\x20style=\x22background:\x20'+(theme==='dark'?'#333':'#e9ecef')+';\x20padding:\x202px\x206px;\x20border-radius:\x203px;\x22>'+e(d['hash'])+'</code>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['valid']?'Content\x20integrity\x20verified':'Verification\x20failed:\x20'+e(l['error']||'Unknown\x20error'))+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a</body>\x0a</html>';}['stringify'](a,b=!![]){return b?JSON['stringify'](a,null,0x2):JSON['stringify'](a);}['parse'](a){try{const b=JSON['parse'](a);if(!b['wip']||!b['payload']||!b['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');return b;}catch(c){if(c instanceof WipError)throw c;throw new WipValidationError('Failed\x20to\x20parse\x20WIP\x20file:\x20'+c);}}async['load'](a){const b=await this['resourceLoader']['load'](a),c=new TextDecoder()['decode'](b);return this['parse'](c);}['getHash'](a){const b=a['meta']['hash'];if(b['includes'](':'))return b['split'](':')[0x1];return b;}['extractImages'](a,b){!a179a['existsSync'](b)&&a179a['mkdirSync'](b,{'recursive':!![]});const c=[];for(const d of a['payload']['media']){const e=getExtensionFromMimeType(d['type']),f=d['filename']||d['id']+'.'+e,g=a179b['join'](b,f),h=Buffer['from'](base64ToUint8Array(d['data']));a179a['writeFileSync'](g,h),c['push'](g);}return c;}['save'](a,b,c=!![]){const d=a179b['dirname'](b);!a179a['existsSync'](d)&&a179a['mkdirSync'](d,{'recursive':!![]}),a179a['writeFileSync'](b,this['stringify'](a,c),'utf-8');}['getLimits'](){return{...this['limits']};}['setLimits'](a){this['limits']={...this['limits'],...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}}export async function createWip(a,b){const c=new WIP(b);return c['create'](a);}export async function verifyWip(a,b){if(b!==undefined){const e=a['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),f=b['toLowerCase']()['replace'](/^sha256:/,'');if(e!==f)return{'valid':![],'error':'Hash\x20mismatch'};}const c=new WIP(),d=await c['verify'](a);return{'valid':d['valid'],'error':d['error']};}export async function wipToHtml(a,b){const c=new WIP();return c['toHtml'](a,b);}export async function loadWip(a,b){const c=new WIP(b);return c['load'](a);}export async function generate_wip(a,b){const c=new WIP(DEFAULT_LIMITS);let d=await c['create']({'text':a['markdown_text'],'textFormat':'markdown','images':a['images']});if(a['account']){const {Account:e}=await import('./account.js'),f=await e['Instance']()['get_address'](a['account']);if(!f)throw new WipValidationError('Account\x20not\x20found:\x20'+a['account']);const {signature:g,...h}=d['meta'],i=computeHash(canonicalizeJson(h)),j=await e['Instance']()['sign'](f,i),k=await e['Instance']()['get'](f);if(!k||!k['pubkey'])throw new WipValidationError('Cannot\x20get\x20public\x20key\x20for\x20account:\x20'+f);let l;if(k['pubkey']['startsWith']('0x')){const p=Buffer['from'](k['pubkey']['slice'](0x2),'hex');if(p['length']===0x382)l=p['slice'](0x1)['toString']('base64');else{if(p['length']===0x381)l=p['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+p['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else l=k['pubkey'];const m=Buffer['from'](j['slice'](0x2),'hex')['toString']('base64'),n={'value':m,'publicKey':l,'algorithm':'Falcon512','address':f};let o;d['meta']['signature']?o=Array['isArray'](d['meta']['signature'])?[...d['meta']['signature'],n]:[d['meta']['signature'],n]:o=[n],d={...d,'meta':{...d['meta'],'signature':o}};}return c['save'](d,b,!![]),b;}export async function verify_wip(a,b,c){const d=new WIP();let e;try{e=await d['load'](a);}catch(k){return{'valid':![],'error':'Failed\x20to\x20load\x20WIP\x20file:\x20'+k,'hashValid':![],'hasSignature':![]};}if(!e['wip']||!e['payload']||!e['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure','hashValid':![],'hasSignature':![]};if(e['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+e['meta']['type'],'hashValid':![],'hasSignature':!!e['meta']['signature']};if(b!==undefined){const l=e['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),m=b['toLowerCase']()['replace'](/^sha256:/,'');if(l!==m)return{'valid':![],'error':'Hash\x20mismatch','hashValid':![],'hasSignature':!!e['meta']['signature']};}if(c&&!e['meta']['signature'])return{'valid':![],'error':'Signature\x20required\x20but\x20WIP\x20file\x20has\x20no\x20signature','hashValid':!![],'hasSignature':![]};const f={'wip':e['wip'],'payload':e['payload']},g=computeHash(canonicalizeJson(f)),h=g===e['meta']['hash'];if(!h)return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered','hashValid':![],'hasSignature':!!e['meta']['signature']};let i;const j=[];if(e['meta']['signature']){const {signature:n,...o}=e['meta'],p=computeHash(canonicalizeJson(o)),q=Array['isArray'](e['meta']['signature'])?e['meta']['signature']:[e['meta']['signature']];let r=!![];for(const s of q){const t=await d['verifySignature'](p,s['value'],s['publicKey'],s['algorithm']);let u;try{const {Falcon512PublicKey:v}=await import('../../keypairs/falcon512/publickey.js'),w=new v(s['publicKey']);u=w['toWAddress']();}catch{}j['push']({'publicKey':s['publicKey'],'address':u,'valid':t}),!t&&(r=![]);}i=r;if(!i){const x=j['filter'](y=>!y['valid']&&y['address'])['map'](y=>y['address']);return{'valid':![],'error':'Signatures\x20from\x20the\x20following\x20addresses\x20are\x20invalid:\x20'+x['join'](',\x20'),'hashValid':!![],'signatureValid':![],'hasSignature':!![],'signatures':j};}}return{'valid':!![],'hashValid':!![],'signatureValid':i,'hasSignature':!!e['meta']['signature'],'signatures':j['length']>0x0?j:undefined};}export async function sign_wip(a,b,c){const d=new WIP(),e=await d['load'](a);if(!e['wip']||!e['payload']||!e['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');if(e['meta']['type']!=='wip')throw new WipValidationError('Invalid\x20meta.type:\x20'+e['meta']['type']);const {Account:f}=await import('./account.js'),g=await f['Instance']()['get_address'](b);if(!g)throw new WipValidationError('Account\x20not\x20found:\x20'+b);const {signature:h,...i}=e['meta'],j=computeHash(canonicalizeJson(i)),k=await f['Instance']()['signData'](g,j);let l;const m=k['publicKey'];if(m['startsWith']('0x')){const r=Buffer['from'](m['slice'](0x2),'hex');if(r['length']===0x382)l=r['slice'](0x1)['toString']('base64');else{if(r['length']===0x381)l=r['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+r['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else l=m;const n={'value':Buffer['from'](k['signature']['slice'](0x2),'hex')['toString']('base64'),'publicKey':l,'algorithm':'Falcon512','address':k['address']};let o;if(e['meta']['signature']){const s=Array['isArray'](e['meta']['signature'])?[...e['meta']['signature']]:[e['meta']['signature']],t=s['findIndex'](u=>u['publicKey']===l);t>=0x0?(s[t]=n,o=s):o=[...s,n];}else o=[n];const p={...e,'meta':{...e['meta'],'signature':o}};let q;if(c)q=c;else{const u=a179b['dirname'](a),v=a179b['extname'](a),w=a179b['basename'](a,v);q=a179b['join'](u,'signed_'+w+v);}return d['save'](p,q,!![]),q;}export async function wip2html(a,b={}){const c=await import('fs'),d=await import('path'),e=c['statSync'](a);if(e['isFile']()){const f=new WIP(),g=await f['load'](a),h=await f['toHtml'](g,b);if(b['outputPath'])return c['writeFileSync'](b['outputPath'],h),b['outputPath'];const i=d['dirname'](a),j=d['extname'](a),k=d['basename'](a,j),l=d['join'](i,k+'.html');return c['writeFileSync'](l,h),l;}else{if(e['isDirectory']()){const m=c['readdirSync'](a),n=m['filter'](q=>q['endsWith']('.wip'));if(n['length']===0x0)throw new WipValidationError('No\x20.wip\x20files\x20found\x20in\x20directory:\x20'+a);const o=[],p=new WIP();for(const q of n){const r=d['join'](a,q),s=await p['load'](r),t=await p['toHtml'](s,b),u=q['replace']('.wip','.html'),v=b['outputPath']?d['join'](b['outputPath'],u):d['join'](a,u),w=d['dirname'](v);!c['existsSync'](w)&&c['mkdirSync'](w,{'recursive':!![]}),c['writeFileSync'](v,t),o['push'](v);}return o;}else throw new WipValidationError('Invalid\x20path:\x20'+a);}}export default WIP;
|
|
1
|
+
import{sha256}from'@noble/hashes/sha256';import{bytesToHex}from'@noble/hashes/utils';import*as a180a from'fs';import*as a180b from'path';import*as a180c from'https';import*as a180d from'http';const WIP_SCHEMA_URL='https://github.com/wowok-ai/docs/blob/main/WIP.md',WIP_VERSION='1.0.0';export const DEFAULT_LIMITS={'maxImageSize':0x2*0x400*0x400,'maxTotalSize':0xa*0x400*0x400,'maxImageCount':0xa,'maxTextLength':0x2710};export class WipError extends Error{constructor(a){super(a),this['name']='WipError';}}export class WipValidationError extends WipError{constructor(a){super(a),this['name']='WipValidationError';}}export class WipSizeError extends WipError{constructor(a){super(a),this['name']='WipSizeError';}}function detectMimeType(a){if(a['length']>=0x4&&a[0x0]===0x89&&a[0x1]===0x50&&a[0x2]===0x4e&&a[0x3]===0x47)return'image/png';if(a['length']>=0x3&&a[0x0]===0xff&&a[0x1]===0xd8&&a[0x2]===0xff)return'image/jpeg';if(a['length']>=0x6&&a[0x0]===0x47&&a[0x1]===0x49&&a[0x2]===0x46)return'image/gif';if(a['length']>=0xc&&a[0x0]===0x52&&a[0x1]===0x49&&a[0x2]===0x46&&a[0x3]===0x46&&a[0x8]===0x57&&a[0x9]===0x45&&a[0xa]===0x42&&a[0xb]===0x50)return'image/webp';return null;}function uint8ArrayToBase64(a){let b='';const c=a['length'];for(let d=0x0;d<c;d++){b+=String['fromCharCode'](a[d]);}return btoa(b);}function base64ToUint8Array(a){const b=atob(a),c=b['length'],d=new Uint8Array(c);for(let e=0x0;e<c;e++){d[e]=b['charCodeAt'](e);}return d;}function canonicalizeJson(a){if(a===null||typeof a!=='object')return JSON['stringify'](a);if(Array['isArray'](a))return'['+a['map'](canonicalizeJson)['join'](',')+']';const b=a,c=Object['keys'](b)['sort'](),d=c['map'](e=>'\x22'+e+'\x22:'+canonicalizeJson(b[e]));return'{'+d['join'](',')+'}';}function computeHash(a){const b=sha256(new TextEncoder()['encode'](a));return bytesToHex(b);}function generateId(a){const b=Date['now']()['toString'](0x24),c=Math['random']()['toString'](0x24)['substring'](0x2,0x8);return a+'-'+b+'-'+c;}function getExtensionFromMimeType(a){const b={'image/png':'png','image/jpeg':'jpg','image/gif':'gif','image/webp':'webp'};return b[a]||'bin';}class ResourceLoader{['maxSize'];constructor(a){this['maxSize']=a;}async['load'](a){if(!a||a['trim']()==='')throw new WipError('WIP\x20file\x20path\x20cannot\x20be\x20empty');if(a['startsWith']('data:'))return this['loadFromDataUrl'](a);if(a['startsWith']('http://')||a['startsWith']('https://'))return this['loadFromNetwork'](a);return this['loadFromFile'](a);}['loadFromDataUrl'](a){const b=a['match'](/^data:image\/(\w+);base64,(.+)$/);if(!b)throw new WipValidationError('Invalid\x20data\x20URL\x20format:\x20'+a['substring'](0x0,0x32)+'...');const c=b[0x2];try{return base64ToUint8Array(c);}catch(d){throw new WipError('Failed\x20to\x20decode\x20data\x20URL:\x20'+d);}}async['loadFromNetwork'](a){return new Promise((b,c)=>{const d=setTimeout(()=>{c(new WipError('Network\x20timeout\x20while\x20fetching:\x20'+a));},0x7530),e=a['startsWith']('https:'),f=e?a180c:a180d,g={'headers':{'Accept':'application/json,*/*'}};e&&(g['rejectUnauthorized']=![]);const h=f['get'](a,g,i=>{clearTimeout(d);if(i['statusCode']!==0xc8){c(new WipError('Failed\x20to\x20fetch:\x20'+i['statusCode']+'\x20'+i['statusMessage']));return;}const j=i['headers']['content-length'];if(j&&parseInt(j)>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+j+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}const k=[];i['on']('data',l=>{k['push'](l);}),i['on']('end',()=>{const l=Buffer['concat'](k);if(l['length']>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+l['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}b(new Uint8Array(l));}),i['on']('error',l=>{c(new WipError('Network\x20error:\x20'+l['message']));});});h['on']('error',i=>{clearTimeout(d),c(new WipError('Network\x20error:\x20'+i['message']));});});}['loadFromFile'](a){const b=a180b['resolve'](a);if(!a180a['existsSync'](b))throw new WipError('File\x20not\x20found:\x20'+b);const c=a180a['statSync'](b);if(!c['isFile']())throw new WipError('Path\x20is\x20not\x20a\x20file:\x20'+b);if(c['size']>this['maxSize'])throw new WipSizeError('File\x20'+b+'\x20size\x20('+c['size']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)');const d=a180a['readFileSync'](b);return new Uint8Array(d);}}export class WIP{['limits'];['resourceLoader'];constructor(a={}){this['limits']={...DEFAULT_LIMITS,...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}async['create'](a){if(a['text']['length']>this['limits']['maxTextLength'])throw new WipSizeError('Text\x20length\x20('+a['text']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxTextLength']+')');const b=[];if(a['images']&&a['images']['length']>0x0){if(a['images']['length']>this['limits']['maxImageCount'])throw new WipSizeError('Image\x20count\x20('+a['images']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxImageCount']+')');for(let j=0x0;j<a['images']['length'];j++){const k=await this['processImage'](a['images'][j],j);b['push'](k);}}const c={'content':{'text':a['text'],'format':a['textFormat']||'plain'},'media':b},d={'wip':WIP_SCHEMA_URL,'payload':c},e=computeHash(canonicalizeJson(d)),f={'type':'wip','version':WIP_VERSION,'created':new Date()['toISOString'](),'hash':e,'algorithm':'sha256'};if(a['signKeyPair']){const {signature:l,...m}=f,n=computeHash(canonicalizeJson(m)),o=await this['sign'](n,a['signKeyPair']['privateKey'],a['signAlgorithm']||'Falcon512');f['signature']={'value':o,'publicKey':a['signKeyPair']['publicKey'],'algorithm':a['signAlgorithm']||'Falcon512'};}const g={'wip':WIP_SCHEMA_URL,'payload':c,'meta':f},h=JSON['stringify'](g);if(h['length']>this['limits']['maxTotalSize'])throw new WipSizeError('Total\x20WIP\x20file\x20size\x20('+h['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['limits']['maxTotalSize']+'\x20bytes)');return g;}async['processImage'](a,b){const c=await this['resourceLoader']['load'](a['source']),d=detectMimeType(c);if(!d)throw new WipValidationError('Unsupported\x20image\x20format:\x20'+a['source']);let e=a['filename'];if(!e){if(a['source']['startsWith']('http')){const f=new URL(a['source']),g=f['pathname'];e=g['substring'](g['lastIndexOf']('/')+0x1)||'image-'+b;}else e=a['source']['substring'](a['source']['lastIndexOf']('/')+0x1)||'image-'+b;}return{'id':a['id']||generateId('img'),'type':d,'data':uint8ArrayToBase64(c),'filename':e};}async['sign'](a,b,c){if(c!=='Falcon512')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+c);const {Falcon512Keypair:d}=await import('../../keypairs/falcon512/index.js'),e=d['fromSecretKey'](b),f=await e['sign'](new TextEncoder()['encode'](a));return uint8ArrayToBase64(f);}async['verify'](a){try{if(!a['wip']||!a['payload']||!a['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure'};if(a['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+a['meta']['type']};const b={'wip':a['wip'],'payload':a['payload']},c=computeHash(canonicalizeJson(b));if(c!==a['meta']['hash'])return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered'};const d=[];if(a['meta']['signature']){const {signature:e,...f}=a['meta'],g=computeHash(canonicalizeJson(f)),h=Array['isArray'](a['meta']['signature'])?a['meta']['signature']:[a['meta']['signature']];for(const i of h){const j=await this['verifySignature'](g,i['value'],i['publicKey'],i['algorithm']);d['push']({'address':i['address'],'valid':j});if(!j)return{'valid':![],'error':'Invalid\x20signature','signatures':d};}}return{'valid':!![],'signatures':d};}catch(k){return{'valid':![],'error':'Verification\x20error:\x20'+k};}}async['verifySignature'](a,b,c,d){if(d!=='Falcon512')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+d);try{const {Falcon512PublicKey:e}=await import('../../keypairs/falcon512/publickey.js');let f;if(c['startsWith']('0x')){const i=Buffer['from'](c['slice'](0x2),'hex');if(i['length']===0x382)f=i['slice'](0x1);else i['length']===0x381?f=i:f=i;}else try{const j=Buffer['from'](c,'base64');j['length']===0x382?f=j['slice'](0x1):f=j;}catch{f=Buffer['from'](c,'base64');}const g=new e(f),h=Uint8Array['from'](Buffer['from'](b,'base64'));return await g['verify'](new TextEncoder()['encode'](a),h);}catch(k){return console['error']('Signature\x20verification\x20error:',k),![];}}async['toHtml'](a,b={}){const {title:title='WIP\x20Document',theme:theme='light'}=b,{payload:c,meta:d}=a,e=o=>{return o['replace'](/&/g,'&')['replace'](/</g,'<')['replace'](/>/g,'>')['replace'](/"/g,'"')['replace'](/'/g,''');},f=(o,p)=>{switch(p){case'html':return o;case'markdown':return o['replace'](/\*\*(.+?)\*\*/g,'<strong>$1</strong>')['replace'](/\*(.+?)\*/g,'<em>$1</em>')['replace'](/\n/g,'<br>');case'plain':default:return e(o)['replace'](/\n/g,'<br>');}},g=theme==='dark'?'#1a1a1a':'#ffffff',h=theme==='dark'?'#e0e0e0':'#333333',i=theme==='dark'?'#444444':'#e0e0e0',j='#4caf50',k='#ff9800',l=await this['verify'](a),m=l['valid']?'<span\x20style=\x22background:\x20'+j+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>✓\x20Verified</span>':'<span\x20style=\x22background:\x20'+k+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>⚠\x20Tampered</span>',n=c['media']['map'](o=>'\x0a\x09\x09\x09\x09<div\x20style=\x22margin:\x2016px\x200;\x20border:\x201px\x20solid\x20'+i+';\x20border-radius:\x208px;\x20overflow:\x20hidden;\x22>\x0a\x09\x09\x09\x09\x09<img\x20src=\x22data:'+o['type']+';base64,'+o['data']+'\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20style=\x22max-width:\x20100%;\x20height:\x20auto;\x20display:\x20block;\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20alt=\x22'+e(o['filename']||o['id'])+'\x22\x20/>\x0a\x09\x09\x09\x09\x09'+(o['filename']?'<div\x20style=\x22padding:\x208px;\x20font-size:\x2012px;\x20color:\x20#666;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-top:\x201px\x20solid\x20'+i+';\x22>'+e(o['filename'])+'</div>':'')+'\x0a\x09\x09\x09\x09</div>\x0a\x09\x09\x09')['join']('');return'<!DOCTYPE\x20html>\x0a<html\x20lang=\x22en\x22>\x0a<head>\x0a\x20\x20\x20\x20<meta\x20charset=\x22UTF-8\x22>\x0a\x20\x20\x20\x20<meta\x20name=\x22viewport\x22\x20content=\x22width=device-width,\x20initial-scale=1.0\x22>\x0a\x20\x20\x20\x20<title>'+e(title)+'</title>\x0a</head>\x0a<body\x20style=\x22margin:\x200;\x20padding:\x2020px;\x20font-family:\x20-apple-system,\x20BlinkMacSystemFont,\x20\x27Segoe\x20UI\x27,\x20Roboto,\x20sans-serif;\x20background:\x20'+g+';\x20color:\x20'+h+';\x20line-height:\x201.6;\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22max-width:\x20800px;\x20margin:\x200\x20auto;\x20background:\x20'+(theme==='dark'?'#252525':'#ffffff')+';\x20border-radius:\x2012px;\x20box-shadow:\x200\x202px\x208px\x20rgba(0,0,0,0.1);\x20overflow:\x20hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2020px\x2024px;\x20border-bottom:\x201px\x20solid\x20'+i+';\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<h1\x20style=\x22margin:\x200;\x20font-size:\x2020px;\x20font-weight:\x20600;\x22>'+e(title)+'</h1>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2012px;\x20color:\x20#666;\x20margin-top:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20WIP\x20v'+d['version']+'\x20•\x20'+new Date(d['created'])['toLocaleString']()+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+m+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20#999;\x20margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-radius:\x204px;\x20font-style:\x20italic;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Important\x20Note:\x20This\x20page\x20is\x20for\x20document\x20browsing\x20and\x20verification\x20reference\x20only.\x20Please\x20verify\x20the\x20document\x20integrity\x20through\x20the\x20API\x20using\x20the\x20WIP\x20file.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['signatures']&&l['signatures']['length']>0x0?'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a3f2a':'#e8f5e9')+';\x20border-radius:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20'+(theme==='dark'?'#81c784':'#2e7d32')+';\x20margin-bottom:\x204px;\x22>✓\x20Signature\x20Verification\x20('+l['signatures']['length']+'\x20signature'+(l['signatures']['length']>0x1?'s':'')+')</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+l['signatures']['map']((o,p)=>'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2010px;\x20color:\x20'+h+';\x20margin-left:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(p+0x1)+'.\x20'+(o['address']?e(o['address']['slice'](0x0,0x14))+'...':'Unknown')+':\x20'+(o['valid']?'<span\x20style=\x22color:\x20#4caf50;\x22>✓\x20Valid</span>':'<span\x20style=\x22color:\x20#f44336;\x22>✗\x20Invalid</span>')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20')['join']('')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2016px;\x20line-height:\x201.8;\x20margin-bottom:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+f(c['content']['text'],c['content']['format'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+n+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2016px\x2024px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f8f9fa')+';\x20border-top:\x201px\x20solid\x20'+i+';\x20font-size:\x2011px;\x20color:\x20#666;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x20flex-wrap:\x20wrap;\x20gap:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<strong>Hash:</strong>\x20<code\x20style=\x22background:\x20'+(theme==='dark'?'#333':'#e9ecef')+';\x20padding:\x202px\x206px;\x20border-radius:\x203px;\x22>'+e(d['hash'])+'</code>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['valid']?'Content\x20integrity\x20verified':'Verification\x20failed:\x20'+e(l['error']||'Unknown\x20error'))+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a</body>\x0a</html>';}['stringify'](a,b=!![]){return b?JSON['stringify'](a,null,0x2):JSON['stringify'](a);}['parse'](a){try{const b=JSON['parse'](a);if(!b['wip']||!b['payload']||!b['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');return b;}catch(c){if(c instanceof WipError)throw c;throw new WipValidationError('Failed\x20to\x20parse\x20WIP\x20file:\x20'+c);}}async['load'](a){const b=await this['resourceLoader']['load'](a),c=new TextDecoder()['decode'](b);return this['parse'](c);}['getHash'](a){const b=a['meta']['hash'];if(b['includes'](':'))return b['split'](':')[0x1];return b;}['extractImages'](a,b){!a180a['existsSync'](b)&&a180a['mkdirSync'](b,{'recursive':!![]});const c=[];for(const d of a['payload']['media']){const e=getExtensionFromMimeType(d['type']),f=d['filename']||d['id']+'.'+e,g=a180b['join'](b,f),h=Buffer['from'](base64ToUint8Array(d['data']));a180a['writeFileSync'](g,h),c['push'](g);}return c;}['save'](a,b,c=!![]){const d=a180b['dirname'](b);!a180a['existsSync'](d)&&a180a['mkdirSync'](d,{'recursive':!![]}),a180a['writeFileSync'](b,this['stringify'](a,c),'utf-8');}['getLimits'](){return{...this['limits']};}['setLimits'](a){this['limits']={...this['limits'],...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}}export async function createWip(a,b){const c=new WIP(b);return c['create'](a);}export async function verifyWip(a,b){if(b!==undefined){const e=a['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),f=b['toLowerCase']()['replace'](/^sha256:/,'');if(e!==f)return{'valid':![],'error':'Hash\x20mismatch'};}const c=new WIP(),d=await c['verify'](a);return{'valid':d['valid'],'error':d['error']};}export async function wipToHtml(a,b){const c=new WIP();return c['toHtml'](a,b);}export async function loadWip(a,b){const c=new WIP(b);return c['load'](a);}export async function generate_wip(a,b){const c=new WIP(DEFAULT_LIMITS);let d=await c['create']({'text':a['markdown_text'],'textFormat':'markdown','images':a['images']});if(a['account']){const {Account:e}=await import('./account.js'),f=await e['Instance']()['get_address'](a['account']);if(!f)throw new WipValidationError('Account\x20not\x20found:\x20'+a['account']);const {signature:g,...h}=d['meta'],i=computeHash(canonicalizeJson(h)),j=await e['Instance']()['sign'](f,i),k=await e['Instance']()['get'](f);if(!k||!k['pubkey'])throw new WipValidationError('Cannot\x20get\x20public\x20key\x20for\x20account:\x20'+f);let l;if(k['pubkey']['startsWith']('0x')){const p=Buffer['from'](k['pubkey']['slice'](0x2),'hex');if(p['length']===0x382)l=p['slice'](0x1)['toString']('base64');else{if(p['length']===0x381)l=p['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+p['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else l=k['pubkey'];const m=Buffer['from'](j['slice'](0x2),'hex')['toString']('base64'),n={'value':m,'publicKey':l,'algorithm':'Falcon512','address':f};let o;d['meta']['signature']?o=Array['isArray'](d['meta']['signature'])?[...d['meta']['signature'],n]:[d['meta']['signature'],n]:o=[n],d={...d,'meta':{...d['meta'],'signature':o}};}return c['save'](d,b,!![]),b;}export async function verify_wip(a,b,c){const d=new WIP();let e;try{e=await d['load'](a);}catch(k){return{'valid':![],'error':'Failed\x20to\x20load\x20WIP\x20file:\x20'+k,'hashValid':![],'hasSignature':![]};}if(!e['wip']||!e['payload']||!e['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure','hashValid':![],'hasSignature':![]};if(e['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+e['meta']['type'],'hashValid':![],'hasSignature':!!e['meta']['signature']};if(b!==undefined){const l=e['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),m=b['toLowerCase']()['replace'](/^sha256:/,'');if(l!==m)return{'valid':![],'error':'Hash\x20mismatch','hashValid':![],'hasSignature':!!e['meta']['signature']};}if(c&&!e['meta']['signature'])return{'valid':![],'error':'Signature\x20required\x20but\x20WIP\x20file\x20has\x20no\x20signature','hashValid':!![],'hasSignature':![]};const f={'wip':e['wip'],'payload':e['payload']},g=computeHash(canonicalizeJson(f)),h=g===e['meta']['hash'];if(!h)return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered','hashValid':![],'hasSignature':!!e['meta']['signature']};let i;const j=[];if(e['meta']['signature']){const {signature:n,...o}=e['meta'],p=computeHash(canonicalizeJson(o)),q=Array['isArray'](e['meta']['signature'])?e['meta']['signature']:[e['meta']['signature']];let r=!![];for(const s of q){const t=await d['verifySignature'](p,s['value'],s['publicKey'],s['algorithm']);let u;try{const {Falcon512PublicKey:v}=await import('../../keypairs/falcon512/publickey.js'),w=new v(s['publicKey']);u=w['toWAddress']();}catch{}j['push']({'publicKey':s['publicKey'],'address':u,'valid':t}),!t&&(r=![]);}i=r;if(!i){const x=j['filter'](y=>!y['valid']&&y['address'])['map'](y=>y['address']);return{'valid':![],'error':'Signatures\x20from\x20the\x20following\x20addresses\x20are\x20invalid:\x20'+x['join'](',\x20'),'hashValid':!![],'signatureValid':![],'hasSignature':!![],'signatures':j};}}return{'valid':!![],'hashValid':!![],'signatureValid':i,'hasSignature':!!e['meta']['signature'],'signatures':j['length']>0x0?j:undefined};}export async function sign_wip(a,b,c){const d=new WIP(),e=await d['load'](a);if(!e['wip']||!e['payload']||!e['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');if(e['meta']['type']!=='wip')throw new WipValidationError('Invalid\x20meta.type:\x20'+e['meta']['type']);const {Account:f}=await import('./account.js'),g=await f['Instance']()['get_address'](b);if(!g)throw new WipValidationError('Account\x20not\x20found:\x20'+b);const {signature:h,...i}=e['meta'],j=computeHash(canonicalizeJson(i)),k=await f['Instance']()['signData'](g,j);let l;const m=k['publicKey'];if(m['startsWith']('0x')){const r=Buffer['from'](m['slice'](0x2),'hex');if(r['length']===0x382)l=r['slice'](0x1)['toString']('base64');else{if(r['length']===0x381)l=r['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+r['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else l=m;const n={'value':Buffer['from'](k['signature']['slice'](0x2),'hex')['toString']('base64'),'publicKey':l,'algorithm':'Falcon512','address':k['address']};let o;if(e['meta']['signature']){const s=Array['isArray'](e['meta']['signature'])?[...e['meta']['signature']]:[e['meta']['signature']],t=s['findIndex'](u=>u['publicKey']===l);t>=0x0?(s[t]=n,o=s):o=[...s,n];}else o=[n];const p={...e,'meta':{...e['meta'],'signature':o}};let q;if(c)q=c;else{const u=a180b['dirname'](a),v=a180b['extname'](a),w=a180b['basename'](a,v);q=a180b['join'](u,'signed_'+w+v);}return d['save'](p,q,!![]),q;}export async function wip2html(a,b={}){const c=await import('fs'),d=await import('path'),e=c['statSync'](a);if(e['isFile']()){const f=new WIP(),g=await f['load'](a),h=await f['toHtml'](g,b);if(b['outputPath'])return c['writeFileSync'](b['outputPath'],h),b['outputPath'];const i=d['dirname'](a),j=d['extname'](a),k=d['basename'](a,j),l=d['join'](i,k+'.html');return c['writeFileSync'](l,h),l;}else{if(e['isDirectory']()){const m=c['readdirSync'](a),n=m['filter'](q=>q['endsWith']('.wip'));if(n['length']===0x0)throw new WipValidationError('No\x20.wip\x20files\x20found\x20in\x20directory:\x20'+a);const o=[],p=new WIP();for(const q of n){const r=d['join'](a,q),s=await p['load'](r),t=await p['toHtml'](s,b),u=q['replace']('.wip','.html'),v=b['outputPath']?d['join'](b['outputPath'],u):d['join'](a,u),w=d['dirname'](v);!c['existsSync'](w)&&c['mkdirSync'](w,{'recursive':!![]}),c['writeFileSync'](v,t),o['push'](v);}return o;}else throw new WipValidationError('Invalid\x20path:\x20'+a);}}export default WIP;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MessengerManager}from'./messenger-manager.js';import{Account}from'../local/account.js';import{W_ERROR,WErrors}from'../exception.js';import{LocalMark}from'../local/local.js';import{MessageStorage}from'./storage.js';import{MessengerError,MessengerErrorCode,CHAIN_PROOF_TYPE,MessageDirection}from'./types.js';import{createHash}from'crypto';import*as a182a from'fs';import*as a182b from'path';import{isValidU64}from'../common.js';import{verifySingleMerkleRoot,hashPlaintext,verifyFalcon512Signature}from'./crypto.js';import{canonicalizeJson}from'./utils.js';import{generateHtmlPage,getThemeColors}from'./templates/wts-html-template.js';import{GetAccountOrMark_Address,GetManyAccountOrMark_Address}from'../local/index.js';import{query_objects}from'../query/object.js';import{Messenger}from'./messenger.js';let managerInstance=null,isInitialized=![],startPromise=null,backgroundTimer=null;async function autoRegisterMessengerAccounts(){const a=await Account['Instance']()['list_messenger_accounts']();for(const b of a){if(!b['address']||!b['m'])continue;try{const c=new Messenger(b['address']);await c['initialize']();}catch(d){console['error']('Failed\x20to\x20initialize\x20account\x20'+b['address']+':',d);}}}export function getMessengerManager(){return!managerInstance&&(managerInstance=new MessengerManager()),!isInitialized&&(isInitialized=!![],startPromise=autoRegisterMessengerAccounts()['then'](()=>{return managerInstance['start']();})['catch'](a=>{return console['error']('Failed\x20to\x20auto-register\x20messenger\x20accounts:',a),managerInstance['start']();})['catch'](a=>{console['error']('Failed\x20to\x20auto-start\x20messenger\x20manager:',a);})),managerInstance;}function registerCleanupHandler(){const a=()=>{backgroundTimer&&(clearInterval(backgroundTimer),backgroundTimer=null),managerInstance&&managerInstance['stop']();};process['on']('exit',a),process['on']('SIGINT',()=>{a(),process['exit']();}),process['on']('SIGTERM',()=>{a(),process['exit']();});}registerCleanupHandler();export async function watch_conversations(a){const b=await Account['Instance']()['get_address'](a?.['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'watch_conversations.account\x20'+a?.['account']);const c=b['toLowerCase'](),d=getMessengerManager();startPromise&&await startPromise;const e=await d['ensureAccountReady'](b);await e['messenger']['pullMessages']();const f=new MessageStorage(c),g=f['getAllMessages'](c),h=new Map(),i=a?.['previewMessageCount']??0x2,j=a?.['skipAutoMarkViewed']??![];for(const n of g){const o=n['fromAddress']['toLowerCase']()===c?n['toAddress']:n['fromAddress'];!h['has'](o)&&h['set'](o,{'peerAddress':o,'lastMessageAt':n['createdAt'],'messageCount':0x0,'unreadCount':0x0,'lastMessagePreview':n['plaintext'],'messages':[]});const p=h['get'](o);p['messages']['push'](n),p['messageCount']++,n['createdAt']>p['lastMessageAt']&&(p['lastMessageAt']=n['createdAt'],p['lastMessagePreview']=n['plaintext']),n['direction']===MessageDirection['RECEIVED']&&n['viewedAt']===undefined&&p['unreadCount']++;}const k=[];for(const [,q]of h){if(a?.['startTime']!==undefined&&q['lastMessageAt']<a['startTime'])continue;if(a?.['endTime']!==undefined&&q['lastMessageAt']>a['endTime'])continue;if(a?.['unreadOnly']&&q['unreadCount']===0x0)continue;const r=[];if(i>0x0){const s=q['messages']['sort']((u,v)=>v['createdAt']-u['createdAt']),t=s['slice'](0x0,i);r['push'](...t['reverse']());if(!j){const u=t['filter'](v=>v['direction']===MessageDirection['RECEIVED']&&v['viewedAt']===undefined)['map'](v=>v['messageId']);u['length']>0x0&&f['updateMessagesViewed'](u);}}k['push']({'peerAddress':q['peerAddress'],'lastMessageAt':q['lastMessageAt'],'messageCount':q['messageCount'],'unreadCount':q['unreadCount'],'lastMessagePreview':q['lastMessagePreview'],...i>0x0&&{'previewMessages':r}});}const l=a?.['sortBy']??'lastMessageAt',m=a?.['sortOrder']??'desc';return k['sort']((v,w)=>{let x=0x0;switch(l){case'lastMessageAt':x=v['lastMessageAt']-w['lastMessageAt'];break;case'unreadCount':x=v['unreadCount']-w['unreadCount'];break;case'messageCount':x=v['messageCount']-w['messageCount'];break;}return m==='asc'?x:-x;}),k;}export async function mark_messages_as_viewed(a,b){if(!a||a['length']===0x0)return 0x0;const c=await Account['Instance']()['get_address'](b);!c&&W_ERROR(WErrors['AccountNotFound'],'mark_messages_as_viewed.account\x20'+b);const d=c['toLowerCase'](),e=new MessageStorage(d);return e['updateMessagesViewed'](a);}export async function mark_conversation_as_viewed(a,b){const c=await Account['Instance']()['get_address'](b);!c&&W_ERROR(WErrors['AccountNotFound'],'mark_conversation_as_viewed.account\x20'+b);const d=c['toLowerCase'](),e=await GetAccountOrMark_Address(a);!e&&W_ERROR(WErrors['AccountNotFound'],'mark_conversation_as_viewed.peerAddress\x20'+a+'\x20is\x20not\x20a\x20valid\x20account/address');const f=e['toLowerCase'](),g=new MessageStorage(d),h=g['getMessagesBySession'](d,f),i=h['filter'](j=>j['direction']===MessageDirection['RECEIVED']&&j['viewedAt']===undefined)['map'](j=>j['messageId']);if(i['length']===0x0)return 0x0;return g['updateMessagesViewed'](i);}export async function send_message(a,b,c,d){const e=await Account['Instance']()['get_address'](a);!e&&W_ERROR(WErrors['AccountNotFound'],'send_message.from\x20'+a);const f=await GetAccountOrMark_Address(b);!f&&W_ERROR(WErrors['AccountNotFound'],'send_message.to\x20'+b+'\x20is\x20not\x20a\x20valid\x20account/address');d?.['guardAddress']!=null&&d?.['passportAddress']!=null&&([d['guardAddress'],d['passportAddress']]=await LocalMark['Instance']()['get_many_address']([d['guardAddress'],d['passportAddress']]),(!d['guardAddress']||!d['passportAddress'])&&W_ERROR(WErrors['AccountNotFound'],'send_message.guardAddress\x20or\x20passportAddress\x20not\x20found'));const g=getMessengerManager();return startPromise&&await startPromise,g['send'](e,f,c,d);}export async function send_file(a,b,c,d){const e=await Account['Instance']()['get_address'](a);!e&&W_ERROR(WErrors['AccountNotFound'],'send_file.from\x20'+a);const f=await GetAccountOrMark_Address(b);!f&&W_ERROR(WErrors['AccountNotFound'],'send_file.to\x20'+b+'\x20is\x20not\x20a\x20valid\x20account/address');d?.['guardAddress']!=null&&d?.['passportAddress']!=null&&([d['guardAddress'],d['passportAddress']]=await LocalMark['Instance']()['get_many_address']([d['guardAddress'],d['passportAddress']]),(!d['guardAddress']||!d['passportAddress'])&&W_ERROR(WErrors['AccountNotFound'],'send_file.guardAddress\x20or\x20passportAddress\x20not\x20found'));const g=getMessengerManager();return startPromise&&await startPromise,g['send_file'](e,f,c,d);}export async function watch_messages(a){a?.['account']!==undefined&&(a['account']=await Account['Instance']()['get_address'](a['account']),!a['account']&&W_ERROR(WErrors['AccountNotFound'],'watch_messages.account\x20'+a['account']));a?.['customListFilter']?.['includeAddresses']!=null&&(a['customListFilter']['includeAddresses']=(await Account['Instance']()['get_many_address'](a['customListFilter']['includeAddresses']))['filter'](e=>e!=null));a?.['customListFilter']?.['excludeAddresses']!=null&&(a['customListFilter']['excludeAddresses']=(await Account['Instance']()['get_many_address'](a['customListFilter']['excludeAddresses']))['filter'](e=>e!=null));const b=getMessengerManager();startPromise&&await startPromise;const c=await b['watch'](a),d=a?.['skipAutoMarkViewed']??![];if(!d&&c['length']>0x0&&a?.['account']){const e=a['account']['toLowerCase'](),f=new MessageStorage(e),g=c['filter'](h=>h['direction']===MessageDirection['RECEIVED']&&h['viewedAt']===undefined)['map'](h=>h['messageId']);g['length']>0x0&&f['updateMessagesViewed'](g);}return c;}export async function pull_messages(a,b){const c=await Account['Instance']()['get_address'](a);!c&&W_ERROR(WErrors['AccountNotFound'],'pull_messages.account\x20'+a);const d=getMessengerManager();startPromise&&await startPromise;const e=await d['ensureAccountReady'](c),f=await e['messenger']['pullMessages'](b);return f['messages']['map'](g=>g);}async function extract_zip_message(a,b){if(!a['zipMetadata'])throw new MessengerError(MessengerErrorCode['INVALID_MESSAGE_TYPE'],'Message\x20is\x20not\x20a\x20ZIP\x20archive');if(!a['plaintext'])throw new MessengerError(MessengerErrorCode['MESSAGE_NOT_DECRYPTED'],'Message\x20plaintext\x20not\x20available');const c=a['plaintext'],d=Buffer['from'](c,'base64');if(a['zipMetadata']?.['fileHash']){const k=createHash('sha256')['update'](d)['digest']('hex'),l=a['zipMetadata']['fileHash']['replace']('0x','');if(k!==l)throw new MessengerError(MessengerErrorCode['HASH_MISMATCH'],'ZIP\x20file\x20hash\x20mismatch:\x20expected\x20'+l+',\x20got\x20'+k);}const {ZipReader:e,BlobReader:f,BlobWriter:g}=await import('@zip.js/zip.js'),h=new e(new f(new Blob([d]))),i=await h['getEntries']();!a182a['existsSync'](b)&&a182a['mkdirSync'](b,{'recursive':!![]});const j=[];for(const m of i){if(!m['directory']){const n=m,o=new g(),p=await n['getData'](o),q=Buffer['from'](await p['arrayBuffer']()),r=a182b['join'](b,m['filename']);a182a['writeFileSync'](r,q),j['push'](r);}}await h['close']();if(j['length']>0x0&&a['zipMetadata']){const s={'fileName':a['zipMetadata']['fileName'],'fileSize':a['zipMetadata']['fileSize'],'fileHash':a['zipMetadata']['fileHash'],'contentType':a['zipMetadata']['contentType'],'localCachePath':j[0x0],'downloadedAt':Date['now']()};a['zipMetadata']=s;const t=a['direction']==='sent'?a['fromAddress']:a['toAddress'],u=new MessageStorage(t);u['saveMessage'](a);}return j[0x0]||'';}export async function extract_zip_messages(a,b,c){const d=[],f=await Account['Instance']()['get_address'](a);if(!f)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'account\x20is\x20required\x20when\x20extracting\x20by\x20message\x20IDs');for(const g of b){try{let h;if(typeof g==='string'){const j=g,k=new MessageStorage(f),l=k['getMessageById'](j);if(!l){console['error']('Message\x20not\x20found:\x20'+j);continue;}h=l;}else h=g;if(!h['zipMetadata']){console['error']('Message\x20'+h['messageId']+'\x20is\x20not\x20a\x20ZIP\x20archive');continue;}const i=await extract_zip_message(h,c);d['push'](i);}catch(m){const n=typeof g==='string'?g:g['messageId'];console['error']('Failed\x20to\x20extract\x20message\x20'+n+':',m);}}return d;}export async function generate_wts(a){const b=await Account['Instance']()['get_address'](a['myAccount']);!b&&W_ERROR(WErrors['AccountNotFound'],'generate_wts.myAccount\x20'+a['myAccount']);const c=await GetAccountOrMark_Address(a['peerAccount']);return!c&&W_ERROR(WErrors['AccountNotFound'],'generate_wts.peerAccount\x20'+a['peerAccount']),getMessengerManager()['generate_wts'](a['outputDir'],b,c,a['range'],a['excludePlaintext']);}function load_wts(a){const b=a182a['readFileSync'](a,'utf-8');return JSON['parse'](b);}function save_wts(a,b){const c=a182b['dirname'](b);!a182a['existsSync'](c)&&a182a['mkdirSync'](c,{'recursive':!![]}),a182a['writeFileSync'](b,JSON['stringify'](a,null,0x2),'utf-8');}function resolveServerPublicKey(a,b){if(b['serverPublicKeys']&&a['serverPublicKeyIndex']!==undefined&&a['serverPublicKeyIndex']>=0x0&&a['serverPublicKeyIndex']<b['serverPublicKeys']['length'])return b['serverPublicKeys'][a['serverPublicKeyIndex']]['publicKey'];const c=a;if(c['serverPublicKey'])return c['serverPublicKey'];return null;}export async function verify_wts(a){try{const b=load_wts(a);if(!b['payload']||!b['meta'])return{'valid':![],'error':'Invalid\x20WTS\x20file\x20structure'};if(b['meta']['type']!=='wts')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+b['meta']['type']};const {payload:c,meta:d}=b,e=[...c['messages']]['sort']((n,o)=>{if(n['leafIndex']===undefined||o['leafIndex']===undefined)return 0x0;return n['leafIndex']-o['leafIndex'];});for(let n=0x0;n<e['length'];n++){const o=e[n];if(!o)return{'valid':![],'error':'Message\x20'+n+':\x20Message\x20is\x20null\x20or\x20undefined'};if(!o['prevRoot'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20prevRoot'};if(!o['merkleRoot'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20merkleRoot'};if(!o['plaintextHash'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20plaintextHash'};if(o['timestamp']===undefined||o['timestamp']===null)return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20timestamp'};if(o['leafIndex']===undefined||o['leafIndex']===null)return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20leafIndex'};const p=verifySingleMerkleRoot(o['prevRoot'],o['merkleRoot'],o['plaintextHash'],o['timestamp'],o['leafIndex']);if(!p['valid'])return{'valid':![],'error':p['error']+'\x20at\x20message\x20'+n+',\x20leafIndex\x20'+o['leafIndex']};if(n>0x0){const q=e[n-0x1];if(o['leafIndex']!==q['leafIndex']+0x1)return{'valid':![],'error':'Merkle\x20chain\x20discontinuity:\x20leafIndex\x20'+q['leafIndex']+'\x20->\x20'+o['leafIndex']+'\x20(expected\x20'+(q['leafIndex']+0x1)+')'};if(o['prevRoot']['toLowerCase']()!==q['merkleRoot']['toLowerCase']())return{'valid':![],'error':'Merkle\x20root\x20mismatch\x20at\x20leafIndex\x20'+o['leafIndex']+':\x20expected\x20prevRoot='+q['merkleRoot']+',\x20got\x20'+o['prevRoot']};}}for(let r=0x0;r<c['messages']['length'];r++){const s=c['messages'][r];if(!s)return{'valid':![],'error':'Message\x20'+r+':\x20Message\x20is\x20null\x20or\x20undefined'};const t=!!s['zipMetadata'];if(!t){if(!s['plaintextHash']['startsWith']('0x')||s['plaintextHash']['length']!==0x42)return{'valid':![],'error':'Message\x20'+r+':\x20Invalid\x20plaintextHash\x20format'};if(s['plaintext']){const v=hashPlaintext(s['plaintext'],s['clientTimestamp'],s['guardAddress'],s['passportAddress'],s['lastReceivedLeafIndex']);if(v['toLowerCase']()!==s['plaintextHash']['toLowerCase']())return{'valid':![],'error':'Message\x20'+r+':\x20Plaintext\x20hash\x20mismatch'};}}const u=resolveServerPublicKey(s,d);if(s['serverSignature']&&u){if(!s['timestamp'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20timestamp\x20for\x20signature\x20verification'};if(!s['merkleRoot'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20merkleRoot\x20for\x20signature\x20verification'};if(!s['prevRoot'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20prevRoot\x20for\x20signature\x20verification'};const w=s['prevRoot']+':'+s['merkleRoot']+':'+s['timestamp']+':'+u,x=verifyFalcon512Signature(u,w,s['serverSignature']);if(!x)return{'valid':![],'error':'Message\x20'+r+':\x20Server\x20signature\x20verification\x20failed'};}}const {sha256:f}=await import('@noble/hashes/sha256'),{bytesToHex:g}=await import('@noble/hashes/utils'),h={'wts':b['wts'],...c},j=g(f(new TextEncoder()['encode'](canonicalizeJson(h))));if(j!==d['hash'])return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered','hashValid':![],'hasSignature':!!d['signature']};if(d['messageCount']!==c['messages']['length'])return{'valid':![],'error':'messageCount\x20mismatch:\x20meta='+d['messageCount']+',\x20actual='+c['messages']['length'],'hashValid':!![],'hasSignature':!!d['signature']};const k=c['messages'][c['messages']['length']-0x1];if(d['merkleRoot']['toLowerCase']()!==k['merkleRoot']['toLowerCase']())return{'valid':![],'error':'merkleRoot\x20mismatch:\x20meta='+d['merkleRoot']+',\x20lastMessage='+k['merkleRoot'],'hashValid':!![],'hasSignature':!!d['signature']};const l=[];let m;if(d['signature']){const {Falcon512PublicKey:y}=await import('../../keypairs/falcon512/publickey.js'),{signature:z,...A}=d,B=g(f(new TextEncoder()['encode'](canonicalizeJson(A)))),C=Array['isArray'](d['signature'])?d['signature']:[d['signature']];let D=!![];for(const E of C){let F;const G=E['publicKey'];if(G['startsWith']('0x')){const H=Buffer['from'](G['slice'](0x2),'hex');if(H['length']===0x382)F=H['slice'](0x1);else{if(H['length']===0x381)F=H;else{let I;try{const J=new y(G['slice'](0x2));I=J['toWAddress']();}catch{}l['push']({'publicKey':G,'address':I,'valid':![]}),D=![];continue;}}}else try{const K=Buffer['from'](G,'base64');if(K['length']===0x382)F=K['slice'](0x1);else{if(K['length']===0x381)F=K;else{let L;try{const M=new y(G);L=M['toWAddress']();}catch{}l['push']({'publicKey':G,'address':L,'valid':![]}),D=![];continue;}}}catch{F=Buffer['from'](G,'base64');}try{const N=new y(F),O=Uint8Array['from'](Buffer['from'](E['value'],'base64')),P=await N['verify'](new TextEncoder()['encode'](B),O);let Q;try{Q=N['toWAddress']();}catch{}l['push']({'publicKey':G,'address':Q,'valid':P}),!P&&(D=![]);}catch{let R;try{const S=new y(F);R=S['toWAddress']();}catch{}l['push']({'publicKey':G,'address':R,'valid':![]}),D=![];}}m=D;if(!m){const T=l['filter'](U=>!U['valid']&&U['address'])['map'](U=>U['address']);return{'valid':![],'error':'Signatures\x20from\x20the\x20following\x20addresses\x20are\x20invalid:\x20'+T['join'](',\x20'),'hashValid':!![],'hasSignature':!![],'signatureValid':![],'signatures':l};}}return{'valid':!![],'hashValid':!![],'hasSignature':!!d['signature'],'signatureValid':m,'signatures':l['length']>0x0?l:undefined};}catch(U){return{'valid':![],'error':'Verification\x20error:\x20'+U,'hashValid':![],'hasSignature':![]};}}export async function sign_wts(a,b,c){const d=await verify_wts(a);if(!d['valid'])throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'WTS\x20file\x20verification\x20failed:\x20'+d['error']);const e=load_wts(a),f=await Account['Instance']()['get_address'](b);!f&&W_ERROR(WErrors['AccountNotFound'],'sign_wts.account\x20'+b);const {sha256:g}=await import('@noble/hashes/sha256'),{bytesToHex:h}=await import('@noble/hashes/utils'),{signature:i,...j}=e['meta'],k=h(g(new TextEncoder()['encode'](canonicalizeJson(j)))),l=await Account['Instance']()['signData'](f,k);let m;const n=l['publicKey'];if(n['startsWith']('0x')){const s=Buffer['from'](n['slice'](0x2),'hex');if(s['length']===0x382)m=s['slice'](0x1)['toString']('base64');else{if(s['length']===0x381)m=s['toString']('base64');else throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Invalid\x20public\x20key\x20length:\x20'+s['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else m=n;const o={'value':Buffer['from'](l['signature']['slice'](0x2),'hex')['toString']('base64'),'publicKey':m,'algorithm':'Falcon512','address':l['address']};let p;if(e['meta']['signature']){const t=Array['isArray'](e['meta']['signature'])?[...e['meta']['signature']]:[e['meta']['signature']],u=t['findIndex'](v=>v['publicKey']===m);u>=0x0?(t[u]=o,p=t):p=[...t,o];}else p=[o];const q={...e,'meta':{...e['meta'],'signature':p}};let r;if(c)r=c;else{const v=a182b['dirname'](a),w=a182b['extname'](a),x=a182b['basename'](a,w);r=a182b['join'](v,'signed_'+x+w);}return save_wts(q,r),r;}export async function wts2html(a,b={}){const c=await import('fs'),d=await import('path'),e=c['statSync'](a);if(e['isDirectory']()){const g=c['readdirSync'](a),h=g['filter'](j=>j['endsWith']('.wts'));if(h['length']===0x0)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'No\x20.wts\x20files\x20found\x20in\x20directory:\x20'+a);const i=[];for(const j of h){const k=d['join'](a,j),l=await convertWtsToHtml(k,b),m=j['replace']('.wts','.html'),n=b['outputPath']?d['join'](b['outputPath'],m):d['join'](a,m),o=d['dirname'](n);!c['existsSync'](o)&&c['mkdirSync'](o,{'recursive':!![]}),c['writeFileSync'](n,l,'utf-8'),i['push'](n);}return i;}const f=await convertWtsToHtml(a,b);if(b['outputPath']){const p=d['basename'](a)['replace']('.wts','.html'),q=d['join'](b['outputPath'],p),r=d['dirname'](q);return!c['existsSync'](r)&&c['mkdirSync'](r,{'recursive':!![]}),c['writeFileSync'](q,f,'utf-8'),q;}return f;}async function convertWtsToHtml(a,b={}){const {title:title='WTS\x20Document',theme:theme='light'}=b,c=await verify_wts(a),d=load_wts(a),{payload:e,meta:f}=d,{bgColor:g,textColor:h,borderColor:i}=getThemeColors(theme),j=f['creator'];let k=-0x1;for(const l of e['messages']){l['to']['toLowerCase']()===j['toLowerCase']()&&(l['lastReceivedLeafIndex']!==undefined&&l['lastReceivedLeafIndex']>=0x0&&(l['lastReceivedLeafIndex']>k&&(k=l['lastReceivedLeafIndex'])));}return generateHtmlPage({'title':title,'theme':theme,'bgColor':g,'textColor':h,'borderColor':i,'meta':f,'payload':e,'verifyResult':c,'maxLastReceivedLeafIndex':k,'myAddress':j});}export async function proof_message(a,b,c){const d=await Account['Instance']()['get_address'](a);!d&&W_ERROR(WErrors['AccountNotFound'],'proof_message.account\x20'+a);const e=new MessageStorage(d),f=e['getMessageById'](b);if(!f)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20not\x20found:\x20'+b);if(f['fromAddress']['toLowerCase']()!==d['toLowerCase']()&&f['toAddress']['toLowerCase']()!==d['toLowerCase']())throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20does\x20not\x20belong\x20to\x20account\x20'+d);if(!f['serverSignature'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20signature');if(!f['serverPublicKey'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20public\x20key');if(!f['plaintext'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20plaintext');const {verifyMessage:g}=await import('./crypto.js'),h={'messageId':f['messageId'],'plaintext':f['plaintext'],'plaintextHash':f['plaintextHash'],'createdAt':f['createdAt'],'guardAddress':f['guardAddress'],'passportAddress':f['passportAddress'],'lastReceivedLeafIndex':f['lastReceivedLeafIndex'],'serverSignature':f['serverSignature'],'serverPublicKey':f['serverPublicKey']};if(f['newRoot']&&f['leafIndex']!==undefined){if(!f['serverTimestamp'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20'+f['messageId']+'\x20missing\x20server\x20timestamp\x20for\x20verification');h['merkleMetadata']={'newRoot':f['newRoot'],'prevRoot':f['prevRoot'],'leafIndex':f['leafIndex'],'serverTimestamp':f['serverTimestamp']};}const i=g(h);if(!i['valid'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20verification\x20failed:\x20'+i['error']);if(!f['serverPublicKey'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20public\x20key');const {CallProof:j}=await import('../call/proof.js'),k=new j({'proof':f['newRoot'],'server_pubkey':f['serverPublicKey'],'server_signature':f['serverSignature'],'proof_type':CHAIN_PROOF_TYPE,'description':'Message\x20proof\x20for\x20'+b,'item_count':f['leafIndex']??0x1,'about_address':f['fromAddress']['toLowerCase']()===d['toLowerCase']()?f['toAddress']:f['fromAddress']}),l={'network':c,'account':d},m=await k['call'](l),{ResponseData:n}=await import('../call/base.js'),o=n(m),p=o['find'](q=>q['type']==='Proof');if(!p||!p['object'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Failed\x20to\x20get\x20proof\x20address\x20from\x20transaction\x20result');return f['proof']=p['object'],e['saveMessage'](f),{'proofAddress':p['object']};}const MIN_PASSPORT_VALIDITY=0xa,MAX_PASSPORT_VALIDITY=0xa*0x16d*0x18*0x3c*0x3c,MAX_BLACKLIST_SIZE_ONCE=0x64,MAX_FRIENDS_SIZE_ONCE=0x64,MAX_GUARDS_SIZE_ONCE=0xa;export async function blacklist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'blacklist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{let d=await GetManyAccountOrMark_Address(a['users']);d['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.add.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');d=[...new Set(d['map'](f=>f['toLowerCase']()))];d['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.add.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const e=await c['addToBlacklist'](b,d);return{'op':'add','result':e};}case'remove':{let f=await GetManyAccountOrMark_Address(a['users']);f['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.remove.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');f=[...new Set(f['map'](h=>h['toLowerCase']()))];f['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.remove.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const g=await c['removeFromBlacklist'](b,f);return{'op':'remove','result':g};}case'clear':{const h=await c['clearBlacklist'](b);return{'op':'clear','result':h};}case'get':{const i=await c['getBlacklist'](b);return{'op':'get','result':i};}case'exist':{let j=await GetManyAccountOrMark_Address(a['users']);j['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.exist.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');j=[...new Set(j['map'](l=>l['toLowerCase']()))];j['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.exist.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const k=await c['existInBlacklist'](b,j);return{'op':'exist','result':k};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'blacklist.unknown\x20op:\x20'+a);}}export async function friendslist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'friendslist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{let d=await GetManyAccountOrMark_Address(a['users']);d['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.add.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');d=[...new Set(d['map'](f=>f['toLowerCase']()))];const e=await c['addToFriendsList'](b,d);return{'op':'add','result':e};}case'remove':{let f=await GetManyAccountOrMark_Address(a['users']);f['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.remove.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');f=[...new Set(f['map'](h=>h['toLowerCase']()))];f['length']>MAX_FRIENDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'friendslist.remove.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_FRIENDS_SIZE_ONCE);const g=await c['removeFromFriendsList'](b,f);return{'op':'remove','result':g};}case'clear':{const h=await c['clearFriendsList'](b);return{'op':'clear','result':h};}case'get':{const i=await c['getFriendsList'](b);return{'op':'get','result':i};}case'exist':{let j=await GetManyAccountOrMark_Address(a['users']);j['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.exist.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');j=[...new Set(j['map'](l=>l['toLowerCase']()))];j['length']>MAX_FRIENDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'friendslist.exist.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_FRIENDS_SIZE_ONCE);const k=await c['existInFriendsList'](b,j);return{'op':'exist','result':k};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'friendslist.unknown\x20op:\x20'+a);}}export async function guardlist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'guardlist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{const d=new Map();for(const k of a['guards']){d['set'](k['guard']['toLowerCase'](),k);}const e=Array['from'](d['values']());e['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'guardlist.add.guards\x20'+a['guards']+'\x20have\x20not\x20valid\x20guards');e['length']>MAX_GUARDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'guardlist.add.guards\x20'+a['guards']+'\x20have\x20too\x20many\x20guards,\x20max\x20'+MAX_GUARDS_SIZE_ONCE);for(const l of e){(!isValidU64(l['passportValiditySeconds'])||l['passportValiditySeconds']<MIN_PASSPORT_VALIDITY||l['passportValiditySeconds']>MAX_PASSPORT_VALIDITY)&&W_ERROR(WErrors['InvalidParam'],'Guard\x20'+l['guard']+':\x20passport\x20validity\x20'+l['passportValiditySeconds']+'\x20must\x20be\x20between\x20'+MIN_PASSPORT_VALIDITY+'\x20and\x20'+MAX_PASSPORT_VALIDITY+'\x20seconds');}const f=await LocalMark['Instance']()['get_many_address'](e['map'](m=>m['guard']));if(f['length']!==e['length']){const m=new Set(f),n=[];for(const o of e){!m['has'](o['guard'])&&!o['guard']['startsWith']('0x')&&n['push'](o['guard']);}W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+n['join'](',\x20'));}const h=await query_objects({'objects':f,'no_cache':![],'network':c['getConfig']()['network']});(!h||!h['objects']||h['objects']['length']===0x0)&&W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+e['map'](p=>p['guard'])['join'](',\x20'));h['objects']['forEach'](p=>{p['type']!=='Guard'&&W_ERROR(WErrors['InvalidParam'],'Guard\x20'+p['object']+'\x20is\x20not\x20a\x20Guard');});const i=e['map']((p,q)=>({'guardAddress':f[q],'passportValiditySeconds':p['passportValiditySeconds']})),j=await c['addToGuardList'](b,i);return{'op':'add','result':j};}case'remove':{const p=[...new Set(a['guards']['map'](s=>s['toLowerCase']()))];p['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'guardlist.remove.guards\x20'+a['guards']+'\x20have\x20not\x20valid\x20guards');p['length']>MAX_GUARDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'guardlist.remove.guards\x20'+a['guards']+'\x20have\x20too\x20many\x20guards,\x20max\x20'+MAX_GUARDS_SIZE_ONCE);const q=await LocalMark['Instance']()['get_many_address'](p);if(q['length']!==p['length']){const s=new Set(q),t=[];for(const u of p){!s['has'](u)&&!u['startsWith']('0x')&&t['push'](u);}W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+t['join'](',\x20'));}const r=await c['removeFromGuardList'](b,q);return{'op':'remove','result':r};}case'get':{const v=await c['getGuardList'](b);return{'op':'get','result':v};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'guardlist.unknown\x20op:\x20'+a);}}export async function settings(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'settings.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'get':{const d=await c['getSettings'](b);return{'op':'get','result':d};}case'set':{const e={};a['allowStrangerMessages']!==undefined&&(e['allowStrangerMessages']=a['allowStrangerMessages']);a['maxInboxSize']!==undefined&&(e['maxInboxSize']=a['maxInboxSize']);const f=await c['setSettings'](b,e);return{'op':'set','result':f};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'settings.unknown\x20op:\x20'+a);}}
|
|
1
|
+
import{MessengerManager}from'./messenger-manager.js';import{Account}from'../local/account.js';import{W_ERROR,WErrors}from'../exception.js';import{LocalMark}from'../local/local.js';import{MessageStorage}from'./storage.js';import{MessengerError,MessengerErrorCode,CHAIN_PROOF_TYPE,MessageDirection}from'./types.js';import{createHash}from'crypto';import*as a183a from'fs';import*as a183b from'path';import{isValidU64}from'../common.js';import{verifySingleMerkleRoot,hashPlaintext,verifyFalcon512Signature}from'./crypto.js';import{canonicalizeJson}from'./utils.js';import{generateHtmlPage,getThemeColors}from'./templates/wts-html-template.js';import{GetAccountOrMark_Address,GetManyAccountOrMark_Address}from'../local/index.js';import{query_objects}from'../query/object.js';import{Messenger}from'./messenger.js';let managerInstance=null,isInitialized=![],startPromise=null,backgroundTimer=null;async function autoRegisterMessengerAccounts(){const a=await Account['Instance']()['list_messenger_accounts']();for(const b of a){if(!b['address']||!b['m'])continue;try{const c=new Messenger(b['address']);await c['initialize']();}catch(d){console['error']('Failed\x20to\x20initialize\x20account\x20'+b['address']+':',d);}}}export function getMessengerManager(){return!managerInstance&&(managerInstance=new MessengerManager()),!isInitialized&&(isInitialized=!![],startPromise=autoRegisterMessengerAccounts()['then'](()=>{return managerInstance['start']();})['catch'](a=>{return console['error']('Failed\x20to\x20auto-register\x20messenger\x20accounts:',a),managerInstance['start']();})['catch'](a=>{console['error']('Failed\x20to\x20auto-start\x20messenger\x20manager:',a);})),managerInstance;}function registerCleanupHandler(){const a=()=>{backgroundTimer&&(clearInterval(backgroundTimer),backgroundTimer=null),managerInstance&&managerInstance['stop']();};process['on']('exit',a),process['on']('SIGINT',()=>{a(),process['exit']();}),process['on']('SIGTERM',()=>{a(),process['exit']();});}registerCleanupHandler();export async function watch_conversations(a){const b=await Account['Instance']()['get_address'](a?.['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'watch_conversations.account\x20'+a?.['account']);const c=b['toLowerCase'](),d=getMessengerManager();startPromise&&await startPromise;const e=await d['ensureAccountReady'](b);await e['messenger']['pullMessages']();const f=new MessageStorage(c),g=f['getAllMessages'](c),h=new Map(),i=a?.['previewMessageCount']??0x2,j=a?.['skipAutoMarkViewed']??![];for(const n of g){const o=n['fromAddress']['toLowerCase']()===c?n['toAddress']:n['fromAddress'];!h['has'](o)&&h['set'](o,{'peerAddress':o,'lastMessageAt':n['createdAt'],'messageCount':0x0,'unreadCount':0x0,'lastMessagePreview':n['plaintext'],'messages':[]});const p=h['get'](o);p['messages']['push'](n),p['messageCount']++,n['createdAt']>p['lastMessageAt']&&(p['lastMessageAt']=n['createdAt'],p['lastMessagePreview']=n['plaintext']),n['direction']===MessageDirection['RECEIVED']&&n['viewedAt']===undefined&&p['unreadCount']++;}const k=[];for(const [,q]of h){if(a?.['startTime']!==undefined&&q['lastMessageAt']<a['startTime'])continue;if(a?.['endTime']!==undefined&&q['lastMessageAt']>a['endTime'])continue;if(a?.['unreadOnly']&&q['unreadCount']===0x0)continue;const r=[];if(i>0x0){const s=q['messages']['sort']((u,v)=>v['createdAt']-u['createdAt']),t=s['slice'](0x0,i);r['push'](...t['reverse']());if(!j){const u=t['filter'](v=>v['direction']===MessageDirection['RECEIVED']&&v['viewedAt']===undefined)['map'](v=>v['messageId']);u['length']>0x0&&f['updateMessagesViewed'](u);}}k['push']({'peerAddress':q['peerAddress'],'lastMessageAt':q['lastMessageAt'],'messageCount':q['messageCount'],'unreadCount':q['unreadCount'],'lastMessagePreview':q['lastMessagePreview'],...i>0x0&&{'previewMessages':r}});}const l=a?.['sortBy']??'lastMessageAt',m=a?.['sortOrder']??'desc';return k['sort']((v,w)=>{let x=0x0;switch(l){case'lastMessageAt':x=v['lastMessageAt']-w['lastMessageAt'];break;case'unreadCount':x=v['unreadCount']-w['unreadCount'];break;case'messageCount':x=v['messageCount']-w['messageCount'];break;}return m==='asc'?x:-x;}),k;}export async function mark_messages_as_viewed(a,b){if(!a||a['length']===0x0)return 0x0;const c=await Account['Instance']()['get_address'](b);!c&&W_ERROR(WErrors['AccountNotFound'],'mark_messages_as_viewed.account\x20'+b);const d=c['toLowerCase'](),e=new MessageStorage(d);return e['updateMessagesViewed'](a);}export async function mark_conversation_as_viewed(a,b){const c=await Account['Instance']()['get_address'](b);!c&&W_ERROR(WErrors['AccountNotFound'],'mark_conversation_as_viewed.account\x20'+b);const d=c['toLowerCase'](),e=await GetAccountOrMark_Address(a);!e&&W_ERROR(WErrors['AccountNotFound'],'mark_conversation_as_viewed.peerAddress\x20'+a+'\x20is\x20not\x20a\x20valid\x20account/address');const f=e['toLowerCase'](),g=new MessageStorage(d),h=g['getMessagesBySession'](d,f),i=h['filter'](j=>j['direction']===MessageDirection['RECEIVED']&&j['viewedAt']===undefined)['map'](j=>j['messageId']);if(i['length']===0x0)return 0x0;return g['updateMessagesViewed'](i);}export async function send_message(a,b,c,d){const e=await Account['Instance']()['get_address'](a);!e&&W_ERROR(WErrors['AccountNotFound'],'send_message.from\x20'+a);const f=await GetAccountOrMark_Address(b);!f&&W_ERROR(WErrors['AccountNotFound'],'send_message.to\x20'+b+'\x20is\x20not\x20a\x20valid\x20account/address');d?.['guardAddress']!=null&&d?.['passportAddress']!=null&&([d['guardAddress'],d['passportAddress']]=await LocalMark['Instance']()['get_many_address']([d['guardAddress'],d['passportAddress']]),(!d['guardAddress']||!d['passportAddress'])&&W_ERROR(WErrors['AccountNotFound'],'send_message.guardAddress\x20or\x20passportAddress\x20not\x20found'));const g=getMessengerManager();return startPromise&&await startPromise,g['send'](e,f,c,d);}export async function send_file(a,b,c,d){const e=await Account['Instance']()['get_address'](a);!e&&W_ERROR(WErrors['AccountNotFound'],'send_file.from\x20'+a);const f=await GetAccountOrMark_Address(b);!f&&W_ERROR(WErrors['AccountNotFound'],'send_file.to\x20'+b+'\x20is\x20not\x20a\x20valid\x20account/address');d?.['guardAddress']!=null&&d?.['passportAddress']!=null&&([d['guardAddress'],d['passportAddress']]=await LocalMark['Instance']()['get_many_address']([d['guardAddress'],d['passportAddress']]),(!d['guardAddress']||!d['passportAddress'])&&W_ERROR(WErrors['AccountNotFound'],'send_file.guardAddress\x20or\x20passportAddress\x20not\x20found'));const g=getMessengerManager();return startPromise&&await startPromise,g['send_file'](e,f,c,d);}export async function watch_messages(a){a?.['account']!==undefined&&(a['account']=await Account['Instance']()['get_address'](a['account']),!a['account']&&W_ERROR(WErrors['AccountNotFound'],'watch_messages.account\x20'+a['account']));a?.['customListFilter']?.['includeAddresses']!=null&&(a['customListFilter']['includeAddresses']=(await Account['Instance']()['get_many_address'](a['customListFilter']['includeAddresses']))['filter'](e=>e!=null));a?.['customListFilter']?.['excludeAddresses']!=null&&(a['customListFilter']['excludeAddresses']=(await Account['Instance']()['get_many_address'](a['customListFilter']['excludeAddresses']))['filter'](e=>e!=null));const b=getMessengerManager();startPromise&&await startPromise;const c=await b['watch'](a),d=a?.['skipAutoMarkViewed']??![];if(!d&&c['length']>0x0&&a?.['account']){const e=a['account']['toLowerCase'](),f=new MessageStorage(e),g=c['filter'](h=>h['direction']===MessageDirection['RECEIVED']&&h['viewedAt']===undefined)['map'](h=>h['messageId']);g['length']>0x0&&f['updateMessagesViewed'](g);}return c;}export async function pull_messages(a,b){const c=await Account['Instance']()['get_address'](a);!c&&W_ERROR(WErrors['AccountNotFound'],'pull_messages.account\x20'+a);const d=getMessengerManager();startPromise&&await startPromise;const e=await d['ensureAccountReady'](c),f=await e['messenger']['pullMessages'](b);return f['messages']['map'](g=>g);}async function extract_zip_message(a,b){if(!a['zipMetadata'])throw new MessengerError(MessengerErrorCode['INVALID_MESSAGE_TYPE'],'Message\x20is\x20not\x20a\x20ZIP\x20archive');if(!a['plaintext'])throw new MessengerError(MessengerErrorCode['MESSAGE_NOT_DECRYPTED'],'Message\x20plaintext\x20not\x20available');const c=a['plaintext'],d=Buffer['from'](c,'base64');if(a['zipMetadata']?.['fileHash']){const k=createHash('sha256')['update'](d)['digest']('hex'),l=a['zipMetadata']['fileHash']['replace']('0x','');if(k!==l)throw new MessengerError(MessengerErrorCode['HASH_MISMATCH'],'ZIP\x20file\x20hash\x20mismatch:\x20expected\x20'+l+',\x20got\x20'+k);}const {ZipReader:e,BlobReader:f,BlobWriter:g}=await import('@zip.js/zip.js'),h=new e(new f(new Blob([d]))),i=await h['getEntries']();!a183a['existsSync'](b)&&a183a['mkdirSync'](b,{'recursive':!![]});const j=[];for(const m of i){if(!m['directory']){const n=m,o=new g(),p=await n['getData'](o),q=Buffer['from'](await p['arrayBuffer']()),r=a183b['join'](b,m['filename']);a183a['writeFileSync'](r,q),j['push'](r);}}await h['close']();if(j['length']>0x0&&a['zipMetadata']){const s={'fileName':a['zipMetadata']['fileName'],'fileSize':a['zipMetadata']['fileSize'],'fileHash':a['zipMetadata']['fileHash'],'contentType':a['zipMetadata']['contentType'],'localCachePath':j[0x0],'downloadedAt':Date['now']()};a['zipMetadata']=s;const t=a['direction']==='sent'?a['fromAddress']:a['toAddress'],u=new MessageStorage(t);u['saveMessage'](a);}return j[0x0]||'';}export async function extract_zip_messages(a,b,c){const d=[],f=await Account['Instance']()['get_address'](a);if(!f)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'account\x20is\x20required\x20when\x20extracting\x20by\x20message\x20IDs');for(const g of b){try{let h;if(typeof g==='string'){const j=g,k=new MessageStorage(f),l=k['getMessageById'](j);if(!l){console['error']('Message\x20not\x20found:\x20'+j);continue;}h=l;}else h=g;if(!h['zipMetadata']){console['error']('Message\x20'+h['messageId']+'\x20is\x20not\x20a\x20ZIP\x20archive');continue;}const i=await extract_zip_message(h,c);d['push'](i);}catch(m){const n=typeof g==='string'?g:g['messageId'];console['error']('Failed\x20to\x20extract\x20message\x20'+n+':',m);}}return d;}export async function generate_wts(a){const b=await Account['Instance']()['get_address'](a['myAccount']);!b&&W_ERROR(WErrors['AccountNotFound'],'generate_wts.myAccount\x20'+a['myAccount']);const c=await GetAccountOrMark_Address(a['peerAccount']);return!c&&W_ERROR(WErrors['AccountNotFound'],'generate_wts.peerAccount\x20'+a['peerAccount']),getMessengerManager()['generate_wts'](a['outputDir'],b,c,a['range'],a['excludePlaintext']);}function load_wts(a){const b=a183a['readFileSync'](a,'utf-8');return JSON['parse'](b);}function save_wts(a,b){const c=a183b['dirname'](b);!a183a['existsSync'](c)&&a183a['mkdirSync'](c,{'recursive':!![]}),a183a['writeFileSync'](b,JSON['stringify'](a,null,0x2),'utf-8');}function resolveServerPublicKey(a,b){if(b['serverPublicKeys']&&a['serverPublicKeyIndex']!==undefined&&a['serverPublicKeyIndex']>=0x0&&a['serverPublicKeyIndex']<b['serverPublicKeys']['length'])return b['serverPublicKeys'][a['serverPublicKeyIndex']]['publicKey'];const c=a;if(c['serverPublicKey'])return c['serverPublicKey'];return null;}export async function verify_wts(a){try{const b=load_wts(a);if(!b['payload']||!b['meta'])return{'valid':![],'error':'Invalid\x20WTS\x20file\x20structure'};if(b['meta']['type']!=='wts')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+b['meta']['type']};const {payload:c,meta:d}=b,e=[...c['messages']]['sort']((n,o)=>{if(n['leafIndex']===undefined||o['leafIndex']===undefined)return 0x0;return n['leafIndex']-o['leafIndex'];});for(let n=0x0;n<e['length'];n++){const o=e[n];if(!o)return{'valid':![],'error':'Message\x20'+n+':\x20Message\x20is\x20null\x20or\x20undefined'};if(!o['prevRoot'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20prevRoot'};if(!o['merkleRoot'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20merkleRoot'};if(!o['plaintextHash'])return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20plaintextHash'};if(o['timestamp']===undefined||o['timestamp']===null)return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20timestamp'};if(o['leafIndex']===undefined||o['leafIndex']===null)return{'valid':![],'error':'Message\x20'+n+':\x20Missing\x20leafIndex'};const p=verifySingleMerkleRoot(o['prevRoot'],o['merkleRoot'],o['plaintextHash'],o['timestamp'],o['leafIndex']);if(!p['valid'])return{'valid':![],'error':p['error']+'\x20at\x20message\x20'+n+',\x20leafIndex\x20'+o['leafIndex']};if(n>0x0){const q=e[n-0x1];if(o['leafIndex']!==q['leafIndex']+0x1)return{'valid':![],'error':'Merkle\x20chain\x20discontinuity:\x20leafIndex\x20'+q['leafIndex']+'\x20->\x20'+o['leafIndex']+'\x20(expected\x20'+(q['leafIndex']+0x1)+')'};if(o['prevRoot']['toLowerCase']()!==q['merkleRoot']['toLowerCase']())return{'valid':![],'error':'Merkle\x20root\x20mismatch\x20at\x20leafIndex\x20'+o['leafIndex']+':\x20expected\x20prevRoot='+q['merkleRoot']+',\x20got\x20'+o['prevRoot']};}}for(let r=0x0;r<c['messages']['length'];r++){const s=c['messages'][r];if(!s)return{'valid':![],'error':'Message\x20'+r+':\x20Message\x20is\x20null\x20or\x20undefined'};const t=!!s['zipMetadata'];if(!t){if(!s['plaintextHash']['startsWith']('0x')||s['plaintextHash']['length']!==0x42)return{'valid':![],'error':'Message\x20'+r+':\x20Invalid\x20plaintextHash\x20format'};if(s['plaintext']){const v=hashPlaintext(s['plaintext'],s['clientTimestamp'],s['guardAddress'],s['passportAddress'],s['lastReceivedLeafIndex']);if(v['toLowerCase']()!==s['plaintextHash']['toLowerCase']())return{'valid':![],'error':'Message\x20'+r+':\x20Plaintext\x20hash\x20mismatch'};}}const u=resolveServerPublicKey(s,d);if(s['serverSignature']&&u){if(!s['timestamp'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20timestamp\x20for\x20signature\x20verification'};if(!s['merkleRoot'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20merkleRoot\x20for\x20signature\x20verification'};if(!s['prevRoot'])return{'valid':![],'error':'Message\x20'+r+':\x20Missing\x20prevRoot\x20for\x20signature\x20verification'};const w=s['prevRoot']+':'+s['merkleRoot']+':'+s['timestamp']+':'+u,x=verifyFalcon512Signature(u,w,s['serverSignature']);if(!x)return{'valid':![],'error':'Message\x20'+r+':\x20Server\x20signature\x20verification\x20failed'};}}const {sha256:f}=await import('@noble/hashes/sha256'),{bytesToHex:g}=await import('@noble/hashes/utils'),h={'wts':b['wts'],...c},j=g(f(new TextEncoder()['encode'](canonicalizeJson(h))));if(j!==d['hash'])return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered','hashValid':![],'hasSignature':!!d['signature']};if(d['messageCount']!==c['messages']['length'])return{'valid':![],'error':'messageCount\x20mismatch:\x20meta='+d['messageCount']+',\x20actual='+c['messages']['length'],'hashValid':!![],'hasSignature':!!d['signature']};const k=c['messages'][c['messages']['length']-0x1];if(d['merkleRoot']['toLowerCase']()!==k['merkleRoot']['toLowerCase']())return{'valid':![],'error':'merkleRoot\x20mismatch:\x20meta='+d['merkleRoot']+',\x20lastMessage='+k['merkleRoot'],'hashValid':!![],'hasSignature':!!d['signature']};const l=[];let m;if(d['signature']){const {Falcon512PublicKey:y}=await import('../../keypairs/falcon512/publickey.js'),{signature:z,...A}=d,B=g(f(new TextEncoder()['encode'](canonicalizeJson(A)))),C=Array['isArray'](d['signature'])?d['signature']:[d['signature']];let D=!![];for(const E of C){let F;const G=E['publicKey'];if(G['startsWith']('0x')){const H=Buffer['from'](G['slice'](0x2),'hex');if(H['length']===0x382)F=H['slice'](0x1);else{if(H['length']===0x381)F=H;else{let I;try{const J=new y(G['slice'](0x2));I=J['toWAddress']();}catch{}l['push']({'publicKey':G,'address':I,'valid':![]}),D=![];continue;}}}else try{const K=Buffer['from'](G,'base64');if(K['length']===0x382)F=K['slice'](0x1);else{if(K['length']===0x381)F=K;else{let L;try{const M=new y(G);L=M['toWAddress']();}catch{}l['push']({'publicKey':G,'address':L,'valid':![]}),D=![];continue;}}}catch{F=Buffer['from'](G,'base64');}try{const N=new y(F),O=Uint8Array['from'](Buffer['from'](E['value'],'base64')),P=await N['verify'](new TextEncoder()['encode'](B),O);let Q;try{Q=N['toWAddress']();}catch{}l['push']({'publicKey':G,'address':Q,'valid':P}),!P&&(D=![]);}catch{let R;try{const S=new y(F);R=S['toWAddress']();}catch{}l['push']({'publicKey':G,'address':R,'valid':![]}),D=![];}}m=D;if(!m){const T=l['filter'](U=>!U['valid']&&U['address'])['map'](U=>U['address']);return{'valid':![],'error':'Signatures\x20from\x20the\x20following\x20addresses\x20are\x20invalid:\x20'+T['join'](',\x20'),'hashValid':!![],'hasSignature':!![],'signatureValid':![],'signatures':l};}}return{'valid':!![],'hashValid':!![],'hasSignature':!!d['signature'],'signatureValid':m,'signatures':l['length']>0x0?l:undefined};}catch(U){return{'valid':![],'error':'Verification\x20error:\x20'+U,'hashValid':![],'hasSignature':![]};}}export async function sign_wts(a,b,c){const d=await verify_wts(a);if(!d['valid'])throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'WTS\x20file\x20verification\x20failed:\x20'+d['error']);const e=load_wts(a),f=await Account['Instance']()['get_address'](b);!f&&W_ERROR(WErrors['AccountNotFound'],'sign_wts.account\x20'+b);const {sha256:g}=await import('@noble/hashes/sha256'),{bytesToHex:h}=await import('@noble/hashes/utils'),{signature:i,...j}=e['meta'],k=h(g(new TextEncoder()['encode'](canonicalizeJson(j)))),l=await Account['Instance']()['signData'](f,k);let m;const n=l['publicKey'];if(n['startsWith']('0x')){const s=Buffer['from'](n['slice'](0x2),'hex');if(s['length']===0x382)m=s['slice'](0x1)['toString']('base64');else{if(s['length']===0x381)m=s['toString']('base64');else throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Invalid\x20public\x20key\x20length:\x20'+s['length']+',\x20expected\x20897\x20or\x20898\x20bytes');}}else m=n;const o={'value':Buffer['from'](l['signature']['slice'](0x2),'hex')['toString']('base64'),'publicKey':m,'algorithm':'Falcon512','address':l['address']};let p;if(e['meta']['signature']){const t=Array['isArray'](e['meta']['signature'])?[...e['meta']['signature']]:[e['meta']['signature']],u=t['findIndex'](v=>v['publicKey']===m);u>=0x0?(t[u]=o,p=t):p=[...t,o];}else p=[o];const q={...e,'meta':{...e['meta'],'signature':p}};let r;if(c)r=c;else{const v=a183b['dirname'](a),w=a183b['extname'](a),x=a183b['basename'](a,w);r=a183b['join'](v,'signed_'+x+w);}return save_wts(q,r),r;}export async function wts2html(a,b={}){const c=await import('fs'),d=await import('path'),e=c['statSync'](a);if(e['isDirectory']()){const g=c['readdirSync'](a),h=g['filter'](j=>j['endsWith']('.wts'));if(h['length']===0x0)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'No\x20.wts\x20files\x20found\x20in\x20directory:\x20'+a);const i=[];for(const j of h){const k=d['join'](a,j),l=await convertWtsToHtml(k,b),m=j['replace']('.wts','.html'),n=b['outputPath']?d['join'](b['outputPath'],m):d['join'](a,m),o=d['dirname'](n);!c['existsSync'](o)&&c['mkdirSync'](o,{'recursive':!![]}),c['writeFileSync'](n,l,'utf-8'),i['push'](n);}return i;}const f=await convertWtsToHtml(a,b);if(b['outputPath']){const p=d['basename'](a)['replace']('.wts','.html'),q=d['join'](b['outputPath'],p),r=d['dirname'](q);return!c['existsSync'](r)&&c['mkdirSync'](r,{'recursive':!![]}),c['writeFileSync'](q,f,'utf-8'),q;}return f;}async function convertWtsToHtml(a,b={}){const {title:title='WTS\x20Document',theme:theme='light'}=b,c=await verify_wts(a),d=load_wts(a),{payload:e,meta:f}=d,{bgColor:g,textColor:h,borderColor:i}=getThemeColors(theme),j=f['creator'];let k=-0x1;for(const l of e['messages']){l['to']['toLowerCase']()===j['toLowerCase']()&&(l['lastReceivedLeafIndex']!==undefined&&l['lastReceivedLeafIndex']>=0x0&&(l['lastReceivedLeafIndex']>k&&(k=l['lastReceivedLeafIndex'])));}return generateHtmlPage({'title':title,'theme':theme,'bgColor':g,'textColor':h,'borderColor':i,'meta':f,'payload':e,'verifyResult':c,'maxLastReceivedLeafIndex':k,'myAddress':j});}export async function proof_message(a,b,c){const d=await Account['Instance']()['get_address'](a);!d&&W_ERROR(WErrors['AccountNotFound'],'proof_message.account\x20'+a);const e=new MessageStorage(d),f=e['getMessageById'](b);if(!f)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20not\x20found:\x20'+b);if(f['fromAddress']['toLowerCase']()!==d['toLowerCase']()&&f['toAddress']['toLowerCase']()!==d['toLowerCase']())throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20does\x20not\x20belong\x20to\x20account\x20'+d);if(!f['serverSignature'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20signature');if(!f['serverPublicKey'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20public\x20key');if(!f['plaintext'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20plaintext');const {verifyMessage:g}=await import('./crypto.js'),h={'messageId':f['messageId'],'plaintext':f['plaintext'],'plaintextHash':f['plaintextHash'],'createdAt':f['createdAt'],'guardAddress':f['guardAddress'],'passportAddress':f['passportAddress'],'lastReceivedLeafIndex':f['lastReceivedLeafIndex'],'serverSignature':f['serverSignature'],'serverPublicKey':f['serverPublicKey']};if(f['newRoot']&&f['leafIndex']!==undefined){if(!f['serverTimestamp'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20'+f['messageId']+'\x20missing\x20server\x20timestamp\x20for\x20verification');h['merkleMetadata']={'newRoot':f['newRoot'],'prevRoot':f['prevRoot'],'leafIndex':f['leafIndex'],'serverTimestamp':f['serverTimestamp']};}const i=g(h);if(!i['valid'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20verification\x20failed:\x20'+i['error']);if(!f['serverPublicKey'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Message\x20does\x20not\x20have\x20server\x20public\x20key');const {CallProof:j}=await import('../call/proof.js'),k=new j({'proof':f['newRoot'],'server_pubkey':f['serverPublicKey'],'server_signature':f['serverSignature'],'proof_type':CHAIN_PROOF_TYPE,'description':'Message\x20proof\x20for\x20'+b,'item_count':f['leafIndex']??0x1,'about_address':f['fromAddress']['toLowerCase']()===d['toLowerCase']()?f['toAddress']:f['fromAddress']}),l={'network':c,'account':d},m=await k['call'](l),{ResponseData:n}=await import('../call/base.js'),o=n(m),p=o['find'](q=>q['type']==='Proof');if(!p||!p['object'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'Failed\x20to\x20get\x20proof\x20address\x20from\x20transaction\x20result');return f['proof']=p['object'],e['saveMessage'](f),{'proofAddress':p['object']};}const MIN_PASSPORT_VALIDITY=0xa,MAX_PASSPORT_VALIDITY=0xa*0x16d*0x18*0x3c*0x3c,MAX_BLACKLIST_SIZE_ONCE=0x64,MAX_FRIENDS_SIZE_ONCE=0x64,MAX_GUARDS_SIZE_ONCE=0xa;export async function blacklist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'blacklist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{let d=await GetManyAccountOrMark_Address(a['users']);d['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.add.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');d=[...new Set(d['map'](f=>f['toLowerCase']()))];d['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.add.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const e=await c['addToBlacklist'](b,d);return{'op':'add','result':e};}case'remove':{let f=await GetManyAccountOrMark_Address(a['users']);f['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.remove.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');f=[...new Set(f['map'](h=>h['toLowerCase']()))];f['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.remove.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const g=await c['removeFromBlacklist'](b,f);return{'op':'remove','result':g};}case'clear':{const h=await c['clearBlacklist'](b);return{'op':'clear','result':h};}case'get':{const i=await c['getBlacklist'](b);return{'op':'get','result':i};}case'exist':{let j=await GetManyAccountOrMark_Address(a['users']);j['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'blacklist.exist.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');j=[...new Set(j['map'](l=>l['toLowerCase']()))];j['length']>MAX_BLACKLIST_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'blacklist.exist.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_BLACKLIST_SIZE_ONCE);const k=await c['existInBlacklist'](b,j);return{'op':'exist','result':k};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'blacklist.unknown\x20op:\x20'+a);}}export async function friendslist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'friendslist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{let d=await GetManyAccountOrMark_Address(a['users']);d['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.add.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');d=[...new Set(d['map'](f=>f['toLowerCase']()))];const e=await c['addToFriendsList'](b,d);return{'op':'add','result':e};}case'remove':{let f=await GetManyAccountOrMark_Address(a['users']);f['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.remove.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');f=[...new Set(f['map'](h=>h['toLowerCase']()))];f['length']>MAX_FRIENDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'friendslist.remove.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_FRIENDS_SIZE_ONCE);const g=await c['removeFromFriendsList'](b,f);return{'op':'remove','result':g};}case'clear':{const h=await c['clearFriendsList'](b);return{'op':'clear','result':h};}case'get':{const i=await c['getFriendsList'](b);return{'op':'get','result':i};}case'exist':{let j=await GetManyAccountOrMark_Address(a['users']);j['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'friendslist.exist.users\x20'+a['users']+'\x20have\x20not\x20valid\x20addresses');j=[...new Set(j['map'](l=>l['toLowerCase']()))];j['length']>MAX_FRIENDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'friendslist.exist.users\x20'+a['users']+'\x20have\x20too\x20many\x20addresses,\x20max\x20'+MAX_FRIENDS_SIZE_ONCE);const k=await c['existInFriendsList'](b,j);return{'op':'exist','result':k};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'friendslist.unknown\x20op:\x20'+a);}}export async function guardlist(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'guardlist.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'add':{const d=new Map();for(const k of a['guards']){d['set'](k['guard']['toLowerCase'](),k);}const e=Array['from'](d['values']());e['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'guardlist.add.guards\x20'+a['guards']+'\x20have\x20not\x20valid\x20guards');e['length']>MAX_GUARDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'guardlist.add.guards\x20'+a['guards']+'\x20have\x20too\x20many\x20guards,\x20max\x20'+MAX_GUARDS_SIZE_ONCE);for(const l of e){(!isValidU64(l['passportValiditySeconds'])||l['passportValiditySeconds']<MIN_PASSPORT_VALIDITY||l['passportValiditySeconds']>MAX_PASSPORT_VALIDITY)&&W_ERROR(WErrors['InvalidParam'],'Guard\x20'+l['guard']+':\x20passport\x20validity\x20'+l['passportValiditySeconds']+'\x20must\x20be\x20between\x20'+MIN_PASSPORT_VALIDITY+'\x20and\x20'+MAX_PASSPORT_VALIDITY+'\x20seconds');}const f=await LocalMark['Instance']()['get_many_address'](e['map'](m=>m['guard']));if(f['length']!==e['length']){const m=new Set(f),n=[];for(const o of e){!m['has'](o['guard'])&&!o['guard']['startsWith']('0x')&&n['push'](o['guard']);}W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+n['join'](',\x20'));}const h=await query_objects({'objects':f,'no_cache':![],'network':c['getConfig']()['network']});(!h||!h['objects']||h['objects']['length']===0x0)&&W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+e['map'](p=>p['guard'])['join'](',\x20'));h['objects']['forEach'](p=>{p['type']!=='Guard'&&W_ERROR(WErrors['InvalidParam'],'Guard\x20'+p['object']+'\x20is\x20not\x20a\x20Guard');});const i=e['map']((p,q)=>({'guardAddress':f[q],'passportValiditySeconds':p['passportValiditySeconds']})),j=await c['addToGuardList'](b,i);return{'op':'add','result':j};}case'remove':{const p=[...new Set(a['guards']['map'](s=>s['toLowerCase']()))];p['length']===0x0&&W_ERROR(WErrors['InvalidParam'],'guardlist.remove.guards\x20'+a['guards']+'\x20have\x20not\x20valid\x20guards');p['length']>MAX_GUARDS_SIZE_ONCE&&W_ERROR(WErrors['InvalidParam'],'guardlist.remove.guards\x20'+a['guards']+'\x20have\x20too\x20many\x20guards,\x20max\x20'+MAX_GUARDS_SIZE_ONCE);const q=await LocalMark['Instance']()['get_many_address'](p);if(q['length']!==p['length']){const s=new Set(q),t=[];for(const u of p){!s['has'](u)&&!u['startsWith']('0x')&&t['push'](u);}W_ERROR(WErrors['InvalidParam'],'Guard\x20not\x20found:\x20'+t['join'](',\x20'));}const r=await c['removeFromGuardList'](b,q);return{'op':'remove','result':r};}case'get':{const v=await c['getGuardList'](b);return{'op':'get','result':v};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'guardlist.unknown\x20op:\x20'+a);}}export async function settings(a){const b=await Account['Instance']()['get_address'](a['account']);!b&&W_ERROR(WErrors['AccountNotFound'],'settings.account\x20'+a['account']);const c=getMessengerManager();startPromise&&await startPromise;await c['ensureAccountReady'](b);switch(a['op']){case'get':{const d=await c['getSettings'](b);return{'op':'get','result':d};}case'set':{const e={};a['allowStrangerMessages']!==undefined&&(e['allowStrangerMessages']=a['allowStrangerMessages']);a['maxInboxSize']!==undefined&&(e['maxInboxSize']=a['maxInboxSize']);const f=await c['setSettings'](b,e);return{'op':'set','result':f};}default:throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'settings.unknown\x20op:\x20'+a);}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from'crypto';import*as a184a from'fs';import*as a184b from'path';import{MessengerSession,DecryptionEngine}from'./session.js';import{MessengerServerClient}from'./server.js';import{MessageStorage,SessionStateStorage}from'./storage.js';import{hashPlaintext,verifyMessage,bytesToBase64}from'./crypto.js';import{canonicalizeJson}from'./utils.js';import{DEFAULT_MESSENGER_CONFIG,MessengerError,MessengerErrorCode,MessageDirection,MessageStatus,WTS_FILE_BYTES_LIMIT,NORMAL_MESSAGE_BYTES_LIMIT,CHAIN_PROOF_TYPE}from'./types.js';import{isValidWowAddress}from'../../utils/wow-types.js';async function getAccount(){const {Account:a}=await import('../local/account.js');return a['Instance']();}export class Messenger{['session'];['serverClient'];['config'];['userAddress']=null;['onMessageCallback']=null;['pollingTimer']=null;['messageConsecutiveEmptyPulls']=0x0;['prekeyConsecutiveOkCount']=0x0;['currentMessageInterval'];['isPollingRunning']=![];['messageStorage'];['sessionStateStorage'];['decryptionEngine'];['waitingMessages']=new Map();['failedMessages']=new Map();['waitingMessageRetries']=new Map();constructor(a,b){this['userAddress']=a,this['config']={...DEFAULT_MESSENGER_CONFIG,...b},this['session']=new MessengerSession(a,this['config']),this['serverClient']=new MessengerServerClient(this['config']),this['messageStorage']=new MessageStorage(a),this['sessionStateStorage']=new SessionStateStorage(a),this['decryptionEngine']=new DecryptionEngine(this['session']['store']),this['currentMessageInterval']=this['config']['message_poll_default_interval_ms']??0x6*0x3c*0x3e8;}['getUserAddress'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');return this['userAddress'];}async['getPublicKey'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await(await getAccount())['get'](this['userAddress'],![]);return a?.['pubkey']||'';}['isValidGuardMessage'](a,b){return Boolean(a&&b&&isValidWowAddress(a)&&isValidWowAddress(b));}async['generateSignatureParams'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=await(await getAccount())['get'](this['userAddress'],![]);if(!b?.['secret'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20or\x20no\x20secret\x20key\x20for\x20'+this['userAddress']);const {Falcon512Keypair:c}=await import('../../keypairs/falcon512/index.js'),d=c['fromSecretKey'](b['secret']),e=d['getPublicKey'](),f=e['toWPublicKey'](),g=Date['now'](),h=this['generateNonce'](),i=a+':'+f+':'+g+':'+h,j=await d['sign'](new TextEncoder()['encode'](i));return{'signatureScheme':'Falcon512','signature':Buffer['from'](j)['toString']('base64'),'timestamp':g,'nonce':h};}['generateNonce'](){const a=new Uint8Array(0x10);return crypto['getRandomValues'](a),Array['from'](a,c=>c['toString'](0x10)['padStart'](0x2,'0'))['join']('');}async['initialize'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');await this['session']['ensureIdentity'](this['userAddress']),await this['session']['registerDevice'](this['userAddress']),await this['session']['ensurePreKeys'](this['userAddress']),await this['checkAndRefillPrekeys'](),this['startPollingTimer']();}async['checkAndRefillPrekeys'](){if(!this['userAddress'])return;await this['session']['ensurePreKeys'](this['userAddress'],![]);}['startPollingTimer'](){this['pollingTimer']&&clearTimeout(this['pollingTimer']),this['isPollingRunning']=!![],this['scheduleNextPoll']();}['stopPollingTimer'](){this['isPollingRunning']=![],this['pollingTimer']&&(clearTimeout(this['pollingTimer']),this['pollingTimer']=null);}['scheduleNextPoll'](){if(!this['isPollingRunning'])return;const a=this['getNextPollInterval']();this['pollingTimer']=setTimeout(()=>{this['poll']()['catch'](b=>{})['finally'](()=>{this['scheduleNextPoll']();});},a);}['getNextPollInterval'](){if(this['waitingMessages']['size']>0x0)return this['config']['message_poll_waiting_interval_ms']??0x3*0x3e8;return this['currentMessageInterval'];}async['poll'](){if(!this['userAddress'])return;try{const a=await this['pullMessages']();a['messages']['length']>0x0?(this['messageConsecutiveEmptyPulls']=0x0,this['currentMessageInterval']=this['config']['message_poll_fast_interval_ms']??0x6*0x3e8,this['onMessageCallback']&&this['onMessageCallback'](a['messages'])):(this['messageConsecutiveEmptyPulls']++,this['messageConsecutiveEmptyPulls']>=(this['config']['message_poll_consecutive_empty_limit']??0x3)&&(this['currentMessageInterval']=this['config']['message_poll_default_interval_ms']??0x6*0x3c*0x3e8,this['messageConsecutiveEmptyPulls']=0x0));if(a['prekey_status']){const b=a['prekey_status'];b['shouldRefill']?(this['prekeyConsecutiveOkCount']=0x0,await this['checkAndRefillPrekeys']()):(this['prekeyConsecutiveOkCount']++,this['prekeyConsecutiveOkCount']>=(this['config']['prekey_poll_consecutive_ok_limit']??0x3)&&(this['prekeyConsecutiveOkCount']=0x0));}}catch(c){}}['triggerFastPoll'](){this['currentMessageInterval']=this['config']['message_poll_fast_interval_ms']??0x6*0x3e8,this['messageConsecutiveEmptyPulls']=0x0,this['isPollingRunning']&&(this['pollingTimer']&&clearTimeout(this['pollingTimer']),this['scheduleNextPoll']());}async['sendMessage'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=Date['now'](),e=Date['now'](),f=this['generateNonce'](),g=new TextEncoder()['encode'](b)['length'];if(g>NORMAL_MESSAGE_BYTES_LIMIT)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20size\x20('+g+'\x20bytes)\x20exceeds\x20maximum\x20allowed\x20size\x20('+NORMAL_MESSAGE_BYTES_LIMIT+'\x20bytes).\x20Consider\x20using\x20sendZipFile\x20for\x20large\x20content.');await this['pullMessages']();const h=this['messageStorage']['getLastReceivedLeafIndex'](this['userAddress'],a),i=await this['session']['encryptMessage'](this['userAddress'],a,b),j=Buffer['from'](new Uint8Array(i['body']))['toString']('base64'),k=hashPlaintext(b,d,c?.['guardAddress'],c?.['passportAddress'],h),l=await(await getAccount())['get'](this['userAddress'],![]);if(!l)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20account\x20not\x20found');const m=l['pubkey'],n=c?.['guardAddress']||'',o=c?.['passportAddress']||'',p=h>=0x0?h['toString']():'',q=c?.['force']?'true':'false',r='send_message:'+this['userAddress']+':'+a+':'+n+':'+o+':'+k+':'+p+':'+m+':'+e+':'+f+':'+q,s=await(await getAccount())['signData'](this['userAddress'],r),t=Buffer['from'](s['signature']['slice'](0x2),'hex'),u=bytesToBase64(new Uint8Array(t)),v=await this['serverClient']['sendMessage']({'sender':s['publicKey'],'recipient':a,'ciphertext':j,'plaintextHash':k,'clientTimestamp':d,'msgType':i['type'],'signatureScheme':'Falcon512','signature':u,'timestamp':e,'nonce':f,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'force':c?.['force'],'lastReceivedLeafIndex':h>=0x0?h:undefined}),w={'messageId':v['messageId'],'fromAddress':this['userAddress'],'toAddress':a,'plaintextHash':k,'plaintext':b,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'lastReceivedLeafIndex':h,'direction':MessageDirection['SENT'],'status':v['status']==='confirmed'?MessageStatus['CONFIRMED']:MessageStatus['PENDING'],'msgType':i['type'],'createdAt':d};v['merkleData']&&(w['leafIndex']=v['merkleData']['leafIndex'],w['prevRoot']=v['merkleData']['prevRoot'],w['newRoot']=v['merkleData']['newRoot'],w['serverSignature']=v['merkleData']['serverSignature'],w['serverTimestamp']=v['merkleData']['serverTimestamp'],w['serverPublicKey']=v['merkleData']['serverPublicKey'],this['sessionStateStorage']['updateSessionState'](this['userAddress'],a,{'currentRoot':v['merkleData']['newRoot'],'prevRoot':v['merkleData']['prevRoot'],'lastLeafIndex':v['merkleData']['leafIndex'],'lastSyncAt':Date['now']()}));this['messageStorage']['saveMessage'](w);if(v['pendingMerkleData'])for(const [x,y]of Object['entries'](v['pendingMerkleData'])){const z=this['messageStorage']['getMessage'](x);z&&z['status']===MessageStatus['PENDING']&&this['messageStorage']['updateMessageStatus'](x,MessageStatus['CONFIRMED'],{'leafIndex':y['leafIndex'],'newRoot':y['newRoot'],'serverSignature':y['serverSignature'],'serverTimestamp':y['serverTimestamp'],'serverPublicKey':y['serverPublicKey']});}return this['triggerFastPoll'](),{'messageId':v['messageId'],'status':w['status'],'merkleData':v['merkleData'],'guardList':v['guard_list'],'lastReceivedLeafIndex':h>=0x0?h:undefined};}async['pullMessages'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=Date['now'](),c=this['generateNonce'](),d='fetch_messages:'+this['userAddress']+':'+(a||0x64)+':'+b+':'+c,e=await(await getAccount())['get'](this['userAddress'],![]),f=e?.['pubkey']||'',g=await(await getAccount())['signData'](this['userAddress'],d),h=Buffer['from'](g['signature']['slice'](0x2),'hex'),i={'signatureScheme':'Falcon512','signature':bytesToBase64(h),'timestamp':b,'nonce':c},j=await this['serverClient']['pullMessages'](this['userAddress'],f,i,a);if(j['messages']['length']===0x0)return{'messages':[],'prekey_status':j['prekey_status']};const k=[],l=[],m=[...j['messages']]['sort'](function(n,o){return(n['clientTimestamp']||0x0)-(o['clientTimestamp']||0x0);});await this['processWaitingMessages'](k,l);for(const n of m){if(this['waitingMessages']['has'](n['id'])){l['push'](n['id']);continue;}if(this['failedMessages']['has'](n['id'])){l['push'](n['id']);continue;}const o=this['messageStorage']['getMessage'](n['id']);if(o){l['push'](n['id']);continue;}const p=await this['tryDecryptMessage'](n);if(p['success']&&p['message']&&p['decryptedData'])this['messageStorage']['saveMessage'](p['message']),k['push'](p['decryptedData']),l['push'](n['id']),this['waitingMessages']['delete'](n['id']);else p['shouldRetry']?this['waitingMessages']['set'](n['id'],n):(this['failedMessages']['set'](n['id'],{'message':n,'error':p['error']||'Unknown\x20error'}),await this['saveFailedMessage'](n,p['error']||'Unknown\x20error'),l['push'](n['id']));}this['waitingMessages']['size']>0x0&&this['isPollingRunning']&&this['reschedulePolling']();if(l['length']>0x0&&this['userAddress']){const q=Date['now'](),r=this['generateNonce'](),s=await(await getAccount())['get'](this['userAddress'],![]);if(s?.['pubkey']){const t='ack_messages:'+this['userAddress']+':'+l['join'](',')+':'+s['pubkey']+':'+q+':'+r,u=await(await getAccount())['signData'](this['userAddress'],t),v=Buffer['from'](u['signature']['slice'](0x2),'hex'),w=bytesToBase64(new Uint8Array(v));await this['serverClient']['acknowledgeMessages'](l,u['publicKey'],{'publicKey':u['publicKey'],'signatureScheme':'Falcon512','signature':w,'timestamp':q,'nonce':r});}}return{'messages':k,'prekey_status':j['prekey_status']};}['getLastSentLeafIndex'](a){if(!this['userAddress'])return-0x1;const b=this['messageStorage']['getMessagesBySession'](this['userAddress'],a),c=b['filter'](d=>d['direction']===MessageDirection['SENT']&&d['leafIndex']!==undefined);if(c['length']===0x0)return-0x1;return Math['max'](...c['map'](d=>d['leafIndex']));}['getSessionMessages'](a){if(!this['userAddress'])return[];return this['messageStorage']['getMessagesBySession'](this['userAddress'],a);}['getSessionState'](a){if(!this['userAddress'])return undefined;return this['sessionStateStorage']['getSessionState'](this['userAddress'],a);}async['submitChainProof'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=this['sessionStateStorage']['getSessionState'](this['userAddress'],b);if(!d||!d['currentRoot'])throw new MessengerError(MessengerErrorCode['SESSION_NOT_ESTABLISHED'],'No\x20session\x20state\x20found');const e=this['messageStorage']['getMessagesBySession'](this['userAddress'],b),f=e[e['length']-0x1];if(!f||!f['serverPublicKey']||!f['serverSignature'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'No\x20temporal\x20proof\x20(missing\x20server\x20public\x20key\x20or\x20signature),\x20cannot\x20submit\x20Proof\x20to\x20WoWok\x20blockchain');const g=f['serverPublicKey'],h=f['serverSignature'],i={'sessionId':d['sessionId'],'merkleRoot':d['currentRoot'],'messageCount':d['messageCount'],'timestamp':Date['now']()},{CallProof:j}=await import('../call/proof.js'),k=new j({'proof':JSON['stringify'](i),'server_pubkey':g,'server_signature':h,'proof_type':CHAIN_PROOF_TYPE,'description':c||'Messenger\x20session\x20proof\x20for\x20'+this['userAddress']+'\x20<->\x20'+b,'item_count':d['messageCount'],'about_address':d['sessionId']}),l=await k['call'](a),m=l?.['objectChanges'],n=m?.['find'](o=>o['objectType']?.['includes']('Proof'))?.['objectId'];return{'proofAddress':n||'','txHash':l?.['digest']||''};}['destroy'](){this['stopPollingTimer']();}['disconnect'](){this['destroy']();}['setOnMessageCallback'](a){this['onMessageCallback']=a;}async['sendZipFile'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=await this['loadFileData'](b),{ZipWriter:e,BlobWriter:f,Uint8ArrayReader:g}=await import('@zip.js/zip.js'),h=c?.['fileName']||a184b['basename'](b)||'file.zip',i=c?.['contentType']||this['detectContentType'](h),j=new f('application/zip'),k=new e(j);await k['add'](h,new g(d)),await k['close']();const l=await j['getData'](),m=new Uint8Array(await l['arrayBuffer']());if(m['length']>WTS_FILE_BYTES_LIMIT)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'ZIP\x20file\x20size\x20('+m['length']+'\x20bytes)\x20exceeds\x20local\x20maximum\x20allowed\x20size\x20('+WTS_FILE_BYTES_LIMIT+'\x20bytes)');const n='0x'+createHash('sha256')['update'](m)['digest']('hex'),o=Buffer['from'](m)['toString']('base64'),p={'fileName':h+'.zip','fileSize':m['length'],'fileHash':n,'contentType':i};await this['pullMessages']();const q=this['messageStorage']['getLastReceivedLeafIndex'](this['userAddress'],a),r=Date['now'](),s=await this['session']['encryptMessage'](this['userAddress'],a,o),t=Buffer['from'](new Uint8Array(s['body']))['toString']('base64'),u=c?.['guardAddress']||'',v=c?.['passportAddress']||'',w=hashPlaintext(o,r,u,v,q),x=Date['now'](),y=this['generateNonce'](),z=await(await getAccount())['get'](this['userAddress'],![]);if(!z)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20account\x20not\x20found');const A=z['pubkey'],B=q>=0x0?q['toString']():'',C=c?.['force']?'true':'false',D='send_message:'+this['userAddress']+':'+a+':'+u+':'+v+':'+w+':'+B+':'+A+':'+x+':'+y+':'+C,E=await(await getAccount())['signData'](this['userAddress'],D),F=Buffer['from'](E['signature']['slice'](0x2),'hex'),G=bytesToBase64(new Uint8Array(F)),H=await this['serverClient']['sendMessage']({'sender':E['publicKey'],'recipient':a,'ciphertext':t,'plaintextHash':w,'clientTimestamp':r,'msgType':s['type'],'zipMetadata':p,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'force':c?.['force'],'lastReceivedLeafIndex':q>=0x0?q:undefined,'signatureScheme':'Falcon512','signature':G,'timestamp':x,'nonce':y}),I={'messageId':H['messageId'],'fromAddress':this['userAddress'],'toAddress':a,'plaintextHash':w,'plaintext':o,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'lastReceivedLeafIndex':q,'direction':MessageDirection['SENT'],'status':H['status']==='confirmed'?MessageStatus['CONFIRMED']:MessageStatus['PENDING'],'msgType':s['type'],'zipMetadata':p,'createdAt':r};H['merkleData']&&(I['leafIndex']=H['merkleData']['leafIndex'],I['prevRoot']=H['merkleData']['prevRoot'],I['newRoot']=H['merkleData']['newRoot'],I['serverSignature']=H['merkleData']['serverSignature'],I['serverTimestamp']=H['merkleData']['serverTimestamp'],I['serverPublicKey']=H['merkleData']['serverPublicKey'],this['sessionStateStorage']['updateSessionState'](this['userAddress'],a,{'currentRoot':H['merkleData']['newRoot'],'prevRoot':H['merkleData']['prevRoot'],'lastLeafIndex':H['merkleData']['leafIndex'],'lastSyncAt':Date['now']()}));this['messageStorage']['saveMessage'](I);if(H['pendingMerkleData'])for(const [J,K]of Object['entries'](H['pendingMerkleData'])){const L=this['messageStorage']['getMessage'](J);L&&L['status']===MessageStatus['PENDING']&&this['messageStorage']['updateMessageStatus'](J,MessageStatus['CONFIRMED'],{'leafIndex':K['leafIndex'],'newRoot':K['newRoot'],'serverSignature':K['serverSignature'],'serverTimestamp':K['serverTimestamp'],'serverPublicKey':K['serverPublicKey']});}return this['triggerFastPoll'](),{'messageId':H['messageId'],'status':I['status'],'merkleData':H['merkleData'],'guardList':H['guard_list'],'lastReceivedLeafIndex':q>=0x0?q:undefined};}async['loadFileData'](a){if(a['startsWith']('http://')||a['startsWith']('https://')){const d=await fetch(a);if(!d['ok'])throw new MessengerError(MessengerErrorCode['NETWORK_ERROR'],'Failed\x20to\x20fetch\x20file\x20from\x20'+a+':\x20'+d['statusText']);const e=await d['arrayBuffer']();return new Uint8Array(e);}const b=a184b['resolve'](a);if(!a184a['existsSync'](b))throw new MessengerError(MessengerErrorCode['FILE_NOT_FOUND'],'File\x20not\x20found:\x20'+b);const c=a184a['readFileSync'](b);return new Uint8Array(c);}['detectContentType'](a){const b=a184b['extname'](a)['toLowerCase']();switch(b){case'.wts':return'wts';case'.wip':return'wip';default:return'zip';}}async['_createSignedRequest'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=Date['now'](),c=this['generateNonce'](),d=canonicalizeJson(a),e=b+':'+c+':'+d,f=await(await getAccount())['signData'](this['userAddress'],e),g=Buffer['from'](f['signature']['slice'](0x2),'hex'),h=bytesToBase64(new Uint8Array(g)),i=await(await getAccount())['get'](this['userAddress'],![]);if(!i||!i['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20public\x20key\x20not\x20found');return{'userAddress':this['userAddress'],'publicKey':i['pubkey'],'signatureScheme':'Falcon512','signature':h,'timestamp':b,'nonce':c,'data':a};}['_validateAddresses'](a){const b=[],c=[];for(const d of a){isValidWowAddress(d)?b['push'](d):c['push'](d);}return{'valid':b,'invalid':c};}async['addToBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'add','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['addToBlacklist'](this['userAddress'],e);}async['removeFromBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromBlacklist'](this['userAddress'],e);}async['clearBlacklist'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a={},b=await this['_createSignedRequest'](a);return this['serverClient']['clearBlacklist'](this['userAddress'],b);}async['getBlacklist'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getBlacklist'](this['userAddress'],a);}async['existInBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'exist','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['existInBlacklist'](this['userAddress'],e);}async['addToFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'add','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['addToFriendsList'](this['userAddress'],e);}async['removeFromFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromFriendsList'](this['userAddress'],e);}async['clearFriendsList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a={},b=await this['_createSignedRequest'](a);return this['serverClient']['clearFriendsList'](this['userAddress'],b);}async['getFriendsList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getFriendsList'](this['userAddress'],a);}async['existInFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'exist','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['existInFriendsList'](this['userAddress'],e);}async['addToGuardList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b={'guards':a},c=await this['_createSignedRequest'](b);return this['serverClient']['addToGuardList'](this['userAddress'],c);}async['removeFromGuardList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromGuardList'](this['userAddress'],e);}async['getGuardList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getGuardList'](this['userAddress'],a);}async['getSettings'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getSettings'](this['userAddress'],a);}async['setSettings'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b={'allowStrangerMessages':a['allowStrangerMessages'],'maxInboxSize':a['maxInboxSize']},c=await this['_createSignedRequest'](b);return this['serverClient']['updateSettings'](this['userAddress'],c);}async['tryDecryptMessage'](a){try{const b=Uint8Array['from'](Buffer['from'](a['bodyB64'],'base64')),c=await this['decryptionEngine']['decryptMessage'](this['userAddress'],a['from'],b['buffer'],a['msgType']);if(!c['success']){const h=this['isRetryableError'](c['error']||'');return{'success':![],'shouldRetry':h,'error':c['error'],'sessionUpdated':c['sessionUpdated']};}const d=c['plaintext'];if(!a['clientTimestamp'])throw new Error('Missing\x20clientTimestamp\x20for\x20message\x20'+a['id']);if(!a['plaintextHash'])throw new Error('Missing\x20plaintextHash\x20for\x20message\x20'+a['id']);const e=verifyMessage({'messageId':a['id'],'plaintext':d,'plaintextHash':a['plaintextHash'],'createdAt':a['clientTimestamp'],'guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'merkleMetadata':a['merkleMetadata']?{'prevRoot':a['merkleMetadata']['prevRoot'],'newRoot':a['merkleMetadata']['newRoot'],'serverTimestamp':a['merkleMetadata']['serverTimestamp'],'leafIndex':a['merkleMetadata']['leafIndex'],'proofSiblings':a['merkleMetadata']['proofSiblings'],'proofIndices':a['merkleMetadata']['proofIndices']}:undefined});if(!e['valid'])throw new Error(e['error']);const f={'messageId':a['id'],'fromAddress':a['from'],'toAddress':this['userAddress'],'plaintextHash':a['plaintextHash'],'plaintext':d,'guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'direction':MessageDirection['RECEIVED'],'status':MessageStatus['DECRYPTED'],'msgType':a['msgType'],'leafIndex':a['merkleMetadata']?.['leafIndex'],'prevRoot':a['merkleMetadata']?.['prevRoot'],'newRoot':a['merkleMetadata']?.['newRoot'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverTimestamp':a['merkleMetadata']?.['serverTimestamp'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'createdAt':a['clientTimestamp'],'receivedAt':Date['now'](),'zipMetadata':a['zipMetadata']};a['merkleMetadata']&&this['sessionStateStorage']['updateSessionState'](this['userAddress'],a['from'],{'currentRoot':a['merkleMetadata']['newRoot'],'prevRoot':a['merkleMetadata']['prevRoot'],'lastLeafIndex':a['merkleMetadata']['leafIndex'],'lastSyncAt':Date['now']()});const g=a['merkleMetadata']?.['serverTimestamp']||a['clientTimestamp']||Date['now']();if(a['lastReceivedLeafIndex']!==undefined&&a['lastReceivedLeafIndex']>=0x0){const i=this['messageStorage']['getMessagesBySession'](this['userAddress'],a['from'])['filter'](j=>j['direction']===MessageDirection['SENT']&&j['status']===MessageStatus['CONFIRMED']&&j['leafIndex']!==undefined&&j['leafIndex']<=a['lastReceivedLeafIndex']);for(const j of i){this['messageStorage']['updateMessageStatus'](j['messageId'],MessageStatus['READ']);}}return{'success':!![],'shouldRetry':![],'message':f,'decryptedData':{'id':a['id'],'from':a['from'],'plaintext':d,'timestamp':g,'merkleVerified':!!a['merkleMetadata'],'merkleData':a['merkleMetadata']?{'leafIndex':a['merkleMetadata']['leafIndex'],'rootHash':a['merkleMetadata']['newRoot']}:undefined},'sessionUpdated':c['sessionUpdated']};}catch(k){const l=k instanceof Error?k['message']:String(k),m=this['isRetryableError'](l);return{'success':![],'shouldRetry':m,'error':l};}}['isRetryableError'](a){const b=[/message number/i,/chain key/i,/session not found/i,/prekey not found/i,/PREKEY 竞争:我的地址较小,保留我的会话/i,/The operation failed for an operation-specific reason/i,/DOMException/i,/收到 WHISPER_MESSAGE 但无现有会话,需要等待 PREKEY_MESSAGE/i];return b['some'](c=>c['test'](a));}async['processWaitingMessages'](a,b){if(this['waitingMessages']['size']===0x0)return;const c=[],d=Array['from'](this['waitingMessages']['values']())['sort'](function(e,f){return(e['clientTimestamp']||0x0)-(f['clientTimestamp']||0x0);});for(const e of d){const f=e['id'],g=await this['tryDecryptMessage'](e);if(g['success']&&g['message']&&g['decryptedData'])this['messageStorage']['saveMessage'](g['message']),a['push'](g['decryptedData']),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f);else{if(!g['shouldRetry'])this['failedMessages']['set'](f,{'message':e,'error':g['error']||'Unknown\x20error'}),await this['saveFailedMessage'](e,g['error']||'Unknown\x20error'),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f);else{const h=this['waitingMessageRetries']['get'](f)||0x0,i=h+0x1;i>=0x3?(this['failedMessages']['set'](f,{'message':e,'error':g['error']||'Retry\x20limit\x20exceeded'}),await this['saveFailedMessage'](e,g['error']||'Retry\x20limit\x20exceeded'),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f)):this['waitingMessageRetries']['set'](f,i);}}}for(const j of c){this['waitingMessages']['delete'](j);}if(c['length']>0x0){}}async['saveFailedMessage'](a,b){const c={'messageId':a['id'],'fromAddress':a['from'],'toAddress':this['userAddress'],'plaintextHash':a['plaintextHash']||'','guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'direction':MessageDirection['RECEIVED'],'status':MessageStatus['DECRYPT_FAILED'],'msgType':a['msgType'],'leafIndex':a['merkleMetadata']?.['leafIndex'],'prevRoot':a['merkleMetadata']?.['prevRoot'],'newRoot':a['merkleMetadata']?.['newRoot'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverTimestamp':a['merkleMetadata']?.['serverTimestamp'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'createdAt':a['clientTimestamp']||Date['now'](),'receivedAt':Date['now'](),'zipMetadata':a['zipMetadata'],'decryptError':b,'decryptAttempts':0x1,'lastDecryptAttemptAt':Date['now']()};this['messageStorage']['saveMessage'](c);}['reschedulePolling'](){if(!this['isPollingRunning']||!this['pollingTimer'])return;clearTimeout(this['pollingTimer']),this['pollingTimer']=null,this['scheduleNextPoll']();}['getFailedMessages'](){return Array['from'](this['failedMessages']['entries']())['map'](([a,b])=>({'messageId':a,'from':b['message']['from'],'error':b['error'],'leafIndex':b['message']['merkleMetadata']?.['leafIndex']}));}['clearFailedMessages'](a){a?this['failedMessages']['delete'](a):this['failedMessages']['clear']();}['getWaitingMessageCount'](){return this['waitingMessages']['size'];}}
|
|
1
|
+
import{createHash}from'crypto';import*as a185a from'fs';import*as a185b from'path';import{MessengerSession,DecryptionEngine}from'./session.js';import{MessengerServerClient}from'./server.js';import{MessageStorage,SessionStateStorage}from'./storage.js';import{hashPlaintext,verifyMessage,bytesToBase64}from'./crypto.js';import{canonicalizeJson}from'./utils.js';import{DEFAULT_MESSENGER_CONFIG,MessengerError,MessengerErrorCode,MessageDirection,MessageStatus,WTS_FILE_BYTES_LIMIT,NORMAL_MESSAGE_BYTES_LIMIT,CHAIN_PROOF_TYPE}from'./types.js';import{isValidWowAddress}from'../../utils/wow-types.js';async function getAccount(){const {Account:a}=await import('../local/account.js');return a['Instance']();}export class Messenger{['session'];['serverClient'];['config'];['userAddress']=null;['onMessageCallback']=null;['pollingTimer']=null;['messageConsecutiveEmptyPulls']=0x0;['prekeyConsecutiveOkCount']=0x0;['currentMessageInterval'];['isPollingRunning']=![];['messageStorage'];['sessionStateStorage'];['decryptionEngine'];['waitingMessages']=new Map();['failedMessages']=new Map();['waitingMessageRetries']=new Map();constructor(a,b){this['userAddress']=a,this['config']={...DEFAULT_MESSENGER_CONFIG,...b},this['session']=new MessengerSession(a,this['config']),this['serverClient']=new MessengerServerClient(this['config']),this['messageStorage']=new MessageStorage(a),this['sessionStateStorage']=new SessionStateStorage(a),this['decryptionEngine']=new DecryptionEngine(this['session']['store']),this['currentMessageInterval']=this['config']['message_poll_default_interval_ms']??0x6*0x3c*0x3e8;}['getUserAddress'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');return this['userAddress'];}async['getPublicKey'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await(await getAccount())['get'](this['userAddress'],![]);return a?.['pubkey']||'';}['isValidGuardMessage'](a,b){return Boolean(a&&b&&isValidWowAddress(a)&&isValidWowAddress(b));}async['generateSignatureParams'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=await(await getAccount())['get'](this['userAddress'],![]);if(!b?.['secret'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20or\x20no\x20secret\x20key\x20for\x20'+this['userAddress']);const {Falcon512Keypair:c}=await import('../../keypairs/falcon512/index.js'),d=c['fromSecretKey'](b['secret']),e=d['getPublicKey'](),f=e['toWPublicKey'](),g=Date['now'](),h=this['generateNonce'](),i=a+':'+f+':'+g+':'+h,j=await d['sign'](new TextEncoder()['encode'](i));return{'signatureScheme':'Falcon512','signature':Buffer['from'](j)['toString']('base64'),'timestamp':g,'nonce':h};}['generateNonce'](){const a=new Uint8Array(0x10);return crypto['getRandomValues'](a),Array['from'](a,c=>c['toString'](0x10)['padStart'](0x2,'0'))['join']('');}async['initialize'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');await this['session']['ensureIdentity'](this['userAddress']),await this['session']['registerDevice'](this['userAddress']),await this['session']['ensurePreKeys'](this['userAddress']),await this['checkAndRefillPrekeys'](),this['startPollingTimer']();}async['checkAndRefillPrekeys'](){if(!this['userAddress'])return;await this['session']['ensurePreKeys'](this['userAddress'],![]);}['startPollingTimer'](){this['pollingTimer']&&clearTimeout(this['pollingTimer']),this['isPollingRunning']=!![],this['scheduleNextPoll']();}['stopPollingTimer'](){this['isPollingRunning']=![],this['pollingTimer']&&(clearTimeout(this['pollingTimer']),this['pollingTimer']=null);}['scheduleNextPoll'](){if(!this['isPollingRunning'])return;const a=this['getNextPollInterval']();this['pollingTimer']=setTimeout(()=>{this['poll']()['catch'](b=>{})['finally'](()=>{this['scheduleNextPoll']();});},a);}['getNextPollInterval'](){if(this['waitingMessages']['size']>0x0)return this['config']['message_poll_waiting_interval_ms']??0x3*0x3e8;return this['currentMessageInterval'];}async['poll'](){if(!this['userAddress'])return;try{const a=await this['pullMessages']();a['messages']['length']>0x0?(this['messageConsecutiveEmptyPulls']=0x0,this['currentMessageInterval']=this['config']['message_poll_fast_interval_ms']??0x6*0x3e8,this['onMessageCallback']&&this['onMessageCallback'](a['messages'])):(this['messageConsecutiveEmptyPulls']++,this['messageConsecutiveEmptyPulls']>=(this['config']['message_poll_consecutive_empty_limit']??0x3)&&(this['currentMessageInterval']=this['config']['message_poll_default_interval_ms']??0x6*0x3c*0x3e8,this['messageConsecutiveEmptyPulls']=0x0));if(a['prekey_status']){const b=a['prekey_status'];b['shouldRefill']?(this['prekeyConsecutiveOkCount']=0x0,await this['checkAndRefillPrekeys']()):(this['prekeyConsecutiveOkCount']++,this['prekeyConsecutiveOkCount']>=(this['config']['prekey_poll_consecutive_ok_limit']??0x3)&&(this['prekeyConsecutiveOkCount']=0x0));}}catch(c){}}['triggerFastPoll'](){this['currentMessageInterval']=this['config']['message_poll_fast_interval_ms']??0x6*0x3e8,this['messageConsecutiveEmptyPulls']=0x0,this['isPollingRunning']&&(this['pollingTimer']&&clearTimeout(this['pollingTimer']),this['scheduleNextPoll']());}async['sendMessage'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=Date['now'](),e=Date['now'](),f=this['generateNonce'](),g=new TextEncoder()['encode'](b)['length'];if(g>NORMAL_MESSAGE_BYTES_LIMIT)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'Message\x20size\x20('+g+'\x20bytes)\x20exceeds\x20maximum\x20allowed\x20size\x20('+NORMAL_MESSAGE_BYTES_LIMIT+'\x20bytes).\x20Consider\x20using\x20sendZipFile\x20for\x20large\x20content.');await this['pullMessages']();const h=this['messageStorage']['getLastReceivedLeafIndex'](this['userAddress'],a),i=await this['session']['encryptMessage'](this['userAddress'],a,b),j=Buffer['from'](new Uint8Array(i['body']))['toString']('base64'),k=hashPlaintext(b,d,c?.['guardAddress'],c?.['passportAddress'],h),l=await(await getAccount())['get'](this['userAddress'],![]);if(!l)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20account\x20not\x20found');const m=l['pubkey'],n=c?.['guardAddress']||'',o=c?.['passportAddress']||'',p=h>=0x0?h['toString']():'',q=c?.['force']?'true':'false',r='send_message:'+this['userAddress']+':'+a+':'+n+':'+o+':'+k+':'+p+':'+m+':'+e+':'+f+':'+q,s=await(await getAccount())['signData'](this['userAddress'],r),t=Buffer['from'](s['signature']['slice'](0x2),'hex'),u=bytesToBase64(new Uint8Array(t)),v=await this['serverClient']['sendMessage']({'sender':s['publicKey'],'recipient':a,'ciphertext':j,'plaintextHash':k,'clientTimestamp':d,'msgType':i['type'],'signatureScheme':'Falcon512','signature':u,'timestamp':e,'nonce':f,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'force':c?.['force'],'lastReceivedLeafIndex':h>=0x0?h:undefined}),w={'messageId':v['messageId'],'fromAddress':this['userAddress'],'toAddress':a,'plaintextHash':k,'plaintext':b,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'lastReceivedLeafIndex':h,'direction':MessageDirection['SENT'],'status':v['status']==='confirmed'?MessageStatus['CONFIRMED']:MessageStatus['PENDING'],'msgType':i['type'],'createdAt':d};v['merkleData']&&(w['leafIndex']=v['merkleData']['leafIndex'],w['prevRoot']=v['merkleData']['prevRoot'],w['newRoot']=v['merkleData']['newRoot'],w['serverSignature']=v['merkleData']['serverSignature'],w['serverTimestamp']=v['merkleData']['serverTimestamp'],w['serverPublicKey']=v['merkleData']['serverPublicKey'],this['sessionStateStorage']['updateSessionState'](this['userAddress'],a,{'currentRoot':v['merkleData']['newRoot'],'prevRoot':v['merkleData']['prevRoot'],'lastLeafIndex':v['merkleData']['leafIndex'],'lastSyncAt':Date['now']()}));this['messageStorage']['saveMessage'](w);if(v['pendingMerkleData'])for(const [x,y]of Object['entries'](v['pendingMerkleData'])){const z=this['messageStorage']['getMessage'](x);z&&z['status']===MessageStatus['PENDING']&&this['messageStorage']['updateMessageStatus'](x,MessageStatus['CONFIRMED'],{'leafIndex':y['leafIndex'],'newRoot':y['newRoot'],'serverSignature':y['serverSignature'],'serverTimestamp':y['serverTimestamp'],'serverPublicKey':y['serverPublicKey']});}return this['triggerFastPoll'](),{'messageId':v['messageId'],'status':w['status'],'merkleData':v['merkleData'],'guardList':v['guard_list'],'lastReceivedLeafIndex':h>=0x0?h:undefined};}async['pullMessages'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=Date['now'](),c=this['generateNonce'](),d='fetch_messages:'+this['userAddress']+':'+(a||0x64)+':'+b+':'+c,e=await(await getAccount())['get'](this['userAddress'],![]),f=e?.['pubkey']||'',g=await(await getAccount())['signData'](this['userAddress'],d),h=Buffer['from'](g['signature']['slice'](0x2),'hex'),i={'signatureScheme':'Falcon512','signature':bytesToBase64(h),'timestamp':b,'nonce':c},j=await this['serverClient']['pullMessages'](this['userAddress'],f,i,a);if(j['messages']['length']===0x0)return{'messages':[],'prekey_status':j['prekey_status']};const k=[],l=[],m=[...j['messages']]['sort'](function(n,o){return(n['clientTimestamp']||0x0)-(o['clientTimestamp']||0x0);});await this['processWaitingMessages'](k,l);for(const n of m){if(this['waitingMessages']['has'](n['id'])){l['push'](n['id']);continue;}if(this['failedMessages']['has'](n['id'])){l['push'](n['id']);continue;}const o=this['messageStorage']['getMessage'](n['id']);if(o){l['push'](n['id']);continue;}const p=await this['tryDecryptMessage'](n);if(p['success']&&p['message']&&p['decryptedData'])this['messageStorage']['saveMessage'](p['message']),k['push'](p['decryptedData']),l['push'](n['id']),this['waitingMessages']['delete'](n['id']);else p['shouldRetry']?this['waitingMessages']['set'](n['id'],n):(this['failedMessages']['set'](n['id'],{'message':n,'error':p['error']||'Unknown\x20error'}),await this['saveFailedMessage'](n,p['error']||'Unknown\x20error'),l['push'](n['id']));}this['waitingMessages']['size']>0x0&&this['isPollingRunning']&&this['reschedulePolling']();if(l['length']>0x0&&this['userAddress']){const q=Date['now'](),r=this['generateNonce'](),s=await(await getAccount())['get'](this['userAddress'],![]);if(s?.['pubkey']){const t='ack_messages:'+this['userAddress']+':'+l['join'](',')+':'+s['pubkey']+':'+q+':'+r,u=await(await getAccount())['signData'](this['userAddress'],t),v=Buffer['from'](u['signature']['slice'](0x2),'hex'),w=bytesToBase64(new Uint8Array(v));await this['serverClient']['acknowledgeMessages'](l,u['publicKey'],{'publicKey':u['publicKey'],'signatureScheme':'Falcon512','signature':w,'timestamp':q,'nonce':r});}}return{'messages':k,'prekey_status':j['prekey_status']};}['getLastSentLeafIndex'](a){if(!this['userAddress'])return-0x1;const b=this['messageStorage']['getMessagesBySession'](this['userAddress'],a),c=b['filter'](d=>d['direction']===MessageDirection['SENT']&&d['leafIndex']!==undefined);if(c['length']===0x0)return-0x1;return Math['max'](...c['map'](d=>d['leafIndex']));}['getSessionMessages'](a){if(!this['userAddress'])return[];return this['messageStorage']['getMessagesBySession'](this['userAddress'],a);}['getSessionState'](a){if(!this['userAddress'])return undefined;return this['sessionStateStorage']['getSessionState'](this['userAddress'],a);}async['submitChainProof'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=this['sessionStateStorage']['getSessionState'](this['userAddress'],b);if(!d||!d['currentRoot'])throw new MessengerError(MessengerErrorCode['SESSION_NOT_ESTABLISHED'],'No\x20session\x20state\x20found');const e=this['messageStorage']['getMessagesBySession'](this['userAddress'],b),f=e[e['length']-0x1];if(!f||!f['serverPublicKey']||!f['serverSignature'])throw new MessengerError(MessengerErrorCode['INVALID_PROOF'],'No\x20temporal\x20proof\x20(missing\x20server\x20public\x20key\x20or\x20signature),\x20cannot\x20submit\x20Proof\x20to\x20WoWok\x20blockchain');const g=f['serverPublicKey'],h=f['serverSignature'],i={'sessionId':d['sessionId'],'merkleRoot':d['currentRoot'],'messageCount':d['messageCount'],'timestamp':Date['now']()},{CallProof:j}=await import('../call/proof.js'),k=new j({'proof':JSON['stringify'](i),'server_pubkey':g,'server_signature':h,'proof_type':CHAIN_PROOF_TYPE,'description':c||'Messenger\x20session\x20proof\x20for\x20'+this['userAddress']+'\x20<->\x20'+b,'item_count':d['messageCount'],'about_address':d['sessionId']}),l=await k['call'](a),m=l?.['objectChanges'],n=m?.['find'](o=>o['objectType']?.['includes']('Proof'))?.['objectId'];return{'proofAddress':n||'','txHash':l?.['digest']||''};}['destroy'](){this['stopPollingTimer']();}['disconnect'](){this['destroy']();}['setOnMessageCallback'](a){this['onMessageCallback']=a;}async['sendZipFile'](a,b,c){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const d=await this['loadFileData'](b),{ZipWriter:e,BlobWriter:f,Uint8ArrayReader:g}=await import('@zip.js/zip.js'),h=c?.['fileName']||a185b['basename'](b)||'file.zip',i=c?.['contentType']||this['detectContentType'](h),j=new f('application/zip'),k=new e(j);await k['add'](h,new g(d)),await k['close']();const l=await j['getData'](),m=new Uint8Array(await l['arrayBuffer']());if(m['length']>WTS_FILE_BYTES_LIMIT)throw new MessengerError(MessengerErrorCode['INVALID_INPUT'],'ZIP\x20file\x20size\x20('+m['length']+'\x20bytes)\x20exceeds\x20local\x20maximum\x20allowed\x20size\x20('+WTS_FILE_BYTES_LIMIT+'\x20bytes)');const n='0x'+createHash('sha256')['update'](m)['digest']('hex'),o=Buffer['from'](m)['toString']('base64'),p={'fileName':h+'.zip','fileSize':m['length'],'fileHash':n,'contentType':i};await this['pullMessages']();const q=this['messageStorage']['getLastReceivedLeafIndex'](this['userAddress'],a),r=Date['now'](),s=await this['session']['encryptMessage'](this['userAddress'],a,o),t=Buffer['from'](new Uint8Array(s['body']))['toString']('base64'),u=c?.['guardAddress']||'',v=c?.['passportAddress']||'',w=hashPlaintext(o,r,u,v,q),x=Date['now'](),y=this['generateNonce'](),z=await(await getAccount())['get'](this['userAddress'],![]);if(!z)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20account\x20not\x20found');const A=z['pubkey'],B=q>=0x0?q['toString']():'',C=c?.['force']?'true':'false',D='send_message:'+this['userAddress']+':'+a+':'+u+':'+v+':'+w+':'+B+':'+A+':'+x+':'+y+':'+C,E=await(await getAccount())['signData'](this['userAddress'],D),F=Buffer['from'](E['signature']['slice'](0x2),'hex'),G=bytesToBase64(new Uint8Array(F)),H=await this['serverClient']['sendMessage']({'sender':E['publicKey'],'recipient':a,'ciphertext':t,'plaintextHash':w,'clientTimestamp':r,'msgType':s['type'],'zipMetadata':p,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'force':c?.['force'],'lastReceivedLeafIndex':q>=0x0?q:undefined,'signatureScheme':'Falcon512','signature':G,'timestamp':x,'nonce':y}),I={'messageId':H['messageId'],'fromAddress':this['userAddress'],'toAddress':a,'plaintextHash':w,'plaintext':o,'guardAddress':c?.['guardAddress'],'passportAddress':c?.['passportAddress'],'lastReceivedLeafIndex':q,'direction':MessageDirection['SENT'],'status':H['status']==='confirmed'?MessageStatus['CONFIRMED']:MessageStatus['PENDING'],'msgType':s['type'],'zipMetadata':p,'createdAt':r};H['merkleData']&&(I['leafIndex']=H['merkleData']['leafIndex'],I['prevRoot']=H['merkleData']['prevRoot'],I['newRoot']=H['merkleData']['newRoot'],I['serverSignature']=H['merkleData']['serverSignature'],I['serverTimestamp']=H['merkleData']['serverTimestamp'],I['serverPublicKey']=H['merkleData']['serverPublicKey'],this['sessionStateStorage']['updateSessionState'](this['userAddress'],a,{'currentRoot':H['merkleData']['newRoot'],'prevRoot':H['merkleData']['prevRoot'],'lastLeafIndex':H['merkleData']['leafIndex'],'lastSyncAt':Date['now']()}));this['messageStorage']['saveMessage'](I);if(H['pendingMerkleData'])for(const [J,K]of Object['entries'](H['pendingMerkleData'])){const L=this['messageStorage']['getMessage'](J);L&&L['status']===MessageStatus['PENDING']&&this['messageStorage']['updateMessageStatus'](J,MessageStatus['CONFIRMED'],{'leafIndex':K['leafIndex'],'newRoot':K['newRoot'],'serverSignature':K['serverSignature'],'serverTimestamp':K['serverTimestamp'],'serverPublicKey':K['serverPublicKey']});}return this['triggerFastPoll'](),{'messageId':H['messageId'],'status':I['status'],'merkleData':H['merkleData'],'guardList':H['guard_list'],'lastReceivedLeafIndex':q>=0x0?q:undefined};}async['loadFileData'](a){if(a['startsWith']('http://')||a['startsWith']('https://')){const d=await fetch(a);if(!d['ok'])throw new MessengerError(MessengerErrorCode['NETWORK_ERROR'],'Failed\x20to\x20fetch\x20file\x20from\x20'+a+':\x20'+d['statusText']);const e=await d['arrayBuffer']();return new Uint8Array(e);}const b=a185b['resolve'](a);if(!a185a['existsSync'](b))throw new MessengerError(MessengerErrorCode['FILE_NOT_FOUND'],'File\x20not\x20found:\x20'+b);const c=a185a['readFileSync'](b);return new Uint8Array(c);}['detectContentType'](a){const b=a185b['extname'](a)['toLowerCase']();switch(b){case'.wts':return'wts';case'.wip':return'wip';default:return'zip';}}async['_createSignedRequest'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b=Date['now'](),c=this['generateNonce'](),d=canonicalizeJson(a),e=b+':'+c+':'+d,f=await(await getAccount())['signData'](this['userAddress'],e),g=Buffer['from'](f['signature']['slice'](0x2),'hex'),h=bytesToBase64(new Uint8Array(g)),i=await(await getAccount())['get'](this['userAddress'],![]);if(!i||!i['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20public\x20key\x20not\x20found');return{'userAddress':this['userAddress'],'publicKey':i['pubkey'],'signatureScheme':'Falcon512','signature':h,'timestamp':b,'nonce':c,'data':a};}['_validateAddresses'](a){const b=[],c=[];for(const d of a){isValidWowAddress(d)?b['push'](d):c['push'](d);}return{'valid':b,'invalid':c};}async['addToBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'add','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['addToBlacklist'](this['userAddress'],e);}async['removeFromBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromBlacklist'](this['userAddress'],e);}async['clearBlacklist'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a={},b=await this['_createSignedRequest'](a);return this['serverClient']['clearBlacklist'](this['userAddress'],b);}async['getBlacklist'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getBlacklist'](this['userAddress'],a);}async['existInBlacklist'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'exist','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['existInBlacklist'](this['userAddress'],e);}async['addToFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'add','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['addToFriendsList'](this['userAddress'],e);}async['removeFromFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromFriendsList'](this['userAddress'],e);}async['clearFriendsList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a={},b=await this['_createSignedRequest'](a);return this['serverClient']['clearFriendsList'](this['userAddress'],b);}async['getFriendsList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getFriendsList'](this['userAddress'],a);}async['existInFriendsList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'exist','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['existInFriendsList'](this['userAddress'],e);}async['addToGuardList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b={'guards':a},c=await this['_createSignedRequest'](b);return this['serverClient']['addToGuardList'](this['userAddress'],c);}async['removeFromGuardList'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const {valid:b,invalid:c}=this['_validateAddresses'](a);if(c['length']>0x0)return{'success':![],'operation':'remove','modifiedCount':0x0,'currentCount':0x0,'maxCount':0x0,'invalidAddresses':c,'message':'Invalid\x20addresses:\x20'+c['join'](',\x20')};const d={'addresses':b},e=await this['_createSignedRequest'](d);return this['serverClient']['removeFromGuardList'](this['userAddress'],e);}async['getGuardList'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getGuardList'](this['userAddress'],a);}async['getSettings'](){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const a=await this['_createSignedRequest']({});return this['serverClient']['getSettings'](this['userAddress'],a);}async['setSettings'](a){if(!this['userAddress'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'User\x20address\x20not\x20set');const b={'allowStrangerMessages':a['allowStrangerMessages'],'maxInboxSize':a['maxInboxSize']},c=await this['_createSignedRequest'](b);return this['serverClient']['updateSettings'](this['userAddress'],c);}async['tryDecryptMessage'](a){try{const b=Uint8Array['from'](Buffer['from'](a['bodyB64'],'base64')),c=await this['decryptionEngine']['decryptMessage'](this['userAddress'],a['from'],b['buffer'],a['msgType']);if(!c['success']){const h=this['isRetryableError'](c['error']||'');return{'success':![],'shouldRetry':h,'error':c['error'],'sessionUpdated':c['sessionUpdated']};}const d=c['plaintext'];if(!a['clientTimestamp'])throw new Error('Missing\x20clientTimestamp\x20for\x20message\x20'+a['id']);if(!a['plaintextHash'])throw new Error('Missing\x20plaintextHash\x20for\x20message\x20'+a['id']);const e=verifyMessage({'messageId':a['id'],'plaintext':d,'plaintextHash':a['plaintextHash'],'createdAt':a['clientTimestamp'],'guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'merkleMetadata':a['merkleMetadata']?{'prevRoot':a['merkleMetadata']['prevRoot'],'newRoot':a['merkleMetadata']['newRoot'],'serverTimestamp':a['merkleMetadata']['serverTimestamp'],'leafIndex':a['merkleMetadata']['leafIndex'],'proofSiblings':a['merkleMetadata']['proofSiblings'],'proofIndices':a['merkleMetadata']['proofIndices']}:undefined});if(!e['valid'])throw new Error(e['error']);const f={'messageId':a['id'],'fromAddress':a['from'],'toAddress':this['userAddress'],'plaintextHash':a['plaintextHash'],'plaintext':d,'guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'direction':MessageDirection['RECEIVED'],'status':MessageStatus['DECRYPTED'],'msgType':a['msgType'],'leafIndex':a['merkleMetadata']?.['leafIndex'],'prevRoot':a['merkleMetadata']?.['prevRoot'],'newRoot':a['merkleMetadata']?.['newRoot'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverTimestamp':a['merkleMetadata']?.['serverTimestamp'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'createdAt':a['clientTimestamp'],'receivedAt':Date['now'](),'zipMetadata':a['zipMetadata']};a['merkleMetadata']&&this['sessionStateStorage']['updateSessionState'](this['userAddress'],a['from'],{'currentRoot':a['merkleMetadata']['newRoot'],'prevRoot':a['merkleMetadata']['prevRoot'],'lastLeafIndex':a['merkleMetadata']['leafIndex'],'lastSyncAt':Date['now']()});const g=a['merkleMetadata']?.['serverTimestamp']||a['clientTimestamp']||Date['now']();if(a['lastReceivedLeafIndex']!==undefined&&a['lastReceivedLeafIndex']>=0x0){const i=this['messageStorage']['getMessagesBySession'](this['userAddress'],a['from'])['filter'](j=>j['direction']===MessageDirection['SENT']&&j['status']===MessageStatus['CONFIRMED']&&j['leafIndex']!==undefined&&j['leafIndex']<=a['lastReceivedLeafIndex']);for(const j of i){this['messageStorage']['updateMessageStatus'](j['messageId'],MessageStatus['READ']);}}return{'success':!![],'shouldRetry':![],'message':f,'decryptedData':{'id':a['id'],'from':a['from'],'plaintext':d,'timestamp':g,'merkleVerified':!!a['merkleMetadata'],'merkleData':a['merkleMetadata']?{'leafIndex':a['merkleMetadata']['leafIndex'],'rootHash':a['merkleMetadata']['newRoot']}:undefined},'sessionUpdated':c['sessionUpdated']};}catch(k){const l=k instanceof Error?k['message']:String(k),m=this['isRetryableError'](l);return{'success':![],'shouldRetry':m,'error':l};}}['isRetryableError'](a){const b=[/message number/i,/chain key/i,/session not found/i,/prekey not found/i,/PREKEY 竞争:我的地址较小,保留我的会话/i,/The operation failed for an operation-specific reason/i,/DOMException/i,/收到 WHISPER_MESSAGE 但无现有会话,需要等待 PREKEY_MESSAGE/i];return b['some'](c=>c['test'](a));}async['processWaitingMessages'](a,b){if(this['waitingMessages']['size']===0x0)return;const c=[],d=Array['from'](this['waitingMessages']['values']())['sort'](function(e,f){return(e['clientTimestamp']||0x0)-(f['clientTimestamp']||0x0);});for(const e of d){const f=e['id'],g=await this['tryDecryptMessage'](e);if(g['success']&&g['message']&&g['decryptedData'])this['messageStorage']['saveMessage'](g['message']),a['push'](g['decryptedData']),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f);else{if(!g['shouldRetry'])this['failedMessages']['set'](f,{'message':e,'error':g['error']||'Unknown\x20error'}),await this['saveFailedMessage'](e,g['error']||'Unknown\x20error'),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f);else{const h=this['waitingMessageRetries']['get'](f)||0x0,i=h+0x1;i>=0x3?(this['failedMessages']['set'](f,{'message':e,'error':g['error']||'Retry\x20limit\x20exceeded'}),await this['saveFailedMessage'](e,g['error']||'Retry\x20limit\x20exceeded'),b['push'](f),c['push'](f),this['waitingMessageRetries']['delete'](f)):this['waitingMessageRetries']['set'](f,i);}}}for(const j of c){this['waitingMessages']['delete'](j);}if(c['length']>0x0){}}async['saveFailedMessage'](a,b){const c={'messageId':a['id'],'fromAddress':a['from'],'toAddress':this['userAddress'],'plaintextHash':a['plaintextHash']||'','guardAddress':a['guardAddress'],'passportAddress':a['passportAddress'],'lastReceivedLeafIndex':a['lastReceivedLeafIndex'],'direction':MessageDirection['RECEIVED'],'status':MessageStatus['DECRYPT_FAILED'],'msgType':a['msgType'],'leafIndex':a['merkleMetadata']?.['leafIndex'],'prevRoot':a['merkleMetadata']?.['prevRoot'],'newRoot':a['merkleMetadata']?.['newRoot'],'serverSignature':a['merkleMetadata']?.['serverSignature'],'serverTimestamp':a['merkleMetadata']?.['serverTimestamp'],'serverPublicKey':a['merkleMetadata']?.['serverPublicKey'],'createdAt':a['clientTimestamp']||Date['now'](),'receivedAt':Date['now'](),'zipMetadata':a['zipMetadata'],'decryptError':b,'decryptAttempts':0x1,'lastDecryptAttemptAt':Date['now']()};this['messageStorage']['saveMessage'](c);}['reschedulePolling'](){if(!this['isPollingRunning']||!this['pollingTimer'])return;clearTimeout(this['pollingTimer']),this['pollingTimer']=null,this['scheduleNextPoll']();}['getFailedMessages'](){return Array['from'](this['failedMessages']['entries']())['map'](([a,b])=>({'messageId':a,'from':b['message']['from'],'error':b['error'],'leafIndex':b['message']['merkleMetadata']?.['leafIndex']}));}['clearFailedMessages'](a){a?this['failedMessages']['delete'](a):this['failedMessages']['clear']();}['getWaitingMessageCount'](){return this['waitingMessages']['size'];}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{x25519}from'@noble/curves/ed25519';import{falcon512padded}from'@noble/post-quantum/falcon.js';import{sha256}from'@noble/hashes/sha256';import{hmac}from'@noble/hashes/hmac';import{hkdf}from'@noble/hashes/hkdf';import{randomBytes}from'@noble/hashes/utils';import{ml_kem768}from'@noble/post-quantum/ml-kem.js';import
|
|
1
|
+
import{x25519}from'@noble/curves/ed25519';import{falcon512padded}from'@noble/post-quantum/falcon.js';import{sha256}from'@noble/hashes/sha256';import{hmac}from'@noble/hashes/hmac';import{hkdf}from'@noble/hashes/hkdf';import{randomBytes}from'@noble/hashes/utils';import{ml_kem768}from'@noble/post-quantum/ml-kem.js';import a186a from'node:crypto';import{ROOT_KEY_SIZE,CHAIN_KEY_SIZE,MESSAGE_KEY_SIZE,DH_KEY_SIZE,AES_GCM_IV_SIZE}from'./types.js';export function generateRandomBytes(a){return randomBytes(a);}export function generateX25519KeyPair(){const a=randomBytes(DH_KEY_SIZE),b=x25519['getPublicKey'](a);return{'publicKey':b,'privateKey':a};}export function x25519DH(a,b){return x25519['getSharedSecret'](a,b);}export function generateFalcon512KeyPair(){const {publicKey:a,secretKey:b}=falcon512padded['keygen']();return{'publicKey':a,'privateKey':b};}export function falcon512Sign(a,b){return falcon512padded['sign'](b,a);}export function falcon512Verify(a,b,c){try{return falcon512padded['verify'](c,b,a);}catch{return![];}}export function generateMLKEMKeyPair(){const {publicKey:a,secretKey:b}=ml_kem768['keygen']();return{'publicKey':a,'secretKey':b};}export function mlkemEncapsulate(a){const {cipherText:b,sharedSecret:c}=ml_kem768['encapsulate'](a);return{'ciphertext':b,'sharedSecret':c};}export function mlkemDecapsulate(a,b){return ml_kem768['decapsulate'](a,b);}export function hkdfDerive(a,b,c,d){return hkdf(sha256,a,d||new Uint8Array(0x0),b,c);}export function hkdfChainKey(a,b){const c=new Uint8Array(a['length']+b['length']);c['set'](a),c['set'](b,a['length']);const d=hkdfDerive(c,new TextEncoder()['encode']('WowokPQChainKey'),ROOT_KEY_SIZE+CHAIN_KEY_SIZE);return{'rootKey':d['slice'](0x0,ROOT_KEY_SIZE),'chainKey':d['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hkdfMessageKey(a){const b=hkdfDerive(a,new TextEncoder()['encode']('WowokPQMessageKey'),MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE);return{'messageKey':b['slice'](0x0,MESSAGE_KEY_SIZE),'nextChainKey':b['slice'](MESSAGE_KEY_SIZE,MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hmacSha256(a,b){return hmac(sha256,a,b);}export function aesGcmEncrypt(a,b,c){const d=randomBytes(AES_GCM_IV_SIZE),e=Buffer['from'](a),f=Buffer['from'](d),g=Buffer['from'](b),h=Buffer['from'](c),i=a186a['createCipheriv']('aes-256-gcm',e,f);i['setAAD'](h);const j=Buffer['concat']([i['update'](g),i['final']()]),k=i['getAuthTag']();return{'ciphertext':new Uint8Array(j),'iv':d,'tag':new Uint8Array(k)};}export function aesGcmDecrypt(a,b,c,d,e){const f=Buffer['from'](a),g=Buffer['from'](c),h=Buffer['from'](b),i=Buffer['from'](d),j=Buffer['from'](e),k=a186a['createDecipheriv']('aes-256-gcm',f,g);k['setAAD'](j),k['setAuthTag'](i);const l=Buffer['concat']([k['update'](h),k['final']()]);return new Uint8Array(l);}export function sha256Hash(a){return sha256(a);}export function constantTimeEqual(c,d){if(c['length']!==d['length'])return![];let e=0x0;for(let f=0x0;f<c['length'];f++){e|=c[f]^d[f];}return e===0x0;}export function bytesToBase64(a){return Buffer['from'](a)['toString']('base64');}export function base64ToBytes(a){return new Uint8Array(Buffer['from'](a,'base64'));}export function bytesToHex(a){return Buffer['from'](a)['toString']('hex');}export function hexToBytes(a){return new Uint8Array(Buffer['from'](a,'hex'));}export function concatBytes(...a){const b=a['reduce']((e,f)=>e+f['length'],0x0),c=new Uint8Array(b);let d=0x0;for(const e of a){c['set'](e,d),d+=e['length'];}return c;}export function deriveRegistrationId(a){const b=(a[0x0]<<0x8|a[0x1])>>>0x0;return b===0x0?0x1:b;}export function generateX25519BindingSignature(a,b){return falcon512Sign(a,b);}export function verifyX25519BindingSignature(a,b,c){return falcon512Verify(a,b,c);}
|