diff --git a/README.md b/README.md index 508e93a2..5c86960d 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ npm install multicoin-address-validator * Gnosis/gno `'Gnosis'` or `'gno'` * Golem/glm `'Golem'` or `'glm'` * Golem (GNT)/gnt `'Golem (GNT)'` or `'gnt'` +* Groestlcoin/grs `'Groestlcoin'` or `'grs'` * HedgeTrade/hedg `'HedgeTrade'` or `'hedg'` * Hush/hush `'Hush'` or `'hush'` * HyperSpace/xsc `'HyperSpace'` or `'xsc'` diff --git a/package.json b/package.json index aebcce86..8d43382d 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,8 @@ "gno", "Golem", "gnt", + "Groestlcoin"", + "grs", "HedgeTrade", "hedg", "Hush", @@ -257,6 +259,7 @@ "bundle": "^2.1.0", "cbor-js": "^0.1.0", "crc": "^3.8.0", + "groestl-hash-js": "1.0.0", "js-sha512": "^0.8.0", "jssha": "^2.4.2", "lodash.isequal": "^4.5.0", diff --git a/src/bitcoin_validator.js b/src/bitcoin_validator.js index a1dab6bd..ed81ae37 100644 --- a/src/bitcoin_validator.js +++ b/src/bitcoin_validator.js @@ -24,6 +24,8 @@ function getChecksum(hashFunction, payload) { return cryptoUtils.blake256Checksum(payload); case 'keccak256': return cryptoUtils.keccak256Checksum(payload); + case 'groestl512x2': + return cryptoUtils.groestl512x2(payload); case 'sha256': default: return cryptoUtils.sha256Checksum(payload); diff --git a/src/crypto/utils.js b/src/crypto/utils.js index ea84d099..12df2f7e 100644 --- a/src/crypto/utils.js +++ b/src/crypto/utils.js @@ -6,6 +6,7 @@ var Blake2B = require('./blake2b'); var base58 = require('./base58'); var base32 = require('./base32'); var BigNum = require('browserify-bignum'); +var groestl = require('groestl-hash-js'); function numberToHex(number) { var hex = Math.round(number).toString(16) @@ -121,6 +122,10 @@ module.exports = { blake2b256: function (hexString) { return new Blake2B(32).update(Buffer.from(hexString, 'hex'), 32).digest('hex'); }, + groestl512x2: function (hexString) { + let result = groestl.groestl_2(Buffer.from(hexString, 'hex'), 1, 0).substr(0, 8); + return result; + }, base58: base58.decode, byteArray2hexStr: byteArray2hexStr, hexStr2byteArray: hexStr2byteArray, diff --git a/src/currencies.js b/src/currencies.js index 7676fa74..c580f33c 100644 --- a/src/currencies.js +++ b/src/currencies.js @@ -41,6 +41,13 @@ var CURRENCIES = [{ addressTypes: { prod: ['30', '05', '32'], testnet: ['6f', 'c4', '3a'] }, bech32Hrp: { prod: ['ltc'], testnet: ['tltc'] }, validator: BTCValidator + }, { + name: 'Groestlcoin', + symbol: 'grs', + addressTypes: { prod: ['24', '05'], testnet: ['6f', 'c4'] }, + bech32Hrp: { prod: ['grs'], testnet: ['tgrs'] }, + hashFunction: 'groestl512x2', + validator: BTCValidator }, { name: 'PeerCoin', symbol: 'ppc', @@ -584,4 +591,3 @@ var CURRENCIES = [{ // .sort((a, b) => a.name.toUpperCase() > b.name.toUpperCase() ? 1 : -1) // .forEach(c => console.log(`"${c.name}","${c.symbol}",`)); // - diff --git a/test/wallet_address_validator.js b/test/wallet_address_validator.js index 565c12be..9644520a 100644 --- a/test/wallet_address_validator.js +++ b/test/wallet_address_validator.js @@ -104,6 +104,31 @@ describe('WAValidator.validate()', function () { valid('tltc1qu78xur5xnq6fjy83amy0qcjfau8m367defyhms', 'litecoin', { networkType: 'testnet' }); }); + it('should return true for correct groestlcoin addresses', function () { + valid('Foa6yZoKq2r4t3tUFKFcfoXSQjSodZsGx1', 'groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'GRS'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'Groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs', 'prod'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs', 'both'); + valid('FpM19fiGQNjNcaRjFaXVX6Nrewr4gnuuMZ', 'grs', 'prod'); + valid('3FyVFsEyyBPzHjD3qUEgX7Jsn4tcJWiqeN', 'grs', 'prod'); + valid('38mKdURe1zcQyrFqRLzR8PRao3iLFU5hwU', 'grs', 'prod'); + valid('mptPo5AvLzJXi4T82vR6g82fT5uJ9cgfsV', 'grs', 'both'); + valid('FdWcvgskHoXUTqeQRAiuGuh5KQ2EoXv5iM', 'groestlcoin'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWq3SbMQT', 'groestlcoin', 'testnet'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWq3SbMQT', 'groestlcoin', 'both'); + + // p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1T2Htk2', 'groestlcoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfZDahUf', 'groestlcoin', 'testnet'); + + // segwit addresses + valid('grs1q49qls5kklryt95g5xx4p6msycpgjp8ramfc9jq', 'groestlcoin'); + valid('tgrs1qgjd3qhncsxdyh5gt7hz4k6zzvfguslwxwgv23j', 'groestlcoin'); + }); + it('should return true for correct peercoin addresses', function () { valid('PHCEsP6od3WJ8K2WKWEDBYKhH95pc9kiZN', 'peercoin'); valid('PSbM1pGoE9dnAuVWvpQqTTYVpKZU41dNAz', 'peercoin');