From 037fbd898427926b83609473cd2420e4ee6469fd Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Wed, 26 Dec 2018 16:13:43 +0900
Subject: [PATCH] # This is a combination of 2 commits. # The first commit's
 message is:

Add types to Networks and Addresses

# This is the 2nd commit message:

Added types
---
 src/address.ts     | 48 +++++++++++++++++----------
 src/bufferutils.ts | 12 ++-----
 src/classify.ts    | 35 ++++++++++----------
 src/crypto.ts      | 19 +++--------
 src/networks.ts    | 82 ++++++++++++++++++++++++++--------------------
 5 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/address.ts b/src/address.ts
index e6f60fc..b758a66 100644
--- a/src/address.ts
+++ b/src/address.ts
@@ -6,8 +6,21 @@ const networks = require('./networks')
 const typeforce = require('typeforce')
 const types = require('./types')
 const payments = require('./payments')
+import * as Networks from './networks'
+import { Network } from './networks'
 
-function fromBase58Check (address) {
+export declare type Base58CheckResult = {
+  hash: Buffer;
+  version: number;
+}
+
+export declare type Bech32Result = {
+  version: number;
+  prefix: string;
+  data: Buffer;
+}
+
+function fromBase58Check (address: string): Base58CheckResult {
   const payload = bs58check.decode(address)
 
   // TODO: 4.0.0, move to "toOutputScript"
@@ -20,7 +33,7 @@ function fromBase58Check (address) {
   return { version: version, hash: hash }
 }
 
-function fromBech32 (address) {
+function fromBech32 (address: string): Bech32Result {
   const result = bech32.decode(address)
   const data = bech32.fromWords(result.words.slice(1))
 
@@ -31,7 +44,7 @@ function fromBech32 (address) {
   }
 }
 
-function toBase58Check (hash, version) {
+function toBase58Check (hash: Buffer, version: number): string {
   typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments)
 
   const payload = Buffer.allocUnsafe(21)
@@ -41,14 +54,14 @@ function toBase58Check (hash, version) {
   return bs58check.encode(payload)
 }
 
-function toBech32 (data, version, prefix) {
+function toBech32 (data: Buffer, version: number, prefix: string): string {
   const words = bech32.toWords(data)
   words.unshift(version)
 
   return bech32.encode(prefix, words)
 }
 
-function fromOutputScript (output, network) {
+function fromOutputScript (output: Buffer, network: Network): string { //TODO: Network
   network = network || networks.bitcoin
 
   try { return payments.p2pkh({ output, network }).address } catch (e) {}
@@ -59,27 +72,28 @@ function fromOutputScript (output, network) {
   throw new Error(bscript.toASM(output) + ' has no matching Address')
 }
 
-function toOutputScript (address, network) {
+function toOutputScript (address: string, network: Network): Buffer {
   network = network || networks.bitcoin
 
-  let decode
+  let decodeBase58: Base58CheckResult
+  let decodeBech32: Bech32Result
   try {
-    decode = fromBase58Check(address)
+    decodeBase58 = fromBase58Check(address)
   } catch (e) {}
 
-  if (decode) {
-    if (decode.version === network.pubKeyHash) return payments.p2pkh({ hash: decode.hash }).output
-    if (decode.version === network.scriptHash) return payments.p2sh({ hash: decode.hash }).output
+  if (decodeBase58) {
+    if (decodeBase58.version === network.pubKeyHash) return payments.p2pkh({ hash: decodeBase58.hash }).output
+    if (decodeBase58.version === network.scriptHash) return payments.p2sh({ hash: decodeBase58.hash }).output
   } else {
     try {
-      decode = fromBech32(address)
+      decodeBech32 = fromBech32(address)
     } catch (e) {}
 
-    if (decode) {
-      if (decode.prefix !== network.bech32) throw new Error(address + ' has an invalid prefix')
-      if (decode.version === 0) {
-        if (decode.data.length === 20) return payments.p2wpkh({ hash: decode.data }).output
-        if (decode.data.length === 32) return payments.p2wsh({ hash: decode.data }).output
+    if (decodeBech32) {
+      if (decodeBech32.prefix !== network.bech32) throw new Error(address + ' has an invalid prefix')
+      if (decodeBech32.version === 0) {
+        if (decodeBech32.data.length === 20) return payments.p2wpkh({ hash: decodeBech32.data }).output
+        if (decodeBech32.data.length === 32) return payments.p2wsh({ hash: decodeBech32.data }).output
       }
     }
   }
diff --git a/src/bufferutils.ts b/src/bufferutils.ts
index a78b07b..b66c84a 100644
--- a/src/bufferutils.ts
+++ b/src/bufferutils.ts
@@ -1,12 +1,12 @@
 // https://github.com/feross/buffer/blob/master/index.js#L1127
-function verifuint (value, max) {
+function verifuint (value: number, max: number): void {
   if (typeof value !== 'number') throw new Error('cannot write a non-number as a number')
   if (value < 0) throw new Error('specified a negative value for writing an unsigned value')
   if (value > max) throw new Error('RangeError: value out of range')
   if (Math.floor(value) !== value) throw new Error('value has a fractional component')
 }
 
-function readUInt64LE (buffer, offset) {
+export function readUInt64LE (buffer: Buffer, offset: number): number {
   const a = buffer.readUInt32LE(offset)
   let b = buffer.readUInt32LE(offset + 4)
   b *= 0x100000000
@@ -15,16 +15,10 @@ function readUInt64LE (buffer, offset) {
   return b + a
 }
 
-function writeUInt64LE (buffer, value, offset) {
+export function writeUInt64LE (buffer: Buffer, value: number, offset: number): number {
   verifuint(value, 0x001fffffffffffff)
 
   buffer.writeInt32LE(value & -1, offset)
   buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4)
   return offset + 8
 }
-
-module.exports = {
-  readUInt64LE: readUInt64LE,
-  writeUInt64LE: writeUInt64LE
-}
-export {}
diff --git a/src/classify.ts b/src/classify.ts
index 3f824c4..5eabc7e 100644
--- a/src/classify.ts
+++ b/src/classify.ts
@@ -9,18 +9,18 @@ const witnessScriptHash = require('./templates/witnessscripthash')
 const witnessCommitment = require('./templates/witnesscommitment')
 
 const types = {
-  P2MS: 'multisig',
-  NONSTANDARD: 'nonstandard',
-  NULLDATA: 'nulldata',
-  P2PK: 'pubkey',
-  P2PKH: 'pubkeyhash',
-  P2SH: 'scripthash',
-  P2WPKH: 'witnesspubkeyhash',
-  P2WSH: 'witnessscripthash',
-  WITNESS_COMMITMENT: 'witnesscommitment'
+  P2MS: <string> 'multisig',
+  NONSTANDARD: <string> 'nonstandard',
+  NULLDATA: <string> 'nulldata',
+  P2PK: <string> 'pubkey',
+  P2PKH: <string> 'pubkeyhash',
+  P2SH: <string> 'scripthash',
+  P2WPKH: <string> 'witnesspubkeyhash',
+  P2WSH: <string> 'witnessscripthash',
+  WITNESS_COMMITMENT: <string> 'witnesscommitment'
 }
 
-function classifyOutput (script) {
+function classifyOutput (script: Buffer): string {
   if (witnessPubKeyHash.output.check(script)) return types.P2WPKH
   if (witnessScriptHash.output.check(script)) return types.P2WSH
   if (pubKeyHash.output.check(script)) return types.P2PKH
@@ -38,7 +38,7 @@ function classifyOutput (script) {
   return types.NONSTANDARD
 }
 
-function classifyInput (script, allowIncomplete) {
+function classifyInput (script: Buffer, allowIncomplete: boolean): string {
   // XXX: optimization, below functions .decompile before use
   const chunks = decompile(script)
   if (!chunks) throw new TypeError('Invalid script')
@@ -51,7 +51,7 @@ function classifyInput (script, allowIncomplete) {
   return types.NONSTANDARD
 }
 
-function classifyWitness (script, allowIncomplete) {
+function classifyWitness (script: Buffer, allowIncomplete: boolean): string {
   // XXX: optimization, below functions .decompile before use
   const chunks = decompile(script)
   if (!chunks) throw new TypeError('Invalid script')
@@ -62,10 +62,9 @@ function classifyWitness (script, allowIncomplete) {
   return types.NONSTANDARD
 }
 
-module.exports = {
-  input: classifyInput,
-  output: classifyOutput,
-  witness: classifyWitness,
-  types: types
+export {
+  classifyInput as input,
+  classifyOutput as output,
+  classifyWitness as witness,
+  types,
 }
-export {}
diff --git a/src/crypto.ts b/src/crypto.ts
index a04c67f..6aabb5b 100644
--- a/src/crypto.ts
+++ b/src/crypto.ts
@@ -1,30 +1,21 @@
 const createHash = require('create-hash')
 
-function ripemd160 (buffer) {
+export function ripemd160 (buffer: Buffer): Buffer {
   return createHash('rmd160').update(buffer).digest()
 }
 
-function sha1 (buffer) {
+export function sha1 (buffer: Buffer): Buffer {
   return createHash('sha1').update(buffer).digest()
 }
 
-function sha256 (buffer) {
+export function sha256 (buffer: Buffer): Buffer {
   return createHash('sha256').update(buffer).digest()
 }
 
-function hash160 (buffer) {
+export function hash160 (buffer: Buffer): Buffer {
   return ripemd160(sha256(buffer))
 }
 
-function hash256 (buffer) {
+export function hash256 (buffer: Buffer): Buffer {
   return sha256(sha256(buffer))
 }
-
-module.exports = {
-  hash160: hash160,
-  hash256: hash256,
-  ripemd160: ripemd160,
-  sha1: sha1,
-  sha256: sha256
-}
-export {}
diff --git a/src/networks.ts b/src/networks.ts
index 0aac048..f8ee1aa 100644
--- a/src/networks.ts
+++ b/src/networks.ts
@@ -1,39 +1,49 @@
 // https://en.bitcoin.it/wiki/List_of_address_prefixes
 // Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731
-
-module.exports = {
-  bitcoin: {
-    messagePrefix: '\x18Bitcoin Signed Message:\n',
-    bech32: 'bc',
-    bip32: {
-      public: 0x0488b21e,
-      private: 0x0488ade4
-    },
-    pubKeyHash: 0x00,
-    scriptHash: 0x05,
-    wif: 0x80
-  },
-  regtest: {
-    messagePrefix: '\x18Bitcoin Signed Message:\n',
-    bech32: 'bcrt',
-    bip32: {
-      public: 0x043587cf,
-      private: 0x04358394
-    },
-    pubKeyHash: 0x6f,
-    scriptHash: 0xc4,
-    wif: 0xef
-  },
-  testnet: {
-    messagePrefix: '\x18Bitcoin Signed Message:\n',
-    bech32: 'tb',
-    bip32: {
-      public: 0x043587cf,
-      private: 0x04358394
-    },
-    pubKeyHash: 0x6f,
-    scriptHash: 0xc4,
-    wif: 0xef
-  }
+export declare type Network = {
+  messagePrefix: string;
+  bech32: string;
+  bip32: bip32;
+  pubKeyHash: number;
+  scriptHash: number;
+  wif: number;
+}
+
+declare type bip32 = {
+  public: number;
+  private: number;
+}
+
+export const bitcoin: Network = {
+  messagePrefix: '\x18Bitcoin Signed Message:\n',
+  bech32: 'bc',
+  bip32: {
+    public: 0x0488b21e,
+    private: 0x0488ade4
+  },
+  pubKeyHash: 0x00,
+  scriptHash: 0x05,
+  wif: 0x80
+}
+export const regtest: Network = {
+  messagePrefix: '\x18Bitcoin Signed Message:\n',
+  bech32: 'bcrt',
+  bip32: {
+    public: 0x043587cf,
+    private: 0x04358394
+  },
+  pubKeyHash: 0x6f,
+  scriptHash: 0xc4,
+  wif: 0xef
+}
+export const testnet: Network = {
+  messagePrefix: '\x18Bitcoin Signed Message:\n',
+  bech32: 'tb',
+  bip32: {
+    public: 0x043587cf,
+    private: 0x04358394
+  },
+  pubKeyHash: 0x6f,
+  scriptHash: 0xc4,
+  wif: 0xef
 }
-export {}