"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

function _react() {
  const data = _interopRequireDefault(require("react"));

  _react = function _react() {
    return data;
  };

  return data;
}

function _crypto() {
  const data = _interopRequireDefault(require("crypto"));

  _crypto = function _crypto() {
    return data;
  };

  return data;
}

function _ripemd() {
  const data = _interopRequireDefault(require("ripemd160"));

  _ripemd = function _ripemd() {
    return data;
  };

  return data;
}

function _bitcoreMnemonic() {
  const data = _interopRequireDefault(require("bitcore-mnemonic"));

  _bitcoreMnemonic = function _bitcoreMnemonic() {
    return data;
  };

  return data;
}

function _crypto2() {
  const data = _interopRequireWildcard(require("@ddn/crypto"));

  _crypto2 = function _crypto2() {
    return data;
  };

  return data;
}

var _config = require("../config");

var _bytes = require("../bytes");

var _fees = require("../fees");

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

let Buffer;

if (typeof Buffer === 'undefined') {
  Buffer = require('buffer/').Buffer;
}

const fixedPoint = _config.constants.fixedPoint;

const base58check = _crypto2().default.base58check;

function toLocalBuffer(buf) {
  if (typeof window !== 'undefined') {
    return new Uint8Array(buf.toArrayBuffer());
  } else {
    return buf.toBuffer();
  }
}

function signBytes(bytes, {
  privateKey
}) {
  const hash = createHash(Buffer.from(bytes, 'hex'));

  const signature = _crypto2().nacl.sign.detached(hash, Buffer.from(privateKey, 'hex'));

  return Buffer.from(signature).toString('hex');
}
/**
 * description:
 * 字符串形式的地址，不再支持纯数字地址；
 * 1. 把地址base58解码成字节数组
 * 2. 把数组分成两个字节数组，字节数组（1）是后4字节数组，字节数组（2）是减去后4字节的数组
 * 3. 把字节数组（2）两次Sha256 Hash
 * 4. 取字节数组（2）hash后的前4位，跟字节数组（1）比较。如果相同校验通过。
 * 5. 校验通过的解码字节数组取第一个字节，地址前缀。
 * 6. 检验前缀的合法性（根据主网参数校验），注意大小写。
 * Note: address.slice(0, -4) === address.slice(0, address.length - 4)
 */


function isAddress(address) {
  const tokenPrefix = _config.constants.tokenPrefix;

  if (typeof address !== 'string') {
    return false;
  }

  if (!base58check.decodeUnsafe(address.slice(1))) {
    return false;
  }

  if ([tokenPrefix].indexOf(address[0]) === -1) {
    return false;
  }

  return true;
} // fixme: 将所有 generateBase58CheckAddress -> generateAddress


function generateAddress(publicKey) {
  const tokenPrefix = _config.constants.tokenPrefix;

  if (typeof publicKey === 'string') {
    publicKey = Buffer.from(publicKey, 'hex');
  }

  const h1 = _crypto2().nacl.hash(publicKey);

  const h2 = new (_ripemd().default)().update(Buffer.from(h1)).digest();
  return tokenPrefix + base58check.encode(h2);
} // 兼容处理


function getKeys(secret) {
  const hash = createHash(Buffer.from(secret));
  const m = new Uint8Array(_crypto2().nacl.sign.seedLength);

  for (let i = 0; i < m.length; i++) m[i] = hash[i];

  const keypair = _crypto2().nacl.sign.keyPair.fromSeed(m);

  return {
    publicKey: bufToHex(keypair.publicKey),
    privateKey: bufToHex(keypair.secretKey)
  };
}
/**
 * Usage:
 * trs.signature = await sign(trs, keypair);
 * @param {object} transaction to be signed
 * @param {object} param1 keypair.privateKey
 */


function sign(_x, _x2) {
  return _sign.apply(this, arguments);
}
/**
 * Usage:
 * trs.sign_signature = await secondSign(trs, keypair)
 * @param {object} transaction to be signed
 * @param {object} param1 keypair.privateKey
 */


function _sign() {
  _sign = _asyncToGenerator(function* (transaction, {
    privateKey
  }) {
    const hash = yield getHash(transaction, true, true);

    const signature = _crypto2().nacl.sign.detached(hash, Buffer.from(privateKey, 'hex'));

    return bufToHex(signature);
  });
  return _sign.apply(this, arguments);
}

function secondSign(_x3, _x4) {
  return _secondSign.apply(this, arguments);
}
/**
 * 生成助记词
 * @param {*} ent 该参数可以是 语言词汇表，比如：Mnemonic.Words.ENGLISH(默认)，可以是位数，128 ~ 256 并 ent % 32 == 0
 */


function _secondSign() {
  _secondSign = _asyncToGenerator(function* (transaction, {
    privateKey
  }) {
    const hash = yield getHash(transaction, false, true);

    const signature = _crypto2().nacl.sign.detached(hash, Buffer.from(privateKey, 'hex'));

    return bufToHex(signature);
  });
  return _secondSign.apply(this, arguments);
}

