checkpoint identity encryption and decryption works fully now

This commit is contained in:
2023-10-15 01:14:10 -04:00
parent d288609e49
commit ad93e35d73
35 changed files with 868 additions and 536 deletions

421
package-lock.json generated
View File

@@ -13,10 +13,11 @@
"@ethersproject/keccak256": "^5.7.0", "@ethersproject/keccak256": "^5.7.0",
"@ethersproject/strings": "^5.7.0", "@ethersproject/strings": "^5.7.0",
"@floating-ui/dom": "^1.5.3", "@floating-ui/dom": "^1.5.3",
"@personaelabs/spartan-ecdsa": "^2.3.0",
"@rainbow-me/rainbowkit": "^1.1.1", "@rainbow-me/rainbowkit": "^1.1.1",
"@semaphore-protocol/group": "^3.10.1", "@semaphore-protocol/group": "^3.10.1",
"@semaphore-protocol/identity": "^3.10.1", "@semaphore-protocol/identity": "^3.10.1",
"@wagmi/core": "^1.4.3",
"@web3modal/wagmi": "^3.1.0",
"autolinker": "^4.0.0", "autolinker": "^4.0.0",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"discreetly-interfaces": "^0.1.39", "discreetly-interfaces": "^0.1.39",
@@ -29,6 +30,7 @@
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"socket.io-client": "^4.7.1", "socket.io-client": "^4.7.1",
"svelte-material-icons": "^3.0.5", "svelte-material-icons": "^3.0.5",
"viem": "^1.16.5",
"wagmi": "^1.4.3" "wagmi": "^1.4.3"
}, },
"devDependencies": { "devDependencies": {
@@ -288,6 +290,18 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/@babel/parser": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"optional": true,
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.23.2", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
@@ -745,30 +759,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
} }
}, },
"node_modules/@ethereumjs/rlp": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz",
"integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==",
"bin": {
"rlp": "bin/rlp"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@ethereumjs/util": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz",
"integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==",
"dependencies": {
"@ethereumjs/rlp": "^4.0.1",
"ethereum-cryptography": "^2.0.0",
"micro-ftch": "^0.3.1"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@ethersproject/bignumber": { "node_modules/@ethersproject/bignumber": {
"version": "5.7.0", "version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz",
@@ -1221,17 +1211,6 @@
"tslib": "^2.3.1" "tslib": "^2.3.1"
} }
}, },
"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": { "node_modules/@noble/hashes": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
@@ -1278,17 +1257,6 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@personaelabs/spartan-ecdsa": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@personaelabs/spartan-ecdsa/-/spartan-ecdsa-2.3.1.tgz",
"integrity": "sha512-svnU2vx6eEhndNOcVxCMpFec1ubEg2VAqGBEMI/QB/eWD11VdFYEmb4boRqr1HzxHMAf8H/gJzg13stATYzJRQ==",
"dependencies": {
"@ethereumjs/util": "^8.0.3",
"@zk-kit/incremental-merkle-tree": "^1.0.0",
"elliptic": "^6.5.4",
"snarkjs": "^0.7.1"
}
},
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.39.0", "version": "1.39.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz",
@@ -1393,19 +1361,6 @@
"url": "https://paulmillr.com/funding/" "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": { "node_modules/@scure/bip39": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
@@ -2454,6 +2409,136 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"dev": true "dev": true
}, },
"node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-core/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==",
"optional": true
},
"node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
"optional": true,
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-ssr": "3.3.4",
"@vue/reactivity-transform": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0",
"postcss": "^8.1.10",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-sfc/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==",
"optional": true
},
"node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
"optional": true,
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
"optional": true,
"dependencies": {
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity-transform": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0"
}
},
"node_modules/@vue/reactivity-transform/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==",
"optional": true
},
"node_modules/@vue/runtime-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
"optional": true,
"dependencies": {
"@vue/reactivity": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
"optional": true,
"dependencies": {
"@vue/runtime-core": "3.3.4",
"@vue/shared": "3.3.4",
"csstype": "^3.1.1"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
"optional": true,
"dependencies": {
"@vue/compiler-ssr": "3.3.4",
"@vue/shared": "3.3.4"
},
"peerDependencies": {
"vue": "3.3.4"
}
},
"node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==",
"optional": true
},
"node_modules/@wagmi/connectors": { "node_modules/@wagmi/connectors": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-3.1.2.tgz",
@@ -3089,6 +3174,145 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}, },
"node_modules/@web3modal/core": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/core/-/core-3.1.0.tgz",
"integrity": "sha512-gXzUCVr4QkgkwxYgu7PBZIUsv3MEJRsYXUDSCU0LZz5BLXnMVSj0+YPhQ1msZLPCo0el/MTPtAzwu0VEOMijTQ==",
"dependencies": {
"valtio": "1.11.2"
}
},
"node_modules/@web3modal/polyfills": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/polyfills/-/polyfills-3.1.0.tgz",
"integrity": "sha512-y830qGJW16k7EZe6N2LIhcLWsHv+TkgC4FuARCSQzJPvVsKi/XsKXGk4Fbrv75nETF7AqCiFrEFQVGnAc7mg8A==",
"dependencies": {
"buffer": "6.0.3"
}
},
"node_modules/@web3modal/scaffold": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/scaffold/-/scaffold-3.1.0.tgz",
"integrity": "sha512-jxCsvkGvVTSds/ezwrX27Xkhlr4IPVeewKAiGxPNZKg9ZGkZ8c+7I2XZnTCKB5XQZvLgqIpGmSYhy4OqAKbHVg==",
"dependencies": {
"@web3modal/core": "3.1.0",
"@web3modal/ui": "3.1.0",
"lit": "3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/@lit/reactive-element": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.0.tgz",
"integrity": "sha512-wn+2+uDcs62ROBmVAwssO4x5xue/uKD3MGGZOXL2sMxReTRIT0JXKyMXeu7gh0aJ4IJNEIG/3aOnUaQvM7BMzQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.0.0.tgz",
"integrity": "sha512-nQ0teRzU1Kdj++VdmttS2WvIen8M79wChJ6guRKIIym2M3Ansg3Adj9O6yuQh2IpjxiUXlNuS81WKlQ4iL3BmA==",
"dependencies": {
"@lit/reactive-element": "^2.0.0",
"lit-element": "^4.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit-element": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.0.tgz",
"integrity": "sha512-N6+f7XgusURHl69DUZU6sTBGlIN+9Ixfs3ykkNDfgfTkDYGGOWwHAYBhDqVswnFGyWgQYR2KiSpu4J76Kccs/A==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0",
"@lit/reactive-element": "^2.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.0.0.tgz",
"integrity": "sha512-DNJIE8dNY0dQF2Gs0sdMNUppMQT2/CvV4OVnSdg7BXAsGqkVwsE5bqQ04POfkYH5dBIuGnJYdFz5fYYyNnOxiA==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/@web3modal/ui": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/ui/-/ui-3.1.0.tgz",
"integrity": "sha512-8Av6psGG/rO5M+5s+I7l2ESUWfeKkeXMIz/Bp2pP3a3yJ+EfO3V4kN1lO/bnbquMYvO+ETmvUXprvcBPMizSBQ==",
"dependencies": {
"lit": "3.0.0",
"qrcode": "1.5.3"
}
},
"node_modules/@web3modal/ui/node_modules/@lit/reactive-element": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.0.tgz",
"integrity": "sha512-wn+2+uDcs62ROBmVAwssO4x5xue/uKD3MGGZOXL2sMxReTRIT0JXKyMXeu7gh0aJ4IJNEIG/3aOnUaQvM7BMzQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.0.0.tgz",
"integrity": "sha512-nQ0teRzU1Kdj++VdmttS2WvIen8M79wChJ6guRKIIym2M3Ansg3Adj9O6yuQh2IpjxiUXlNuS81WKlQ4iL3BmA==",
"dependencies": {
"@lit/reactive-element": "^2.0.0",
"lit-element": "^4.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit-element": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.0.tgz",
"integrity": "sha512-N6+f7XgusURHl69DUZU6sTBGlIN+9Ixfs3ykkNDfgfTkDYGGOWwHAYBhDqVswnFGyWgQYR2KiSpu4J76Kccs/A==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0",
"@lit/reactive-element": "^2.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.0.0.tgz",
"integrity": "sha512-DNJIE8dNY0dQF2Gs0sdMNUppMQT2/CvV4OVnSdg7BXAsGqkVwsE5bqQ04POfkYH5dBIuGnJYdFz5fYYyNnOxiA==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/@web3modal/wagmi": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/wagmi/-/wagmi-3.1.0.tgz",
"integrity": "sha512-PSzhHtj2GTY+36d6lbfzl4EVeuzA4XcMOW7+/CyLFzUDpG4BI5fsKrDbc7NqZU6L6BjN9dPi/oZO/Q+PM8MrPw==",
"dependencies": {
"@web3modal/polyfills": "3.1.0",
"@web3modal/scaffold": "3.1.0"
},
"optionalDependencies": {
"react": ">=17",
"react-dom": ">=17",
"vue": ">=3"
},
"peerDependencies": {
"@wagmi/core": ">=1",
"react": ">=17",
"react-dom": ">=17",
"viem": ">=1",
"vue": ">=3"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@zk-kit/incremental-merkle-tree": { "node_modules/@zk-kit/incremental-merkle-tree": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@zk-kit/incremental-merkle-tree/-/incremental-merkle-tree-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@zk-kit/incremental-merkle-tree/-/incremental-merkle-tree-1.1.0.tgz",
@@ -3557,11 +3781,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
},
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.22.1", "version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
@@ -4380,25 +4599,6 @@
"integrity": "sha512-HiRdtyKS2+VhiXvjhMvvxiMC33FJJqTA5EB2YHgFZW6v7HkK4Q9Ahv2V7O2ZPgAjw+MyCJVMQvigj13H8t+wvA==", "integrity": "sha512-HiRdtyKS2+VhiXvjhMvvxiMC33FJJqTA5EB2YHgFZW6v7HkK4Q9Ahv2V7O2ZPgAjw+MyCJVMQvigj13H8t+wvA==",
"dev": true "dev": true
}, },
"node_modules/elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.1",
"inherits": "^2.0.4",
"minimalistic-assert": "^1.0.1",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/elliptic/node_modules/bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5018,17 +5218,6 @@
"fast-safe-stringify": "^2.0.6" "fast-safe-stringify": "^2.0.6"
} }
}, },
"node_modules/ethereum-cryptography": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz",
"integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==",
"dependencies": {
"@noble/curves": "1.1.0",
"@noble/hashes": "1.3.1",
"@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1"
}
},
"node_modules/ethers": { "node_modules/ethers": {
"version": "6.8.0", "version": "6.8.0",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz",
@@ -5647,16 +5836,6 @@
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
}, },
"node_modules/hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
"dependencies": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/hoopy": { "node_modules/hoopy": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -6905,11 +7084,6 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/micro-ftch": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz",
"integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg=="
},
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
@@ -6977,11 +7151,6 @@
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
}, },
"node_modules/minimalistic-crypto-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -7087,7 +7256,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true, "devOptional": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -7443,7 +7612,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true "devOptional": true
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
@@ -7568,7 +7737,7 @@
"version": "8.4.31", "version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true, "devOptional": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -8046,7 +8215,6 @@
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
}, },
@@ -8058,7 +8226,6 @@
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0", "loose-envify": "^1.1.0",
"scheduler": "^0.23.0" "scheduler": "^0.23.0"
@@ -8482,7 +8649,6 @@
"version": "0.23.0", "version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
@@ -9955,6 +10121,19 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
} }
}, },
"node_modules/vue": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
"optional": true,
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-sfc": "3.3.4",
"@vue/runtime-dom": "3.3.4",
"@vue/server-renderer": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/w3c-xmlserializer": { "node_modules/w3c-xmlserializer": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",

