diff --git a/package-lock.json b/package-lock.json index 0e476020..a55e82b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "thenewboston", - "version": "1.0.0-alpha.43", + "version": "1.0.0-alpha.44", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "thenewboston", - "version": "1.0.0-alpha.43", + "version": "1.0.0-alpha.44", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -47,6 +47,7 @@ "resolve-url-loader": "^3.1.2", "semver": "7.3.2", "terser-webpack-plugin": "^4.2.3", + "thenewboston": "^1.1.0-alpha.0", "ts-pnp": "^1.2.0", "tweetnacl": "^1.0.3", "typeface-roboto": "^0.0.75", @@ -1297,9 +1298,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", "dependencies": { "regenerator-runtime": "^0.13.4" } @@ -14214,17 +14215,17 @@ } }, "node_modules/elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "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.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^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": { @@ -20693,8 +20694,7 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "node_modules/json3": { "version": "3.3.3", @@ -21297,6 +21297,11 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -22400,6 +22405,41 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", "dev": true }, + "node_modules/nock": { + "version": "13.0.11", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.0.11.tgz", + "integrity": "sha512-sKZltNkkWblkqqPAsjYW0bm3s9DcHRPiMOyKO/PkfJ+ANHZ2+LA2PLe22r4lLrKgXaiSaDQwW3qGsJFtIpQIeQ==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash.set": "^4.3.2", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/nock/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nock/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/node-abi": { "version": "2.19.3", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz", @@ -23777,14 +23817,14 @@ } }, "node_modules/plist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", - "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-MSrkwZBdQ6YapHy87/8hDU8MnIcyxBKjeF+McXnr5A9MtffPewTs7G3hlpodT5TacyfIyFTaJEhh3GGcmasTgQ==", "dev": true, "dependencies": { - "base64-js": "^1.2.3", + "base64-js": "^1.5.1", "xmlbuilder": "^9.0.7", - "xmldom": "0.1.x" + "xmldom": "^0.5.0" }, "engines": { "node": ">=6" @@ -26916,6 +26956,14 @@ "react-is": "^16.8.1" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, "node_modules/property-expr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", @@ -30291,6 +30339,18 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, + "node_modules/thenewboston": { + "version": "1.1.0-alpha.0", + "resolved": "https://registry.npmjs.org/thenewboston/-/thenewboston-1.1.0-alpha.0.tgz", + "integrity": "sha512-IJOP2Q+h5RDESs+1jwVyr+za8Ll+uqd3grVFGt4RZ/wK3hLOdQbVrMqpPuNGK9EL8lSFzq2UCTlLc9JDeyZabQ==", + "dependencies": { + "@babel/runtime": "^7.13.9", + "axios": "^0.21.0", + "core-js": "^3.7.0", + "nock": "^13.0.11", + "tweetnacl": "^1.0.3" + } + }, "node_modules/throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -32728,12 +32788,12 @@ "dev": true }, "node_modules/xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz", + "integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==", "dev": true, "engines": { - "node": ">=0.1" + "node": ">=10.0.0" } }, "node_modules/xtend": { @@ -34108,9 +34168,9 @@ } }, "@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -44959,17 +45019,17 @@ } }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { @@ -50193,8 +50253,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json3": { "version": "3.3.3", @@ -50685,6 +50744,11 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -51587,6 +51651,32 @@ } } }, + "nock": { + "version": "13.0.11", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.0.11.tgz", + "integrity": "sha512-sKZltNkkWblkqqPAsjYW0bm3s9DcHRPiMOyKO/PkfJ+ANHZ2+LA2PLe22r4lLrKgXaiSaDQwW3qGsJFtIpQIeQ==", + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash.set": "^4.3.2", + "propagate": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "node-abi": { "version": "2.19.3", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz", @@ -52733,14 +52823,14 @@ } }, "plist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", - "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-MSrkwZBdQ6YapHy87/8hDU8MnIcyxBKjeF+McXnr5A9MtffPewTs7G3hlpodT5TacyfIyFTaJEhh3GGcmasTgQ==", "dev": true, "requires": { - "base64-js": "^1.2.3", + "base64-js": "^1.5.1", "xmlbuilder": "^9.0.7", - "xmldom": "0.1.x" + "xmldom": "^0.5.0" } }, "pngjs": { @@ -55339,6 +55429,11 @@ "react-is": "^16.8.1" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" + }, "property-expr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", @@ -58179,6 +58274,18 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, + "thenewboston": { + "version": "1.1.0-alpha.0", + "resolved": "https://registry.npmjs.org/thenewboston/-/thenewboston-1.1.0-alpha.0.tgz", + "integrity": "sha512-IJOP2Q+h5RDESs+1jwVyr+za8Ll+uqd3grVFGt4RZ/wK3hLOdQbVrMqpPuNGK9EL8lSFzq2UCTlLc9JDeyZabQ==", + "requires": { + "@babel/runtime": "^7.13.9", + "axios": "^0.21.0", + "core-js": "^3.7.0", + "nock": "^13.0.11", + "tweetnacl": "^1.0.3" + } + }, "throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -60226,9 +60333,9 @@ "dev": true }, "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz", + "integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==", "dev": true }, "xtend": { diff --git a/package.json b/package.json index 8e48ced5..490406cc 100644 --- a/package.json +++ b/package.json @@ -158,6 +158,7 @@ "resolve-url-loader": "^3.1.2", "semver": "7.3.2", "terser-webpack-plugin": "^4.2.3", + "thenewboston": "^1.1.0-alpha.0", "ts-pnp": "^1.2.0", "tweetnacl": "^1.0.3", "typeface-roboto": "^0.0.75", diff --git a/src/renderer/containers/Account/CreateAccountModal/index.tsx b/src/renderer/containers/Account/CreateAccountModal/index.tsx index e7d9a9ce..e66e8d41 100644 --- a/src/renderer/containers/Account/CreateAccountModal/index.tsx +++ b/src/renderer/containers/Account/CreateAccountModal/index.tsx @@ -1,6 +1,7 @@ import React, {FC, useMemo, useState} from 'react'; import {useDispatch, useSelector} from 'react-redux'; import {useHistory} from 'react-router-dom'; +import {Account} from 'thenewboston'; import Modal from '@renderer/components/Modal'; import { @@ -15,10 +16,8 @@ import {setManagedAccount} from '@renderer/store/app'; import {setAccountBalance} from '@renderer/store/accountBalances'; import {setManagedAccountBalance} from '@renderer/store/managedAccountBalances'; import {AppDispatch} from '@renderer/types'; -import {generateAccount} from '@renderer/utils/accounts'; import {getNicknameField} from '@renderer/utils/forms/fields'; import yup from '@renderer/utils/forms/yup'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayErrorToast, displayToast} from '@renderer/utils/toast'; import CreateAccountModalFields, {FormValues, initialValues} from './CreateAccountModalFields'; @@ -49,8 +48,8 @@ const CreateAccountModal: FC = ({close, isGetStartedModal = fals if (type === 'add') { try { - const {publicKeyHex, signingKeyHex} = getKeyPairFromSigningKeyHex(signingKey); - accountNumberStr = publicKeyHex; + const {accountNumberHex, signingKeyHex} = new Account(signingKey); + accountNumberStr = accountNumberHex; signingKeyStr = signingKeyHex; // check if accountNumber is a friend @@ -79,8 +78,8 @@ const CreateAccountModal: FC = ({close, isGetStartedModal = fals } if (type === 'create') { - const {publicKeyHex, signingKeyHex} = generateAccount(); - accountNumberStr = publicKeyHex; + const {accountNumberHex, signingKeyHex} = new Account(); + accountNumberStr = accountNumberHex; signingKeyStr = signingKeyHex; displayToast('You successfully created an account!', 'success'); } diff --git a/src/renderer/containers/Bank/AddBankSigningKeysModal/index.tsx b/src/renderer/containers/Bank/AddBankSigningKeysModal/index.tsx index 165c7038..2ea6fea5 100644 --- a/src/renderer/containers/Bank/AddBankSigningKeysModal/index.tsx +++ b/src/renderer/containers/Bank/AddBankSigningKeysModal/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useMemo} from 'react'; import {useDispatch, useSelector} from 'react-redux'; +import {Account} from 'thenewboston'; import {FormTextArea} from '@renderer/components/FormComponents'; import Modal from '@renderer/components/Modal'; @@ -14,7 +15,6 @@ import {getBankConfigs, getManagedAccounts, getManagedBanks} from '@renderer/sel import {setManagedBank} from '@renderer/store/app'; import {AppDispatch} from '@renderer/types'; import yup from '@renderer/utils/forms/yup'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayToast} from '@renderer/utils/toast'; interface ComponentProps { @@ -49,15 +49,6 @@ const AddBankSigningKeysModal: FC = ({close}) => { return `${prefix} Signing Keys`; }, [managedBank]); - const checkPrivateSigningKey = (publicKey: string, privateKey: string): boolean => { - try { - const {publicKeyHex} = getKeyPairFromSigningKeyHex(privateKey); - return publicKeyHex === publicKey; - } catch (error) { - return false; - } - }; - const handleSubmit = ({accountSigningKey, nidSigningKey}: FormValues): void => { dispatch( setManagedBank({ @@ -79,7 +70,7 @@ const AddBankSigningKeysModal: FC = ({close}) => { .test({ message: SIGNING_KEY_INVALID_ACCOUNT_ERROR, name: 'is-valid-private-key-account', - test: (key: any) => checkPrivateSigningKey(accountNumber, key), + test: (key: any) => Account.isValidPair(accountNumber, key), }), nidSigningKey: yup .string() @@ -88,7 +79,7 @@ const AddBankSigningKeysModal: FC = ({close}) => { .test({ message: SIGNING_KEY_INVALID_NID_ERROR, name: 'is-valid-private-key-nid', - test: (key: any) => checkPrivateSigningKey(nodeIdentifier, key), + test: (key: any) => Account.isValidPair(nodeIdentifier, key), }), }); }, [accountNumber, nodeIdentifier]); diff --git a/src/renderer/containers/EditTrustModal/index.tsx b/src/renderer/containers/EditTrustModal/index.tsx index 78568dd8..4ba426b6 100644 --- a/src/renderer/containers/EditTrustModal/index.tsx +++ b/src/renderer/containers/EditTrustModal/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useMemo, useState} from 'react'; import axios from 'axios'; +import {Account} from 'thenewboston'; import {FormInput} from '@renderer/components/FormComponents'; import Modal from '@renderer/components/Modal'; @@ -7,7 +8,6 @@ import {useNavigationalHistory} from '@renderer/hooks'; import {ManagedNode} from '@renderer/types'; import {formatAddressFromNode} from '@renderer/utils/address'; import yup from '@renderer/utils/forms/yup'; -import {generateSignature, getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayToast} from '@renderer/utils/toast'; interface ComponentProps { @@ -35,12 +35,8 @@ const EditTrustModal: FC = ({close, requestingNode, targetIdenti const handleSubmit = async (values: FormValues): Promise => { try { setSubmitting(true); - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(requestingNode.nid_signing_key); - const requestData = { - message: values, - node_identifier: publicKeyHex, - signature: generateSignature(JSON.stringify(values), signingKey), - }; + const networkIdKeyPair = new Account(requestingNode.nid_signing_key); + const requestData = networkIdKeyPair.createSignedMessage(values); const address = `${formatAddressFromNode(requestingNode)}/${targetType}/${targetIdentifier}`; await axios.patch(address, requestData); reload(); diff --git a/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/BulkPurchaseConfirmationServicesModalFields/index.tsx b/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/BulkPurchaseConfirmationServicesModalFields/index.tsx index 92bf4078..1b508f5e 100644 --- a/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/BulkPurchaseConfirmationServicesModalFields/index.tsx +++ b/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/BulkPurchaseConfirmationServicesModalFields/index.tsx @@ -2,6 +2,7 @@ import React, {ChangeEvent, Dispatch, FC, useCallback, useEffect, useMemo} from import {useDispatch, useSelector} from 'react-redux'; import clsx from 'clsx'; import noop from 'lodash/noop'; +import {Account} from 'thenewboston'; import {Button, Icon, IconType} from '@thenewboston/ui'; import ExpandableText from '@renderer/components/ExpandableText'; @@ -19,7 +20,6 @@ import { } from '@renderer/selectors'; import {AppDispatch, ManagedNode} from '@renderer/types'; import {formatAddressFromNode, isSameNode} from '@renderer/utils/address'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayErrorToast} from '@renderer/utils/toast'; import {getBankTxFee, getPrimaryValidatorTxFee} from '@renderer/utils/transactions'; @@ -72,7 +72,7 @@ const BulkPurchaseConfirmationServicesModalFields: FC = ({ const primaryValidatorConfig = useSelector(getPrimaryValidatorConfig)!; const {data: selectedBankConfig} = bankConfigs[selectedBankAddress]; const {node_identifier: selectedBankNodeIdentifier} = selectedBankConfig; - const {publicKeyHex: selectedBankAccountNumber} = getKeyPairFromSigningKeyHex(selectedBank.account_signing_key); + const {accountNumberHex: selectedBankAccountNumber} = new Account(selectedBank.account_signing_key); const selectedBankBalance = accountBalances[selectedBankAccountNumber]; const testConnection = useCallback( diff --git a/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/index.tsx b/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/index.tsx index cacd74af..4c521953 100644 --- a/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/index.tsx +++ b/src/renderer/containers/PurchaseConfirmationServices/BulkPurchaseConfirmationServicesModal/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useEffect, useMemo, useReducer, useState} from 'react'; import {useDispatch, useSelector} from 'react-redux'; +import {Account} from 'thenewboston'; import Modal from '@renderer/components/Modal'; import {fetchBankConfig} from '@renderer/dispatchers/banks'; @@ -7,7 +8,6 @@ import {getActiveBankConfig, getPrimaryValidatorConfig} from '@renderer/selector import {AppDispatch, ManagedNode} from '@renderer/types'; import {formatAddressFromNode} from '@renderer/utils/address'; import {sendBlock} from '@renderer/utils/blocks'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayErrorToast, displayToast} from '@renderer/utils/toast'; import BulkPurchaseConfirmationServicesModalFields from './BulkPurchaseConfirmationServicesModalFields'; @@ -45,7 +45,7 @@ const BulkPurchaseConfirmationServicesModal: FC = ({bank, close, const handleSubmit = async (): Promise => { try { setSubmitting(true); - const {publicKeyHex: bankAccountNumber} = getKeyPairFromSigningKeyHex(bank.account_signing_key); + const {accountNumberHex: bankAccountNumber} = new Account(bank.account_signing_key); const recipients = Object.entries(formValues) .map(([nodeIdentifier, {amount}]) => { const validatorData = selectedValidators[nodeIdentifier]; diff --git a/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/PurchaseConfirmationServicesModalFields/index.tsx b/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/PurchaseConfirmationServicesModalFields/index.tsx index 7ee5e916..feb0a8af 100644 --- a/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/PurchaseConfirmationServicesModalFields/index.tsx +++ b/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/PurchaseConfirmationServicesModalFields/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useEffect, useMemo} from 'react'; import {useDispatch, useSelector} from 'react-redux'; +import {Account} from 'thenewboston'; import {FormInput, FormSelectDetailed} from '@renderer/components/FormComponents'; import RequiredAsterisk from '@renderer/components/RequiredAsterisk'; @@ -13,7 +14,6 @@ import { getAuthenticatedBanks, } from '@renderer/selectors'; import {AppDispatch, BaseValidator, InputOption} from '@renderer/types'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayErrorToast} from '@renderer/utils/toast'; import {getBankTxFee, getPrimaryValidatorTxFee} from '@renderer/utils/transactions'; @@ -37,7 +37,7 @@ const PurchaseConfirmationServicesModalFields: FC = ({submitting const authenticatedBanks = useSelector(getAuthenticatedBanks); const accountBalances = useSelector(getAccountBalances); const selectedBank = authenticatedBanks[values.bankAddress]; - const {publicKeyHex: accountNumber} = getKeyPairFromSigningKeyHex(selectedBank.account_signing_key); + const {accountNumberHex: accountNumber} = new Account(selectedBank.account_signing_key); const selectedAccountBalance = accountBalances[accountNumber]; useEffect(() => { diff --git a/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/index.tsx b/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/index.tsx index 4508c71d..56dd560f 100644 --- a/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/index.tsx +++ b/src/renderer/containers/PurchaseConfirmationServices/PurchaseConfirmationServicesModal/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useCallback, useMemo, useState} from 'react'; import {useSelector} from 'react-redux'; +import {Account} from 'thenewboston'; import Modal from '@renderer/components/Modal'; import {INVALID_AMOUNT_ERROR} from '@renderer/constants/form-validation'; @@ -13,7 +14,6 @@ import { import {BaseValidator} from '@renderer/types'; import {sendBlock} from '@renderer/utils/blocks'; import yup from '@renderer/utils/forms/yup'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayErrorToast, displayToast} from '@renderer/utils/toast'; import {getBankTxFee, getPrimaryValidatorTxFee} from '@renderer/utils/transactions'; @@ -46,7 +46,7 @@ const PurchaseConfirmationServicesModal: FC = ({close, initialBa try { setSubmitting(true); const selectedBank = authenticatedBanks[bankAddress]; - const {publicKeyHex: bankAccountNumber} = getKeyPairFromSigningKeyHex(selectedBank.account_signing_key); + const {accountNumberHex: bankAccountNumber} = new Account(selectedBank.account_signing_key); await sendBlock(activeBankConfig, activePrimaryValidator, selectedBank.account_signing_key, bankAccountNumber, [ {accountNumber: validator.account_number, amount: parseInt(amount, 10)}, ]); @@ -103,7 +103,7 @@ const PurchaseConfirmationServicesModal: FC = ({close, initialBa if (!amount || !bankAddress) return true; const selectedBank = authenticatedBanks[bankAddress]; - const {publicKeyHex: accountNumber} = getKeyPairFromSigningKeyHex(selectedBank.account_signing_key); + const {accountNumberHex: accountNumber} = new Account(selectedBank.account_signing_key); const managedAccountBalance = accountBalances[accountNumber]; if (!managedAccountBalance) return false; @@ -135,7 +135,7 @@ const PurchaseConfirmationServicesModal: FC = ({close, initialBa (address) => { if (!address) return true; const selectedBank = authenticatedBanks[address]; - const {publicKeyHex: accountNumber} = getKeyPairFromSigningKeyHex(selectedBank.account_signing_key); + const {accountNumberHex: accountNumber} = new Account(selectedBank.account_signing_key); return accountNumber !== validator.account_number; }, ) diff --git a/src/renderer/containers/PurchaseConfirmationServices/utils.ts b/src/renderer/containers/PurchaseConfirmationServices/utils.ts index c5897e92..863aab0e 100644 --- a/src/renderer/containers/PurchaseConfirmationServices/utils.ts +++ b/src/renderer/containers/PurchaseConfirmationServices/utils.ts @@ -1,9 +1,10 @@ import axios from 'axios'; import omit from 'lodash/omit'; +import {Account} from 'thenewboston'; + import {AXIOS_TIMEOUT_MS} from '@renderer/config'; import {BaseValidator, ManagedNode} from '@renderer/types'; import {formatAddressFromNode} from '@renderer/utils/address'; -import {generateSignedMessage, getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; export type SelectedValidatorState = { [nodeIdentifier: string]: BaseValidator & { @@ -66,7 +67,7 @@ export const checkConnectionBankToValidator = async ( await axios.get(`${bankAddress}/validators/${validator.node_identifier}`, {timeout: AXIOS_TIMEOUT_MS}); } catch (error) { if (!managedBank.nid_signing_key) throw new Error('No NID SK'); - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(managedBank.nid_signing_key); + const bankNetworkKeyPair = new Account(managedBank.nid_signing_key); const validatorData = { account_number: validator.account_number, daily_confirmation_rate: validator.daily_confirmation_rate, @@ -78,7 +79,7 @@ export const checkConnectionBankToValidator = async ( trust: 0, version: validator.version, }; - const signedMessage = generateSignedMessage(validatorData, publicKeyHex, signingKey); + const signedMessage = bankNetworkKeyPair.createSignedMessage(validatorData); await axios.post(`${bankAddress}/validators`, signedMessage, { headers: { 'Content-Type': 'application/json', @@ -98,13 +99,13 @@ export const checkConnectionValidatorToBank = async ( await axios.get(`${validatorAddress}/banks/${bankNodeIdentifier}`, {timeout: AXIOS_TIMEOUT_MS}); } catch (error) { if (!managedBank.nid_signing_key) throw new Error('No NID SK'); - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(managedBank.nid_signing_key); + const validatorNetworkKeyPair = new Account(managedBank.nid_signing_key); const connectionRequestData = { ip_address: managedBank.ip_address, port: managedBank.port, protocol: managedBank.protocol, }; - const signedMessage = generateSignedMessage(connectionRequestData, publicKeyHex, signingKey); + const signedMessage = validatorNetworkKeyPair.createSignedMessage(connectionRequestData); await axios.post(`${validatorAddress}/connection_requests`, signedMessage, { headers: { 'Content-Type': 'application/json', diff --git a/src/renderer/containers/Validator/AddValidatorSigningKeysModal/index.tsx b/src/renderer/containers/Validator/AddValidatorSigningKeysModal/index.tsx index a0ec5860..2fa0a3e9 100644 --- a/src/renderer/containers/Validator/AddValidatorSigningKeysModal/index.tsx +++ b/src/renderer/containers/Validator/AddValidatorSigningKeysModal/index.tsx @@ -1,5 +1,6 @@ import React, {FC, useMemo} from 'react'; import {useDispatch, useSelector} from 'react-redux'; +import {Account} from 'thenewboston'; import {FormTextArea} from '@renderer/components/FormComponents'; import Modal from '@renderer/components/Modal'; @@ -9,7 +10,6 @@ import {getManagedAccounts, getManagedValidators, getValidatorConfigs} from '@re import {setManagedValidator} from '@renderer/store/app'; import {AppDispatch} from '@renderer/types'; import yup from '@renderer/utils/forms/yup'; -import {getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {displayToast} from '@renderer/utils/toast'; interface ComponentProps { @@ -55,8 +55,8 @@ const AddValidatorSigningKeysModal: FC = ({close}) => { const checkPrivateSigningKey = (publicKey: string, privateKey: string): boolean => { try { - const {publicKeyHex} = getKeyPairFromSigningKeyHex(privateKey); - return publicKeyHex === publicKey; + const {accountNumberHex} = new Account(privateKey); + return accountNumberHex === publicKey; } catch (error) { return false; } diff --git a/src/renderer/dispatchers/balances.ts b/src/renderer/dispatchers/balances.ts index 09acf532..14e95772 100644 --- a/src/renderer/dispatchers/balances.ts +++ b/src/renderer/dispatchers/balances.ts @@ -5,6 +5,7 @@ import {setManagedAccountBalance} from '@renderer/store/managedAccountBalances'; import {AppDispatch, Balance, RootState} from '@renderer/types'; import {formatAddressFromNode} from '@renderer/utils/address'; import {AXIOS_TIMEOUT_MS} from '@renderer/config'; +import {Account, PrimaryValidator} from 'thenewboston'; export const fetchAccountBalance = (accountNumber: string) => async ( dispatch: AppDispatch, @@ -12,13 +13,14 @@ export const fetchAccountBalance = (accountNumber: string) => async ( ): Promise => { const state = getState(); const managedAccounts = getManagedAccounts(state); - const primaryValidator = getPrimaryValidator(state); + const pvAddressData = getPrimaryValidator(state); const isManagedAccount = !!managedAccounts[accountNumber]; - if (!primaryValidator) throw new Error('No primary validator. Unable to fetch account balance.'); - const address = formatAddressFromNode(primaryValidator); + if (!pvAddressData) throw new Error('No primary validator. Unable to fetch account balance.'); + const pvAddress = formatAddressFromNode(pvAddressData); + const PV = new PrimaryValidator(pvAddress); - const {data} = await axios.get(`${address}/accounts/${accountNumber}/balance`, {timeout: AXIOS_TIMEOUT_MS}); + const data = await PV.getAccountBalance(accountNumber); const balance = data.balance || 0; const balancePayload = { account_number: accountNumber, diff --git a/src/renderer/hooks/useCleanSockets.tsx b/src/renderer/hooks/useCleanSockets.tsx index 3de17e06..3910dfa5 100644 --- a/src/renderer/hooks/useCleanSockets.tsx +++ b/src/renderer/hooks/useCleanSockets.tsx @@ -1,6 +1,7 @@ import {useCallback, useEffect} from 'react'; import {useDispatch, useSelector} from 'react-redux'; import axios from 'axios'; +import {Account} from 'thenewboston'; import {getInactiveCleanSockets} from '@renderer/selectors/sockets'; import { @@ -12,7 +13,6 @@ import { SocketConnectionStatus, } from '@renderer/types'; import {formatAddressFromNode, formatSocketAddressFromNode} from '@renderer/utils/address'; -import {generateSignedMessage, getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {initializeSocketForCleanStatus} from '@renderer/utils/sockets'; import handleCleanSocketEvent from '@renderer/utils/sockets/clean'; import {displayErrorToast} from '@renderer/utils/toast'; @@ -32,8 +32,8 @@ const useCleanSockets = (): void => { const address = formatAddressFromNode(cleanSocket); const socketAddress = formatSocketAddressFromNode(cleanSocket); - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(cleanSocket.signingKey); - const signedMessage = generateSignedMessage(cleanData, publicKeyHex, signingKey); + const socketNetworkId = new Account(cleanSocket.signingKey); + const signedMessage = socketNetworkId.createSignedMessage(cleanData); const {data} = await axios.post(`${address}/clean`, signedMessage, { headers: { 'Content-Type': 'application/json', diff --git a/src/renderer/hooks/useCrawlSockets.tsx b/src/renderer/hooks/useCrawlSockets.tsx index db97467e..86ee390e 100644 --- a/src/renderer/hooks/useCrawlSockets.tsx +++ b/src/renderer/hooks/useCrawlSockets.tsx @@ -1,6 +1,7 @@ import {useCallback, useEffect} from 'react'; import {useDispatch, useSelector} from 'react-redux'; import axios from 'axios'; +import {Account} from 'thenewboston'; import {getInactiveCrawlSockets} from '@renderer/selectors/sockets'; import { @@ -12,7 +13,6 @@ import { SocketConnectionStatus, } from '@renderer/types'; import {formatAddressFromNode, formatSocketAddressFromNode} from '@renderer/utils/address'; -import {generateSignedMessage, getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {initializeSocketForCrawlStatus} from '@renderer/utils/sockets'; import handleCrawlSocketEvent from '@renderer/utils/sockets/crawl'; import {displayErrorToast} from '@renderer/utils/toast'; @@ -32,8 +32,8 @@ const useCrawlSockets = (): void => { const address = formatAddressFromNode(crawlSocket); const socketAddress = formatSocketAddressFromNode(crawlSocket); - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(crawlSocket.signingKey); - const signedMessage = generateSignedMessage(crawlData, publicKeyHex, signingKey); + const socketNetworkKeyPair = new Account(crawlSocket.signingKey); + const signedMessage = socketNetworkKeyPair.createSignedMessage(crawlData); const {data} = await axios.post(`${address}/crawl`, signedMessage, { headers: { 'Content-Type': 'application/json', diff --git a/src/renderer/utils/accounts.ts b/src/renderer/utils/accounts.ts deleted file mode 100644 index f3c4d76e..00000000 --- a/src/renderer/utils/accounts.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {sign} from 'tweetnacl'; - -import {getKeyPairDetails} from '@renderer/utils/signing'; - -export const generateAccount = () => { - const keyPair = sign.keyPair(); - return getKeyPairDetails(keyPair); -}; diff --git a/src/renderer/utils/blocks.ts b/src/renderer/utils/blocks.ts index 0d1a1061..558e6e4f 100644 --- a/src/renderer/utils/blocks.ts +++ b/src/renderer/utils/blocks.ts @@ -1,22 +1,11 @@ import axios from 'axios'; +import {Account} from 'thenewboston'; import {AcceptedFees, BankConfig, Tx, ValidatorConfig} from '@renderer/types'; import {formatAddress} from '@renderer/utils/address'; -import {generateBlock, getKeyPairFromSigningKeyHex} from '@renderer/utils/signing'; import {getBankTxFee, getPrimaryValidatorTxFee} from '@renderer/utils/transactions'; import {AXIOS_TIMEOUT_MS} from '@renderer/config'; -const createBlock = async ( - activePrimaryValidator: ValidatorConfig, - senderSigningKey: string, - senderAccountNumber: string, - txs: Tx[], -): Promise => { - const {publicKeyHex, signingKey} = getKeyPairFromSigningKeyHex(senderSigningKey); - const balanceLock = await fetchAccountBalanceLock(senderAccountNumber, activePrimaryValidator); - return generateBlock(balanceLock, publicKeyHex, signingKey, txs); -}; - const fetchAccountBalanceLock = async ( accountNumber: string, activePrimaryValidator: ValidatorConfig, @@ -78,8 +67,9 @@ export const sendBlock = async ( const {ip_address: ipAddress, port, protocol} = activeBankConfig; const address = formatAddress(ipAddress, port, protocol); - - const block = await createBlock(primaryValidatorConfig, senderSigningKey, senderAccountNumber, txs); + const sender = new Account(senderSigningKey); + const balanceLock = await fetchAccountBalanceLock(senderAccountNumber, primaryValidatorConfig); + const block = sender.createBlockMessage(balanceLock, txs); await axios.post(`${address}/blocks`, block, { headers: { 'Content-Type': 'application/json', diff --git a/src/renderer/utils/signing.ts b/src/renderer/utils/signing.ts deleted file mode 100644 index 05487e27..00000000 --- a/src/renderer/utils/signing.ts +++ /dev/null @@ -1,58 +0,0 @@ -import {sign, SignKeyPair} from 'tweetnacl'; -import orderBy from 'lodash/orderBy'; - -import {Tx} from '@renderer/types'; - -export const generateBlock = ( - balanceLock: string, - publicKeyHex: string, - signingKey: Uint8Array, - transactions: Tx[], -) => { - const message = { - balance_key: balanceLock, - txs: orderBy(transactions, ['recipient']), - }; - const strMessage: string = JSON.stringify(message); - const block = { - account_number: publicKeyHex, - message, - signature: generateSignature(strMessage, signingKey), - }; - return JSON.stringify(block); -}; - -export const generateSignature = (message: string, signingKey: Uint8Array) => { - const encoder = new TextEncoder(); - const encodedData = encoder.encode(message); - const signatureArray = sign(encodedData, signingKey); - const signature = Buffer.from(signatureArray).toString('hex'); - return signature.substring(0, 128); -}; - -export const generateSignedMessage = (message: any, publicKeyHex: string, signingKey: Uint8Array) => { - const strMessage = JSON.stringify(message); - const signedMessage = { - message, - node_identifier: publicKeyHex, - signature: generateSignature(strMessage, signingKey), - }; - return JSON.stringify(signedMessage); -}; - -export const getKeyPairDetails = (keyPair: SignKeyPair) => { - const {publicKey, secretKey: signingKey} = keyPair; - const publicKeyHex = Buffer.from(publicKey).toString('hex'); - const signingKeyHex = Buffer.from(signingKey).toString('hex'); - return { - publicKey, - publicKeyHex, - signingKey, - signingKeyHex: signingKeyHex.replace(publicKeyHex, ''), - }; -}; - -export const getKeyPairFromSigningKeyHex = (signingKeyHex: string) => { - const keyPair = sign.keyPair.fromSeed(Buffer.from(signingKeyHex, 'hex')); - return getKeyPairDetails(keyPair); -};