function generateSecret(ent) {
  const param = ent || _bitcoreMnemonic().default.Words.ENGLISH;

  return new (_bitcoreMnemonic().default)(param).toString();
}

function isValidSecret(secret) {
  return _bitcoreMnemonic().default.isValid(secret);
} // hex


function getId(_x5) {
  return _getId.apply(this, arguments);
}
/**
 * 获得交易数据的哈希值
 * 等于 getBytes + createHash
 *
 * note: tweetnacl 包的所有方法必须使用 Uint8Array 类型的参数。
 * @param {object} trs 交易数据
 * @param {boolean} skipSignature 跳过签名
 * @param {boolean} skipSecondSignature 跳过二次签名
 */


function _getId() {
  _getId = _asyncToGenerator(function* (transaction) {
    const hash = yield getHash(transaction);
    return hash.toString('hex');
  });
  return _getId.apply(this, arguments);
}

function getHash(_x6, _x7, _x8) {
  return _getHash.apply(this, arguments);
}
/**
 * 使用中注意 data 格式，默认是unit8Arrary，如果是涉密字段（经过 buffer、签名、加密的字段）都是可以直接使用的，不然就要对其简单处理 Buffer.from(data)
 * 返回值为 Buffer
 * @param {String}  data 需要 hash 的数据，格式为 unit8Arrary, 这里的方法与 crypto.createHash('sha256').update(strBuffer).digest() 相似，结果不同
 */


function _getHash() {
  _getHash = _asyncToGenerator(function* (trs, skipSignature, skipSecondSignature) {
    const bytes = yield (0, _bytes.getBytes)(trs, skipSignature, skipSecondSignature);
    return createHash(bytes);
  });
  return _getHash.apply(this, arguments);
}

function createHash(data) {
  return Buffer.from(_crypto2().nacl.hash(data));
}

function generateMd5Hash(content) {
  const md5 = _crypto().default.createHash('md5');

  const result = md5.update(content).digest('hex');
  return result;
} // 验证签名
// todo: 本方法并没有被实际使用，请参考 peer/kernal/transaction/transaction.js的 verifySignature 重构


function verify(_x9, _x10) {
  return _verify.apply(this, arguments);
}
/**
 * 二次签名验证
 * @param {object} transaction 交易数据
 * @param {string} publicKey 二次签名公钥
 */


function _verify() {
  _verify = _asyncToGenerator(function* (transaction, senderPublicKey) {
    if (!transaction.signature) {
      return false;
    }

    if (!senderPublicKey) {
      senderPublicKey = transaction.senderPublicKey;
    }

    const bytes = yield (0, _bytes.getBytes)(transaction, true, true);
    return verifyBytes(bytes, transaction.signature, senderPublicKey);
  });
  return _verify.apply(this, arguments);
}

function verifySecondSignature(_x11, _x12) {
  return _verifySecondSignature.apply(this, arguments);
}
/**
 * 该方法验证使用私钥签名的字节信息是否正确，参数公钥与私钥对应，即：私钥签名的信息，公钥可以验证通过
 * @param {hash} bytes 字节流 hash 值
 * @param {string} signature 签名
 * @param {string} publicKey 公钥
 */


function _verifySecondSignature() {
  _verifySecondSignature = _asyncToGenerator(function* (transaction, publicKey) {
    if (!transaction.sign_signature) {
      return false;
    }

    const bytes = yield (0, _bytes.getBytes)(transaction, false, true);
    return verifyBytes(bytes, transaction.sign_signature, publicKey);
  });
  return _verifySecondSignature.apply(this, arguments);
}

function verifyBytes(bytes, signature, publicKey) {
  // 保证字节类型
  if (!(bytes instanceof Buffer)) {
    bytes = Buffer.from(bytes);
  }

  const hash = createHash(bytes);
  const signatureBuffer = Buffer.from(signature, 'hex');
  const publicKeyBuffer = Buffer.from(publicKey, 'hex');

  const res = _crypto2().nacl.sign.detached.verify(hash, signatureBuffer, publicKeyBuffer);

  return res;
}

function bufToHex(data) {
  return Buffer.from(data).toString('hex');
} // 注意接口变更说明


var _default = {
  createHash,
  getBytes: _bytes.getBytes,
  getHash,
  getId,
  getFee: _fees.getFee,
  sign,
  // 一致
  secondSign,
  // 一致
  getKeys,
  // 一致
  generateAddress,
  // 测试和前端用 一致
  isAddress,
  // 验证
  verify,
  verifySecondSignature,
  verifyBytes,
  fixedPoint,
  // 测试和前端用
  signBytes,
  toLocalBuffer,
  // 测试和前端用
  generateSecret,
  // 测试和前端用,重构： generatePhasekey() -> generateSecret()
  isValidSecret,
  generateMd5Hash // 测试和前端用

};
exports.default = _default;