View File

@@ -63,10 +63,11 @@
"@ethersproject/keccak256": "^5.7.0", "@ethersproject/keccak256": "^5.7.0",
"@ethersproject/strings": "^5.7.0", "@ethersproject/strings": "^5.7.0",
"@floating-ui/dom": "^1.5.3", "@floating-ui/dom": "^1.5.3",
"@personaelabs/spartan-ecdsa": "^2.3.0",
"@rainbow-me/rainbowkit": "^1.1.1", "@rainbow-me/rainbowkit": "^1.1.1",
"@semaphore-protocol/group": "^3.10.1", "@semaphore-protocol/group": "^3.10.1",
"@semaphore-protocol/identity": "^3.10.1", "@semaphore-protocol/identity": "^3.10.1",
"@wagmi/core": "^1.4.3",
"@web3modal/wagmi": "^3.1.0",
"autolinker": "^4.0.0", "autolinker": "^4.0.0",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"discreetly-interfaces": "^0.1.39", "discreetly-interfaces": "^0.1.39",
@@ -79,6 +80,7 @@
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"socket.io-client": "^4.7.1", "socket.io-client": "^4.7.1",
"svelte-material-icons": "^3.0.5", "svelte-material-icons": "^3.0.5",
"viem": "^1.16.5",
"wagmi": "^1.4.3" "wagmi": "^1.4.3"
} }
} }

View File

