From d302119ffbca66505f208b161c15ba1e2adf4f94 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 11 Jan 2022 22:44:04 +0100 Subject: [PATCH] Implement more advanced address checks --- components/forms/TransactionForm.js | 36 +++++++++++++++-------------- lib/displayHelpers.js | 29 ++++++++++++++++++++++- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/components/forms/TransactionForm.js b/components/forms/TransactionForm.js index 54de8dd..5ed86be 100644 --- a/components/forms/TransactionForm.js +++ b/components/forms/TransactionForm.js @@ -7,7 +7,7 @@ import { withRouter } from "next/router"; import Button from "../../components/inputs/Button"; import Input from "../../components/inputs/Input"; import StackableContainer from "../layout/StackableContainer"; -import { exampleAddress } from "../../lib/displayHelpers"; +import { checkAddress, exampleAddress } from "../../lib/displayHelpers"; class TransactionForm extends React.Component { constructor(props) { @@ -56,23 +56,25 @@ class TransactionForm extends React.Component { }; handleCreate = async () => { - if (this.state.toAddress.length === 45) { - this.setState({ processing: true }); - const tx = this.createTransaction( - this.state.toAddress, - this.state.amount, - this.state.gas - ); - console.log(tx); - const dataJSON = JSON.stringify(tx); - const res = await axios.post("/api/transaction", { dataJSON }); - const { transactionID } = res.data; - this.props.router.push( - `${this.props.address}/transaction/${transactionID}` - ); - } else { - this.setState({ addressError: "Use a valid cosmos-hub address" }); + const addressError = checkAddress(this.state.toAddress); + if (addressError) { + this.setState({ addressError: `Invalid address for network ${process.env.NEXT_PUBLIC_CHAIN_ID}: ${addressError}` }); + return; } + + this.setState({ processing: true }); + const tx = this.createTransaction( + this.state.toAddress, + this.state.amount, + this.state.gas + ); + console.log(tx); + const dataJSON = JSON.stringify(tx); + const res = await axios.post("/api/transaction", { dataJSON }); + const { transactionID } = res.data; + this.props.router.push( + `${this.props.address}/transaction/${transactionID}` + ); }; render() { diff --git a/lib/displayHelpers.js b/lib/displayHelpers.js index f5706da..284a281 100644 --- a/lib/displayHelpers.js +++ b/lib/displayHelpers.js @@ -91,4 +91,31 @@ const examplePubkey = (index) => { return toBase64(data); } -export { abbreviateLongString, printableCoin, printableCoins, exampleAddress, examplePubkey }; +/** + * Returns an error message for invalid addresses. + * + * Returns null of there is no error. + */ +const checkAddress = (input) => { + if (!input) return "Empty"; + + let data; + let prefix; + try { + ({ data, prefix } = Bech32.decode(input)); + } catch (error) { + return error.toString(); + } + + if (prefix !== process.env.NEXT_PUBLIC_ADDRESS_PREFIX) { + return `Expected address prefix '${process.env.NEXT_PUBLIC_ADDRESS_PREFIX}' but got '${prefix}'`; + } + + if (data.length !== 20) { + return "Invalid address length in bech32 data. Must be 20 bytes."; + } + + return null; +} + +export { abbreviateLongString, printableCoin, printableCoins, exampleAddress, examplePubkey, checkAddress };