From da5068c12f05e4884a5e7449aade1fa188c5039b Mon Sep 17 00:00:00 2001 From: James Calfee <james@jcalfee.info> Date: Wed, 12 Oct 2016 16:53:56 -0400 Subject: [PATCH] Validate all transfer amounts to at most 3 decimal places. (#466) * Warning cleanup * Validate all transfer amounts to at most 3 decimal places. close #461 --- app/components/modules/Transfer.jsx | 2 ++ app/utils/ParsersAndFormatters.js | 7 +++++++ shared/serializer/src/number_utils.js | 24 ++++++++++++------------ shared/serializer/src/types.js | 15 ++++++--------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/app/components/modules/Transfer.jsx b/app/components/modules/Transfer.jsx index 343665181..3299d0dc7 100644 --- a/app/components/modules/Transfer.jsx +++ b/app/components/modules/Transfer.jsx @@ -9,6 +9,7 @@ import {transferTips} from 'app/utils/Tips' import {powerTip, powerTip2, powerTip3} from 'app/utils/Tips' import {browserTests} from 'shared/ecc/test/BrowserTests' import {validate_account_name} from 'app/utils/ChainValidation'; +import {countDecimals} from 'app/utils/ParsersAndFormatters' /** Warning .. This is used for Power UP too. */ class TransferForm extends Component { @@ -76,6 +77,7 @@ class TransferForm extends Component { ! values.amount ? 'Required' : ! /^[0-9]*\.?[0-9]*/.test(values.amount) ? 'Amount is in the form 99999.999' : insufficientFunds(values.asset, values.amount) ? 'Insufficient funds' : + countDecimals(values.amount) > 3 ? 'Use only 3 digits of precison' : null, asset: props.toVesting ? null : diff --git a/app/utils/ParsersAndFormatters.js b/app/utils/ParsersAndFormatters.js index 099674afe..3b43ba696 100644 --- a/app/utils/ParsersAndFormatters.js +++ b/app/utils/ParsersAndFormatters.js @@ -55,3 +55,10 @@ export const repLog10 = rep2 => { out = parseInt(out) return out } + +export function countDecimals(amount) { + if(amount == null) return amount + amount = String(amount).match(/[\d\.]+/g).join('') // just dots and digits + const parts = amount.split('.') + return parts.length > 2 ? undefined : parts.length === 1 ? 0 : parts[1].length +} \ No newline at end of file diff --git a/shared/serializer/src/number_utils.js b/shared/serializer/src/number_utils.js index 64c1db8e4..4520389de 100644 --- a/shared/serializer/src/number_utils.js +++ b/shared/serializer/src/number_utils.js @@ -2,35 +2,35 @@ import assert from "assert" /** Convert 12.34 with a precision of 3 into 12340 - + @arg {number|string} number - Use strings for large numbers. This may contain one decimal but no sign @arg {number} precision - number of implied decimal places (usually causes right zero padding) @return {string} - */ export function toImpliedDecimal(number, precision) { - + if(typeof number === "number") { assert(number <= 9007199254740991, "overflow") number = ""+number; } else if( number.toString ) number = number.toString() - + assert(typeof number === "string", "number should be an actual number or string: " + (typeof number)) number = number.trim() assert(/^[0-9]*\.?[0-9]*$/.test(number), "Invalid decimal number " + number) - + let [ whole = "", decimal = ""] = number.split(".") - + let padding = precision - decimal.length assert(padding >= 0, "Too many decimal digits in " + number + " to create an implied decimal of " + precision) - + for(let i = 0; i < padding; i++) decimal += "0" - + while(whole.charAt(0) === "0") whole = whole.substring(1) - + return whole + decimal } @@ -41,13 +41,13 @@ export function fromImpliedDecimal(number, precision) { } else if( number.toString ) number = number.toString() - + while(number.length < precision + 1)// 0.123 number = "0" + number - + // 44000 => 44.000 let dec_string = number.substring(number.length - precision) return number.substring(0, number.length - precision) + (dec_string ? "." + dec_string : "") - -} \ No newline at end of file + +} diff --git a/shared/serializer/src/types.js b/shared/serializer/src/types.js index 206e4990a..f76bcea03 100644 --- a/shared/serializer/src/types.js +++ b/shared/serializer/src/types.js @@ -2,18 +2,15 @@ // Low-level types that make up operations -var ByteBuffer = require('bytebuffer'); -var Serializer = require('./serializer'); -var v = require('./validation'); -var ObjectId = require('./object_id') -var fp = require('./fast_parser'); -var chain_types = require('./ChainTypes') -var Long = ByteBuffer.Long +const v = require('./validation'); +const ObjectId = require('./object_id') +const fp = require('./fast_parser'); +const chain_types = require('./ChainTypes') import { PublicKey, Address, ecc_config } from "../../ecc" -import { toImpliedDecimal, fromImpliedDecimal } from "./number_utils" +import { fromImpliedDecimal } from "./number_utils" -var Types = {} +const Types = {} module.exports = Types const HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump -- GitLab