@@ -3,6 +3,13 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>%sveltekit.error.message%</title> <title>%sveltekit.error.message%</title>
<style>
body {
background-color: #1f1f1f;
color: #f1f1f1;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}
</style>
</head> </head>
<body> <body>
<h1>Something didn't work right</h1> <h1>Something didn't work right</h1>

View File

@@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import { identityExists } from '$lib/stores';
import { getIdentityBackup } from '$lib/utils/'; import { getIdentityBackup } from '$lib/utils/';
$: id = getIdentityBackup(); $: id = getIdentityBackup();
$: identityBackupExists = id ? true : false;
$: encodedIdentity = 'data:text/json;charset=utf-8,' + encodeURIComponent(id!); $: encodedIdentity = 'data:text/json;charset=utf-8,' + encodeURIComponent(id!);
let revealIdentity = false; let revealIdentity = false;
@@ -26,22 +26,25 @@
</script> </script>
<div class="m-2 sm:m-3 flex flex-col gap-4"> <div class="m-2 sm:m-3 flex flex-col gap-4">
{#if identityBackupExists} {#if $identityExists == 'safe' || $identityExists == 'unsafe'}
<a class="btn variant-ghost-success" href={encodedIdentity} download="Discreetly_Identity.json" <a class="btn variant-ghost-success" href={encodedIdentity} download="Discreetly_Identity.json"
>Download Identity Backup as JSON</a >Download Identity Backup as JSON</a
> >
{#if !revealIdentity}
<div class="btn variant-ghost-success" on:click={reveal}>Show Identity</div>
{:else}
<div class="btn variant-ghost-success" on:click={reveal}>Hide Identity</div>
<textarea id="reveleadIdentity" class="textarea text-sm" rows="9" value={id} />
{/if}
{:else if $identityExists == 'encrypted'}
<p class="h5 text-primary-500">
Identity exists but is encrypted. Please unlock your keystore to reveal your identity.
</p>
{:else} {:else}
<div class="text-sm text-primary-500"> <div class="text-sm text-primary-500">
Error getting your identity backup. Please contact the developers for help. Error getting your identity backup. Please contact the developers for help.
</div> </div>
{/if} {/if}
{#if !revealIdentity}
<div class="btn variant-ghost-success" on:click={reveal}>Show Identity</div>
{:else}
<div class="btn variant-ghost-success" on:click={reveal}>Hide Identity</div>
<textarea id="reveleadIdentity" class="textarea text-sm" rows="9" value={id} />
{/if}
</div> </div>
<style> <style>

View File

@@ -7,7 +7,7 @@
<h2 class="h2 my-2 md:my-3 text-center">{heading}</h2> <h2 class="h2 my-2 md:my-3 text-center">{heading}</h2>
{/if} {/if}
<slot name="header" /> <slot name="header" />
<div class="flex flex-col gap-2 md:gap-5 max-w-xl w-full mx-auto pb-3"> <div class="flex flex-col gap-2 md:gap-5 max-w-5xl w-full mx-auto pb-3">
<slot /> <slot />
</div> </div>
</div> </div>

View File

@@ -0,0 +1,101 @@
<script lang="ts">
import { createWeb3Modal, defaultWagmiConfig } from '@web3modal/wagmi';
import { getAccount, signMessage, watchAccount, disconnect, Config } from '@wagmi/core';
import { mainnet, arbitrum, optimism, base, polygon } from '@wagmi/core/chains';
import { onMount } from 'svelte';
import { getCommitment } from '$lib/utils';
import type { Web3Modal } from '@web3modal/wagmi/dist/types/src/client';
import { alertQueue, configStore, selectedServer } from '$lib/stores';
import { getEthAddressRoomNames } from '$lib/services/server';
const projectId = 'fcc228af1d77425f1482f07a961fb32d';
let modal: Web3Modal;
let btnEl: HTMLElement;
let address: string = '';
let loadingRooms: boolean = false;
let groups: string[] = [];
let isConnected = false;
const chains = [mainnet, arbitrum, optimism, base, polygon];
const metadata = {
name: 'Discreetly',
description: 'Join Discreetly via your Ethereum address.',
url: 'https://app.discreetly.chat',
icons: ['https://avatars.githubusercontent.com/u/37784886']
};
let wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata });
async function proveOwnership() {
const commitment = getCommitment();
if (commitment) {
const signature = await signMessage({
message: commitment
});
} else {
alertQueue.enqueue('Error getting Identity');
}
}
function connect() {
if (getAccount().isConnected) {
disconnect();
} else {
modal.open();
}
}
onMount(() => {
modal = createWeb3Modal({ wagmiConfig, projectId, chains });
btnEl?.addEventListener('click', connect);
watchAccount((account) => {
address = account.address ?? '';
if (account.isConnected) {
btnEl!.innerText = 'Disconnect';
loadingRooms = true;
getEthAddressRoomNames($selectedServer, address)
.then((groupNames) => {
loadingRooms = false;
groups = groupNames;
})
.finally(() => {
loadingRooms = false;
});
isConnected = true;
} else {
btnEl!.innerText = 'Connect';
isConnected = false;
}
});
});
</script>
<div class="flex flex-col gap-3 justify-between">
<div>
<h3 class="h4 mb-2">Step 1: Connect your wallet</h3>
<button bind:this={btnEl} class="btn variant-outline-tertiary">Connect</button>
</div>
{#if isConnected}
<div>
<p class="h6">Your connected address is: {address}</p>
</div>
{#if groups.length > 0 || $configStore.beta}
<p>You are eligible for the following Ethereum Groups:</p>
<ul>
{#each groups as group}
<li>{group}</li>
{/each}
</ul>
<div>
<h3 class="h4 mb-2">
Step 2: Sign your Identity Commitment to prove ownership of this address
</h3>
<button on:click={proveOwnership} id="btn" class="btn variant-outline-success">Sign</button>
</div>
{:else if loadingRooms}
<p>Loading rooms...</p>
{:else}
<p>You are not eligible for any Ethereum Groups.</p>
{/if}
{/if}
</div>

View File

@@ -1,9 +1,8 @@
<script lang="ts"> <script lang="ts">
import SelectServer from '$lib/components/SelectServer.svelte'; import { inviteCode } from '$lib/gateways/inviteCode';
import { alertAll } from '$lib/utils'; import { alertQueue } from '$lib/stores';
import { inviteCode } from '$lib/utils/inviteCode';
export let code = ''; export let code = '';
let acceptedRoomNames: string[] = []; let acceptedRoomNames: string[] = [];
let loading = false; let loading = false;
let err: string | undefined; let err: string | undefined;
@@ -13,13 +12,13 @@
inviteCode(code) inviteCode(code)
.then(({ acceptedRoomNames, err }) => { .then(({ acceptedRoomNames, err }) => {
if (err) { if (err) {
alertAll(err); alertQueue.enqueue(err);
} else { } else {
acceptedRoomNames = acceptedRoomNames; acceptedRoomNames = acceptedRoomNames;
} }
}) })
.catch((err) => { .catch((err) => {
alertAll(err); alertQueue.enqueue(err);
}) })
.finally(() => { .finally(() => {
loading = false; loading = false;
@@ -80,52 +79,46 @@
} }
</script> </script>
<div class="flex flex-col items-center px-2 mb-2 sm:mb-4"> <label class="label" for="inviteCode">
<label class="label w-full" for="selectServer" <span class="h5">Enter Invite Code:</span>
><span class="h5">Select or Add a Server</span> <input
<SelectServer /> class="input"
</label> type="text"
<label class="label mt-3" for="inviteCode"> placeholder="Invite Code"
<span class="h5">Invite Code</span> id="inviteCode"
<input bind:value={code}
class="input" on:keydown={(event) => inviteCodeKeyPress(event)}
type="text" />
placeholder="Invite Code" </label>
id="inviteCode" {#if !loading}
bind:value={code} <button
on:keydown={(event) => inviteCodeKeyPress(event)} class="btn variant-ghost-success mt-3"
/> type="button"
{#if !loading} disabled={!code}
<button on:click={() => addCode(code)}>Submit</button
class="btn variant-ghost-success" >
type="button" {:else}
disabled={!code} <p class="italic">Loading...</p>
on:click={() => addCode(code)}>Submit</button {/if}
>
{:else}
<p class="italic">Loading...</p>
{/if}
</label>
{#if err} {#if err}
<aside class="p"> <aside class="p">
<div> <div>
If you are having trouble and would like help, please message us on <a If you are having trouble and would like help, please message us on <a
href="https://discord.gg/brJQ36KVxk" href="https://discord.gg/brJQ36KVxk"
class="underline link">Discord</a class="underline link">Discord</a
> >
</div>
</aside>
{/if}
{#if acceptedRoomNames.length > 0}
<p class="text-center mt-2">You've been added to:</p>
<div class="my-2">
{#each acceptedRoomNames as name}
<ins class="ins border-y border-success-800">{name}</ins>
{/each}
</div> </div>
{/if} </aside>
</div> {/if}
{#if acceptedRoomNames.length > 0}
<p class="text-center mt-2">You've been added to:</p>
<div class="my-2">
{#each acceptedRoomNames as name}
<ins class="ins border-y border-success-800">{name}</ins>
{/each}
</div>
{/if}
<style> <style>
aside { aside {

View File

@@ -1,86 +0,0 @@
<script lang="ts">
import { passwordSet, configStore, keyStore } from '$lib/stores';
import Lock from 'svelte-material-icons/Lock.svelte';
import LockOpen from 'svelte-material-icons/LockOpenVariant.svelte';
import NoPassword from 'svelte-material-icons/LockOff.svelte';
import { getModalStore, type ModalSettings } from '@skeletonlabs/skeleton';
import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { onMount } from 'svelte';
import { alertAll, setPassword } from '$lib/utils';
const modalStore = getModalStore();
export let cls: string = '';
let minPasswordLength = 3;
function setPasswordModal() {
const modal: ModalSettings = {
type: 'prompt',
title: 'Set a Password',
body: 'Set a password or pin to encrypt your identity and room passwords',
value: '',
valueAttr: { type: 'password', minlength: minPasswordLength, required: true },
response: async (r: string) => {
if (r != '' && r != null && r != undefined && r.length >= minPasswordLength) {
setPassword(r);
}
}
};
modalStore.trigger(modal);
}
function unlock() {
const modal: ModalSettings = {
type: 'prompt',
title: 'Unlock',
body: 'Enter your password to unlock your keystores',
value: '',
valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
}
}
};
modalStore.trigger(modal);
}
function lock() {
$keyStore = null;
}
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script>
<div class={cls} id="lock">
{#if $passwordSet}
{#if $keyStore instanceof CryptoKey}
<div on:click={lock} title="Unlocked, click to lock">
<LockOpen class="w-full text-warning-300-600-token" />
</div>
{:else}
<div on:click={unlock} title="Locked" class="w-full text-success-500"><Lock /></div>
{/if}
{:else}
<div on:click={setPasswordModal} title="Password not set">
<NoPassword class="w-full text-error-500" />
</div>
{/if}
</div>
<style>
#lock {
cursor: pointer;
}
</style>

View File

@@ -1,18 +1,12 @@
<script lang="ts"> <div class="card">
import Button from './button.svelte'; {#if $$slots.header}
import type { ButtonI } from '$lib/types'; <header class="card-header h3"><slot name="header" /></header>
export let title: string; {/if}
export let buttons: ButtonI[] = []; {#if $$slots.description}
</script> <aside class="p italic px-4 pt-3"><slot name="description" /></aside>
{/if}
<div class="m-4 px-5 py-4 text-center bg-body-tertiary rounded-2"> <section class="p-4"><slot /></section>
<h2 class="text-body-emphasis m-3">{title}</h2> {#if $$slots.footer}
<div class="col-lg-8 mx-auto fs-5 text-muted"> <footer class="card-footer"><slot name="footer" /></footer>
<slot /> {/if}
</div>
<div class="d-inline-flex gap-5 my-3">
{#each buttons as button}
<Button link={button.link} cls={button.cls} text={button.text} />
{/each}
</div>
</div> </div>

View File

@@ -1,4 +1,5 @@
import { addConsoleMessage } from '$lib/utils'; import { alertQueue, configStore } from '$lib/stores';
import { get } from 'svelte/store';
/** /**
* Derives an encryption key from a given password using PBKDF2. * Derives an encryption key from a given password using PBKDF2.
@@ -47,14 +48,17 @@ export async function encrypt(plainText: string, key: CryptoKey): Promise<string
key, key,
encoder.encode(plainText) encoder.encode(plainText)
); );
console.log(encryptedContent);
const encryptedContentArr = new Uint8Array(encryptedContent); const encryptedContentArr = new Uint8Array(encryptedContent);
const encryptedBytes = [...iv, ...encryptedContentArr]; const encryptedBytes = [...iv, ...encryptedContentArr];
return btoa(String.fromCharCode(...encryptedBytes)); return btoa(String.fromCharCode(...encryptedBytes));
} else if (get(configStore).hashedPwd) {
alertQueue.enqueue('Unlock your identity with /unlock or click on the lock');
console.error('Unlock your identity with /unlock or click on the lock');
return null;
} else { } else {
addConsoleMessage('No Password Set, please set a password with /setpassword', 'error'); alertQueue.enqueue('No Password Set, please set a password with /setpassword');
console.error('No password set, please set a password first'); console.error('No password set, please set a password first');
return null; return null;
} }
@@ -66,7 +70,6 @@ export async function decrypt(cipherText: string, key: CryptoKey): Promise<strin
} }
if (key instanceof CryptoKey) { if (key instanceof CryptoKey) {
const decoder = new TextDecoder(); const decoder = new TextDecoder();
console.log(cipherText);
const encryptedBytes = Uint8Array.from(atob(cipherText), (c) => c.charCodeAt(0)); const encryptedBytes = Uint8Array.from(atob(cipherText), (c) => c.charCodeAt(0));
const iv = encryptedBytes.slice(0, 12); const iv = encryptedBytes.slice(0, 12);
@@ -79,8 +82,12 @@ export async function decrypt(cipherText: string, key: CryptoKey): Promise<strin
); );
return decoder.decode(decryptedContent); return decoder.decode(decryptedContent);
} else if (get(configStore).hashedPwd) {
alertQueue.enqueue('Unlock your identity with /unlock or click on the lock');
console.error('Unlock your identity with /unlock or click on the lock');
return null;
} else { } else {
addConsoleMessage('No Password Set, please set a password with /setpassword', 'error'); alertQueue.enqueue('No Password Set, please set a password with /setpassword');
console.error('No password set, please set a password first'); console.error('No password set, please set a password first');
return null; return null;
} }

View File

@@ -3,8 +3,10 @@ import { IdentityStoreE } from './types';
import { dev } from '$app/environment'; import { dev } from '$app/environment';
let defaultServers: serverStoreI; let defaultServers: serverStoreI;
let beta = false;
if (dev) { if (dev) {
beta = true;
defaultServers = { defaultServers = {
'https://server.discreetly.chat/': { 'https://server.discreetly.chat/': {
name: 'Discreetly Server', name: 'Discreetly Server',
@@ -23,6 +25,7 @@ if (dev) {
} }
}; };
} }
const configDefaults: ConfigurationI = { const configDefaults: ConfigurationI = {
signUpStatus: { signUpStatus: {
completedSignup: false, completedSignup: false,
@@ -31,7 +34,7 @@ const configDefaults: ConfigurationI = {
identityStore: IdentityStoreE.NO_IDENTITY, identityStore: IdentityStoreE.NO_IDENTITY,
numMessagesToSave: 500, numMessagesToSave: 500,
hashedPwd: undefined, hashedPwd: undefined,
beta: false beta: beta
}; };
export { defaultServers, configDefaults }; export { defaultServers, configDefaults };

View File

@@ -1,6 +1,6 @@
import { alertAll, getCommitment, updateRooms } from '$lib/utils/'; import { getCommitment, updateRooms } from '$lib/utils/';
import { postInviteCode } from '$lib/services/server'; import { postInviteCode } from '$lib/services/server';
import { selectedServer, configStore } from '$lib/stores'; import { selectedServer, configStore, alertQueue } from '$lib/stores';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import type { JoinResponseI } from '$lib/types'; import type { JoinResponseI } from '$lib/types';
@@ -11,8 +11,7 @@ export async function inviteCode(newCode: string) {
try { try {
const idc = getCommitment(); const idc = getCommitment();
if (!idc) { if (!idc) {
// TODO convert this to alertAll at some point alertQueue.enqueue('No identity commitment found');
alertAll('No identity commitment found');
throw new Error('No identity commitment found'); throw new Error('No identity commitment found');
} }
const result = (await postInviteCode(server, { const result = (await postInviteCode(server, {

View File

@@ -15,6 +15,13 @@ export async function getServerData(serverUrl: string): Promise<ServerI> {
return get([serverUrl]) as Promise<ServerI>; return get([serverUrl]) as Promise<ServerI>;
} }
export async function getEthAddressRoomNames(
server: string,
ethAddress: string
): Promise<string[]> {
return get([server, `api/eth/group/${ethAddress}`]) as Promise<string[]>;
}
export async function postInviteCode(serverUrl: string, data: { code: string; idc: string }) { export async function postInviteCode(serverUrl: string, data: { code: string; idc: string }) {
return post([serverUrl, 'join'], data); return post([serverUrl, 'join'], data);
} }

View File

@@ -1,5 +1,5 @@
import { storable, sessionable, encryptable } from './storeFactory'; import { storable, sessionable, encryptable, queueable } from './storeFactory';
import { derived, writable, type Readable } from 'svelte/store'; import { derived, writable } from 'svelte/store';
import { configDefaults } from '$lib/defaults'; import { configDefaults } from '$lib/defaults';
import type { import type {
ConfigurationI, ConfigurationI,
@@ -14,7 +14,6 @@ import type {
roomKeyStoreI, roomKeyStoreI,
keyStoreI keyStoreI
} from '$lib/types'; } from '$lib/types';
import { decrypt } from '$lib/crypto/crypto';
/* ------------------ Server State ------------------*/ /* ------------------ Server State ------------------*/
/** /**
@@ -90,6 +89,8 @@ export const rateLimitStore = storable({} as rateLimitStoreI, 'rateLimit');
*/ */
export const keyStore = writable({} as keyStoreI); export const keyStore = writable({} as keyStoreI);
export const alertQueue = queueable([] as string[]);
/** /**
* @description Configuration store, stores the user's settings * @description Configuration store, stores the user's settings
*/ */
@@ -130,13 +131,50 @@ export const identityStore = storable({} as IdentityStoreI, 'identity');
*/ */
export const identityKeyStore = encryptable({} as IdentityStoreI, 'identityencrypted'); export const identityKeyStore = encryptable({} as IdentityStoreI, 'identityencrypted');
export const identityExists = derived( export const lockStateStore = derived(
[identityStore, identityKeyStore], [keyStore, passwordSet],
([$identityStore, $identityKeyStore]) => { ([$keyStore, $passwordSet]): 'unlocked' | 'locked' | null => {
if ($identityStore._commitment || $identityKeyStore._commitment) { if ($passwordSet) {
return true; if ($keyStore instanceof CryptoKey) {
return 'unlocked';
} else {
return 'locked';
}
} else { } else {
return false; return null;
}
}
);
export const identityExists = derived(
[identityStore, identityKeyStore, lockStateStore],
([$identityStore, $identityKeyStore, $lockStateStore]):
| 'safe'
| 'unsafe'
| 'encrypted'
| null => {
const id = $identityKeyStore;
const id_ = $identityStore;
if ($lockStateStore == null) {
if (id_._commitment?.length > 0) {
return 'unsafe';
} else {
return null;
}
} else if ($lockStateStore === 'unlocked') {
if (id._commitment) {
return 'safe';
} else {
return null;
}
} else if ($lockStateStore === 'locked') {
if (typeof id === 'object') {
return 'encrypted';
} else {
return null;
}
} else {
return null;
} }
} }
); );

View File

@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { writable, get } from 'svelte/store'; import { writable, get } from 'svelte/store';
import type { Writable } from 'svelte/store'; import type { Writable } from 'svelte/store';
import { keyStore } from '.'; import { keyStore, lockStateStore } from '.';
import { decrypt, encrypt } from '$lib/crypto/crypto'; import { decrypt, encrypt } from '$lib/crypto/crypto';
import type { EncryptableT } from '$lib/types';
export function storable<Type>(data: Type, localStorageKey: string): Writable<Type> { export function storable<Type>(data: Type, localStorageKey: string): Writable<Type> {
const store = writable<Type>(data); const store = writable<Type>(data);
@@ -73,29 +74,31 @@ export function sessionable<Type>(data: Type, sessionStorageKey: string): Writab
}; };
} }
export function encryptable<Type>(data: Type, localStorageKey: string): Writable<Type> { export function encryptable<Type>(data: Type, localStorageKey: string): EncryptableT<Type> {
const store = writable<Type>(data); const store = writable<Type>(data);
const { subscribe, set } = store; const { subscribe, set } = store;
const isBrowser = typeof window !== 'undefined'; const isBrowser = typeof window !== 'undefined';
if (isBrowser && localStorage.getItem(localStorageKey) !== null) { function read() {
const storedValue = localStorage.getItem(localStorageKey); if (isBrowser && localStorage.getItem(localStorageKey) !== null) {
if (storedValue) { const storedValue = localStorage.getItem(localStorageKey);
try {
const key = get(keyStore); if (storedValue) {
if (!key) { try {
throw new Error('Key store not initialized, cannot encrypt data'); const key = get(keyStore);
} if (!(get(lockStateStore) === 'unlocked') || !key) {
console.debug('Encryptable State: ', storedValue, key); throw new Error('Key store not initialized, cannot encrypt data');
decrypt(storedValue, key).then((decryptedData) => {
if (decryptedData !== null) {
set(JSON.parse(decryptedData) as Type);
} else {
console.error('Error decrypting data');
} }
}); decrypt(storedValue, key).then((decryptedData) => {
} catch (e) { if (decryptedData !== null) {
console.warn(`Error reading local storage for key: ${localStorageKey}; ${e}`); set(JSON.parse(decryptedData)) as Type;
} else {
console.error('Error decrypting data');
}
});
} catch (e) {
console.warn(`Error reading local storage for key: ${localStorageKey}; ${e}`);
}
} }
} }
} }
@@ -134,6 +137,43 @@ export function encryptable<Type>(data: Type, localStorageKey: string): Writable
console.error('Error encrypting data'); console.error('Error encrypting data');
} }
}); });
},
read
};
}
export type QueueStore = ReturnType<typeof queueService>;
declare function queueService(): {
set: (value: any[]) => void;
subscribe: (run: (value: any[]) => any, invalidate?: any) => () => void;
update: (callBack: (value: any[]) => any[]) => void;
enqueue: (value: any) => void;
dequeue: () => any;
};
export function queueable<Type>(data: Type[]): ReturnType<typeof queueService> {
const store = writable<Type[]>(data);
const { subscribe, set } = store;
return {
subscribe,
set: (value: Type[]) => {
set(value);
},
update: (callBack: (value: Type[]) => Type[]) => {
const updatedStore = callBack(get(store));
set(updatedStore);
},
enqueue: (value: Type) => {
const updatedStore = get(store);
updatedStore.push(value);
set(updatedStore);
},
dequeue: () => {
const updatedStore = get(store);
const val = updatedStore.shift();
set(updatedStore);
return val;
} }
}; };
} }

View File

@@ -1,3 +1,4 @@
export * from './stores'; export * from './stores';
export * from './enums'; export * from './enums';
export * from './interfaces'; export * from './interfaces';
export * from './svelte';

View File

@@ -1,5 +1,7 @@
import type { ServerI, MessageI, HexColor } from 'discreetly-interfaces'; import type { ServerI, MessageI, HexColor } from 'discreetly-interfaces';
import type { RoomI } from './interfaces'; import type { RoomI } from './interfaces';
import type { Identity } from '@semaphore-protocol/identity';
import type { Writable } from 'svelte/store';
// Keyed by server URL // Keyed by server URL
export interface serverStoreI { export interface serverStoreI {
@@ -58,3 +60,7 @@ export interface roomKeyStoreI {
} }
export type keyStoreI = CryptoKey | undefined | null; export type keyStoreI = CryptoKey | undefined | null;
export interface EncryptableT<Type> extends Writable<Type> {
read: () => void;
}

15
src/lib/types/svelte.ts Normal file
View File

@@ -0,0 +1,15 @@
import type { Toast, ToastSettings } from '@skeletonlabs/skeleton';
import type { Subscriber, Invalidator, Unsubscriber } from 'svelte/motion';
export type toastStoreT = {
subscribe: (
this: void,
run: Subscriber<Toast[]>,
invalidate?: Invalidator<Toast[]> | undefined
) => Unsubscriber;
close: (id: string) => void;
trigger: (toast: ToastSettings) => string;
freeze: (index: number) => void;
unfreeze: (index: number) => void;
clear: () => void;
};

View File

@@ -1,18 +0,0 @@
import { getToastStore } from '@skeletonlabs/skeleton';
import { addConsoleMessage } from './console';
export function alertToast(alertMessage: string, timeout = 5000) {
const toastStore = getToastStore();
toastStore.trigger({ message: alertMessage, timeout: timeout });
console.warn(alertMessage);
}
export function alertAll(
alertMessage: string,
level: 'warning' | 'info' | 'userinput' | 'error' | 'space' | undefined = 'warning',
timeout = 5000
) {
alertToast(alertMessage, timeout);
console.warn(alertMessage);
addConsoleMessage(alertMessage, level);
}

View File

@@ -1,103 +1,90 @@
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import { configStore, identityKeyStore, identityStore, keyStore } from '../stores'; import {
alertQueue,
configStore,
identityKeyStore,
identityStore,
identityExists,
keyStore,
lockStateStore
} from '../stores';
import { Identity } from '@semaphore-protocol/identity'; import { Identity } from '@semaphore-protocol/identity';
import type { IdentityStoreI } from '$lib/types'; import type { IdentityStoreI } from '$lib/types';
import { addConsoleMessage } from './console';
export function createIdentity(regenerate = false): 'created' | 'exists' | 'unsafe' | 'error' { export function createIdentity(regenerate = false): 'created' | 'exists' | 'unsafe' | 'error' {
const old_id = get(identityKeyStore) as unknown as IdentityStoreI; const identityStatus = get(identityExists);
if (!old_id._commitment || regenerate) { console.log(identityStatus);
if (!get(identityExists) || regenerate) {
console.debug('Creating identity'); console.debug('Creating identity');
const identity = new Identity() as unknown as IdentityStoreI; const identity = new Identity() as unknown as IdentityStoreI;
const config = get(configStore); const config = get(configStore);
const key = get(keyStore); const lockState = get(lockStateStore);
if (config.hashedPwd && config.hashedPwd.length > 0) { if (config.hashedPwd && config.hashedPwd.length > 0) {
if (key) { if (lockState === 'unlocked') {
try { try {
identityKeyStore.set(identity); identityKeyStore.set(identity);
if (get(identityKeyStore)._commitment !== null) { if (get(identityExists) === 'safe') {
console.log('Identity Created! Congrats on your new journey'); alertQueue.enqueue('Identity Created! Congrats on your new journey');
return 'created'; return 'created';
} else { } else {
console.error('Error creating identity'); alertQueue.enqueue('Error creating identity');
return 'error'; return 'error';
} }
} catch (e) { } catch (e) {
console.error(`Error creating identity: ${e}`); alertQueue.enqueue(`Error creating identity: ${e}`);
return 'error'; return 'error';
} }
} else { } else {
addConsoleMessage( alertQueue.enqueue('Unlock your account by clicking on the lock');
'Unlock your identity with /unlock or click on the lock in the corner',
'error'
);
return 'error'; return 'error';
} }
} else { } else {
addConsoleMessage( alertQueue.enqueue(
'For your security please set a password with /password or click on the lock in the corner', 'For your security please set a password with /password or click on the lock in the corner'
'warning'
); );
identityStore.set(identity); identityStore.set(identity);
return 'unsafe'; return 'unsafe';
} }
} else { } else {
console.warn('Identity already exists'); alertQueue.enqueue('Identity already exists');
return 'exists'; return 'exists';
} }
} }
export function getIdentity(): IdentityStoreI { export function getIdentity(): IdentityStoreI | null {
const decryptedIdentity = get(identityKeyStore) as unknown as IdentityStoreI; const decryptedIdentity = get(identityKeyStore) as unknown as IdentityStoreI;
if (decryptedIdentity !== null) {
if (decryptedIdentity._commitment) {
console.log(decryptedIdentity);
return decryptedIdentity; return decryptedIdentity;
} else { } else {
const identity = get(identityStore); const identity = get(identityStore);
if (identity !== null) { if (identity._commitment?.length > 0) {
console.warn('Identity not encrypted, set a password!'); alertQueue.enqueue('Identity not encrypted, set a password!');
return identity; return identity;
} else { } else {
console.warn('Identity not created, create an identity!'); alertQueue.enqueue('Identity not created, create an identity!');
} }
} }
throw new Error('Identity not created'); return null;
} }
export function getCommitment() { export function getCommitment(): string | null {
const id = get(identityKeyStore) as IdentityStoreI; const id = getIdentity();
const id_ = get(identityStore); if (id) {
if (id !== null && id !== undefined) {
return id._commitment; return id._commitment;
} } else {
if (id_ !== null && id_ !== undefined) { return null;
console.warn('PLEASE ADD A PASSWORD!');
return id_._commitment;
} }
} }
export function getIdentityBackup() { export function getIdentityBackup(): string | null {
const id = get(identityKeyStore); const id = getIdentity();
const id_ = get(identityStore); if (id) {
if (id !== null && id !== undefined) {
return JSON.stringify(id); return JSON.stringify(id);
} else {
return null;
} }
if (id_ !== null && id_ !== undefined) {
console.warn('PLEASE ADD A PASSWORD!');
return JSON.stringify(id_);
}
}
export function doesIdentityExist(): 'safe' | 'unsafe' | 'none' {
const id = get(identityKeyStore);
const id_ = get(identityStore);
if (id._commitment !== null && id._commitment !== undefined) {
return 'safe';
}
if (id_._commitment !== null && id_._commitment !== undefined) {
console.warn('PLEASE ADD A PASSWORD');
return 'unsafe';
}
return 'none';
} }
export function encryptIdentity(identity: IdentityStoreI) { export function encryptIdentity(identity: IdentityStoreI) {

View File

@@ -1,7 +1,5 @@
export * from './alert';
export * from './console'; export * from './console';
export * from './identity'; export * from './identity';
export * from './inviteCode';
export * from './password'; export * from './password';
export * from './rateLimit'; export * from './rateLimit';
export * from './rooms'; export * from './rooms';

View File

@@ -1,14 +1,22 @@
import { deriveKey, hashPassword } from '$lib/crypto/crypto'; import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { get, writable } from 'svelte/store'; import { get } from 'svelte/store';
import { configStore, identityKeyStore, identityStore, keyStore } from '$lib/stores'; import {
import { doesIdentityExist, encryptIdentity } from './identity'; configStore,
identityKeyStore,
identityStore,
keyStore,
identityExists,
alertQueue,
roomKeyStore
} from '$lib/stores';
import { encryptIdentity } from './identity';
import type { IdentityStoreI } from '$lib/types'; import type { IdentityStoreI } from '$lib/types';
export async function setPassword(password: string): Promise<'success' | string> { export async function setPassword(password: string): Promise<'success' | string> {
const hashedPassword = await hashPassword(password); const hashedPassword = await hashPassword(password);
let identity: IdentityStoreI | undefined; let identity: IdentityStoreI | undefined;
if (hashedPassword !== null) { if (hashedPassword !== null) {
const idStatus = doesIdentityExist(); const idStatus = get(identityExists);
/****************************** /******************************
* STAGE1: DECRYPT/STORE EVERYTHING INTO MEMORY * STAGE1: DECRYPT/STORE EVERYTHING INTO MEMORY
******************************/ ******************************/
@@ -49,3 +57,18 @@ export async function setPassword(password: string): Promise<'success' | string>
} }
return 'error'; return 'error';
} }
export async function unlockPadlock(password: string) {
const hashedPassword = await hashPassword(password);
if (get(configStore).hashedPwd == hashedPassword) {
deriveKey(password).then((key) => {
keyStore.set(key);
// Don't remove these. There is no reactive way to automatically decrypt encrypted stores, so we have to trigger it manually when the keys are derived
identityKeyStore.read();
roomKeyStore.read();
});
} else {
alertQueue.enqueue('Incorrect Password');
keyStore.set(null);
}
}

View File

@@ -5,7 +5,8 @@ import {
selectedServer, selectedServer,
serverStore, serverStore,
messageStore, messageStore,
currentSelectedRoom currentSelectedRoom,
alertQueue
} from '$lib/stores'; } from '$lib/stores';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import { import {
@@ -44,8 +45,7 @@ async function getRoomIdsIfEmpty(server: string, roomIds: string[]): Promise<str
if (roomIds.length < 1) { if (roomIds.length < 1) {
const idc = getCommitment(); const idc = getCommitment();
if (!idc) { if (!idc) {
// TODO convert this to alertAll at some point alertQueue.enqueue('No identity commitment found');
console.error('No identity commitment found');
throw new Error('No identity commitment found'); throw new Error('No identity commitment found');
} }
return await getRoomIdsByIdentityCommitment(server, idc); return await getRoomIdsByIdentityCommitment(server, idc);

View File

@@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { Modal, initializeStores } from '@skeletonlabs/skeleton'; import { Modal, getToastStore, initializeStores } from '@skeletonlabs/skeleton';
import { Toast, storePopup } from '@skeletonlabs/skeleton'; import { Toast, storePopup } from '@skeletonlabs/skeleton';
import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom'; import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
import '../app.postcss'; import '../app.postcss';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import AppHeader from './AppHeader.svelte'; import AppHeader from './AppHeader.svelte';
import Loading from '$lib/components/loading.svelte'; import Loading from '$lib/components/loading.svelte';
import { selectedServer } from '$lib/stores'; import { selectedServer, alertQueue } from '$lib/stores';
import { getServerList, isInputFieldFocused, setDefaultServers } from '$lib/utils/'; import { getServerList, isInputFieldFocused, setDefaultServers } from '$lib/utils/';
import { updateServer } from '$lib/utils/'; import { updateServer } from '$lib/utils/';
import { Drawer, getDrawerStore } from '@skeletonlabs/skeleton'; import { Drawer, getDrawerStore } from '@skeletonlabs/skeleton';
@@ -14,10 +14,12 @@
import SelectRoom from '$lib/components/SelectRoom.svelte'; import SelectRoom from '$lib/components/SelectRoom.svelte';
import Console from './console/Console.svelte'; import Console from './console/Console.svelte';
import Sidebar from './Sidebar.svelte'; import Sidebar from './Sidebar.svelte';
import AppFooter from './AppFooter.svelte'; import AppFooter from './Footer.svelte';
initializeStores(); initializeStores();
const toastStore = getToastStore();
const drawerStore = getDrawerStore(); const drawerStore = getDrawerStore();
// Hack to get BigInt <-> JSON compatibility // Hack to get BigInt <-> JSON compatibility
(BigInt.prototype as any).toJSON = function () { (BigInt.prototype as any).toJSON = function () {
@@ -46,6 +48,12 @@
} }
} }
}); });
setInterval(() => {
const toast = alertQueue.dequeue();
if (toast) {
toastStore.trigger({ message: toast });
}
}, 500);
}); });
</script> </script>

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { passwordSet, configStore, keyStore } from '$lib/stores'; import { passwordSet, configStore, keyStore, alertQueue } from '$lib/stores';
import { import {
getModalStore, getModalStore,
TabAnchor, TabAnchor,
@@ -23,7 +23,7 @@
import LockOpen from 'svelte-material-icons/LockOpenVariant.svelte'; import LockOpen from 'svelte-material-icons/LockOpenVariant.svelte';
import NoPassword from 'svelte-material-icons/LockOff.svelte'; import NoPassword from 'svelte-material-icons/LockOff.svelte';
import Door from 'svelte-material-icons/Door.svelte'; import Door from 'svelte-material-icons/Door.svelte';
import { alertAll } from '$lib/utils'; import { unlockPadlock } from '$lib/utils';
const modalStore = getModalStore(); const modalStore = getModalStore();
const drawerStore = getDrawerStore(); const drawerStore = getDrawerStore();
@@ -49,13 +49,7 @@
valueAttr: { type: 'password', minlength: 4, required: true }, valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => { response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) { if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r); unlockPadlock(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
} }
} }
}; };
@@ -65,13 +59,6 @@
function lock() { function lock() {
$keyStore = null; $keyStore = null;
} }
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script> </script>
<div class="card p-4 w-72 shadow-xl" data-popup="popupMenu"> <div class="card p-4 w-72 shadow-xl" data-popup="popupMenu">
@@ -79,7 +66,7 @@
<!-- (optionally you can provide a label here) --> <!-- (optionally you can provide a label here) -->
<ul> <ul>
<li id="will-close"> <li id="will-close">
<a href="/settings"> <a href="/about">
<Information /> <Information />
<span class="flex-auto">About</span> <span class="flex-auto">About</span>
</a> </a>

