diff --git a/packages/bitcore-node/src/providers/chain-state/index.ts b/packages/bitcore-node/src/providers/chain-state/index.ts index f7d852f30f8..eebd36de4ef 100644 --- a/packages/bitcore-node/src/providers/chain-state/index.ts +++ b/packages/bitcore-node/src/providers/chain-state/index.ts @@ -119,5 +119,9 @@ class ChainStateProxy implements CSP.ChainStateProvider { streamMissingWalletAddresses(params) { return this.get(params).streamMissingWalletAddresses(params); } + + isValid(params) { + return this.get(params).isValid(params); + } } export let ChainStateProvider = new ChainStateProxy(); diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index ad7a1ff9c9d..9fb2b7a4251 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -17,6 +17,7 @@ import { StringifyJsonStream } from '../../../utils/stringifyJsonStream'; import { StateStorage } from '../../../models/state'; import { SpentHeightIndicators, CoinJSON } from '../../../types/Coin'; import { Config } from '../../../services/config'; +import { Validation } from 'crypto-wallet-core'; @LoggifyClass export class InternalStateProvider implements CSP.IChainStateService { @@ -548,4 +549,44 @@ export class InternalStateProvider implements CSP.IChainStateService { } return locatorBlocks.map(block => block.hash); } + + public isValid(params) { + const { input } = params; + + if (this.isValidBlockOrTx(input)) { + return { isValid: true, type: 'blockOrTx' }; + } else if (this.isValidAddress(params)) { + return { isValid: true, type: 'addr' }; + } else if (this.isValidBlockIndex(input)) { + return { isValid: true, type: 'blockOrTx' }; + } else { + return { isValid: false, type: 'invalid' }; + } + } + + private isValidBlockOrTx(inputValue: string): boolean { + const regexp = /^[0-9a-fA-F]{64}$/; + if (regexp.test(inputValue)) { + return true; + } else { + return false; + } + } + + private isValidAddress(params): boolean { + const { chain, network, input } = params; + const addr = this.extractAddress(input); + return !!Validation.validateAddress(chain, network, addr); + } + + private isValidBlockIndex(inputValue): boolean { + return isFinite(inputValue); + } + + private extractAddress(address: string): string { + const extractedAddress = address + .replace(/^(bitcoincash:|bchtest:|bitcoin:)/i, '') + .replace(/\?.*/, ''); + return extractedAddress || address; + } } diff --git a/packages/bitcore-node/src/routes/api/valid.ts b/packages/bitcore-node/src/routes/api/valid.ts new file mode 100644 index 00000000000..8f02046afb6 --- /dev/null +++ b/packages/bitcore-node/src/routes/api/valid.ts @@ -0,0 +1,23 @@ +import express = require('express'); +const router = express.Router({ mergeParams: true }); +import { ChainStateProvider } from '../../providers/chain-state'; + +router.get('/:input', async function(req, res) { + let { input, chain, network } = req.params; + try { + let isValid = await ChainStateProvider.isValid({ + chain, + network, + input + }); + return res.send(isValid); + } catch (err) { + return res.status(500).send(err); + } +}); + + +module.exports = { + router: router, + path: '/valid' +}; diff --git a/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts b/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts index cf9dcf07a90..e881139ec6f 100644 --- a/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts +++ b/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts @@ -114,6 +114,10 @@ export declare namespace CSP { res: Response; }; + export type isValidParams = ChainNetwork & { + input: string; + } + export type Provider = { get(params: { chain: string }): T }; export type ChainStateProvider = Provider & IChainStateService; export interface IChainStateService { @@ -147,6 +151,7 @@ export declare namespace CSP { getCoinsForTx(params: { chain: string; network: string; txid: string }): Promise; getLocalTip(params): Promise; getLocatorHashes(params): Promise; + isValid(params: isValidParams): {isValid: boolean, type:string}; } type ChainStateServices = { [key: string]: IChainStateService };