From 9f924f2790ef800bfdac6d8c01795238732cc53e Mon Sep 17 00:00:00 2001 From: tari404 <2680383605@qq.com> Date: Fri, 18 Oct 2024 21:51:41 +0800 Subject: [PATCH 01/13] feat(amaci): add deactiavte & add new key feature --- package-lock.json | 147 +++++++++- package.json | 7 +- src/assets/icons/close.svg | 1 + src/components/KeyManager/Deactivate.tsx | 126 +++++++++ src/components/KeyManager/NewKey.tsx | 250 ++++++++++++++++++ src/components/KeyManager/RecordItem.tsx | 50 ++++ .../KeyManager/icons/deactivate.svg | 1 + src/components/KeyManager/icons/loading.svg | 1 + src/components/KeyManager/icons/next.svg | 1 + .../KeyManager/icons/reactivate.svg | 1 + src/components/KeyManager/index.module.sass | 127 +++++++++ src/components/KeyManager/index.tsx | 65 ++++- src/components/KeyManager/lib.ts | 17 ++ src/components/Main/AMaci.tsx | 9 +- src/components/Main/Maci.tsx | 9 +- src/components/Main/ctx.tsx | 66 ++++- src/components/Signup/index.tsx | 8 +- src/lib/circom.ts | 89 +++++++ src/lib/config.ts | 2 +- src/lib/maci.ts | 117 +++++++- src/lib/tree.d.ts | 3 + src/lib/tree.js | 169 ++++++++++++ src/styles/globals.sass | 53 ++++ 23 files changed, 1294 insertions(+), 25 deletions(-) create mode 100644 src/assets/icons/close.svg create mode 100644 src/components/KeyManager/Deactivate.tsx create mode 100644 src/components/KeyManager/NewKey.tsx create mode 100644 src/components/KeyManager/RecordItem.tsx create mode 100644 src/components/KeyManager/icons/deactivate.svg create mode 100644 src/components/KeyManager/icons/loading.svg create mode 100644 src/components/KeyManager/icons/next.svg create mode 100644 src/components/KeyManager/icons/reactivate.svg create mode 100644 src/components/KeyManager/index.module.sass create mode 100644 src/components/KeyManager/lib.ts create mode 100644 src/lib/tree.d.ts create mode 100644 src/lib/tree.js diff --git a/package-lock.json b/package-lock.json index 2107224..748d3cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "cosmjs-types": "0.8.0", "eslint": "8.48.0", "eslint-config-next": "13.4.19", + "ethers": "^6.13.4", "ffjavascript": "^0.2.60", "next": "13.4.19", "react": "18.2.0", @@ -43,6 +44,11 @@ "node": ">=0.10.0" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, "node_modules/@ant-design/colors": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz", @@ -971,6 +977,11 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -2461,6 +2472,72 @@ "node": ">= 16" } }, + "node_modules/ethers": { + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", + "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmmirror.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -5740,9 +5817,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/type-check": { "version": "0.4.0", @@ -5846,6 +5923,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "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==" + }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz", @@ -6267,6 +6349,11 @@ "resolved": "https://registry.npmmirror.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" }, + "@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, "@ant-design/colors": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.0.0.tgz", @@ -6973,6 +7060,11 @@ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "requires": {} }, + "aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -8194,6 +8286,44 @@ } } }, + "ethers": { + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", + "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", + "requires": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "dependencies": { + "@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "requires": { + "@noble/hashes": "1.3.2" + } + }, + "@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "requires": { + "undici-types": "~6.19.2" + } + }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "requires": {} + } + } + }, "ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmmirror.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -10717,9 +10847,9 @@ } }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "type-check": { "version": "0.4.0", @@ -10798,6 +10928,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, "untildify": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz", diff --git a/package.json b/package.json index f8accb2..3564f4c 100644 --- a/package.json +++ b/package.json @@ -19,16 +19,17 @@ "antd": "^5.8.6", "blake-hash": "^2.0.0", "circom": "https://github.com/weijiekoh/circomlib.git#24ed08eee0bb613b8c0135d66c1013bd9f78d50a", + "cosmjs-types": "0.8.0", "eslint": "8.48.0", "eslint-config-next": "13.4.19", + "ethers": "^6.13.4", "ffjavascript": "^0.2.60", "next": "13.4.19", "react": "18.2.0", "react-dom": "18.2.0", "sass": "^1.66.1", "typescript": "5.2.2", - "yaml-loader": "^0.8.0", - "cosmjs-types": "0.8.0" + "yaml-loader": "^0.8.0" }, "devDependencies": { "eslint-config-prettier": "^9.0.0", @@ -36,4 +37,4 @@ "eslint-plugin-prettier": "^5.0.0", "prettier": "^3.0.3" } -} \ No newline at end of file +} diff --git a/src/assets/icons/close.svg b/src/assets/icons/close.svg new file mode 100644 index 0000000..c909fd5 --- /dev/null +++ b/src/assets/icons/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/KeyManager/Deactivate.tsx b/src/components/KeyManager/Deactivate.tsx new file mode 100644 index 0000000..0fcbb96 --- /dev/null +++ b/src/components/KeyManager/Deactivate.tsx @@ -0,0 +1,126 @@ +import { useRef, useImperativeHandle, forwardRef, ChangeEvent, useState, useContext } from 'react' +import Image from 'next/image' + +import { MainContext } from '../Main/ctx' +import { DialogHandle, toTimeString } from './lib' +import styles from './index.module.sass' + +import * as MACI from '@/lib/maci' +import { batchGenMessage, privateKeyFromTxt } from '@/lib/circom' + +import close from '@/assets/icons/close.svg' + +import common from '@/styles/common.module.sass' +import font from '@/styles/font.module.sass' +import { getConfig } from '@/lib/config' + +export default forwardRef(function Deactivate(_, ref) { + const { address, client, addRecord } = useContext(MainContext) + + const dialogRef = useRef(null) + + const cutOffDate = toTimeString(new Date((Math.floor(Date.now() / 1800000) + 2) * 1800000)) + + const openDialog = () => { + if (dialogRef.current) { + dialogRef.current.showModal() + } + setMessage('') + setInputKey('') + setSubmiting(false) + } + const closeDialog = () => { + if (dialogRef.current) { + dialogRef.current.close() + } + } + + useImperativeHandle(ref, () => ({ + openDialog, + closeDialog, + })) + + const [inputKey, setInputKey] = useState('') + const onChange = (e: ChangeEvent) => { + const v = e.target.value + setMessage('') + setInputKey(v) + } + + const [message, setMessage] = useState('') + const [submiting, setSubmiting] = useState(false) + const next = async () => { + if (!inputKey || submiting || !client) { + return + } + + const maciAccount = privateKeyFromTxt(inputKey) + if (!maciAccount) { + setMessage('Invalid aMACI key!') + setInputKey('') + return + } + + setSubmiting(true) + + const stateIdx = await MACI.fetchStateIdxByPubKey(maciAccount.pubKey) + if (stateIdx < 0) { + setMessage('Unsigned aMACI key!') + setInputKey('') + setSubmiting(false) + return + } + + const payload = batchGenMessage(stateIdx, maciAccount, getConfig().coordPubKey, [[0, 0]]) + + try { + await MACI.submitDeactivate(client, address, payload) + setSubmiting(false) + addRecord('deactivate') + closeDialog() + } catch { + setMessage('Deactivation canceled!') + setSubmiting(false) + } + } + + return ( + + +
+

Deactivate your aMACI key

+

+ The key set will be updated{' '} + every 30 minutes. The next + deactivation cut-off will be on{' '} + {cutOffDate}. +

+
+
+