View File

@@ -15,9 +15,9 @@
import NoPassword from 'svelte-material-icons/LockOff.svelte'; import NoPassword from 'svelte-material-icons/LockOff.svelte';
import Plus from 'svelte-material-icons/Plus.svelte'; import Plus from 'svelte-material-icons/Plus.svelte';
import { hashPassword, deriveKey } from '$lib/crypto/crypto'; import { hashPassword, deriveKey } from '$lib/crypto/crypto';
import { configStore, keyStore, passwordSet } from '$lib/stores'; import { configStore, keyStore, passwordSet, alertQueue } from '$lib/stores';
import { alertAll } from '$lib/utils';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { unlockPadlock } from '$lib/utils';
const modalStore = getModalStore(); const modalStore = getModalStore();
@@ -30,13 +30,7 @@
valueAttr: { type: 'password', minlength: 4, required: true }, valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => { response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) { if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r); unlockPadlock(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
} }
} }
}; };
@@ -46,14 +40,6 @@
function lock() { function lock() {
$keyStore = null; $keyStore = null;
} }
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script> </script>
<AppRail height="h-full"> <AppRail height="h-full">

View File

@@ -1,8 +1,14 @@
<script lang="ts"> <script lang="ts">
import { currentSelectedRoom, keyStore, rateLimitStore, roomKeyStore } from '$lib/stores'; import {
currentSelectedRoom,
keyStore,
rateLimitStore,
roomKeyStore,
alertQueue
} from '$lib/stores';
import { genProof } from '$lib/crypto/rlnProver'; import { genProof } from '$lib/crypto/rlnProver';
import type { Socket } from 'socket.io-client'; import type { Socket } from 'socket.io-client';
import { getIdentity, alertToast, clearMessageHistory, alertAll } from '$lib/utils'; import { getIdentity, clearMessageHistory } from '$lib/utils';
import Send from 'svelte-material-icons/Send.svelte'; import Send from 'svelte-material-icons/Send.svelte';
import { decrypt, encrypt } from '$lib/crypto/crypto'; import { decrypt, encrypt } from '$lib/crypto/crypto';
@@ -32,23 +38,25 @@
function checkStatus(): boolean { function checkStatus(): boolean {
if (!connected) { if (!connected) {
alertToast('NOT CONNECTED TO CHAT SERVER'); alertQueue.enqueue('NOT CONNECTED TO CHAT SERVER');
sendingMessage = false; sendingMessage = false;
return false; return false;
} }
if (messageText.length < 1) { if (messageText.length < 1) {
alertToast('MESSAGE IS EMPTY'); alertQueue.enqueue('MESSAGE IS EMPTY');
sendingMessage = false; sendingMessage = false;
return false; return false;
} }
if (messageText.length > 2000) { if (messageText.length > 2000) {
alertToast('MESSAGE IS TOO LONG, SENDING MAY FAIL UNDER NETWORK CONSTRAINED CONDITIONS'); alertQueue.enqueue(
'MESSAGE IS TOO LONG, SENDING MAY FAIL UNDER NETWORK CONSTRAINED CONDITIONS'
);
sendingMessage = false; sendingMessage = false;
return false; return false;
} }
// This is 100% thanks to Violet for spamming the chat with spaces // This is 100% thanks to Violet for spamming the chat with spaces
if (messageText.replaceAll(' ', '') == '') { if (messageText.replaceAll(' ', '') == '') {
alertToast('MESSAGE IS EMPTY'); alertQueue.enqueue('MESSAGE IS EMPTY');
sendingMessage = false; sendingMessage = false;
return false; return false;
} }
@@ -56,7 +64,7 @@
} }
function help() { function help() {
alertToast('Commands: /clear, /help'); alertQueue.enqueue('Commands: /clear, /help');
} }
function processCommand(value: string) { function processCommand(value: string) {
@@ -154,11 +162,11 @@
} catch (err: any) { } catch (err: any) {
console.error('Error sending message: ', err); console.error('Error sending message: ', err);
if (err.message.includes('Merkle Proof')) { if (err.message.includes('Merkle Proof')) {
alertToast( alertQueue.enqueue(
"Couldn't generate Merkle Proof. Maybe you don't belong in the room or don't have an updated member list." "Couldn't generate Merkle Proof. Maybe you don't belong in the room or don't have an updated member list."
); );
} else { } else {
alertToast(err as string); alertQueue.enqueue(err as string);
} }
} finally { } finally {
sendingMessage = false; sendingMessage = false;

View File

@@ -1,13 +1,14 @@
<script lang="ts"> <script lang="ts">
import { deriveKey, hashPassword } from '$lib/crypto/crypto'; import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { configStore, identityKeyStore, keyStore, passwordSet } from '$lib/stores';
import { import {
addConsoleMessage, configStore,
clearConsoleMessages, identityKeyStore,
doesIdentityExist, keyStore,
setPassword passwordSet,
} from '$lib/utils/'; identityExists
import { inviteCode } from '$lib/utils/inviteCode'; } from '$lib/stores';
import { addConsoleMessage, clearConsoleMessages, setPassword, unlockPadlock } from '$lib/utils/';
import { inviteCode } from '$lib/gateways/inviteCode';
import { createIdentity } from '$lib/utils/'; import { createIdentity } from '$lib/utils/';
export let placeholder: string = 'Enter / Command'; export let placeholder: string = 'Enter / Command';
@@ -79,20 +80,7 @@
addConsoleMessage('Locked!'); addConsoleMessage('Locked!');
break; break;
case '/unlock': case '/unlock':
const hashedPwd = await hashPassword(args[0]); unlockPadlock(args[0]);
if (hashedPwd === $configStore.hashedPwd) {
if ($keyStore && !(args[1] === 'force')) {
addConsoleMessage(
'Already Unlocked! use `/unlock PASSWORD force` to override this and derive the key again',
'warning'
);
break;
}
$keyStore = await deriveKey(args[0]);
addConsoleMessage('Unlocked!');
} else {
addConsoleMessage(`Invalid password!`, 'warning');
}
break; break;
case '/export': case '/export':
addConsoleMessage('Exporting Identity'); addConsoleMessage('Exporting Identity');
@@ -117,7 +105,7 @@
addConsoleMessage(`Identity: ${$identityKeyStore}`); addConsoleMessage(`Identity: ${$identityKeyStore}`);
break; break;
case '/createIdentity': case '/createIdentity':
const idStatus = doesIdentityExist(); const idStatus = $identityExists;
if (idStatus === 'safe') { if (idStatus === 'safe') {
addConsoleMessage('✅ Identity Exists Already'); addConsoleMessage('✅ Identity Exists Already');
} else if (idStatus === 'unsafe') { } else if (idStatus === 'unsafe') {

View File

@@ -1,8 +1,46 @@
<script lang="ts"> <script lang="ts">
import Container from '$lib/components/Container.svelte'; import Container from '$lib/components/Container.svelte';
import JoinMore from './JoinMore.svelte'; import EthereumWallet from '$lib/components/Gateways/EthereumWallet.svelte';
import InviteCodeGateway from '$lib/components/Gateways/InviteCode.svelte';
import SelectServer from '$lib/components/SelectServer.svelte';
import Card from '$lib/components/card.svelte';
import { configStore } from '$lib/stores';
</script> </script>
<Container heading="Join More Communities"> <Container heading="Join More Communities">
<JoinMore /> <div class="variant-ghost-success p-4 rounded-token">
<h3 class="h4">Select Server, or add a new Server:</h3>
<SelectServer />
</div>
<div class="flex flex-row flex-wrap gap-5 justify-evenly">
<Card>
<svelte:fragment slot="header">Join via invite code:</svelte:fragment>
<svelte:fragment slot="description"
>If you were given an invite code, you can
</svelte:fragment>
<InviteCodeGateway code={$configStore.signUpStatus.inviteCode} />
</Card>
<Card>
<svelte:fragment slot="header">Discord Bot</svelte:fragment>
<svelte:fragment slot="description"
>Add the discord bot to your server Today!
</svelte:fragment>
<a
href="https://discord.com/api/oauth2/authorize?client_id=1142162852132700200&permissions=2147483648&scope=bot"
class="btn variant-ghost-primary">Invite Discord Bot!</a
>
</Card>
<Card>
<svelte:fragment slot="header">Join via Jubmojii:</svelte:fragment>
<svelte:fragment slot="description">Coming Soon!</svelte:fragment>
</Card>
<Card>
<svelte:fragment slot="header">Join via Ethereum Address:</svelte:fragment>
<svelte:fragment slot="description"
>Are you a genesis validator, daohack survivor, nouns holder? You can join using your
Ethereum address.
</svelte:fragment>
<EthereumWallet />
</Card>
</div>
</Container> </Container>

View File

@@ -1,13 +0,0 @@
<script lang="ts">
import Join from '$lib/components/Join.svelte';
import { configStore } from '$lib/stores';
</script>
<div class="card variant-ghost-tertiary">
<header class="card-header">
<h4 class="h4">Join More Rooms</h4>
</header>
<section class="p-2 mb-2">
<Join code={$configStore.signUpStatus.inviteCode} />
</section>
</div>

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { identityExists } from '$lib/stores';
import DeleteIdentity from './identity/DeleteIdentity.svelte'; import DeleteIdentity from './identity/DeleteIdentity.svelte';
import BackupIdentity from './identity/BackupIdentity.svelte'; import BackupIdentity from './identity/BackupIdentity.svelte';
import RestoreIdentity from './identity/RestoreIdentity.svelte'; import RestoreIdentity from './identity/RestoreIdentity.svelte';
@@ -8,6 +7,7 @@
import IdentityIcon from 'svelte-material-icons/Account.svelte'; import IdentityIcon from 'svelte-material-icons/Account.svelte';
import Eye from 'svelte-material-icons/Eye.svelte'; import Eye from 'svelte-material-icons/Eye.svelte';
import Container from '../../lib/components/Container.svelte'; import Container from '../../lib/components/Container.svelte';
import { identityExists } from '$lib/stores';
</script> </script>
<Container heading="Manage Settings"> <Container heading="Manage Settings">

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import { identityKeyStore, keyStore } from '$lib/stores'; import { alertQueue, identityKeyStore, keyStore } from '$lib/stores';
import { alertAll } from '$lib/utils';
import { FileDropzone } from '@skeletonlabs/skeleton'; import { FileDropzone } from '@skeletonlabs/skeleton';
import { poseidon2 } from 'poseidon-lite/poseidon2'; import { poseidon2 } from 'poseidon-lite/poseidon2';
import { poseidon1 } from 'poseidon-lite/poseidon1'; import { poseidon1 } from 'poseidon-lite/poseidon1';
@@ -19,37 +18,37 @@
id = backup; id = backup;
} catch (e) { } catch (e) {
console.warn('Could not parse json as object'); console.warn('Could not parse json as object');
alertAll('Invalid JSON detected'); alertQueue.enqueue('Invalid JSON detected');
return; return;
} }
} }
if (!id._nullifier) { if (!id._nullifier) {
alertAll("_nullifier doesn't exist in backup"); alertQueue.enqueue("_nullifier doesn't exist in backup");
} }
if (!id._trapdoor) { if (!id._trapdoor) {
alertAll("_trapdoor doesn't exist in backup"); alertQueue.enqueue("_trapdoor doesn't exist in backup");
} }
if (!id._secret) { if (!id._secret) {
alertAll("_secret doesn't exist in backup"); alertQueue.enqueue("_secret doesn't exist in backup");
} }
const checkSecret = poseidon2([id._nullifier, id._trapdoor]); const checkSecret = poseidon2([id._nullifier, id._trapdoor]);
if (checkSecret != id._secret) { if (checkSecret != id._secret) {
alertAll('Secret does not match secret from backup'); alertQueue.enqueue('Secret does not match secret from backup');
} }
if (!id._commitment) { if (!id._commitment) {
alertAll("_commitment doesn't exist in backup"); alertQueue.enqueue("_commitment doesn't exist in backup");
} }
const checkCommitment = poseidon1([id._secret]); const checkCommitment = poseidon1([id._secret]);
if (checkCommitment != id._commitment) { if (checkCommitment != id._commitment) {
alertAll('Commitment does not match commitment backup'); alertQueue.enqueue('Commitment does not match commitment backup');
} }
console.log('Restoring identity from backup file...'); console.log('Restoring identity from backup file...');
if ($keyStore !== undefined || $keyStore !== null) { if ($keyStore !== undefined || $keyStore !== null) {
$identityKeyStore = id; $identityKeyStore = id;
} else { } else {
alertAll('Please set a password or unlock before restoring your identity'); alertQueue.enqueue('Please set a password or unlock before restoring your identity');
} }
alertAll( alertQueue.enqueue(
`Identity restored from backup file with identity commitment: `Identity restored from backup file with identity commitment:
${$identityKeyStore._commitment}` ${$identityKeyStore._commitment}`
); );
@@ -60,7 +59,7 @@
console.debug(`Backup/recovery file type detected as ${f?.type}`); console.debug(`Backup/recovery file type detected as ${f?.type}`);
let unverifiedBackup: any; let unverifiedBackup: any;
if (!f) { if (!f) {
alertAll('No file selected'); alertQueue.enqueue('No file selected');
return; return;
} }
if (f.type == 'application/json' || f.type == 'text/plain') { if (f.type == 'application/json' || f.type == 'text/plain') {
@@ -69,7 +68,7 @@
restoreBackup(unverifiedBackup); restoreBackup(unverifiedBackup);
}); });
} else { } else {
alertAll( alertQueue.enqueue(
'Invalid file type, must be a JSON object with the _nullifier, _trapdoor, _secret, and _commitment as stringified bigints' 'Invalid file type, must be a JSON object with the _nullifier, _trapdoor, _secret, and _commitment as stringified bigints'
); );
console.warn('Invalid file type'); console.warn('Invalid file type');
@@ -80,7 +79,7 @@
const textBox = document.getElementById('jsonRecovery') as HTMLInputElement; const textBox = document.getElementById('jsonRecovery') as HTMLInputElement;
const json = textBox.value; const json = textBox.value;
if (!json || json == '') { if (!json || json == '') {
alertAll('No JSON detected'); alertQueue.enqueue('No JSON detected');
return; return;
} else { } else {
restoreBackup(json); restoreBackup(json);

View File

@@ -45,5 +45,5 @@
</form> </form>
</Container> </Container>
{:else} {:else}
<h2 class="h3">Password Set!</h2> <Container heading="Password set" />
{/if} {/if}

View File

@@ -1,35 +1,67 @@
<script lang="ts"> <script lang="ts">
import { configStore, identityKeyStore, identityStore, serverStore } from '$lib/stores'; import {
configStore,
identityExists,
identityKeyStore,
identityStore,
lockStateStore,
passwordSet,
serverStore
} from '$lib/stores';
import { IdentityStoreE } from '$lib/types'; import { IdentityStoreE } from '$lib/types';
import { alertQueue } from '$lib/stores';
function toggleBeta() {
$configStore.beta = !$configStore.beta;
}
function triggerAlert() {
alertQueue.enqueue('TEST');
}
</script> </script>
<div id="status" class="flex flex-col gap-5"> <div class="p-4">
<div> <div id="status" class="flex flex-col gap-5">
<h2 class="h3">configStore</h2> <div>
<div>Completed Signup: {JSON.stringify($configStore.signUpStatus.completedSignup)}</div> <h2 class="h3">configStore</h2>
<div>Identity Backedup: {JSON.stringify($configStore.signUpStatus.identityBackedUp)}</div> <div>Completed Signup: {JSON.stringify($configStore.signUpStatus.completedSignup)}</div>
<div>IdentityStore Type: {IdentityStoreE[$configStore.identityStore]}</div> <div>Identity Backedup: {JSON.stringify($configStore.signUpStatus.identityBackedUp)}</div>
<div>Beta: {JSON.stringify($configStore.beta)}</div> <div>IdentityStore Type: {IdentityStoreE[$configStore.identityStore]}</div>
<div>Hashed Password: {JSON.stringify($configStore.hashedPwd)}</div> <div on:click={toggleBeta}>Beta: {JSON.stringify($configStore.beta)}</div>
</div> <div>Hashed Password: {JSON.stringify($configStore.hashedPwd)}</div>
<div> </div>
<h2 class="h3">Identity Data</h2> <div>
{#each Object.keys($identityStore) as key} <h2 class="h3">Identity Data</h2>
<div>Unprotected {key}: {JSON.stringify($identityStore[key])}</div> {#if $identityExists == 'safe' || $identityExists == 'unsafe'}
{/each} {#each Object.keys($identityStore) as key}
{#each Object.keys($identityKeyStore) as key} <div>Unprotected {key}: {JSON.stringify($identityStore[key])}</div>
<div>Protected {key}: {JSON.stringify($identityKeyStore[key])}</div> {/each}
{/each} {#each Object.keys($identityKeyStore) as key}
</div> <div>Protected {key}: {JSON.stringify($identityKeyStore[key])}</div>
<div> {/each}
<h2 class="h3">Server Data</h2> {:else if $identityExists == 'encrypted'}
{#each Object.keys($serverStore) as key} <div>Identity Exists but is encrypted</div>
<div>{$serverStore[key].name}:</div> {:else}
<div class="ps-5">id: {$serverStore[key].id}</div> <div>No Identity Found</div>
<div class="ps-5">version: {$serverStore[key].version}</div> {/if}
<div class="ps-5">url: {key}</div> </div>
{/each} <div>
<h2 class="h3">Server Data</h2>
{#each Object.keys($serverStore) as key}
<div>{$serverStore[key].name}:</div>
<div class="ps-5">id: {$serverStore[key].id}</div>
<div class="ps-5">version: {$serverStore[key].version}</div>
<div class="ps-5">url: {key}</div>
{/each}
</div>
<div>
<h2 class="h3">Status States</h2>
<div>identityExists: {$identityExists}</div>
<div>Password Set: {$passwordSet}</div>
<div>Lock State: {$lockStateStore}</div>
</div>
</div> </div>
<button class="btn variant-outline-primary m-4" on:click={triggerAlert}>Test Alert</button>
</div> </div>
<style> <style>

View File

@@ -1,21 +1,21 @@
<script lang="ts"> <script lang="ts">
import { identityStore, configStore, consoleStore } from '$lib/stores'; import { configStore, identityExists } from '$lib/stores';
import { createIdentity, doesIdentityExist } from '$lib/utils/';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import ArrowRight from 'svelte-material-icons/ArrowRightBold.svelte'; import ArrowRight from 'svelte-material-icons/ArrowRightBold.svelte';
import Text from 'svelte-material-icons/TextBox.svelte'; import Text from 'svelte-material-icons/TextBox.svelte';
import Account from 'svelte-material-icons/AccountHardHat.svelte'; import Account from 'svelte-material-icons/AccountHardHat.svelte';
import { inviteCode } from '$lib/utils/inviteCode'; import { inviteCode } from '$lib/gateways/inviteCode';
import { addConsoleMessage } from '$lib/utils/console'; import { addConsoleMessage } from '$lib/utils/console';
import Console from '../console/Console.svelte';
function checkForIdentity() { function checkForIdentity() {
const idStatus = doesIdentityExist(); const idStatus = $identityExists;
if (idStatus === 'safe') { if (idStatus === 'safe') {
addConsoleMessage('✅ Identity Found'); addConsoleMessage('✅ Identity Found');
} else if (idStatus === 'encrypted') {
addConsoleMessage('⚠️ Identity Found, but it is encrypted');
} else if (idStatus === 'unsafe') { } else if (idStatus === 'unsafe') {
addConsoleMessage('⚠️ Identity Found, but it is unsafe'); addConsoleMessage('⚠️ Identity Found, but it is unsafe');
} else if (idStatus === 'none') { } else if (idStatus === null) {
addConsoleMessage('❌ No Identity Found'); addConsoleMessage('❌ No Identity Found');
} }
} }