diff --git a/README.md b/README.md
index fd25893..facfd4c 100644
--- a/README.md
+++ b/README.md
@@ -2,30 +2,30 @@
Tides is a messaging application built as Chrome extension that enables secure and private communication using the Nostr protocol.
-
-
-
-
-
-
-
## Features
- Secure login via:
- - NIP-07 browser extension (recommended)
+ - NIP-07 browser extension
- Chrome storage
- Manual private key (nsec)
- Real-time encrypted messaging
-- Contact management with profile pictures and usernames
-- Message notifications with sound
-- Media sharing support (images, videos, GIFs)
+- Media link sharing and preview support:
+ - Images (PNG, JPG, WEBP, GIF)
+ - Videos (MP4, WEBM)
+ - YouTube videos
+ - Twitter/X posts
+ - Nostr notes and profiles
- Emoji picker
- Link previews
- Multi-relay support
+- Zaps support
+- Search history for contacts
+- Integrated Noderunners Radio stream
+
## Installation
-1. Download the latest release from the releases page
+1. Download the latest release (v1.1.0) from the releases page
2. Install in Chrome:
- Open Chrome and navigate to `chrome://extensions`
@@ -37,7 +37,7 @@ Tides is a messaging application built as Chrome extension that enables secure a
## Login Methods
-1. **NIP-07 Extension (Recommended)**
+1. **NIP-07 Extension**
- Install a Nostr signer extension (like nos2x or Alby)
- Click "Login with Extension" in Tides
@@ -57,13 +57,18 @@ Built using:
- Chrome Storage API for data persistence
- Web Notifications API
- Giphy API for GIF support
+- WebLN for Lightning Network integration
Supports NIPs:
- NIP-01: Basic protocol
- NIP-04: Encrypted Direct Messages
- NIP-05: DNS Identifiers
- NIP-07: Browser Extension
+- NIP-19: bech32-encoded entities
+- NIP-21: nostr: URL scheme
+- NIP-25: Reactions
- NIP-44: Versioned Encryption
+- NIP-57: Lightning Zaps
- NIP-89: Application Handlers
## Privacy & Security
@@ -73,6 +78,4 @@ Supports NIPs:
- Private keys never leave your device
- Open source and auditable
-## License
-MIT License - See LICENSE file for details
diff --git a/lib/emoji-picker.js b/lib/emoji-picker.js
new file mode 100644
index 0000000..c3e09de
--- /dev/null
+++ b/lib/emoji-picker.js
@@ -0,0 +1,26 @@
+// Basic emoji picker implementation
+class EmojiPicker {
+ constructor(options) {
+ this.onSelect = options.onSelect;
+ this.emojis = ['😊', '😂', '❤️', '👍', '😎', '🎉', '🔥', '✨'];
+ }
+
+ togglePicker(triggerElement) {
+ const picker = document.createElement('div');
+ picker.className = 'emoji-picker';
+ picker.innerHTML = this.emojis.map(emoji =>
+ `${emoji} `
+ ).join('');
+
+ picker.addEventListener('click', (e) => {
+ if (e.target.classList.contains('emoji-option')) {
+ this.onSelect(e.target.textContent);
+ picker.remove();
+ }
+ });
+
+ triggerElement.parentNode.appendChild(picker);
+ }
+}
+
+self.EmojiPicker = EmojiPicker;
diff --git a/lib/qrcode.min.js b/lib/qrcode.min.js
new file mode 100644
index 0000000..53e720c
--- /dev/null
+++ b/lib/qrcode.min.js
@@ -0,0 +1,8 @@
+/**
+ * Minified by jsDelivr using Terser v3.14.1.
+ * Original file: /npm/qrcode-generator@1.4.4/qrcode.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+var qrcode=function(){var t=function(t,r){var e=t,n=f[r],o=null,i=0,a=null,u=[],c={},g=function(t,r){o=function(t){for(var r=new Array(t),e=0;e=7&&v(t),null==a&&(a=y(e,n,u)),w(a,r)},l=function(t,r){for(var e=-1;e<=7;e+=1)if(!(t+e<=-1||i<=t+e))for(var n=-1;n<=7;n+=1)r+n<=-1||i<=r+n||(o[t+e][r+n]=0<=e&&e<=6&&(0==n||6==n)||0<=n&&n<=6&&(0==e||6==e)||2<=e&&e<=4&&2<=n&&n<=4)},h=function(){for(var t=8;t>n&1);o[Math.floor(n/3)][n%3+i-8-3]=a}for(n=0;n<18;n+=1){a=!t&&1==(r>>n&1);o[n%3+i-8-3][Math.floor(n/3)]=a}},d=function(t,r){for(var e=n<<3|r,a=p.getBCHTypeInfo(e),u=0;u<15;u+=1){var f=!t&&1==(a>>u&1);u<6?o[u][8]=f:u<8?o[u+1][8]=f:o[i-15+u][8]=f}for(u=0;u<15;u+=1){f=!t&&1==(a>>u&1);u<8?o[8][i-u-1]=f:u<9?o[8][15-u-1+1]=f:o[8][15-u-1]=f}o[i-8][8]=!t},w=function(t,r){for(var e=-1,n=i-1,a=7,u=0,f=p.getMaskFunction(r),c=i-1;c>0;c-=2)for(6==c&&(c-=1);;){for(var g=0;g<2;g+=1)if(null==o[n][c-g]){var l=!1;u>>a&1)),f(n,c-g)&&(l=!l),o[n][c-g]=l,-1==(a-=1)&&(u+=1,a=7)}if((n+=e)<0||i<=n){n-=e,e=-e;break}}},y=function(t,r,e){for(var n=C.getRSBlocks(t,r),o=k(),i=0;i8*u)throw"code length overflow. ("+o.getLengthInBits()+">"+8*u+")";for(o.getLengthInBits()+4<=8*u&&o.put(0,4);o.getLengthInBits()%8!=0;)o.putBit(!1);for(;!(o.getLengthInBits()>=8*u||(o.put(236,8),o.getLengthInBits()>=8*u));)o.put(17,8);return function(t,r){for(var e=0,n=0,o=0,i=new Array(r.length),a=new Array(r.length),u=0;u=0?h.getAt(s):0}}var v=0;for(g=0;gn)&&(t=n,r=e)}return r}())},c.createTableTag=function(t,r){t=t||2;var e="";e+='',e+="";for(var n=0;n";for(var o=0;o ';e+=""}return e+=" ",e+="
"},c.createSvgTag=function(t,r,e,n){var o={};"object"==typeof arguments[0]&&(t=(o=arguments[0]).cellSize,r=o.margin,e=o.alt,n=o.title),t=t||2,r=void 0===r?4*t:r,(e="string"==typeof e?{text:e}:e||{}).text=e.text||null,e.id=e.text?e.id||"qrcode-description":null,(n="string"==typeof n?{text:n}:n||{}).text=n.text||null,n.id=n.text?n.id||"qrcode-title":null;var i,a,u,f,g=c.getModuleCount()*t+2*r,l="";for(f="l"+t+",0 0,"+t+" -"+t+",0 0,-"+t+"z ",l+='",l+=n.text?''+m(n.text)+" ":"",l+=e.text?''+m(e.text)+" ":"",l+=' ',l+=' ',l+=" "},c.createDataURL=function(t,r){t=t||2,r=void 0===r?4*t:r;var e=c.getModuleCount()*t+2*r,n=r,o=e-r;return D(e,e,function(r,e){if(n<=r&&r "};var m=function(t){for(var r="",e=0;e":r+=">";break;case"&":r+="&";break;case'"':r+=""";break;default:r+=n}}return r};return c.createASCII=function(t,r){if((t=t||1)<2)return function(t){t=void 0===t?2:t;var r,e,n,o,i,a=1*c.getModuleCount()+2*t,u=t,f=a-t,g={"██":"█","█ ":"▀"," █":"▄"," ":" "},l={"██":"▀","█ ":"▀"," █":" "," ":" "},h="";for(r=0;r=f?l[i]:g[i];h+="\n"}return a%2&&t>0?h.substring(0,h.length-a-1)+Array(a+1).join("▀"):h.substring(0,h.length-1)}(r);t-=1,r=void 0===r?2*t:r;var e,n,o,i,a=c.getModuleCount()*t+2*r,u=r,f=a-r,g=Array(t+1).join("██"),l=Array(t+1).join(" "),h="",s="";for(e=0;e >>8),r.push(255&a)):r.push(n)}}return r}};var r,e,n,o=1,i=2,a=4,u=8,f={L:1,M:0,Q:3,H:2},c=0,g=1,l=2,h=3,s=4,v=5,d=6,w=7,p=(r=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],n=function(t){for(var r=0;0!=t;)r+=1,t>>>=1;return r},(e={}).getBCHTypeInfo=function(t){for(var r=t<<10;n(r)-n(1335)>=0;)r^=1335<=0;)r^=7973<5&&(e+=3+i-5)}for(n=0;n=256;)r-=255;return t[r]}};return n}();function B(t,r){if(void 0===t.length)throw t.length+"/"+r;var e=function(){for(var e=0;e>>7-r%8&1)},put:function(t,r){for(var n=0;n>>r-n-1&1))},getLengthInBits:function(){return r},putBit:function(e){var n=Math.floor(r/8);t.length<=n&&t.push(0),e&&(t[n]|=128>>>r%8),r+=1}};return e},A=function(t){var r=o,e=t,n={getMode:function(){return r},getLength:function(t){return e.length},write:function(t){for(var r=e,n=0;n+2>>8&255)+(255&n),t.put(n,13),e+=2}if(e>>8)},writeBytes:function(t,e,n){e=e||0,n=n||t.length;for(var o=0;o0&&(r+=","),r+=t[e];return r+="]"}};return r},L=function(t){var r=t,e=0,n=0,o=0,i={read:function(){for(;o<8;){if(e>=r.length){if(0==o)return-1;throw"unexpected end of file./"+o}var t=r.charAt(e);if(e+=1,"="==t)return o=0,-1;t.match(/^\s$/)||(n=n<<6|a(t.charCodeAt(0)),o+=6)}var i=n>>>o-8&255;return o-=8,i}},a=function(t){if(65<=t&&t<=90)return t-65;if(97<=t&&t<=122)return t-97+26;if(48<=t&&t<=57)return t-48+52;if(43==t)return 62;if(47==t)return 63;throw"c:"+t};return i},D=function(t,r,e){for(var n=function(t,r){var e=t,n=r,o=new Array(t*r),i={setPixel:function(t,r,n){o[r*e+t]=n},write:function(t){t.writeString("GIF87a"),t.writeShort(e),t.writeShort(n),t.writeByte(128),t.writeByte(0),t.writeByte(0),t.writeByte(0),t.writeByte(0),t.writeByte(0),t.writeByte(255),t.writeByte(255),t.writeByte(255),t.writeString(","),t.writeShort(0),t.writeShort(0),t.writeShort(e),t.writeShort(n),t.writeByte(0);var r=a(2);t.writeByte(2);for(var o=0;r.length-o>255;)t.writeByte(255),t.writeBytes(r,o,255),o+=255;t.writeByte(r.length-o),t.writeBytes(r,o,r.length-o),t.writeByte(0),t.writeString(";")}},a=function(t){for(var r=1<>>r!=0)throw"length over";for(;c+r>=8;)f.writeByte(255&(t<>>=8-c,g=0,c=0;g|=t<0&&f.writeByte(g)}});h.write(r,n);var s=0,v=String.fromCharCode(o[s]);for(s+=1;s=6;)h(u>>>f-6),f-=6},l.flush=function(){if(f>0&&(h(u<<6-f),u=0,f=0),c%3!=0)for(var t=3-c%3,r=0;r>6,128|63&n):n<55296||n>=57344?r.push(224|n>>12,128|n>>6&63,128|63&n):(e++,n=65536+((1023&n)<<10|1023&t.charCodeAt(e)),r.push(240|n>>18,128|n>>12&63,128|n>>6&63,128|63&n))}return r}(t)},function(t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports&&(module.exports=t())}(function(){return qrcode});
+//# sourceMappingURL=/sm/467f1e4dbdb6a7c0f745f3affd92b4084db234a4e15305cb31384a24c2a4b457.map
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..98cf105
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1111 @@
+{
+ "name": "tides",
+ "version": "1.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "tides",
+ "version": "1.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "emoji-picker-element": "^1.23.0",
+ "nostr-tools": "^1.17.0",
+ "qrcode-generator": "^1.4.4"
+ },
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^25.0.2",
+ "@rollup/plugin-node-resolve": "^15.1.0",
+ "@rollup/plugin-terser": "^0.4.3",
+ "@types/chrome": "^0.0.260",
+ "rollup": "^2.79.1",
+ "rollup-plugin-copy": "^3.4.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@noble/ciphers": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz",
+ "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/curves": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
+ "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
+ "dependencies": {
+ "@noble/hashes": "1.3.1"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
+ "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@rollup/plugin-commonjs": {
+ "version": "25.0.8",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz",
+ "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "commondir": "^1.0.1",
+ "estree-walker": "^2.0.2",
+ "glob": "^8.0.3",
+ "is-reference": "1.2.1",
+ "magic-string": "^0.30.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.68.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-node-resolve": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz",
+ "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "@types/resolve": "1.20.2",
+ "deepmerge": "^4.2.2",
+ "is-module": "^1.0.0",
+ "resolve": "^1.22.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.78.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-terser": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
+ "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
+ "dev": true,
+ "dependencies": {
+ "serialize-javascript": "^6.0.1",
+ "smob": "^1.0.0",
+ "terser": "^5.17.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-terser/node_modules/serialize-javascript": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
+ "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@scure/base": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
+ "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/@scure/bip32": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
+ "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
+ "dependencies": {
+ "@noble/curves": "~1.1.0",
+ "@noble/hashes": "~1.3.1",
+ "@scure/base": "~1.1.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip39": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
+ "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
+ "dependencies": {
+ "@noble/hashes": "~1.3.0",
+ "@scure/base": "~1.1.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@types/chrome": {
+ "version": "0.0.260",
+ "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.260.tgz",
+ "integrity": "sha512-lX6QpgfsZRTDpNcCJ+3vzfFnFXq9bScFRTlfhbK5oecSAjamsno+ejFTCbNtc5O/TPnVK9Tja/PyecvWQe0F2w==",
+ "dev": true,
+ "dependencies": {
+ "@types/filesystem": "*",
+ "@types/har-format": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true
+ },
+ "node_modules/@types/filesystem": {
+ "version": "0.0.36",
+ "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz",
+ "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==",
+ "dev": true,
+ "dependencies": {
+ "@types/filewriter": "*"
+ }
+ },
+ "node_modules/@types/filewriter": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz",
+ "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==",
+ "dev": true
+ },
+ "node_modules/@types/fs-extra": {
+ "version": "8.1.5",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz",
+ "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/har-format": {
+ "version": "1.2.16",
+ "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz",
+ "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==",
+ "dev": true
+ },
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "22.7.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz",
+ "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@types/resolve": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
+ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
+ "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/emoji-picker-element": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/emoji-picker-element/-/emoji-picker-element-1.23.0.tgz",
+ "integrity": "sha512-eITYquXyUoaTkpxJxEMIzCO6y3xpFxLvLuIRbnG+fL5u0aicHzKFvjSScrOSEwqg+2LWUlDqu08vqBFvtBOAeQ=="
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globby": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
+ "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
+ "dev": true,
+ "dependencies": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/globby/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/globby/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globby/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
+ "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
+ "dev": true
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
+ "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-reference": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
+ "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.12",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
+ "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/nostr-tools": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz",
+ "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==",
+ "dependencies": {
+ "@noble/ciphers": "0.2.0",
+ "@noble/curves": "1.1.0",
+ "@noble/hashes": "1.3.1",
+ "@scure/base": "1.1.1",
+ "@scure/bip32": "1.3.1",
+ "@scure/bip39": "1.2.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/qrcode-generator": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz",
+ "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw=="
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "2.79.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
+ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rollup-plugin-copy": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz",
+ "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==",
+ "dev": true,
+ "dependencies": {
+ "@types/fs-extra": "^8.0.1",
+ "colorette": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "10.0.1",
+ "is-plain-object": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.3"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smob": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
+ "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
+ "dev": true
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.36.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
+ "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
index dd6fa53..8448084 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "tides",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "A Nostr-based Messenger",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
@@ -47,7 +47,8 @@
}
},
"scripts": {
- "build": "rollup -c && cp src/icons/*.png dist/icons/",
+ "prebuild": "mkdir -p dist/lib",
+ "build": "rollup -c && cp src/icons/*.png dist/icons/ && cp -r lib/* dist/lib/",
"start": "echo \"Starting...\"",
"clean": "rm -rf dist"
},
@@ -57,7 +58,8 @@
"license": "ISC",
"dependencies": {
"emoji-picker-element": "^1.23.0",
- "nostr-tools": "^1.17.0"
+ "nostr-tools": "^1.17.0",
+ "qrcode-generator": "^1.4.4"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.2",
diff --git a/rollup.config.js b/rollup.config.js
index 6bdc187..a8b4929 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -3,46 +3,49 @@ import commonjs from '@rollup/plugin-commonjs'
import terser from '@rollup/plugin-terser'
import copy from 'rollup-plugin-copy'
-const createConfig = (input, output, name) => ({
- input,
- output: {
- file: `dist/${output}`,
- format: 'iife',
- name,
- sourcemap: true,
- globals: {
- 'nostr-tools': 'NostrTools'
- }
- },
- external: ['nostr-tools'],
- plugins: [
- resolve({
- browser: true,
- preferBuiltins: false,
- mainFields: ['browser', 'module', 'main']
- }),
- commonjs({
- include: /node_modules/,
- transformMixedEsModules: true
- }),
- terser(),
- copy({
- targets: [
- { src: 'src/popup.html', dest: 'dist' },
- { src: 'src/style.css', dest: 'dist' },
- { src: 'src/manifest.json', dest: 'dist' },
- { src: 'src/sounds/*', dest: 'dist/sounds' },
- { src: 'src/icons/Logo.png', dest: 'dist/icons' },
- { src: 'src/icons/default-avatar.png', dest: 'dist/icons' },
- {
- src: 'node_modules/nostr-tools/lib/nostr.bundle.js',
- dest: 'dist/lib',
- rename: 'nostr-tools.js'
- }
- ]
- })
- ]
-});
+function createConfig(input, output, name) {
+ return {
+ input,
+ output: {
+ file: `dist/${output}`,
+ format: 'iife',
+ name,
+ globals: {
+ qrcode: 'qrcode',
+ 'nostr-tools': 'NostrTools'
+ }
+ },
+ external: ['qrcode', 'nostr-tools'],
+ plugins: [
+ resolve({
+ browser: true,
+ preferBuiltins: false,
+ mainFields: ['browser', 'module', 'main']
+ }),
+ commonjs({
+ include: /node_modules/,
+ transformMixedEsModules: true
+ }),
+ terser(),
+ copy({
+ targets: [
+ { src: 'src/popup.html', dest: 'dist' },
+ { src: 'src/style.css', dest: 'dist' },
+ { src: 'src/manifest.json', dest: 'dist' },
+ { src: 'src/sounds/*', dest: 'dist/sounds' },
+ { src: 'src/icons/Logo.png', dest: 'dist/icons' },
+ { src: 'src/icons/default-avatar.png', dest: 'dist/icons' },
+ {
+ src: 'node_modules/nostr-tools/lib/nostr.bundle.js',
+ dest: 'dist/lib',
+ rename: 'nostr-tools.js'
+ },
+ { src: 'node_modules/qrcode-generator/qrcode.min.js', dest: 'dist/lib' }
+ ]
+ })
+ ]
+ };
+}
export default [
createConfig('src/background.js', 'background.js', 'Background'),
diff --git a/src/auth.js b/src/auth.js
index 871db28..53c3c60 100644
--- a/src/auth.js
+++ b/src/auth.js
@@ -1,5 +1,5 @@
import { nostrCore, pool, RELAYS, shortenIdentifier } from './shared.js';
-import { validateEvent, getStoredCredentials } from './utils.js';
+import { validateEvent, getStoredCredentials, soundManager } from './utils.js';
import { storeMetadata } from './userMetadata.js';
class Auth {
@@ -30,6 +30,7 @@ class Auth {
if (user) {
await this.storeCredentials(user);
+ soundManager.play('login');
}
return user;
@@ -56,7 +57,6 @@ class Auth {
};
await this.storeCredentials(credentials);
- soundManager.play('login');
return credentials;
} catch (error) {
@@ -85,7 +85,6 @@ class Auth {
};
await this.storeCredentials(credentials);
- soundManager.play('login');
return credentials;
} catch (error) {
diff --git a/src/background.js b/src/background.js
index 2e3263e..58d6ed5 100644
--- a/src/background.js
+++ b/src/background.js
@@ -1,109 +1,401 @@
-// Core dependencies
-import { pool, relayPool, RELAYS, pubkeyToNpub, nostrCore } from './shared.js';
-import { validateEvent, toLowerCaseHex, soundManager } from './utils.js';
-import { auth } from './auth.js';
-import { messageManager, sendMessage, receiveMessage, fetchMessages } from './messages.js';
-import { fetchContacts, setContacts, processContactEvent } from './contact.js';
-import { getUserMetadata, getDisplayName, getAvatarUrl, storeMetadata } from './userMetadata.js';
-import { publishAppHandlerEvent } from './nip89.js';
-
-// Move to top level (after imports):
-let currentSubscription = null;
-
-// Register service worker
-self.addEventListener('install', async (event) => {
- console.log('Service Worker installing.');
- event.waitUntil(self.skipWaiting());
-});
-
-self.addEventListener('activate', async (event) => {
- console.log('Service Worker activated.');
- event.waitUntil(Promise.all([
- clients.claim(),
- auth.init()
- ]));
-});
-
-self.addEventListener('message', async (event) => {
- const { type, data } = event.data;
-
- if (type === 'LOGIN_SUCCESS') {
- const user = await auth.getCurrentUser();
- if (user) {
+var Background = (function(NostrTools) {
+ 'use strict';
+
+ // Core dependencies initialization from NostrTools
+ const nostrCore = {
+ nip19: NostrTools.nip19,
+ getPublicKey: NostrTools.getPublicKey,
+ getEventHash: NostrTools.getEventHash,
+ getSignature: NostrTools.getSignature
+ };
+
+ const pool = new NostrTools.SimplePool();
+ const RELAYS = [
+ "wss://relay.damus.io",
+ "wss://relay.nostr.band",
+ "wss://nos.lol",
+ "wss://relay.snort.social",
+ "wss://nostr.wine"
+ ];
+
+ // Utils
+ const validateEvent = (event) => {
+ try {
+ return event && 'object' === typeof event && event.id && event.pubkey &&
+ event.created_at && event.kind && event.content;
+ } catch (error) {
+ console.error('Event validation failed:', error);
+ return null;
+ }
+ };
+
+ const soundManager = new class {
+ constructor() {
+ this.sounds = new Map([
+ ['login', chrome.runtime.getURL('sounds/login.mp3')],
+ ['message', chrome.runtime.getURL('sounds/icq_message.mp3')]
+ ]);
+ this.played = new Set();
+ this.enabled = true;
+ }
+
+ async play(type, once = false) {
+ if (!this.enabled || (once && this.played.has(type))) return;
+ const soundUrl = this.sounds.get(type);
+ if (soundUrl) {
+ try {
+ const audio = new Audio(soundUrl);
+ if (type === 'login') {
+ audio.volume = 0.1;
+ }
+ await audio.play();
+ if (once) this.played.add(type);
+ } catch (error) {
+ console.error(`Error playing ${type} sound:`, error);
+ }
+ }
+ }
+ };
+
+ // State management
+ let currentSubscription = null;
+ const contacts = new Map();
+ const messageManager = new class {
+ constructor() {
+ this.subscriptions = new Map();
+ this.messageCache = new Map();
+ }
+
+ async handleIncomingMessage(event) {
+ const decryptedContent = await this.decryptMessage(event);
+ if (decryptedContent) {
+ chrome.runtime.sendMessage({
+ type: 'NEW_MESSAGE',
+ data: {
+ id: event.id,
+ pubkey: event.pubkey,
+ content: decryptedContent,
+ created_at: event.created_at
+ }
+ });
+ soundManager.play('message');
+ }
+ }
+
+ async decryptMessage(event) {
+ // Your existing decryption logic
+ }
+ };
+
+ // Add auth class before Service Worker Event Listeners
+ const auth = new class {
+ constructor() {
+ this.currentUser = null;
+ }
+
+ async init() {
+ const credentials = await this.getStoredCredentials();
+ if (credentials) {
+ this.currentUser = credentials;
+ return credentials;
+ }
+ return null;
+ }
+
+ async getCurrentUser() {
+ return this.currentUser || await this.getStoredCredentials();
+ }
+
+ async getStoredCredentials() {
try {
- await relayPool.ensureConnection();
+ const { currentUser } = await chrome.storage.local.get('currentUser');
+ return currentUser || null;
+ } catch (error) {
+ console.error('Failed to get stored credentials:', error);
+ return null;
+ }
+ }
+
+ async login(method, key) {
+ try {
+ let credentials;
+ if (method === 'NIP-07') {
+ credentials = await this.loginWithNIP07();
+ } else if (method === 'NSEC') {
+ credentials = await this.loginWithNSEC(key);
+ } else {
+ throw new Error('Invalid login method');
+ }
+
+ if (credentials) {
+ await this.storeCredentials(credentials);
+ soundManager.play('login');
+ }
+ return credentials;
+ } catch (error) {
+ console.error('Login failed:', error);
+ throw error;
+ }
+ }
+
+ async loginWithNIP07() {
+ try {
+ // Check if NIP-07 extension exists in extension context
+ if (typeof window?.nostr === 'undefined') {
+ throw new Error('No Nostr extension found. Please install Alby or nos2x.');
+ }
+
+ // Test if we can actually get permissions
+ await window.nostr.enable();
+
+ // Get public key
+ const pubkey = await window.nostr.getPublicKey();
+
+ // Verify we can sign (this confirms the extension is working)
+ const testEvent = {
+ kind: 1,
+ created_at: Math.floor(Date.now() / 1000),
+ tags: [],
+ content: 'test'
+ };
- if (currentSubscription) {
- currentSubscription.unsub();
+ try {
+ await window.nostr.signEvent(testEvent);
+ } catch (e) {
+ throw new Error('Nostr extension cannot sign events. Please check its permissions.');
}
- // First fetch existing data
- const contacts = await fetchContacts(user.pubkey);
- if (contacts.length > 0) {
- setContacts(contacts);
+ const npub = nostrCore.nip19.npubEncode(pubkey);
+ return {
+ type: 'NIP-07',
+ pubkey: pubkey.toLowerCase(),
+ npub,
+ displayId: npub.slice(0, 8) + '...' + npub.slice(-4)
+ };
+ } catch (error) {
+ console.error('NIP-07 login failed:', error);
+ throw error;
+ }
+ }
+
+ async loginWithNSEC(nsec) {
+ try {
+ const { type, data: privkey } = nostrCore.nip19.decode(nsec);
+ if (type !== 'nsec') throw new Error('Invalid nsec format');
+ const pubkey = nostrCore.getPublicKey(privkey);
+ const npub = nostrCore.nip19.npubEncode(pubkey);
+ return {
+ type: 'NSEC',
+ pubkey,
+ privkey,
+ npub,
+ displayId: npub.slice(0, 8) + '...' + npub.slice(-4)
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async storeCredentials(credentials) {
+ if (!credentials?.pubkey) throw new Error('Invalid credentials format');
+ this.currentUser = credentials;
+ await chrome.storage.local.set({
+ currentUser: credentials,
+ [`credentials:${credentials.pubkey}`]: credentials
+ });
+ return credentials;
+ }
+ };
+
+ // Service Worker Event Listeners
+ self.addEventListener('install', async (event) => {
+ console.log('Service Worker installing.');
+ event.waitUntil(self.skipWaiting());
+ });
+
+ self.addEventListener('activate', async (event) => {
+ console.log('Service Worker activated.');
+ event.waitUntil(Promise.all([
+ clients.claim(),
+ auth.init()
+ ]));
+ });
+
+ self.addEventListener('message', async (event) => {
+ const { type, data } = event.data;
+
+ if (type === 'LOGIN_SUCCESS') {
+ const user = await auth.getCurrentUser();
+ if (user) {
+ try {
+ await relayPool.ensureConnection();
+
+ if (currentSubscription) {
+ currentSubscription.unsub();
+ }
+
+ // First fetch existing data
+ const contacts = await fetchContacts(user.pubkey);
+ if (contacts.length > 0) {
+ setContacts(contacts);
+ chrome.runtime.sendMessage({
+ type: 'CONTACTS_UPDATED',
+ data: contacts
+ });
+ }
+
+ // Then set up live subscriptions
+ currentSubscription = pool.sub(
+ RELAYS.map(relay => ({
+ relay,
+ filter: [
+ { kinds: [3], authors: [user.pubkey] },
+ { kinds: [0], authors: [user.pubkey] },
+ { kinds: [4], '#p': [user.pubkey] },
+ { kinds: [9735], '#p': [user.pubkey] },
+ { kinds: [42], '#e': user.channelIds },
+ { kinds: [30311], '#p': [user.pubkey] }
+ ]
+ }))
+ );
+
+ currentSubscription.on('event', async (event) => {
+ if (validateEvent(event)) {
+ console.log('Received event:', event);
+ if (event.kind === 0) {
+ const metadata = JSON.parse(event.content);
+ await storeMetadata(event.pubkey, metadata);
+ } else if (event.kind === 3) {
+ const contacts = await processContactEvent(event);
+ setContacts(contacts);
+ chrome.runtime.sendMessage({
+ type: 'CONTACTS_UPDATED',
+ data: contacts
+ });
+ } else if (event.kind === 4) {
+ await messageManager.handleIncomingMessage(event);
+ } else if (event.kind === 9735) {
+ const zapAmount = event.tags.find(t => t[0] === 'amount')?.[1];
+ const messageId = event.tags.find(t => t[0] === 'e')?.[1];
+ if (zapAmount && messageId) {
+ chrome.runtime.sendMessage({
+ type: 'ZAP_RECEIVED',
+ data: { messageId, amount: parseInt(zapAmount) }
+ });
+ }
+ } else if (event.kind === 30311) {
+ const streamMetadata = JSON.parse(event.content);
+ const streamId = event.tags.find(t => t[0] === 'd')?.[1];
+ if (streamId) {
+ const streamData = {
+ pubkey: event.pubkey,
+ displayName: streamMetadata.title || 'Unnamed Stream',
+ isChannel: true,
+ avatarUrl: streamMetadata.image || '/icons/default-avatar.png',
+ streamUrl: streamId,
+ embedUrl: `https://zap.stream/embed/${streamId}`,
+ about: streamMetadata.description
+ };
+
+ chrome.runtime.sendMessage({
+ type: 'STREAM_UPDATED',
+ data: streamData
+ });
+ }
+ }
+ }
+ });
+
+ soundManager.play('login', true);
+
+ chrome.runtime.sendMessage({
+ type: 'INIT_COMPLETE',
+ data: { user }
+ });
+ } catch (error) {
+ console.error('Error during initialization:', error);
chrome.runtime.sendMessage({
- type: 'CONTACTS_UPDATED',
- data: contacts
+ type: 'INIT_ERROR',
+ error: error.message
});
}
+ }
+ }
+ });
- // Then set up live subscriptions
- currentSubscription = pool.sub(
- RELAYS.map(relay => ({
- relay,
- filter: [
- { kinds: [3], authors: [user.pubkey] },
- { kinds: [0], authors: [user.pubkey] },
- { kinds: [4], '#p': [user.pubkey] },
- { kinds: [42], '#e': user.channelIds }
- ]
- }))
- );
-
- currentSubscription.on('event', async (event) => {
- if (validateEvent(event)) {
- console.log('Received event:', event);
- if (event.kind === 0) {
- const metadata = JSON.parse(event.content);
- await storeMetadata(event.pubkey, metadata);
- } else if (event.kind === 3) {
- const contacts = await processContactEvent(event);
- setContacts(contacts);
- chrome.runtime.sendMessage({
- type: 'CONTACTS_UPDATED',
- data: contacts
- });
- } else if (event.kind === 4) {
- await messageManager.handleIncomingMessage(event);
- }
+ // Add this to your message listener
+ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
+ if (message.type === 'GET_ZAP_INVOICE') {
+ (async () => {
+ try {
+ const { lightningAddress, amount, zapRequest } = message.data;
+
+ let lightningUrl;
+ if (lightningAddress.includes('@')) {
+ const [name, domain] = lightningAddress.split('@');
+ lightningUrl = `https://${domain}/.well-known/lnurlp/${name}`;
+ } else {
+ lightningUrl = lightningAddress;
}
- });
- soundManager.play('login', true);
-
- chrome.runtime.sendMessage({
- type: 'INIT_COMPLETE',
- data: { user }
- });
- } catch (error) {
- console.error('Error during initialization:', error);
+ // Get LNURL data with proper headers
+ const response = await fetch(lightningUrl, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!response.ok) throw new Error('Failed to fetch lightning address info');
+ const lnurlData = await response.json();
+
+ // Get invoice with proper headers
+ const callbackUrl = new URL(lnurlData.callback);
+ callbackUrl.search = new URLSearchParams({
+ amount: amount * 1000,
+ nostr: JSON.stringify(zapRequest)
+ }).toString();
+
+ const invoiceResponse = await fetch(callbackUrl.toString(), {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!invoiceResponse.ok) throw new Error('Failed to generate invoice');
+ const { pr: invoice } = await invoiceResponse.json();
+
+ sendResponse({ invoice });
+ } catch (error) {
+ console.error('Zap invoice error:', error);
+ sendResponse({ error: error.message });
+ }
+ })();
+ return true;
+ }
+ });
+
+ // Public API
+ return {
+ updateContactStatus: function(pubkey, isOnline) {
+ const contact = contacts.get(pubkey);
+ if (contact) {
+ contact.isOnline = isOnline;
chrome.runtime.sendMessage({
- type: 'INIT_ERROR',
- error: error.message
+ type: 'contactStatusUpdated',
+ pubkey,
+ isOnline
});
}
- }
- }
-});
-
-export function updateContactStatus(pubkey, isOnline) {
- const contact = contacts.get(pubkey);
- if (contact) {
- contact.isOnline = isOnline;
- chrome.runtime.sendMessage({
- type: 'contactStatusUpdated',
- pubkey,
- isOnline
- });
- }
-}
+ },
+ messageManager,
+ soundManager,
+ pool,
+ contacts,
+ auth
+ };
+
+})(NostrTools);
diff --git a/src/embed.html b/src/embed.html
new file mode 100644
index 0000000..e79ba13
--- /dev/null
+++ b/src/embed.html
@@ -0,0 +1,44 @@
+
+
+
+ Noderunners Radio
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/manifest.json b/src/manifest.json
index 5add174..8dedcba 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,20 +1,19 @@
{
"manifest_version": 3,
"name": "Tides",
- "version": "1.0.1",
- "description": "A Nostr-based Messenger",
- "permissions": ["storage", "notifications"],
+ "version": "1.1.0",
+ "description": "A Nostr Messenger For Your Chromium Browser",
+ "permissions": [
+ "storage",
+ "notifications"
+ ],
+ "host_permissions": [
+ "*://*/*",
+ "https://*.twitch.tv/*"
+ ],
"background": {
"service_worker": "background-wrapper.js"
},
- "content_scripts": [{
- "matches": [""],
- "js": ["lib/nostr-tools.js"]
- }],
- "web_accessible_resources": [{
- "resources": ["sounds/*", "icons/*", "lib/*"],
- "matches": [""]
- }],
"action": {
"default_popup": "popup.html",
"default_icon": {
@@ -27,5 +26,12 @@
"16": "icons/Logo.png",
"48": "icons/Logo.png",
"128": "icons/Logo.png"
+ },
+ "web_accessible_resources": [{
+ "resources": ["sounds/*", "icons/*", "lib/*"],
+ "matches": [""]
+ }],
+ "content_security_policy": {
+ "extension_pages": "script-src 'self'; object-src 'self'; frame-src https://www.youtube.com https://youtube.com https://*.twitter.com https://*.x.com https://*.instagram.com https://*.tiktok.com https://player.twitch.tv https://embed.twitch.tv https://*.twitch.tv https://radio.noderunners.org"
}
}
diff --git a/src/messages.js b/src/messages.js
index e714801..726de77 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -14,60 +14,65 @@ export class MessageManager {
async fetchMessages(pubkey) {
const currentUser = await auth.getCurrentUser();
if (!currentUser?.pubkey) {
- throw new Error("User not authenticated");
+ throw new Error('User not authenticated');
}
try {
await relayPool.ensureConnection();
- const relays = relayPool.getConnectedRelays();
+ const connectedRelays = relayPool.getConnectedRelays();
const userPubkey = currentUser.pubkey.toLowerCase();
- const contactPubkey = pubkey.toLowerCase();
-
+ const targetPubkey = pubkey.toLowerCase();
+
+ // Create filters for both sent and received messages
const filters = [
{
kinds: [4],
- "#p": [contactPubkey],
+ '#p': [targetPubkey],
authors: [userPubkey]
},
{
kinds: [4],
- "#p": [userPubkey],
- authors: [contactPubkey]
+ '#p': [userPubkey],
+ authors: [targetPubkey]
}
];
- if (userPubkey === contactPubkey) {
+ // Handle self-messages
+ if (userPubkey === targetPubkey) {
filters.length = 0;
filters.push({
kinds: [4],
- "#p": [userPubkey],
+ '#p': [userPubkey],
authors: [userPubkey]
});
}
- const events = await this.pool.list(relays, filters);
+ const events = await this.pool.list(connectedRelays, filters);
+ // Process and decrypt messages
const messages = await Promise.all(
events
.filter(this.validateEvent)
.sort((a, b) => a.created_at - b.created_at)
- .map(async event => {
+ .map(async (event) => {
const decrypted = await this.decryptMessage(event);
- return decrypted ? {
+ if (!decrypted) return null;
+
+ return {
id: event.id,
pubkey: event.pubkey,
content: decrypted,
timestamp: event.created_at * 1000,
tags: event.tags
- } : null;
+ };
})
);
return messages.filter(Boolean);
- } catch (error) {
- console.error("Error fetching messages:", error);
- throw error;
+ } catch (err) {
+ console.error('Error fetching messages:', err);
+ throw err;
}
}
@@ -75,77 +80,40 @@ export class MessageManager {
try {
const currentUser = await auth.getCurrentUser();
const privateKey = await auth.getPrivateKey();
- if (!privateKey) throw new Error('No private key available');
-
+
+ if (!privateKey) {
+ throw new Error('No private key available');
+ }
+
let decrypted;
- const isOwnMessage = event.pubkey === currentUser.pubkey;
+ const isSent = event.pubkey === currentUser.pubkey;
+ // Get recipient pubkey from tags
+ const recipientPubkey = isSent
+ ? event.tags.find(tag => tag[0] === 'p')?.[1]
+ : event.pubkey;
+
+ if (!recipientPubkey) {
+ throw new Error('No recipient pubkey found in tags');
+ }
+
+ // Handle different encryption methods
if (privateKey === window.nostr) {
decrypted = await window.nostr.nip04.decrypt(
- isOwnMessage ? event.tags.find(t => t[0] === 'p')?.[1] : event.pubkey,
+ isSent ? recipientPubkey : event.pubkey,
event.content
);
} else {
decrypted = await NostrTools.nip04.decrypt(
privateKey,
- isOwnMessage ? event.tags.find(t => t[0] === 'p')?.[1] : event.pubkey,
+ isSent ? recipientPubkey : event.pubkey,
event.content
);
}
-
- // First check if it's a market order
- try {
- const parsed = JSON.parse(decrypted);
- if (parsed.items && parsed.shipping_id) {
- return {
- type: 'market-order',
- content: parsed
- };
- }
- } catch {}
-
- // Check if content is a Giphy URL
- if (decrypted.includes('giphy.com')) {
- return {
- type: 'media',
- content: '',
- mediaUrl: decrypted,
- urls: [decrypted]
- };
- }
-
- // Then check for media links
- const mediaMatch = decrypted.match(/https?:\/\/[^\s<]+[^<.,:;"')\]\s](?:\.(?:jpg|jpeg|gif|png|mp4|webm|mov|ogg))/i);
- const urlMatch = decrypted.match(/https?:\/\/[^\s<]+/g);
- const textContent = decrypted.replace(mediaMatch?.[0] || '', '').trim();
- if (mediaMatch) {
- return {
- type: 'media',
- content: textContent || decrypted,
- mediaUrl: mediaMatch[0],
- urls: urlMatch?.filter(url => url !== mediaMatch[0]) || []
- };
- }
-
- // Check for URLs that might need preview
- if (urlMatch) {
- return {
- type: 'text',
- content: decrypted,
- urls: urlMatch,
- needsPreview: true
- };
- }
-
- // Regular text (may include emojis)
- return {
- type: 'text',
- content: decrypted
- };
-
- } catch (error) {
- console.error('Failed to decrypt message:', error);
+ return decrypted;
+ } catch (err) {
+ console.error('Failed to decrypt message:', err);
return null;
}
}
@@ -159,8 +127,8 @@ export class MessageManager {
event.created_at &&
event.kind &&
event.content;
- } catch (error) {
- console.error('Event validation failed:', error);
+ } catch (err) {
+ console.error('Event validation failed:', err);
return null;
}
}
diff --git a/src/popup.html b/src/popup.html
index 678da68..4d59fdc 100644
--- a/src/popup.html
+++ b/src/popup.html
@@ -17,9 +17,10 @@
-
+
+