Compare commits
	
		
			No commits in common. "main" and "notcommon" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										109
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,109 +0,0 @@
 | 
			
		||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
 | 
			
		||||
# how to include another gitignore? 
 | 
			
		||||
#   https://stackoverflow.com/questions/7005142/can-i-include-other-gitignore-file-in-a-gitignore-file-like-include-in-c-li
 | 
			
		||||
#   https://github.com/github/gitignore
 | 
			
		||||
#   https://github.com/SlideWave/gitignore-include?tab=readme-ov-file#examples
 | 
			
		||||
#   https://gitignore.io
 | 
			
		||||
 | 
			
		||||
### .gitignore.global.txt ###
 | 
			
		||||
 | 
			
		||||
# Self defined pattern to ignore
 | 
			
		||||
?*.gitignore
 | 
			
		||||
?*.gitignore/
 | 
			
		||||
?*.gitignore.*
 | 
			
		||||
?*.gitignore.*/
 | 
			
		||||
*.gitomit
 | 
			
		||||
*.gitomit/
 | 
			
		||||
*.gitomit.*
 | 
			
		||||
*.gitomit.*/
 | 
			
		||||
# 保留
 | 
			
		||||
!.gitignore
 | 
			
		||||
!.gitignore.*
 | 
			
		||||
!.gitkeep
 | 
			
		||||
 | 
			
		||||
# 通用
 | 
			
		||||
.svn/
 | 
			
		||||
.deploy_git/
 | 
			
		||||
.idea/
 | 
			
		||||
.sass-cache/
 | 
			
		||||
.wrangler
 | 
			
		||||
/test/unit/coverage/
 | 
			
		||||
/test/e2e/reports/
 | 
			
		||||
node_modules/
 | 
			
		||||
*.aab
 | 
			
		||||
*.apk
 | 
			
		||||
*.ipa
 | 
			
		||||
*.min.js
 | 
			
		||||
*.min.css
 | 
			
		||||
*.min.html
 | 
			
		||||
*.iml
 | 
			
		||||
*.njsproj
 | 
			
		||||
*.ntvs*
 | 
			
		||||
*.sw*
 | 
			
		||||
*.sln
 | 
			
		||||
*.suo
 | 
			
		||||
.gitattributes
 | 
			
		||||
.umi
 | 
			
		||||
.umi-production
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
yarn-debug.log*
 | 
			
		||||
yarn-error.log*
 | 
			
		||||
yarn.lock
 | 
			
		||||
selenium-debug.log
 | 
			
		||||
Thumbs.db
 | 
			
		||||
thumbs.db
 | 
			
		||||
_desktop.ini
 | 
			
		||||
 | 
			
		||||
# vue-cli 项目
 | 
			
		||||
/dist/
 | 
			
		||||
 | 
			
		||||
# 来自 vue-cli 创建项目的 .gitignore
 | 
			
		||||
.project
 | 
			
		||||
 | 
			
		||||
# hexo
 | 
			
		||||
/public/
 | 
			
		||||
 | 
			
		||||
# Hardhat
 | 
			
		||||
/artifacts/
 | 
			
		||||
/cache/
 | 
			
		||||
 | 
			
		||||
# seafile 临时文件
 | 
			
		||||
._*
 | 
			
		||||
 | 
			
		||||
.$*
 | 
			
		||||
 | 
			
		||||
# office 暂存文件
 | 
			
		||||
~$*
 | 
			
		||||
 | 
			
		||||
# 用户shell配置脚本
 | 
			
		||||
.bashrc_custom
 | 
			
		||||
 | 
			
		||||
# 苹果系统临时文件
 | 
			
		||||
.DS_Store
 | 
			
		||||
 | 
			
		||||
# 安卓缓存文件夹
 | 
			
		||||
.thumbnails
 | 
			
		||||
 | 
			
		||||
# local env files
 | 
			
		||||
.env.local
 | 
			
		||||
.env.*.local
 | 
			
		||||
 | 
			
		||||
# hexo
 | 
			
		||||
/db.json
 | 
			
		||||
 | 
			
		||||
# wo
 | 
			
		||||
# 服务端
 | 
			
		||||
/_archive/*
 | 
			
		||||
/_datastore/*
 | 
			
		||||
/_filestore/*
 | 
			
		||||
/_logstore/*
 | 
			
		||||
/_webroot/*
 | 
			
		||||
/_ssl/*
 | 
			
		||||
# uniapp 客户端
 | 
			
		||||
/unpackage/*
 | 
			
		||||
!/unpackage/res/
 | 
			
		||||
package-lock.json
 | 
			
		||||
pages4loader.json5
 | 
			
		||||
 | 
			
		||||
### .gitignore.local.txt ###
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
const Coins = {}
 | 
			
		||||
Coins.TIC = require('./tic.js').TIC
 | 
			
		||||
Coins.ETH = require('./eth.js').ETH
 | 
			
		||||
Coins.ERC20 = require('./eth.js').ERC20
 | 
			
		||||
Coins.BTC = require('./btc.js').BTC
 | 
			
		||||
Coins.TIC = require('./tic.js').TIC;
 | 
			
		||||
Coins.ETH = require('./eth.js').ETH;
 | 
			
		||||
Coins.ERC20 = require('./eth.js').ERC20;
 | 
			
		||||
Coins.BTC = require('./btc.js').BTC;
 | 
			
		||||
 | 
			
		||||
class Account {
 | 
			
		||||
    constructor(coinType,privateKey,contractAddress){
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										299
									
								
								btc.js
									
									
									
									
									
								
							
							
						
						
									
										299
									
								
								btc.js
									
									
									
									
									
								
							@ -1,173 +1,150 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const axios = require('axios')
 | 
			
		||||
const HDNode = require('./utils/hdnode')
 | 
			
		||||
const bitcoinjs = require('bitcoinjs-lib')
 | 
			
		||||
const ticc = require('tic-crypto')
 | 
			
		||||
const BTC_NODE = require('./netConfig').BTC_NODE
 | 
			
		||||
const BTC_NODE2 = require('./netConfig').BTC_NODE2
 | 
			
		||||
const BTC_TXFEE = 30
 | 
			
		||||
const axios = require('axios');
 | 
			
		||||
const HDNode = require('./utils/hdnode');
 | 
			
		||||
const bitcoinjs = require('bitcoinjs-lib');
 | 
			
		||||
const Ticrypto = require('tic.crypto');
 | 
			
		||||
const BTC_NODE = require('./netConfig').BTC_NODE;
 | 
			
		||||
const BTC_NODE2 = require('./netConfig').BTC_NODE2;
 | 
			
		||||
const BTC_TXFEE = 30;
 | 
			
		||||
 | 
			
		||||
class BTC {
 | 
			
		||||
  constructor (privateKey) {
 | 
			
		||||
    if (!ticc.is_prikey({ prikey: privateKey }))
 | 
			
		||||
      throw new Error('Invalid PrivateKey')
 | 
			
		||||
    var publicKey = ticc.prikey_to_pubkey(privateKey)
 | 
			
		||||
    Object.defineProperties(this, {
 | 
			
		||||
      privateKey: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false,
 | 
			
		||||
        value: privateKey
 | 
			
		||||
      },
 | 
			
		||||
      publicKey: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false,
 | 
			
		||||
        value: ticc.prikey_to_pubkey({ prikey: privateKey, coin: 'BTC' })
 | 
			
		||||
      },
 | 
			
		||||
      address: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false,
 | 
			
		||||
        value: ticc.pubkey_to_address({ pubkey: publicKey, coin: 'BTC' })
 | 
			
		||||
      },
 | 
			
		||||
      url: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        get: function () {
 | 
			
		||||
          return this._url
 | 
			
		||||
        },
 | 
			
		||||
        set: function (url) {
 | 
			
		||||
          if (typeof url !== 'string') {
 | 
			
		||||
            throw new Error('invalid url')
 | 
			
		||||
          }
 | 
			
		||||
          this._url = url
 | 
			
		||||
    constructor(privateKey){
 | 
			
		||||
        if(!Ticrypto.isSeckey(privateKey)) throw new Error('Invalid PrivateKey')
 | 
			
		||||
        var publicKey = Ticrypto.seckey2pubkey(privateKey)
 | 
			
		||||
        Object.defineProperties(this,{
 | 
			
		||||
            "privateKey" : {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
                value : privateKey
 | 
			
		||||
            },
 | 
			
		||||
            "publicKey": {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
                value : Ticrypto.seckey2pubkey(privateKey,{coin:"BTC"})
 | 
			
		||||
            },
 | 
			
		||||
            "address" : {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
                value : Ticrypto.pubkey2address(publicKey,{coin:"BTC"}) 
 | 
			
		||||
            },
 | 
			
		||||
            "url" : {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                get: function() { return this._url; },
 | 
			
		||||
                set: function(url) {
 | 
			
		||||
                    if (typeof(url) !== 'string') { throw new Error('invalid url'); }
 | 
			
		||||
                    this._url = url;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "defaultGas":{
 | 
			
		||||
                enumerable: true,
 | 
			
		||||
                get: function() { return this._defaultGasFee; },
 | 
			
		||||
                set: function(value) {
 | 
			
		||||
                    if (typeof(value) !== 'number') { throw new Error('invalid defaultGasFee'); }
 | 
			
		||||
                    this._defaultGasFee = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        this._url = BTC_NODE;
 | 
			
		||||
        this._defaultGasFee = BTC_TXFEE;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    static generateNewAccount(){
 | 
			
		||||
        var mnemonic = Ticrypto.randomSecword()
 | 
			
		||||
        return Object.assign(new BTC(Ticrypto.secword2keypair(mnemonic, {coin:"BTC"}).seckey),{mnemonic : mnemonic})
 | 
			
		||||
    }
 | 
			
		||||
    static fromMnemonic(mnemonic){
 | 
			
		||||
        HDNode.isValidMnemonic(mnemonic)
 | 
			
		||||
        return Object.assign(new BTC(Ticrypto.secword2keypair(mnemonic, {coin:"BTC"}).seckey),{mnemonic:mnemonic})
 | 
			
		||||
    }
 | 
			
		||||
    static async getBalance(address){
 | 
			
		||||
        return (await axios.get(`${BTC_NODE}/addrs/${address}/balance`)).data.balance
 | 
			
		||||
    }
 | 
			
		||||
    static async getActions(address){
 | 
			
		||||
        return (await axios.get(`${BTC_NODE}/addrs/${address}`)).data.txrefs
 | 
			
		||||
    }
 | 
			
		||||
    static async getUTXO(address){
 | 
			
		||||
        // console.log(`${BTC_NODE2}/unspent?active=${address}`,`${BTC_NODE2}/unspent?active=${address}`)
 | 
			
		||||
        try {
 | 
			
		||||
            return (await axios.get(`${BTC_NODE2}/unspent?active=${address}`)).data.unspent_outputs
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      defaultGas: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        get: function () {
 | 
			
		||||
          return this._defaultGasFee
 | 
			
		||||
        },
 | 
			
		||||
        set: function (value) {
 | 
			
		||||
          if (typeof value !== 'number') {
 | 
			
		||||
            throw new Error('invalid defaultGasFee')
 | 
			
		||||
          }
 | 
			
		||||
          this._defaultGasFee = value
 | 
			
		||||
    }
 | 
			
		||||
    static encrypt(data, key){
 | 
			
		||||
        if(!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
        return Ticrypto.encrypt(data,key)
 | 
			
		||||
    }
 | 
			
		||||
    static decrypt(data, key){
 | 
			
		||||
        return Ticrypto.decrypt(data, key, {format:"json"})  //return null for wrong key
 | 
			
		||||
    }
 | 
			
		||||
    static isValidAddress(address){
 | 
			
		||||
        return address.length == 34 && address[0] == '1'
 | 
			
		||||
    }
 | 
			
		||||
    async sendTransaction(toAddress, amount, option = {gasFee : BTC_TXFEE}){
 | 
			
		||||
        let set = bitcoinjs.ECPair.fromPrivateKey(Buffer.from(this.privateKey,'hex'));//导入私钥用于签名
 | 
			
		||||
        let txb = new bitcoinjs.TransactionBuilder();//初始化交易对象
 | 
			
		||||
        let tx = await BTC.getUTXO('1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD')
 | 
			
		||||
        if(!tx) return null
 | 
			
		||||
        var tot = 0;//用于记录UTXO总量
 | 
			
		||||
        amount+=1e4;//消费金额是转出金额加上10000的矿工费
 | 
			
		||||
        txb.setVersion(1);//设置交易版本号
 | 
			
		||||
        for(var i=0;i<tx.length;i++){   //将UTXO的相关信息依次填入交易体中
 | 
			
		||||
            txb.addInput(tx[i].tx_hash_big_endian, tx[i].tx_output_n);
 | 
			
		||||
            tot+=tx[i].value;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        txb.addOutput(toAddress, amount-1e4);//填入转出目标地址和对应的金额
 | 
			
		||||
        txb.addOutput(this.address, tot-amount); //填入找零地址,也就是原地址,并填入把找零金额
 | 
			
		||||
        for(var i=0;i<tx.length;i++){//对交易体中的UTXO依次签名
 | 
			
		||||
            txb.sign(i, set);
 | 
			
		||||
        }
 | 
			
		||||
        // let txBody = txb.buildIncomplete().toHex()
 | 
			
		||||
        let data = {tx : txb.buildIncomplete().toHex()}
 | 
			
		||||
        try {
 | 
			
		||||
            let res = await axios.post(`${BTC_NODE}/txs/push`,data)
 | 
			
		||||
            return res
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    this._url = BTC_NODE
 | 
			
		||||
    this._defaultGasFee = BTC_TXFEE
 | 
			
		||||
  }
 | 
			
		||||
  static generateNewAccount () {
 | 
			
		||||
    var mnemonic = ticc.randomize_secword()
 | 
			
		||||
    return Object.assign(
 | 
			
		||||
      new BTC(
 | 
			
		||||
        ticc.secword_to_keypair({ secword: mnemonic, coin: 'BTC' }).prikey
 | 
			
		||||
      ),
 | 
			
		||||
      { mnemonic: mnemonic }
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
  static fromMnemonic (mnemonic) {
 | 
			
		||||
    HDNode.isValidMnemonic(mnemonic)
 | 
			
		||||
    return Object.assign(
 | 
			
		||||
      new BTC(
 | 
			
		||||
        ticc.secword_to_keypair({ secword: mnemonic, coin: 'BTC' }).prikey
 | 
			
		||||
      ),
 | 
			
		||||
      { mnemonic: mnemonic }
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
  static async getBalance (address) {
 | 
			
		||||
    return (await axios.get(`${BTC_NODE}/addrs/${address}/balance`)).data
 | 
			
		||||
      .balance
 | 
			
		||||
  }
 | 
			
		||||
  static async getActions (address) {
 | 
			
		||||
    return (await axios.get(`${BTC_NODE}/addrs/${address}`)).data.txrefs
 | 
			
		||||
  }
 | 
			
		||||
  static async getUTXO (address) {
 | 
			
		||||
    // console.log(`${BTC_NODE2}/unspent?active=${address}`,`${BTC_NODE2}/unspent?active=${address}`)
 | 
			
		||||
    try {
 | 
			
		||||
      return (await axios.get(`${BTC_NODE2}/unspent?active=${address}`)).data
 | 
			
		||||
        .unspent_outputs
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      return null
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  static encrypt (data, key) {
 | 
			
		||||
    if (!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
    return ticc.encrypt_easy({ data, key })
 | 
			
		||||
  }
 | 
			
		||||
  static decrypt (data, key) {
 | 
			
		||||
    return ticc.decrypt_easy(data, key, { format: 'json' }) //return null for wrong key
 | 
			
		||||
  }
 | 
			
		||||
  static isValidAddress (address) {
 | 
			
		||||
    return address.length == 34 && address[0] == '1'
 | 
			
		||||
  }
 | 
			
		||||
  async sendTransaction (toAddress, amount, option = { gasFee: BTC_TXFEE }) {
 | 
			
		||||
    let set = bitcoinjs.ECPair.fromPrivateKey(
 | 
			
		||||
      Buffer.from(this.privateKey, 'hex')
 | 
			
		||||
    ) //导入私钥用于签名
 | 
			
		||||
    let txb = new bitcoinjs.TransactionBuilder() //初始化交易对象
 | 
			
		||||
    let tx = await BTC.getUTXO('1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD')
 | 
			
		||||
    if (!tx) return null
 | 
			
		||||
    var tot = 0 //用于记录UTXO总量
 | 
			
		||||
    amount += 1e4 //消费金额是转出金额加上10000的矿工费
 | 
			
		||||
    txb.setVersion(1) //设置交易版本号
 | 
			
		||||
    for (var i = 0; i < tx.length; i++) {
 | 
			
		||||
      //将UTXO的相关信息依次填入交易体中
 | 
			
		||||
      txb.addInput(tx[i].tx_hash_big_endian, tx[i].tx_output_n)
 | 
			
		||||
      tot += tx[i].value
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    txb.addOutput(toAddress, amount - 1e4) //填入转出目标地址和对应的金额
 | 
			
		||||
    txb.addOutput(this.address, tot - amount) //填入找零地址,也就是原地址,并填入把找零金额
 | 
			
		||||
    for (var i = 0; i < tx.length; i++) {
 | 
			
		||||
      //对交易体中的UTXO依次签名
 | 
			
		||||
      txb.sign(i, set)
 | 
			
		||||
    }
 | 
			
		||||
    // let txBody = txb.buildIncomplete().toHex()
 | 
			
		||||
    let data = { tx: txb.buildIncomplete().toHex() }
 | 
			
		||||
    try {
 | 
			
		||||
      let res = await axios.post(`${BTC_NODE}/txs/push`, data)
 | 
			
		||||
      return res
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      return null
 | 
			
		||||
    // async sendTransaction(toAddress, amount, option = {gasFee : BTC_TXFEE}){
 | 
			
		||||
    //     var privateKey = bitcore.PrivateKey(this.privateKey)
 | 
			
		||||
    //     var ecdsa = new bitcore.crypto.ECDSA();
 | 
			
		||||
 | 
			
		||||
    //     var newtx = {
 | 
			
		||||
    //         inputs: [{addresses: [this.address]}],
 | 
			
		||||
    //         outputs: [{addresses: [toAddress], value: amount}]
 | 
			
		||||
    //     };
 | 
			
		||||
    //     try {
 | 
			
		||||
    //         var tmptx = (await axios.post('https://api.blockcypher.com/v1/btc/test3/txs/new',newtx)).data;
 | 
			
		||||
    //         tmptx.pubkeys = [];
 | 
			
		||||
    //         tmptx.pubkeys.push(privateKey.toPublicKey().toString("hex"))
 | 
			
		||||
    //         ecdsa.hashbuf = bitcore.crypto.Hash.sha256(new Buffer(tmptx.tosign));
 | 
			
		||||
    //         ecdsa.privkey = privateKey;
 | 
			
		||||
    //         ecdsa.pubkey = privateKey.toPublicKey();
 | 
			
		||||
    //         ecdsa.deterministicK();
 | 
			
		||||
    //         let signatureExpected = ecdsa.sign();
 | 
			
		||||
    //         tmptx.signatures = [Buffer.from(signatureExpected.sig.toDER()).toString('hex')]
 | 
			
		||||
    //         let res = (await axios.post('https://api.blockcypher.com/v1/btc/test3/txs/send',tmptx)).data
 | 
			
		||||
    //         return res
 | 
			
		||||
    //     } catch (error) {
 | 
			
		||||
    //         return error.response.data
 | 
			
		||||
    //     }
 | 
			
		||||
    // }       
 | 
			
		||||
 | 
			
		||||
    async getBalance(){
 | 
			
		||||
        return await BTC.getBalance(this.address)
 | 
			
		||||
    }
 | 
			
		||||
    async getActions(){
 | 
			
		||||
        return await BTC.getActions(this.address)
 | 
			
		||||
    }
 | 
			
		||||
    encrypt(key){
 | 
			
		||||
        return BTC.encrypt(this,key)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // async sendTransaction(toAddress, amount, option = {gasFee : BTC_TXFEE}){
 | 
			
		||||
  //     var privateKey = bitcore.PrivateKey(this.privateKey)
 | 
			
		||||
  //     var ecdsa = new bitcore.crypto.ECDSA()
 | 
			
		||||
 | 
			
		||||
  //     var newtx = {
 | 
			
		||||
  //         inputs: [{addresses: [this.address]}],
 | 
			
		||||
  //         outputs: [{addresses: [toAddress], value: amount}]
 | 
			
		||||
  //     }
 | 
			
		||||
  //     try {
 | 
			
		||||
  //         var tmptx = (await axios.post('https://api.blockcypher.com/v1/btc/test3/txs/new',newtx)).data
 | 
			
		||||
  //         tmptx.pubkeys = []
 | 
			
		||||
  //         tmptx.pubkeys.push(privateKey.toPublicKey().toString("hex"))
 | 
			
		||||
  //         ecdsa.hashbuf = bitcore.crypto.Hash.sha256(new Buffer(tmptx.tosign))
 | 
			
		||||
  //         ecdsa.privkey = privateKey
 | 
			
		||||
  //         ecdsa.pubkey = privateKey.toPublicKey()
 | 
			
		||||
  //         ecdsa.deterministicK()
 | 
			
		||||
  //         let signatureExpected = ecdsa.sign()
 | 
			
		||||
  //         tmptx.signatures = [Buffer.from(signatureExpected.sig.toDER()).toString('hex')]
 | 
			
		||||
  //         let res = (await axios.post('https://api.blockcypher.com/v1/btc/test3/txs/send',tmptx)).data
 | 
			
		||||
  //         return res
 | 
			
		||||
  //     } catch (error) {
 | 
			
		||||
  //         return error.response.data
 | 
			
		||||
  //     }
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  async getBalance () {
 | 
			
		||||
    return await BTC.getBalance(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  async getActions () {
 | 
			
		||||
    return await BTC.getActions(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  encrypt (key) {
 | 
			
		||||
    return BTC.encrypt(this, key)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  BTC
 | 
			
		||||
}
 | 
			
		||||
    BTC
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										903
									
								
								eth.js
									
									
									
									
									
								
							
							
						
						
									
										903
									
								
								eth.js
									
									
									
									
									
								
							@ -1,526 +1,461 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
const eth = require('etherscan-api').init('E3ZFFAEMNN33KX4HHVUZ4KF8XY1FXMR4BI')
 | 
			
		||||
const secretStorage = require('./utils/secret-storage')
 | 
			
		||||
const SigningKey = require('./utils/signing-key.js')
 | 
			
		||||
const ticc = require('tic-crypto')
 | 
			
		||||
const HDNode = require('./utils/hdnode')
 | 
			
		||||
const utils = require('./util.js')
 | 
			
		||||
const axios = require('axios')
 | 
			
		||||
const eth = require('etherscan-api').init('E3ZFFAEMNN33KX4HHVUZ4KF8XY1FXMR4BI');
 | 
			
		||||
const secretStorage = require('./utils/secret-storage');
 | 
			
		||||
const SigningKey = require('./utils/signing-key.js');
 | 
			
		||||
const Ticrypto = require('tic.crypto');
 | 
			
		||||
const HDNode = require('./utils/hdnode');
 | 
			
		||||
const utils = require('./util.js');
 | 
			
		||||
const axios = require('axios');
 | 
			
		||||
 | 
			
		||||
require('setimmediate')
 | 
			
		||||
require('setimmediate');
 | 
			
		||||
 | 
			
		||||
const GAS_UNIT_WEI = 1e18 //1wei
 | 
			
		||||
const GAS_UNIT_GWEI = 1e9 //1gwei = 1e9 wei
 | 
			
		||||
const GAS_Fee = 0.000021
 | 
			
		||||
const GAS_Fee_ERC20 = 0.00006
 | 
			
		||||
const GAS_LIMIT = 21000
 | 
			
		||||
const GAS_LIMIT_ERC20 = 6e4
 | 
			
		||||
const defaultPath = "m/44'/60'/0'/0/0"
 | 
			
		||||
const ETH_NODE = require('./netConfig').ETH_NODE
 | 
			
		||||
const GAS_UNIT_WEI = 1e18;  //1wei
 | 
			
		||||
const GAS_UNIT_GWEI = 1e9;  //1gwei = 1e9 wei
 | 
			
		||||
const GAS_Fee = 0.000021;
 | 
			
		||||
const GAS_Fee_ERC20 = 0.000060;
 | 
			
		||||
const GAS_LIMIT = 21000;
 | 
			
		||||
const GAS_LIMIT_ERC20 = 60000;
 | 
			
		||||
const defaultPath = "m/44'/60'/0'/0/0";
 | 
			
		||||
const ETH_NODE = require('./netConfig').ETH_NODE;
 | 
			
		||||
 | 
			
		||||
const transactionFields = [
 | 
			
		||||
  { name: 'nonce', maxLength: 32 },
 | 
			
		||||
  { name: 'gasPrice', maxLength: 32 },
 | 
			
		||||
  { name: 'gasLimit', maxLength: 32 },
 | 
			
		||||
  { name: 'to', length: 20 },
 | 
			
		||||
  { name: 'value', maxLength: 32 },
 | 
			
		||||
  { name: 'data' }
 | 
			
		||||
]
 | 
			
		||||
    {name: 'nonce',    maxLength: 32, },
 | 
			
		||||
    {name: 'gasPrice', maxLength: 32, },
 | 
			
		||||
    {name: 'gasLimit', maxLength: 32, },
 | 
			
		||||
    {name: 'to',          length: 20, },
 | 
			
		||||
    {name: 'value',    maxLength: 32, },
 | 
			
		||||
    {name: 'data'},
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
class ETH {
 | 
			
		||||
  constructor (privateKey) {
 | 
			
		||||
    if (
 | 
			
		||||
      privateKey.length == 64 &&
 | 
			
		||||
      !(privateKey.split('x')[1] && privateKey.split('x')[0] === '0')
 | 
			
		||||
    )
 | 
			
		||||
      privateKey = '0x' + privateKey
 | 
			
		||||
    var signingKey = privateKey
 | 
			
		||||
    if (!(privateKey instanceof SigningKey)) {
 | 
			
		||||
      signingKey = new SigningKey(privateKey)
 | 
			
		||||
    }
 | 
			
		||||
    Object.defineProperties(this, {
 | 
			
		||||
      privateKey: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false,
 | 
			
		||||
        value: signingKey.privateKey
 | 
			
		||||
      },
 | 
			
		||||
      address: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false,
 | 
			
		||||
        value: signingKey.address
 | 
			
		||||
      },
 | 
			
		||||
      url: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        get: function () {
 | 
			
		||||
          return this._url
 | 
			
		||||
        },
 | 
			
		||||
        set: function (url) {
 | 
			
		||||
          if (typeof url !== 'string') {
 | 
			
		||||
            throw new Error('invalid url')
 | 
			
		||||
          }
 | 
			
		||||
          this._url = url
 | 
			
		||||
    constructor(privateKey){
 | 
			
		||||
        if(privateKey.length == 64 && !(privateKey.split('x')[1] && privateKey.split('x')[0] === '0'))
 | 
			
		||||
            privateKey = '0x'+privateKey;
 | 
			
		||||
        var signingKey = privateKey;
 | 
			
		||||
        if (!(privateKey instanceof SigningKey)) {
 | 
			
		||||
            signingKey = new SigningKey(privateKey);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      defaultGasFee: {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        get: function () {
 | 
			
		||||
          return this._defaultGasFee
 | 
			
		||||
        },
 | 
			
		||||
        set: function (value) {
 | 
			
		||||
          if (typeof value !== 'number') {
 | 
			
		||||
            throw new Error('invalid defaultGasFee')
 | 
			
		||||
          }
 | 
			
		||||
          this._defaultGasFee = value
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    this._defaultGasFee = GAS_Fee
 | 
			
		||||
    this._url = ETH_NODE
 | 
			
		||||
  }
 | 
			
		||||
  static generateNewAccount (option = { path: defaultPath }) {
 | 
			
		||||
    //major path as default path >/0'/0/0
 | 
			
		||||
    var mnemonic = ticc.randomize_secword()
 | 
			
		||||
    return Object.assign(ETH.fromMnemonic(mnemonic, option), {
 | 
			
		||||
      mnemonic,
 | 
			
		||||
      mnemonic
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  static fromMnemonic (mnemonic, option = { path: defaultPath }) {
 | 
			
		||||
    HDNode.isValidMnemonic(mnemonic) //check valid mnemonic,will throw Error if not valid
 | 
			
		||||
    let seed = HDNode.mnemonicToSeed(mnemonic)
 | 
			
		||||
    return new ETH(HDNode.fromSeed(seed).derivePath(option.path).privateKey)
 | 
			
		||||
  }
 | 
			
		||||
  static async getBalance (address) {
 | 
			
		||||
    if (!address) {
 | 
			
		||||
      throw new Error('Address is required')
 | 
			
		||||
    }
 | 
			
		||||
    let res = (
 | 
			
		||||
      await axios.post(ETH_NODE, {
 | 
			
		||||
        jsonrpc: '2.0',
 | 
			
		||||
        method: 'eth_getBalance',
 | 
			
		||||
        params: [address, 'latest'],
 | 
			
		||||
        id: 1
 | 
			
		||||
      })
 | 
			
		||||
    ).data
 | 
			
		||||
    if (res) return parseInt(res.result) / 1e18
 | 
			
		||||
    //1000000000000000000
 | 
			
		||||
    else return null
 | 
			
		||||
  }
 | 
			
		||||
  static async getActions (address) {
 | 
			
		||||
    let tx = await eth.account.txlist(address, 0, 'latast')
 | 
			
		||||
    if (tx && tx.message === 'OK') return tx.result
 | 
			
		||||
    else return []
 | 
			
		||||
  }
 | 
			
		||||
  static fromEncryptedWallet (json, password, progressCallback) {
 | 
			
		||||
    if (progressCallback && typeof progressCallback !== 'function') {
 | 
			
		||||
      throw new Error('invalid callback')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new Promise(function (resolve, reject) {
 | 
			
		||||
      if (secretStorage.isCrowdsaleWallet(json)) {
 | 
			
		||||
        try {
 | 
			
		||||
          var privateKey = secretStorage.decryptCrowdsale(json, password)
 | 
			
		||||
          resolve(new ETH(privateKey))
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
          reject(error)
 | 
			
		||||
        }
 | 
			
		||||
      } else if (secretStorage.isValidWallet(json)) {
 | 
			
		||||
        secretStorage
 | 
			
		||||
          .decrypt(json, password, progressCallback)
 | 
			
		||||
          .then(
 | 
			
		||||
            function (signingKey) {
 | 
			
		||||
              var wallet = new ETH(signingKey)
 | 
			
		||||
              if (signingKey.mnemonic && signingKey.path) {
 | 
			
		||||
                utils.defineProperty(wallet, 'mnemonic', signingKey.mnemonic)
 | 
			
		||||
                utils.defineProperty(wallet, 'path', signingKey.path)
 | 
			
		||||
              }
 | 
			
		||||
              resolve(wallet)
 | 
			
		||||
              return null
 | 
			
		||||
        Object.defineProperties(this, {
 | 
			
		||||
            'privateKey' : {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
                value : signingKey.privateKey
 | 
			
		||||
            },
 | 
			
		||||
            function (error) {
 | 
			
		||||
              reject(error)
 | 
			
		||||
            'address' : {
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
                value : signingKey.address,
 | 
			
		||||
            },
 | 
			
		||||
            'url' : {
 | 
			
		||||
                enumerable: true,
 | 
			
		||||
                get: function() { return this._url; },
 | 
			
		||||
                set: function(url) {
 | 
			
		||||
                    if (typeof(url) !== 'string') { throw new Error('invalid url'); }
 | 
			
		||||
                    this._url = url;
 | 
			
		||||
                },
 | 
			
		||||
            },      
 | 
			
		||||
            'defaultGasFee' : { 
 | 
			
		||||
                enumerable: true,
 | 
			
		||||
                get: function() { return this._defaultGasFee; },
 | 
			
		||||
                set: function(value) {
 | 
			
		||||
                    if (typeof(value) !== 'number') { throw new Error('invalid defaultGasFee'); }
 | 
			
		||||
                    this._defaultGasFee = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          )
 | 
			
		||||
          .catch(function (error) {
 | 
			
		||||
            reject(error)
 | 
			
		||||
          })
 | 
			
		||||
      } else {
 | 
			
		||||
        reject('invalid wallet JSON')
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  static parseTransaction (rawTransaction) {
 | 
			
		||||
    rawTransaction = utils.hexlify(rawTransaction, 'rawTransaction')
 | 
			
		||||
    var signedTransaction = utils.RLP.decode(rawTransaction)
 | 
			
		||||
    if (signedTransaction.length !== 9) {
 | 
			
		||||
      throw new Error('invalid transaction')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var raw = []
 | 
			
		||||
 | 
			
		||||
    var transaction = {}
 | 
			
		||||
    transactionFields.forEach(function (fieldInfo, index) {
 | 
			
		||||
      transaction[fieldInfo.name] = signedTransaction[index]
 | 
			
		||||
      raw.push(signedTransaction[index])
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if (transaction.to) {
 | 
			
		||||
      if (transaction.to == '0x') {
 | 
			
		||||
        delete transaction.to
 | 
			
		||||
      } else {
 | 
			
		||||
        transaction.to = utils.getAddress(transaction.to)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ;['gasPrice', 'gasLimit', 'nonce', 'value'].forEach(function (name) {
 | 
			
		||||
      if (!transaction[name]) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      if (transaction[name].length === 0) {
 | 
			
		||||
        transaction[name] = utils.bigNumberify(0)
 | 
			
		||||
      } else {
 | 
			
		||||
        transaction[name] = utils.bigNumberify(transaction[name])
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if (transaction.nonce) {
 | 
			
		||||
      transaction.nonce = transaction.nonce.toNumber()
 | 
			
		||||
    } else {
 | 
			
		||||
      transaction.nonce = 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var v = utils.arrayify(signedTransaction[6])
 | 
			
		||||
    var r = utils.arrayify(signedTransaction[7])
 | 
			
		||||
    var s = utils.arrayify(signedTransaction[8])
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      v.length >= 1 &&
 | 
			
		||||
      r.length >= 1 &&
 | 
			
		||||
      r.length <= 32 &&
 | 
			
		||||
      s.length >= 1 &&
 | 
			
		||||
      s.length <= 32
 | 
			
		||||
    ) {
 | 
			
		||||
      transaction.v = utils.bigNumberify(v).toNumber()
 | 
			
		||||
      transaction.r = signedTransaction[7]
 | 
			
		||||
      transaction.s = signedTransaction[8]
 | 
			
		||||
 | 
			
		||||
      var chainId = (transaction.v - 35) / 2
 | 
			
		||||
      if (chainId < 0) {
 | 
			
		||||
        chainId = 0
 | 
			
		||||
      }
 | 
			
		||||
      chainId = parseInt(chainId)
 | 
			
		||||
 | 
			
		||||
      transaction.chainId = chainId
 | 
			
		||||
 | 
			
		||||
      var recoveryParam = transaction.v - 27
 | 
			
		||||
 | 
			
		||||
      if (chainId) {
 | 
			
		||||
        raw.push(utils.hexlify(chainId))
 | 
			
		||||
        raw.push('0x')
 | 
			
		||||
        raw.push('0x')
 | 
			
		||||
        recoveryParam -= chainId * 2 + 8
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var digest = utils.keccak256(utils.RLP.encode(raw))
 | 
			
		||||
      try {
 | 
			
		||||
        transaction.from = SigningKey.recover(digest, r, s, recoveryParam)
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.log(error)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return transaction
 | 
			
		||||
  }
 | 
			
		||||
  static encrypt (data, key) {
 | 
			
		||||
    if (!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
    return ticc.encrypt_easy({ data, key })
 | 
			
		||||
  }
 | 
			
		||||
  static decrypt (data, key) {
 | 
			
		||||
    return ticc.decrypt_easy(data, key, { format: 'json' }) //return null for wrong key
 | 
			
		||||
  }
 | 
			
		||||
  static async estimateGasPrice () {
 | 
			
		||||
    try {
 | 
			
		||||
      return (
 | 
			
		||||
        parseInt(
 | 
			
		||||
          (
 | 
			
		||||
            await axios.post(ETH_NODE, {
 | 
			
		||||
              method: 'eth_gasPrice',
 | 
			
		||||
              id: '6842',
 | 
			
		||||
              jsonrpc: '2.0'
 | 
			
		||||
            })
 | 
			
		||||
          ).data.result
 | 
			
		||||
        ) / 1e9
 | 
			
		||||
      )
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return 1
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static isValidAddress (address) {
 | 
			
		||||
    let res = address.match(/^(0x)?[0-9a-fA-F]{40}$/)
 | 
			
		||||
    return res && res[0].slice(0, 2) === '0x'
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getBalance () {
 | 
			
		||||
    return ETH.getBalance(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  async getActions () {
 | 
			
		||||
    return ETH.getActions(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  async getTransactionCount () {
 | 
			
		||||
    if (!this._url) {
 | 
			
		||||
      throw new Error('Base url required')
 | 
			
		||||
    }
 | 
			
		||||
    var self = this
 | 
			
		||||
    return (
 | 
			
		||||
      (
 | 
			
		||||
        await axios.post(this._url, {
 | 
			
		||||
          jsonrpc: '2.0',
 | 
			
		||||
          method: 'eth_getTransactionCount',
 | 
			
		||||
          params: [self.address, 'latest'],
 | 
			
		||||
          id: 1
 | 
			
		||||
        })
 | 
			
		||||
      ).data.result || null
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
  signTransaction (transaction) {
 | 
			
		||||
    var chainId = transaction.chainId
 | 
			
		||||
    if (chainId == null && this.provider) {
 | 
			
		||||
      chainId = this.provider.chainId
 | 
			
		||||
        this._defaultGasFee = GAS_Fee;
 | 
			
		||||
        this._url = ETH_NODE;
 | 
			
		||||
    }
 | 
			
		||||
    if (!chainId) {
 | 
			
		||||
      chainId = 0
 | 
			
		||||
    static generateNewAccount(option = {path:defaultPath}){
 | 
			
		||||
        //major path as default path >/0'/0/0
 | 
			
		||||
        var mnemonic =  Ticrypto.randomSecword();
 | 
			
		||||
        return Object.assign(ETH.fromMnemonic(mnemonic, option),{mnemonic,mnemonic})
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var raw = []
 | 
			
		||||
    transactionFields.forEach(function (fieldInfo) {
 | 
			
		||||
      var value = transaction[fieldInfo.name] || []
 | 
			
		||||
      value = utils.arrayify(utils.hexlify(value), fieldInfo.name)
 | 
			
		||||
 | 
			
		||||
      // Fixed-width field
 | 
			
		||||
      if (
 | 
			
		||||
        fieldInfo.length &&
 | 
			
		||||
        value.length !== fieldInfo.length &&
 | 
			
		||||
        value.length > 0
 | 
			
		||||
      ) {
 | 
			
		||||
        var error = new Error('invalid ' + fieldInfo.name)
 | 
			
		||||
        error.reason = 'wrong length'
 | 
			
		||||
        error.value = value
 | 
			
		||||
        throw error
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Variable-width (with a maximum)
 | 
			
		||||
      if (fieldInfo.maxLength) {
 | 
			
		||||
        value = utils.stripZeros(value)
 | 
			
		||||
        if (value.length > fieldInfo.maxLength) {
 | 
			
		||||
          var error = new Error('invalid ' + fieldInfo.name)
 | 
			
		||||
          error.reason = 'too long'
 | 
			
		||||
          error.value = value
 | 
			
		||||
          throw error
 | 
			
		||||
    static fromMnemonic(mnemonic, option = {path:defaultPath}){
 | 
			
		||||
        HDNode.isValidMnemonic(mnemonic)    //check valid mnemonic,will throw Error if not valid
 | 
			
		||||
        let seed = HDNode.mnemonicToSeed(mnemonic)
 | 
			
		||||
        return new ETH(HDNode.fromSeed(seed).derivePath(option.path).privateKey)
 | 
			
		||||
    }
 | 
			
		||||
    static async getBalance(address){
 | 
			
		||||
        if(!address){ throw new Error('Address is required'); }
 | 
			
		||||
        let res = (await axios.post(ETH_NODE,{
 | 
			
		||||
            "jsonrpc":"2.0","method":"eth_getBalance","params":[address, "latest"],"id":1
 | 
			
		||||
        })).data
 | 
			
		||||
        if(res)
 | 
			
		||||
        return parseInt(res.result)/1e18    //1000000000000000000
 | 
			
		||||
        else return null
 | 
			
		||||
    }
 | 
			
		||||
    static async getActions(address){
 | 
			
		||||
        let tx = await eth.account.txlist(address, 0 ,'latast')
 | 
			
		||||
        if(tx && tx.message === "OK")
 | 
			
		||||
            return tx.result
 | 
			
		||||
        else return [] 
 | 
			
		||||
    }
 | 
			
		||||
    static fromEncryptedWallet(json, password, progressCallback) {
 | 
			
		||||
        if (progressCallback && typeof(progressCallback) !== 'function') {
 | 
			
		||||
            throw new Error('invalid callback');
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        return new Promise(function(resolve, reject) {
 | 
			
		||||
    
 | 
			
		||||
            if (secretStorage.isCrowdsaleWallet(json)) {
 | 
			
		||||
                try {
 | 
			
		||||
                    var privateKey = secretStorage.decryptCrowdsale(json, password);
 | 
			
		||||
                    resolve(new ETH(privateKey));
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    reject(error);
 | 
			
		||||
                }
 | 
			
		||||
    
 | 
			
		||||
            } else if (secretStorage.isValidWallet(json)) {
 | 
			
		||||
    
 | 
			
		||||
                secretStorage.decrypt(json, password, progressCallback).then(function(signingKey) {
 | 
			
		||||
                    var wallet = new ETH(signingKey);
 | 
			
		||||
                    if (signingKey.mnemonic && signingKey.path) {
 | 
			
		||||
                        utils.defineProperty(wallet, 'mnemonic', signingKey.mnemonic);
 | 
			
		||||
                        utils.defineProperty(wallet, 'path', signingKey.path);
 | 
			
		||||
                    }
 | 
			
		||||
                    resolve(wallet);
 | 
			
		||||
                    return null;
 | 
			
		||||
                }, function(error) {
 | 
			
		||||
                    reject(error);
 | 
			
		||||
                }).catch(function(error) { reject(error); });
 | 
			
		||||
    
 | 
			
		||||
            } else {
 | 
			
		||||
                reject('invalid wallet JSON');
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    static parseTransaction(rawTransaction){
 | 
			
		||||
        rawTransaction = utils.hexlify(rawTransaction, 'rawTransaction');
 | 
			
		||||
        var signedTransaction = utils.RLP.decode(rawTransaction);
 | 
			
		||||
        if (signedTransaction.length !== 9) { throw new Error('invalid transaction'); }
 | 
			
		||||
    
 | 
			
		||||
        var raw = [];
 | 
			
		||||
    
 | 
			
		||||
        var transaction = {};
 | 
			
		||||
        transactionFields.forEach(function(fieldInfo, index) {
 | 
			
		||||
            transaction[fieldInfo.name] = signedTransaction[index];
 | 
			
		||||
            raw.push(signedTransaction[index]);
 | 
			
		||||
        });
 | 
			
		||||
    
 | 
			
		||||
        if (transaction.to) {
 | 
			
		||||
            if (transaction.to == '0x') {
 | 
			
		||||
                delete transaction.to;
 | 
			
		||||
            } else {
 | 
			
		||||
                transaction.to = utils.getAddress(transaction.to);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        ['gasPrice', 'gasLimit', 'nonce', 'value'].forEach(function(name) {
 | 
			
		||||
            if (!transaction[name]) { return; }
 | 
			
		||||
            if (transaction[name].length === 0) {
 | 
			
		||||
                transaction[name] = utils.bigNumberify(0);
 | 
			
		||||
            } else {
 | 
			
		||||
                transaction[name] = utils.bigNumberify(transaction[name]);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    
 | 
			
		||||
        if (transaction.nonce) {
 | 
			
		||||
            transaction.nonce = transaction.nonce.toNumber();
 | 
			
		||||
        } else {
 | 
			
		||||
            transaction.nonce = 0;
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        var v = utils.arrayify(signedTransaction[6]);
 | 
			
		||||
        var r = utils.arrayify(signedTransaction[7]);
 | 
			
		||||
        var s = utils.arrayify(signedTransaction[8]);
 | 
			
		||||
    
 | 
			
		||||
        if (v.length >= 1 && r.length >= 1 && r.length <= 32 && s.length >= 1 && s.length <= 32) {
 | 
			
		||||
            transaction.v = utils.bigNumberify(v).toNumber();
 | 
			
		||||
            transaction.r = signedTransaction[7];
 | 
			
		||||
            transaction.s = signedTransaction[8];
 | 
			
		||||
    
 | 
			
		||||
            var chainId = (transaction.v - 35) / 2;
 | 
			
		||||
            if (chainId < 0) { chainId = 0; }
 | 
			
		||||
            chainId = parseInt(chainId);
 | 
			
		||||
    
 | 
			
		||||
            transaction.chainId = chainId;
 | 
			
		||||
    
 | 
			
		||||
            var recoveryParam = transaction.v - 27;
 | 
			
		||||
    
 | 
			
		||||
            if (chainId) {
 | 
			
		||||
                raw.push(utils.hexlify(chainId));
 | 
			
		||||
                raw.push('0x');
 | 
			
		||||
                raw.push('0x');
 | 
			
		||||
                recoveryParam -= chainId * 2 + 8;
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
            var digest = utils.keccak256(utils.RLP.encode(raw));
 | 
			
		||||
            try {
 | 
			
		||||
                transaction.from = SigningKey.recover(digest, r, s, recoveryParam);
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                console.log(error);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
        return transaction;
 | 
			
		||||
    }
 | 
			
		||||
    static encrypt(data, key){
 | 
			
		||||
        if(!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
        return Ticrypto.encrypt(data,key)
 | 
			
		||||
    }
 | 
			
		||||
    static decrypt(data, key){
 | 
			
		||||
        return Ticrypto.decrypt(data, key, {format:"json"})  //return null for wrong key
 | 
			
		||||
    }
 | 
			
		||||
    static async estimateGasPrice(){
 | 
			
		||||
        try{
 | 
			
		||||
            return parseInt((await axios.post(ETH_NODE, {
 | 
			
		||||
                "method": "eth_gasPrice",
 | 
			
		||||
                "id": "6842",
 | 
			
		||||
                "jsonrpc": "2.0"
 | 
			
		||||
            })).data.result)/1e9
 | 
			
		||||
        }
 | 
			
		||||
        catch(err){
 | 
			
		||||
            return 1
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      raw.push(utils.hexlify(value))
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if (chainId) {
 | 
			
		||||
      raw.push(utils.hexlify(chainId))
 | 
			
		||||
      raw.push('0x')
 | 
			
		||||
      raw.push('0x')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var digest = utils.keccak256(utils.RLP.encode(raw))
 | 
			
		||||
    var signingKey = new SigningKey(this.privateKey)
 | 
			
		||||
    var signature = signingKey.signDigest(digest)
 | 
			
		||||
 | 
			
		||||
    var v = 27 + signature.recoveryParam
 | 
			
		||||
    if (chainId) {
 | 
			
		||||
      raw.pop()
 | 
			
		||||
      raw.pop()
 | 
			
		||||
      raw.pop()
 | 
			
		||||
      v += chainId * 2 + 8
 | 
			
		||||
    static isValidAddress(address){
 | 
			
		||||
        let res = address.match(/^(0x)?[0-9a-fA-F]{40}$/)
 | 
			
		||||
        return res && res[0].slice(0,2) === '0x'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    raw.push(utils.hexlify(v))
 | 
			
		||||
    raw.push(utils.stripZeros(utils.arrayify(signature.r)))
 | 
			
		||||
    raw.push(utils.stripZeros(utils.arrayify(signature.s)))
 | 
			
		||||
    async getBalance(){
 | 
			
		||||
        return ETH.getBalance(this.address)
 | 
			
		||||
    }
 | 
			
		||||
    async getActions(){
 | 
			
		||||
        return ETH.getActions(this.address)
 | 
			
		||||
    }
 | 
			
		||||
    async getTransactionCount(){
 | 
			
		||||
        if(!this._url){ throw new Error('Base url required'); }
 | 
			
		||||
        var self = this;
 | 
			
		||||
        return (await axios.post(this._url,{
 | 
			
		||||
            "jsonrpc":"2.0","method":"eth_getTransactionCount","params":[self.address, "latest"],"id":1
 | 
			
		||||
        })).data.result||null
 | 
			
		||||
    }
 | 
			
		||||
    signTransaction(transaction){
 | 
			
		||||
        var chainId = transaction.chainId;
 | 
			
		||||
        if (chainId == null && this.provider) { chainId = this.provider.chainId; }
 | 
			
		||||
        if (!chainId) { chainId = 0; }
 | 
			
		||||
 | 
			
		||||
    return utils.RLP.encode(raw)
 | 
			
		||||
  }
 | 
			
		||||
  async sendTransaction (toAddress, amount, option = { gasFee: GAS_Fee }) {
 | 
			
		||||
    /****************************************************************   
 | 
			
		||||
        var raw = [];
 | 
			
		||||
        transactionFields.forEach(function(fieldInfo) {
 | 
			
		||||
            var value = transaction[fieldInfo.name] || ([]);
 | 
			
		||||
            value = utils.arrayify(utils.hexlify(value), fieldInfo.name);
 | 
			
		||||
 | 
			
		||||
            // Fixed-width field
 | 
			
		||||
            if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {
 | 
			
		||||
                var error = new Error('invalid ' + fieldInfo.name);
 | 
			
		||||
                error.reason = 'wrong length';
 | 
			
		||||
                error.value = value;
 | 
			
		||||
                throw error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Variable-width (with a maximum)
 | 
			
		||||
            if (fieldInfo.maxLength) {
 | 
			
		||||
                value = utils.stripZeros(value);
 | 
			
		||||
                if (value.length > fieldInfo.maxLength) {
 | 
			
		||||
                    var error = new Error('invalid ' + fieldInfo.name);
 | 
			
		||||
                    error.reason = 'too long';
 | 
			
		||||
                    error.value = value;
 | 
			
		||||
                    throw error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            raw.push(utils.hexlify(value));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (chainId) {
 | 
			
		||||
            raw.push(utils.hexlify(chainId));
 | 
			
		||||
            raw.push('0x');
 | 
			
		||||
            raw.push('0x');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var digest = utils.keccak256(utils.RLP.encode(raw));
 | 
			
		||||
        var signingKey = new SigningKey(this.privateKey);
 | 
			
		||||
        var signature = signingKey.signDigest(digest);
 | 
			
		||||
 | 
			
		||||
        var v = 27 + signature.recoveryParam
 | 
			
		||||
        if (chainId) {
 | 
			
		||||
            raw.pop();
 | 
			
		||||
            raw.pop();
 | 
			
		||||
            raw.pop();
 | 
			
		||||
            v += chainId * 2 + 8;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        raw.push(utils.hexlify(v));
 | 
			
		||||
        raw.push(utils.stripZeros(utils.arrayify(signature.r)));
 | 
			
		||||
        raw.push(utils.stripZeros(utils.arrayify(signature.s)));
 | 
			
		||||
 | 
			
		||||
        return utils.RLP.encode(raw);
 | 
			
		||||
    }
 | 
			
		||||
    async sendTransaction(toAddress, amount, option = {gasFee : GAS_Fee}){
 | 
			
		||||
        /****************************************************************   
 | 
			
		||||
            1 Ether = 1e18 wei  
 | 
			
		||||
            1Gwei = 1e9 wei   
 | 
			
		||||
            *GWei as the unit of gasPrice, minimum gasPrice is 1Gwei
 | 
			
		||||
            *unit of amount is ether,should be translate to wei
 | 
			
		||||
        ****************************************************************/
 | 
			
		||||
    let nonce = await this.getTransactionCount()
 | 
			
		||||
    if (!nonce) nonce = '0x0'
 | 
			
		||||
    var gasPrice, gasLimit
 | 
			
		||||
    if (!option.gasPrice || !option.gasLimit) {
 | 
			
		||||
      //Normal Mode:use customized gasFee( ether ) to caculate gasPrice( wei ), gasLimit use default value
 | 
			
		||||
      gasLimit = GAS_LIMIT
 | 
			
		||||
      gasPrice = String((option.gasFee * GAS_UNIT_WEI) / gasLimit)
 | 
			
		||||
    } else {
 | 
			
		||||
      //Advance Mode:specified the gasLimit and gasPrice( gwei )
 | 
			
		||||
      gasLimit = option.gasLimit
 | 
			
		||||
      gasPrice = String(GAS_UNIT_GWEI * option.gasPrice)
 | 
			
		||||
    }
 | 
			
		||||
    let transaction = {
 | 
			
		||||
      nonce: nonce,
 | 
			
		||||
      gasLimit: gasLimit,
 | 
			
		||||
      gasPrice: utils.bigNumberify(gasPrice),
 | 
			
		||||
      to: toAddress,
 | 
			
		||||
        let nonce = await this.getTransactionCount();
 | 
			
		||||
        if(!nonce) nonce = '0x0'
 | 
			
		||||
        var gasPrice, gasLimit;
 | 
			
		||||
        if(!option.gasPrice || !option.gasLimit){
 | 
			
		||||
            //Normal Mode:use customized gasFee( ether ) to caculate gasPrice( wei ), gasLimit use default value
 | 
			
		||||
            gasLimit = GAS_LIMIT;
 | 
			
		||||
            gasPrice = String(option.gasFee * GAS_UNIT_WEI / gasLimit);
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            //Advance Mode:specified the gasLimit and gasPrice( gwei )
 | 
			
		||||
            gasLimit = option.gasLimit;
 | 
			
		||||
            gasPrice = String(GAS_UNIT_GWEI * option.gasPrice)
 | 
			
		||||
        }
 | 
			
		||||
        let transaction = {
 | 
			
		||||
            nonce: nonce,
 | 
			
		||||
            gasLimit: gasLimit,
 | 
			
		||||
            gasPrice: utils.bigNumberify(gasPrice),
 | 
			
		||||
            to: toAddress,
 | 
			
		||||
 | 
			
		||||
      value: utils.parseEther(String(amount))
 | 
			
		||||
            value: utils.parseEther(String(amount)),
 | 
			
		||||
        };
 | 
			
		||||
        try{
 | 
			
		||||
            let signedTransaction = this.signTransaction(transaction);
 | 
			
		||||
            let ethTxRes = (await axios.post(ETH_NODE,{
 | 
			
		||||
                "jsonrpc":"2.0",
 | 
			
		||||
                "method":"eth_sendRawTransaction",
 | 
			
		||||
                "params":[signedTransaction.toString('hex')],
 | 
			
		||||
                "id":6842
 | 
			
		||||
            })).data
 | 
			
		||||
            if(ethTxRes && ethTxRes.result)
 | 
			
		||||
                return ethTxRes
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
        catch(err){
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      let signedTransaction = this.signTransaction(transaction)
 | 
			
		||||
      let ethTxRes = (
 | 
			
		||||
        await axios.post(ETH_NODE, {
 | 
			
		||||
          jsonrpc: '2.0',
 | 
			
		||||
          method: 'eth_sendRawTransaction',
 | 
			
		||||
          params: [signedTransaction.toString('hex')],
 | 
			
		||||
          id: 6842
 | 
			
		||||
        })
 | 
			
		||||
      ).data
 | 
			
		||||
      if (ethTxRes && ethTxRes.result) return ethTxRes
 | 
			
		||||
      return null
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return null
 | 
			
		||||
    encrypt(key){
 | 
			
		||||
        return ETH.encrypt(this, key)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  encrypt (key) {
 | 
			
		||||
    return ETH.encrypt(this, key)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ERC20 extends ETH {
 | 
			
		||||
  constructor (privateKey, contractAddress) {
 | 
			
		||||
    if (!contractAddress) throw new Error('Missing contractAddress')
 | 
			
		||||
    super(privateKey)
 | 
			
		||||
    Object.defineProperty(this, 'contractAddress', {
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
      writable: false,
 | 
			
		||||
      value: contractAddress
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  static async getDecimals (contractAddress) {
 | 
			
		||||
    if (!contractAddress) throw new Error('Missing params')
 | 
			
		||||
    let queryAddress =
 | 
			
		||||
      '0x313ce567' + contractAddress.split('x')[1].padStart(64, '0')
 | 
			
		||||
    let params = [{ to: contractAddress, data: queryAddress }, 'latest']
 | 
			
		||||
    let queryData = {
 | 
			
		||||
      jsonrpc: '2.0',
 | 
			
		||||
      method: 'eth_call',
 | 
			
		||||
      params: params,
 | 
			
		||||
      id: 6842
 | 
			
		||||
class ERC20 extends ETH{
 | 
			
		||||
    constructor(privateKey, contractAddress){
 | 
			
		||||
        if(!contractAddress) throw new Error('Missing contractAddress')
 | 
			
		||||
        super(privateKey);
 | 
			
		||||
        Object.defineProperty(this, 'contractAddress',{
 | 
			
		||||
            enumerable:true,
 | 
			
		||||
            writable:false,
 | 
			
		||||
            value:contractAddress
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    return parseInt((await axios.post(ETH_NODE, queryData)).data.result)
 | 
			
		||||
  }
 | 
			
		||||
  static async getBalance (address, contractAddress) {
 | 
			
		||||
    if (!address || !contractAddress) throw new Error('Missing params')
 | 
			
		||||
    let queryAddress = '0x70a08231' + address.split('x')[1].padStart(64, '0')
 | 
			
		||||
    let params = [{ to: contractAddress, data: queryAddress }, 'latest']
 | 
			
		||||
    let queryData = {
 | 
			
		||||
      jsonrpc: '2.0',
 | 
			
		||||
      method: 'eth_call',
 | 
			
		||||
      params: params,
 | 
			
		||||
      id: 6842
 | 
			
		||||
    static async getDecimals(contractAddress){
 | 
			
		||||
        if(!contractAddress) throw new Error('Missing params')
 | 
			
		||||
        let queryAddress = '0x313ce567' + (contractAddress.split('x')[1]).padStart(64,'0')
 | 
			
		||||
        let params = [{"to":contractAddress, "data":queryAddress},"latest"]
 | 
			
		||||
        let queryData = {
 | 
			
		||||
            "jsonrpc":"2.0",
 | 
			
		||||
            "method":"eth_call",
 | 
			
		||||
            "params":params,
 | 
			
		||||
            "id":6842
 | 
			
		||||
        }
 | 
			
		||||
        return parseInt((await axios.post(ETH_NODE, queryData)).data.result)
 | 
			
		||||
    }
 | 
			
		||||
    // return parseInt(erc20res.result)/Number('10'.padEnd(ERC20Table[obj.name].decimals+1,'0'))
 | 
			
		||||
    let res = (await axios.post(ETH_NODE, queryData)).data.result
 | 
			
		||||
    if (res == '0x') return 0
 | 
			
		||||
    return parseInt(res)
 | 
			
		||||
  }
 | 
			
		||||
  static async getActions (address, contractAddress) {
 | 
			
		||||
    try {
 | 
			
		||||
      let res = await eth.account.tokentx(address, contractAddress)
 | 
			
		||||
      if (res && res.result) return res.result
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return []
 | 
			
		||||
    static async getBalance(address, contractAddress){
 | 
			
		||||
        if(!address || !contractAddress) throw new Error('Missing params')
 | 
			
		||||
        let queryAddress = '0x70a08231' + (address.split('x')[1]).padStart(64,'0')
 | 
			
		||||
        let params = [{"to":contractAddress, "data":queryAddress},"latest"]
 | 
			
		||||
        let queryData = {
 | 
			
		||||
            "jsonrpc":"2.0",
 | 
			
		||||
            "method":"eth_call",
 | 
			
		||||
            "params":params,
 | 
			
		||||
            "id":6842
 | 
			
		||||
        }
 | 
			
		||||
        // return parseInt(erc20res.result)/Number('10'.padEnd(ERC20Table[obj.name].decimals+1,'0')) 
 | 
			
		||||
        let res = (await axios.post(ETH_NODE, queryData)).data.result
 | 
			
		||||
        if(res == '0x') return 0
 | 
			
		||||
        return parseInt(res)
 | 
			
		||||
    }
 | 
			
		||||
    static async getActions(address, contractAddress){
 | 
			
		||||
        try{   
 | 
			
		||||
            let res = (await eth.account.tokentx(address,contractAddress))
 | 
			
		||||
            if(res && res.result)
 | 
			
		||||
                return res.result
 | 
			
		||||
        }
 | 
			
		||||
        catch(err){
 | 
			
		||||
            return []
 | 
			
		||||
        }
 | 
			
		||||
        return 
 | 
			
		||||
    }
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getBalance () {
 | 
			
		||||
    return ERC20.getBalance(this.address, this.contractAddress)
 | 
			
		||||
  }
 | 
			
		||||
  async getActions () {
 | 
			
		||||
    return ERC20.getActions(this.address, this.contractAddress)
 | 
			
		||||
  }
 | 
			
		||||
  async getDecimals () {
 | 
			
		||||
    let decimals = await ERC20.getDecimals(this.contractAddress)
 | 
			
		||||
    if (decimals)
 | 
			
		||||
      Object.defineProperty(this, 'decimals', {
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        value: decimals,
 | 
			
		||||
        writable: false
 | 
			
		||||
      })
 | 
			
		||||
    else return 0 // any good idea?
 | 
			
		||||
  }
 | 
			
		||||
  async sendTransaction (
 | 
			
		||||
    toAddress,
 | 
			
		||||
    amount,
 | 
			
		||||
    option = { gasFee: GAS_Fee_ERC20 }
 | 
			
		||||
  ) {
 | 
			
		||||
    /****************************************************************   
 | 
			
		||||
    async getBalance(){
 | 
			
		||||
        return ERC20.getBalance(this.address, this.contractAddress)
 | 
			
		||||
    }
 | 
			
		||||
    async getActions(){
 | 
			
		||||
        return ERC20.getActions(this.address, this.contractAddress)
 | 
			
		||||
    }  
 | 
			
		||||
    async getDecimals(){
 | 
			
		||||
        let decimals = await ERC20.getDecimals(this.contractAddress)
 | 
			
		||||
        if(decimals)
 | 
			
		||||
            Object.defineProperty(this, 'decimals', {
 | 
			
		||||
                enumerable:true,
 | 
			
		||||
                value:decimals,
 | 
			
		||||
                writable:false
 | 
			
		||||
            })
 | 
			
		||||
        else
 | 
			
		||||
            return 0    // any good idea?
 | 
			
		||||
    }
 | 
			
		||||
    async sendTransaction(toAddress, amount, option = {gasFee : GAS_Fee_ERC20}){
 | 
			
		||||
        /****************************************************************   
 | 
			
		||||
            1 Ether = 1e18 wei  
 | 
			
		||||
            1 Gwei = 1e9 wei   
 | 
			
		||||
            *GWei as the unit of gasPrice, minimum gasPrice is 1Gwei
 | 
			
		||||
            minimum gaslimit for erc20transaction is 6e4
 | 
			
		||||
            minimum gaslimit for erc20transaction is 60000
 | 
			
		||||
        ****************************************************************/
 | 
			
		||||
    var nonce = await this.getTransactionCount()
 | 
			
		||||
    var gasPrice,
 | 
			
		||||
      gasLimit,
 | 
			
		||||
      decimals,
 | 
			
		||||
      contractAddress = this.contractAddress
 | 
			
		||||
    if (!nonce) nonce = '0x0'
 | 
			
		||||
    if (!option.gasPrice || !option.gasLimit) {
 | 
			
		||||
      //Normal Mode:use customized gasFee( ether ) to caculate gasPrice( wei ), gasLimit use default value
 | 
			
		||||
      gasLimit = GAS_LIMIT_ERC20
 | 
			
		||||
      gasPrice = String((option.gasFee * GAS_UNIT_WEI) / gasLimit)
 | 
			
		||||
    } else {
 | 
			
		||||
      //Advance Mode:specified the gasLimit and gasPrice( gwei )
 | 
			
		||||
      gasLimit = option.gasLimit
 | 
			
		||||
      gasPrice = String(GAS_UNIT_GWEI * option.gasPrice)
 | 
			
		||||
        var nonce = await this.getTransactionCount();
 | 
			
		||||
        var gasPrice, gasLimit, decimals, contractAddress = this.contractAddress;
 | 
			
		||||
        if(!nonce) nonce = '0x0'
 | 
			
		||||
        if(!option.gasPrice || !option.gasLimit){
 | 
			
		||||
            //Normal Mode:use customized gasFee( ether ) to caculate gasPrice( wei ), gasLimit use default value
 | 
			
		||||
            gasLimit = GAS_LIMIT_ERC20;
 | 
			
		||||
            gasPrice = String(option.gasFee * GAS_UNIT_WEI / gasLimit);
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            //Advance Mode:specified the gasLimit and gasPrice( gwei )
 | 
			
		||||
            gasLimit = option.gasLimit;
 | 
			
		||||
            gasPrice = String(GAS_UNIT_GWEI * option.gasPrice)
 | 
			
		||||
        }
 | 
			
		||||
        if(!option.decimals) decimals = await ERC20.getDecimals(contractAddress)
 | 
			
		||||
        let txBody = '0x' + 'a9059cbb' + toAddress.split('x')[1].padStart(64,'0')+ Number(amount*Math.pow(10,decimals)).toString(16).padStart(64,'0')
 | 
			
		||||
        let transaction = {
 | 
			
		||||
            nonce: nonce,
 | 
			
		||||
            gasLimit: gasLimit,
 | 
			
		||||
            gasPrice : utils.bigNumberify(gasPrice),
 | 
			
		||||
            to: contractAddress,
 | 
			
		||||
            value : 0,
 | 
			
		||||
            data : txBody
 | 
			
		||||
        };
 | 
			
		||||
        let signedTransaction = this.signTransaction(transaction);
 | 
			
		||||
        try{
 | 
			
		||||
            let erc20TxRes = (await axios.post(ETH_NODE, {
 | 
			
		||||
                "jsonrpc":"2.0",
 | 
			
		||||
                "method":"eth_sendRawTransaction",
 | 
			
		||||
                "params":[signedTransaction.toString('hex')],
 | 
			
		||||
                "id":6842
 | 
			
		||||
            })).data
 | 
			
		||||
            if(erc20TxRes && erc20TxRes.result)
 | 
			
		||||
                return erc20TxRes.result
 | 
			
		||||
            console.log(erc20TxRes)
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
        catch(err){
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!option.decimals) decimals = await ERC20.getDecimals(contractAddress)
 | 
			
		||||
    let txBody =
 | 
			
		||||
      '0x' +
 | 
			
		||||
      'a9059cbb' +
 | 
			
		||||
      toAddress.split('x')[1].padStart(64, '0') +
 | 
			
		||||
      Number(amount * Math.pow(10, decimals))
 | 
			
		||||
        .toString(16)
 | 
			
		||||
        .padStart(64, '0')
 | 
			
		||||
    let transaction = {
 | 
			
		||||
      nonce: nonce,
 | 
			
		||||
      gasLimit: gasLimit,
 | 
			
		||||
      gasPrice: utils.bigNumberify(gasPrice),
 | 
			
		||||
      to: contractAddress,
 | 
			
		||||
      value: 0,
 | 
			
		||||
      data: txBody
 | 
			
		||||
    }
 | 
			
		||||
    let signedTransaction = this.signTransaction(transaction)
 | 
			
		||||
    try {
 | 
			
		||||
      let erc20TxRes = (
 | 
			
		||||
        await axios.post(ETH_NODE, {
 | 
			
		||||
          jsonrpc: '2.0',
 | 
			
		||||
          method: 'eth_sendRawTransaction',
 | 
			
		||||
          params: [signedTransaction.toString('hex')],
 | 
			
		||||
          id: 6842
 | 
			
		||||
        })
 | 
			
		||||
      ).data
 | 
			
		||||
      if (erc20TxRes && erc20TxRes.result) return erc20TxRes.result
 | 
			
		||||
      console.log(erc20TxRes)
 | 
			
		||||
      return null
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return null
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  ETH,
 | 
			
		||||
  ERC20
 | 
			
		||||
    ETH, ERC20
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								index.js
									
									
									
									
									
								
							@ -1,16 +1,16 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const TIC = require('./tic.js').TIC
 | 
			
		||||
const ETH = require('./eth.js').ETH
 | 
			
		||||
const ERC20 = require('./eth.js').ERC20
 | 
			
		||||
const BTC = require('./btc.js').BTC
 | 
			
		||||
const Account = require('./Account').Account
 | 
			
		||||
const Crypto = require('tic-crypto')
 | 
			
		||||
const TIC = require('./tic.js').TIC;
 | 
			
		||||
const ETH = require('./eth.js').ETH;
 | 
			
		||||
const ERC20 = require('./eth.js').ERC20;
 | 
			
		||||
const BTC = require('./btc.js').BTC;
 | 
			
		||||
const Account = require('./Account').Account;
 | 
			
		||||
const Crypto = require('tic.crypto');
 | 
			
		||||
module.exports = {
 | 
			
		||||
  TIC,
 | 
			
		||||
  ETH,
 | 
			
		||||
  BTC,
 | 
			
		||||
  ERC20,
 | 
			
		||||
  Account,
 | 
			
		||||
  Crypto
 | 
			
		||||
}
 | 
			
		||||
    TIC,
 | 
			
		||||
    ETH,
 | 
			
		||||
    BTC,
 | 
			
		||||
    ERC20,
 | 
			
		||||
    Account,
 | 
			
		||||
    Crypto,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								netConfig.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								netConfig.js
									
									
									
									
									
								
							@ -1,10 +1,10 @@
 | 
			
		||||
 | 
			
		||||
const TIC_NODE = 'https://bank.bittic.net:60000/api'
 | 
			
		||||
const BTC_NODE = 'https://api.blockcypher.com/v1/btc/main'
 | 
			
		||||
const BTC_NODE2 = 'https://blockchain.info' //https://blockchain.info/unspent?active=12HnmPpLomtPL53Q4s6xEqRB4wkMHi5GEZ
 | 
			
		||||
const ETH_NODE = 'https://mainnet.infura.io/8284219b092f4cc69f3de29e532b1eb2'
 | 
			
		||||
const ETH_NODE2 = 'https://api.myetherapi.com/eth'
 | 
			
		||||
const ETH_TEST_NODE = 'https://ropsten.infura.io/8284219b092f4cc69f3de29e532b1eb2'
 | 
			
		||||
const TIC_NODE = 'https://bank.bittic.net:7285/api';
 | 
			
		||||
const BTC_NODE = 'https://api.blockcypher.com/v1/btc/main';
 | 
			
		||||
const BTC_NODE2 = 'https://blockchain.info'//https://blockchain.info/unspent?active=12HnmPpLomtPL53Q4s6xEqRB4wkMHi5GEZ
 | 
			
		||||
const ETH_NODE = 'https://mainnet.infura.io/8284219b092f4cc69f3de29e532b1eb2';
 | 
			
		||||
const ETH_NODE2 = 'https://api.myetherapi.com/eth';
 | 
			
		||||
const ETH_TEST_NODE = 'https://ropsten.infura.io/8284219b092f4cc69f3de29e532b1eb2';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    TIC_NODE,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "tic-chaintool",
 | 
			
		||||
  "name": "tool4chain",
 | 
			
		||||
  "version": "1.2.1",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "aes-js": "^3.1.1",
 | 
			
		||||
@ -10,12 +10,16 @@
 | 
			
		||||
    "js-sha3": "^0.8.0",
 | 
			
		||||
    "scrypt-js": "^2.0.3",
 | 
			
		||||
    "setimmediate": "^1.0.5",
 | 
			
		||||
    "tic.action": "git+https://git.faronear.org/npm/tic.action#20190714_release_passtoken",
 | 
			
		||||
    "tic-crypto": "git+https://git.faronear.org/npm/tic-crypto#20190109_preview",
 | 
			
		||||
    "uuid": "^8.3.1"
 | 
			
		||||
    "tic.action": "git+https://git.faronear.org/tic/tic.action",
 | 
			
		||||
    "tic.crypto": "git+https://git.faronear.org/tic/tic.crypto",
 | 
			
		||||
    "uuid": "^3.3.2"
 | 
			
		||||
  },
 | 
			
		||||
  "deprecated": false,
 | 
			
		||||
  "description": "blockchain tool for ticwallet",
 | 
			
		||||
  "keywords": ["tool", "blockchain", "tic"],
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "tool",
 | 
			
		||||
    "blockchain",
 | 
			
		||||
    "tic"
 | 
			
		||||
  ],
 | 
			
		||||
  "main": "index.js"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,68 +0,0 @@
 | 
			
		||||
# https://help.seafile.com/syncing_client/excluding_files/
 | 
			
		||||
# 注释。通配符:* 匹配0到若干个字符,包括代表目录的/。? 匹配1个字符,包括/。
 | 
			
		||||
# seafile-ignore.txt 只能控制在客户端需要忽略哪些文件。你依然可以在 seahub 的 web 界面创建这些被客户端忽略的文件。
 | 
			
		||||
# 在这种情况下,
 | 
			
		||||
# 这些文件会被同步到客户端,但是用户在客户端对这些文件的后续修改会被忽略,不会被同步回服务器。
 | 
			
		||||
# 文件在服务器端的后续更改会被同步到客户端,如果客户端也同时修改了这些文件,系统会生成冲突文件。
 | 
			
		||||
# seafile-ignore.txt 只能忽略还没有被同步的文件。对于已经被同步的文件,如果后来把它添加到 seafile-ignore.txt 中,系统只会忽略后续更改,已经上传的版本不会受影响。
 | 
			
		||||
 | 
			
		||||
### seafile-ignore.global.txt ###
 | 
			
		||||
 | 
			
		||||
# 自定义的后缀名,凡有 sfignore 后缀的都不进行同步
 | 
			
		||||
*.sfignore
 | 
			
		||||
*.sfignore/
 | 
			
		||||
*.sfignore.*
 | 
			
		||||
*.sfignore.*/
 | 
			
		||||
*.sfomit
 | 
			
		||||
*.sfomit.*
 | 
			
		||||
*.sfomit/
 | 
			
		||||
*.sfomit.*/
 | 
			
		||||
 | 
			
		||||
.DS_Store
 | 
			
		||||
*/.DS_Store
 | 
			
		||||
 | 
			
		||||
.thumbnails
 | 
			
		||||
*/.thumbnails
 | 
			
		||||
 | 
			
		||||
Thumbs.db
 | 
			
		||||
*/Thumbs.db
 | 
			
		||||
thumbs.db
 | 
			
		||||
*/thumbs.db
 | 
			
		||||
 | 
			
		||||
_desktop.ini
 | 
			
		||||
*/_desktop.ini
 | 
			
		||||
 | 
			
		||||
._*
 | 
			
		||||
*/._*
 | 
			
		||||
 | 
			
		||||
.$*
 | 
			
		||||
*/.$*
 | 
			
		||||
 | 
			
		||||
~$*
 | 
			
		||||
*/~$*
 | 
			
		||||
 | 
			
		||||
node_modules/
 | 
			
		||||
*/node_modules/
 | 
			
		||||
package-lock.json
 | 
			
		||||
 | 
			
		||||
pages4loader.json5
 | 
			
		||||
 | 
			
		||||
.deploy_git/
 | 
			
		||||
*/.deploy_git/
 | 
			
		||||
 | 
			
		||||
# HBuilder 目录
 | 
			
		||||
unpackage/
 | 
			
		||||
*/unpackage/
 | 
			
		||||
 | 
			
		||||
Icon
 | 
			
		||||
OneDrive/Icon
 | 
			
		||||
 | 
			
		||||
# wrangler project
 | 
			
		||||
 | 
			
		||||
.dev.vars*
 | 
			
		||||
*/.dev.vars*
 | 
			
		||||
.wrangler/
 | 
			
		||||
*/.wrangler/
 | 
			
		||||
 | 
			
		||||
### seafile-ignore.local.txt ###
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										267
									
								
								tic.js
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								tic.js
									
									
									
									
									
								
							@ -1,157 +1,136 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
const axios = require('axios')
 | 
			
		||||
const ticc = require('tic-crypto')
 | 
			
		||||
const ticActionTransfer = require('tic.action').ActionTransfer
 | 
			
		||||
const Ticrypto = require('tic.crypto')
 | 
			
		||||
const ticActTransfer = require('tic.action').ActTransfer
 | 
			
		||||
 | 
			
		||||
const TIC_TXFEE = 10
 | 
			
		||||
const TIC_TXFEE = 10;
 | 
			
		||||
const TIC_NODE = require('./netConfig').TIC_NODE
 | 
			
		||||
 | 
			
		||||
class TIC {
 | 
			
		||||
  constructor (prikey, option = {}) {
 | 
			
		||||
    if (!prikey || !ticc.is_prikey({ prikey })) throw 'ERROR:Invalid Seckey'
 | 
			
		||||
    Object.defineProperties(this, {
 | 
			
		||||
      prikey: {
 | 
			
		||||
        value: prikey,
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false
 | 
			
		||||
      },
 | 
			
		||||
      pubkey: {
 | 
			
		||||
        value: ticc.prikey_to_pubkey({ prikey }),
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false
 | 
			
		||||
      },
 | 
			
		||||
      address: {
 | 
			
		||||
        value: ticc.pubkey_to_address({
 | 
			
		||||
          pubkey: ticc.prikey_to_pubkey(prikey)
 | 
			
		||||
        }),
 | 
			
		||||
        enumerable: true,
 | 
			
		||||
        writable: false
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    Object.assign(this, {
 | 
			
		||||
      _url: option._url || TIC_NODE,
 | 
			
		||||
      _defaultFee: option.fee || TIC_TXFEE //fee cannot be zero
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  get url () {
 | 
			
		||||
    return this._url
 | 
			
		||||
  }
 | 
			
		||||
  set url (newURL) {
 | 
			
		||||
    this._url = newURL
 | 
			
		||||
  }
 | 
			
		||||
  get txfee () {
 | 
			
		||||
    return this._defaultFee
 | 
			
		||||
  }
 | 
			
		||||
  set txfee (fee) {
 | 
			
		||||
    this._defaultFee = fee
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static generateNewAccount () {
 | 
			
		||||
    var secword = ticc.randomize_secword()
 | 
			
		||||
    return Object.assign(new TIC(ticc.secword_to_keypair({ secword }).prikey), {
 | 
			
		||||
      secword: secword
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  static fromMnemonic (secword) {
 | 
			
		||||
    if (!secword || !ticc.is_secword(secword)) throw 'ERROR:Invalid Secword'
 | 
			
		||||
    return new TIC(ticc.secword_to_keypair({ secword }).prikey)
 | 
			
		||||
  }
 | 
			
		||||
  static async getBalance (address) {
 | 
			
		||||
    if (!address) {
 | 
			
		||||
      throw new Error('Address is required')
 | 
			
		||||
    constructor(seckey,option={}){
 | 
			
		||||
        if(!seckey||!Ticrypto.isSeckey(seckey)) throw "ERROR:Invalid Seckey"
 | 
			
		||||
        Object.defineProperties(this, {
 | 
			
		||||
            'seckey' : {
 | 
			
		||||
                value : seckey,
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
            },
 | 
			
		||||
            'pubkey' : {
 | 
			
		||||
                value : Ticrypto.seckey2pubkey(seckey), 
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false,
 | 
			
		||||
            },
 | 
			
		||||
            'address' : {
 | 
			
		||||
                value : Ticrypto.pubkey2address(Ticrypto.seckey2pubkey(seckey)),
 | 
			
		||||
                enumerable : true,
 | 
			
		||||
                writable : false
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        Object.assign(this,{
 | 
			
		||||
            _url : option._url||TIC_NODE,
 | 
			
		||||
            _defaultFee : option.fee||TIC_TXFEE  //fee cannot be zero
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      await axios.post(TIC_NODE + '/Account/getBalance', {
 | 
			
		||||
        Account: {
 | 
			
		||||
          address: address
 | 
			
		||||
    get url(){return this._url}
 | 
			
		||||
    set url(newURL){this._url = newURL}
 | 
			
		||||
    get txfee(){return this._defaultFee}
 | 
			
		||||
    set txfee(fee){this._defaultFee = fee}
 | 
			
		||||
 | 
			
		||||
    static generateNewAccount(){
 | 
			
		||||
        var secword = Ticrypto.randomSecword()
 | 
			
		||||
        return Object.assign(new TIC(Ticrypto.secword2keypair(secword).seckey),{secword:secword})
 | 
			
		||||
    }
 | 
			
		||||
    static fromMnemonic(secword){
 | 
			
		||||
        if(!secword||!Ticrypto.isSecword(secword)) throw "ERROR:Invalid Secword"
 | 
			
		||||
        return new TIC(Ticrypto.secword2keypair(secword).seckey)
 | 
			
		||||
    }
 | 
			
		||||
    static async getBalance(address){
 | 
			
		||||
        if(!address){ throw new Error('Address is required'); }
 | 
			
		||||
        return (await axios.post(TIC_NODE+'/Account/getBalance',{
 | 
			
		||||
            "Account" : {
 | 
			
		||||
                "address":address
 | 
			
		||||
            }
 | 
			
		||||
        })).data
 | 
			
		||||
    }
 | 
			
		||||
    static async getActions(address){
 | 
			
		||||
        if(!address){ throw new Error('Address is required'); }
 | 
			
		||||
        return (await axios.post(TIC_NODE+'/Action/getActionList',{
 | 
			
		||||
            "Action" : {
 | 
			
		||||
                "actorAddress" : address,
 | 
			
		||||
                "toAddress" : address
 | 
			
		||||
            },
 | 
			
		||||
            "config":{
 | 
			
		||||
                "logic":"OR"
 | 
			
		||||
            }
 | 
			
		||||
        })).data 
 | 
			
		||||
    }
 | 
			
		||||
    static encrypt(data, key){
 | 
			
		||||
        if(!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
        return Ticrypto.encrypt(data,key)
 | 
			
		||||
    }
 | 
			
		||||
    static decrypt(data, key){
 | 
			
		||||
        return Ticrypto.decrypt(data, key, {format:"json"})  //return null for wrong key
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static isValidAddress(address){
 | 
			
		||||
        return Ticrypto.isAddress(address)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async sendTransaction(toAddress, amount, option = {gasFee : TIC_TXFEE}){
 | 
			
		||||
        if(!toAddress||!amount){throw new Error("ERROR:RequiredParamsMissing")}  //amount cannot be zero
 | 
			
		||||
        let action = new ticActTransfer({
 | 
			
		||||
            amount: parseInt(amount), 
 | 
			
		||||
            toAddress: toAddress,
 | 
			
		||||
            fee: option.gasFee
 | 
			
		||||
        })
 | 
			
		||||
        //对交易数据签名,packMe 内的参数是交易发起人的keypair
 | 
			
		||||
        action.packMe({
 | 
			
		||||
            seckey: this.seckey,
 | 
			
		||||
            pubkey: this.pubkey,
 | 
			
		||||
            address: this.address
 | 
			
		||||
        })
 | 
			
		||||
        let data = {
 | 
			
		||||
            Action:action
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    ).data
 | 
			
		||||
  }
 | 
			
		||||
  static async getActions (address) {
 | 
			
		||||
    if (!address) {
 | 
			
		||||
      throw new Error('Address is required')
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      await axios.post(TIC_NODE + '/Action/getActionList', {
 | 
			
		||||
        Action: {
 | 
			
		||||
          actorAddress: address,
 | 
			
		||||
          toAddress: address
 | 
			
		||||
        },
 | 
			
		||||
        config: {
 | 
			
		||||
          logic: 'OR'
 | 
			
		||||
        try{
 | 
			
		||||
 | 
			
		||||
            let res = (await axios.post(this._url + '/Action/prepare',data)).data
 | 
			
		||||
            return res
 | 
			
		||||
        }catch(err){
 | 
			
		||||
            return null
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    ).data
 | 
			
		||||
  }
 | 
			
		||||
  static encrypt (data, key) {
 | 
			
		||||
    if (!data || !key) throw new Error('Required Params Missing')
 | 
			
		||||
    return ticc.encrypt_easy({ data, key })
 | 
			
		||||
  }
 | 
			
		||||
  static decrypt (data, key) {
 | 
			
		||||
    return ticc.decrypt_easy(data, key, { format: 'json' }) //return null for wrong key
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static isValidAddress (address) {
 | 
			
		||||
    return ticc.which_chain_address({ address })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async sendTransaction (toAddress, amount, option = { gasFee: TIC_TXFEE }) {
 | 
			
		||||
    if (!toAddress || !amount) {
 | 
			
		||||
      throw new Error('ERROR:RequiredParamsMissing')
 | 
			
		||||
    } //amount cannot be zero
 | 
			
		||||
    let action = new ticActionTransfer({
 | 
			
		||||
      amount: parseInt(amount),
 | 
			
		||||
      toAddress: toAddress,
 | 
			
		||||
      fee: option.gasFee
 | 
			
		||||
    })
 | 
			
		||||
    //对交易数据签名,packMe 内的参数是交易发起人的keypair
 | 
			
		||||
    action.packMe({
 | 
			
		||||
      prikey: this.prikey,
 | 
			
		||||
      pubkey: this.pubkey
 | 
			
		||||
    })
 | 
			
		||||
    let data = {
 | 
			
		||||
      Action: action
 | 
			
		||||
    }  
 | 
			
		||||
    async getBalance(){
 | 
			
		||||
        return TIC.getBalance(this.address)
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      let res = (await axios.post(this._url + '/Action/prepare', data)).data
 | 
			
		||||
      return res
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return null
 | 
			
		||||
    async getActions(){
 | 
			
		||||
        return TIC.getActions(this.address)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  async getBalance () {
 | 
			
		||||
    return TIC.getBalance(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  async getActions () {
 | 
			
		||||
    return TIC.getActions(this.address)
 | 
			
		||||
  }
 | 
			
		||||
  getSerializedTx (option) {
 | 
			
		||||
    if (!option.toAddress || !option.amount) {
 | 
			
		||||
      throw new Error('ERROR:RequiredParamsMissing')
 | 
			
		||||
    getSerializedTx(option){
 | 
			
		||||
        if(!option.toAddress||!option.amount){throw new Error("ERROR:RequiredParamsMissing")}
 | 
			
		||||
        let action=new ticActTransfer({
 | 
			
		||||
            amount: parseInt(option.amount), 
 | 
			
		||||
            toAddress: option.toAddress,
 | 
			
		||||
            fee:option.fee||this._defaultFee
 | 
			
		||||
        })
 | 
			
		||||
        //sign for txBody use function packMe, which needs actor's keypair as parameter
 | 
			
		||||
        action.packMe({
 | 
			
		||||
        seckey: this.seckey,
 | 
			
		||||
        pubkey: this.pubkey,
 | 
			
		||||
        address: this.address
 | 
			
		||||
        })
 | 
			
		||||
        return action
 | 
			
		||||
    }
 | 
			
		||||
    let action = new ticActionTransfer({
 | 
			
		||||
      amount: parseInt(option.amount),
 | 
			
		||||
      toAddress: option.toAddress,
 | 
			
		||||
      fee: option.fee || this._defaultFee
 | 
			
		||||
    })
 | 
			
		||||
    //sign for txBody use function packMe, which needs actor's keypair as parameter
 | 
			
		||||
    action.packMe({
 | 
			
		||||
      prikey: this.prikey,
 | 
			
		||||
      pubkey: this.pubkey
 | 
			
		||||
    })
 | 
			
		||||
    return action
 | 
			
		||||
  }
 | 
			
		||||
  //default key for sign&encrypt is account's prikey,other keys are optional.
 | 
			
		||||
  sign (message, key = this.prikey) {
 | 
			
		||||
    return ticc.sign_easy({ data: message, prikey: key })
 | 
			
		||||
  }
 | 
			
		||||
  verify (message, signature) {
 | 
			
		||||
    return ticc.sign_easy({ data: message, signature, prikey: this.prikey })
 | 
			
		||||
  }
 | 
			
		||||
  encrypt (key) {
 | 
			
		||||
    return TIC.encrypt(this, key)
 | 
			
		||||
  }
 | 
			
		||||
    //default key for sign&encrypt is account's seckey,other keys are optional.
 | 
			
		||||
    sign(message,key = this.seckey){
 | 
			
		||||
        return Ticrypto.sign(message,key)
 | 
			
		||||
    }
 | 
			
		||||
    verify(message,signature){
 | 
			
		||||
        return Ticrypto.sign(message,signature,this.seckey)
 | 
			
		||||
    }
 | 
			
		||||
    encrypt(key){
 | 
			
		||||
        return TIC.encrypt(this, key)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { TIC }
 | 
			
		||||
module.exports = {TIC}
 | 
			
		||||
 | 
			
		||||
@ -1,111 +1,97 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var bigNumberify = require('./bignumber').bigNumberify
 | 
			
		||||
var convert = require('./convert')
 | 
			
		||||
var getAddress = require('./address').getAddress
 | 
			
		||||
var utf8 = require('./utf8')
 | 
			
		||||
var bigNumberify = require('./bignumber').bigNumberify;
 | 
			
		||||
var convert = require('./convert');
 | 
			
		||||
var getAddress = require('./address').getAddress;
 | 
			
		||||
var utf8 = require('./utf8');
 | 
			
		||||
 | 
			
		||||
var hashKeccak256 = require('./keccak256')
 | 
			
		||||
var hashSha256 = require('./sha2').sha256
 | 
			
		||||
var hashKeccak256 = require('./keccak256');
 | 
			
		||||
var hashSha256 = require('./sha2').sha256;
 | 
			
		||||
 | 
			
		||||
var regexBytes = new RegExp('^bytes([0-9]+)$')
 | 
			
		||||
var regexNumber = new RegExp('^(u?int)([0-9]*)$')
 | 
			
		||||
var regexArray = new RegExp('^(.*)\\[([0-9]*)\\]$')
 | 
			
		||||
var regexBytes = new RegExp("^bytes([0-9]+)$");
 | 
			
		||||
var regexNumber = new RegExp("^(u?int)([0-9]*)$");
 | 
			
		||||
var regexArray = new RegExp("^(.*)\\[([0-9]*)\\]$");
 | 
			
		||||
 | 
			
		||||
var Zeros = '0000000000000000000000000000000000000000000000000000000000000000'
 | 
			
		||||
var Zeros = '0000000000000000000000000000000000000000000000000000000000000000';
 | 
			
		||||
 | 
			
		||||
function _pack (type, value, isArray) {
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case 'address':
 | 
			
		||||
      if (isArray) {
 | 
			
		||||
        return convert.padZeros(value, 32)
 | 
			
		||||
      }
 | 
			
		||||
      return convert.arrayify(value)
 | 
			
		||||
    case 'string':
 | 
			
		||||
      return utf8.toUtf8Bytes(value)
 | 
			
		||||
    case 'bytes':
 | 
			
		||||
      return convert.arrayify(value)
 | 
			
		||||
    case 'bool':
 | 
			
		||||
      value = value ? '0x01' : '0x00'
 | 
			
		||||
      if (isArray) {
 | 
			
		||||
        return convert.padZeros(value, 32)
 | 
			
		||||
      }
 | 
			
		||||
      return convert.arrayify(value)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var match = type.match(regexNumber)
 | 
			
		||||
  if (match) {
 | 
			
		||||
    var signed = match[1] === 'int'
 | 
			
		||||
    var size = parseInt(match[2] || '256')
 | 
			
		||||
    if (size % 8 != 0 || size === 0 || size > 256) {
 | 
			
		||||
      throw new Error('invalid number type - ' + type)
 | 
			
		||||
function _pack(type, value, isArray) {
 | 
			
		||||
    switch(type) {
 | 
			
		||||
        case 'address':
 | 
			
		||||
            if (isArray) { return convert.padZeros(value, 32); }
 | 
			
		||||
            return convert.arrayify(value);
 | 
			
		||||
        case 'string':
 | 
			
		||||
            return utf8.toUtf8Bytes(value);
 | 
			
		||||
        case 'bytes':
 | 
			
		||||
            return convert.arrayify(value);
 | 
			
		||||
        case 'bool':
 | 
			
		||||
            value = (value ? '0x01': '0x00');
 | 
			
		||||
            if (isArray) { return convert.padZeros(value, 32); }
 | 
			
		||||
            return convert.arrayify(value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isArray) {
 | 
			
		||||
      size = 256
 | 
			
		||||
    var match =  type.match(regexNumber);
 | 
			
		||||
    if (match) {
 | 
			
		||||
        var signed = (match[1] === 'int')
 | 
			
		||||
        var size = parseInt(match[2] || "256")
 | 
			
		||||
        if ((size % 8 != 0) || size === 0 || size > 256) {
 | 
			
		||||
            throw new Error('invalid number type - ' + type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isArray) { size = 256; }
 | 
			
		||||
 | 
			
		||||
        value = bigNumberify(value).toTwos(size);
 | 
			
		||||
 | 
			
		||||
        return convert.padZeros(value, size / 8);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    value = bigNumberify(value).toTwos(size)
 | 
			
		||||
 | 
			
		||||
    return convert.padZeros(value, size / 8)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  match = type.match(regexBytes)
 | 
			
		||||
  if (match) {
 | 
			
		||||
    var size = match[1]
 | 
			
		||||
    if (size != parseInt(size) || size === 0 || size > 32) {
 | 
			
		||||
      throw new Error('invalid number type - ' + type)
 | 
			
		||||
    match = type.match(regexBytes);
 | 
			
		||||
    if (match) {
 | 
			
		||||
        var size = match[1];
 | 
			
		||||
        if (size != parseInt(size) || size === 0 || size > 32) {
 | 
			
		||||
            throw new Error('invalid number type - ' + type);
 | 
			
		||||
        }
 | 
			
		||||
        size = parseInt(size);
 | 
			
		||||
        if (convert.arrayify(value).byteLength !== size) { throw new Error('invalid value for ' + type); }
 | 
			
		||||
        if (isArray) { return (value + Zeros).substring(0, 66); }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
    size = parseInt(size)
 | 
			
		||||
    if (convert.arrayify(value).byteLength !== size) {
 | 
			
		||||
      throw new Error('invalid value for ' + type)
 | 
			
		||||
    }
 | 
			
		||||
    if (isArray) {
 | 
			
		||||
      return (value + Zeros).substring(0, 66)
 | 
			
		||||
    }
 | 
			
		||||
    return value
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  match = type.match(regexArray)
 | 
			
		||||
  if (match) {
 | 
			
		||||
    var valueType = match[1]
 | 
			
		||||
    var count = parseInt(match[2] || value.length)
 | 
			
		||||
    if (count != value.length) {
 | 
			
		||||
      throw new Error('invalid value for ' + type)
 | 
			
		||||
    match = type.match(regexArray);
 | 
			
		||||
    if (match) {
 | 
			
		||||
        var baseType = match[1];
 | 
			
		||||
        var count = parseInt(match[2] || value.length);
 | 
			
		||||
        if (count != value.length) { throw new Error('invalid value for ' + type); }
 | 
			
		||||
        var result = [];
 | 
			
		||||
        value.forEach(function(value) {
 | 
			
		||||
            value = _pack(baseType, value, true);
 | 
			
		||||
            result.push(value);
 | 
			
		||||
        });
 | 
			
		||||
        return convert.concat(result);
 | 
			
		||||
    }
 | 
			
		||||
    var result = []
 | 
			
		||||
    value.forEach(function (value) {
 | 
			
		||||
      value = _pack(valueType, value, true)
 | 
			
		||||
      result.push(value)
 | 
			
		||||
    })
 | 
			
		||||
    return convert.concat(result)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  throw new Error('unknown type - ' + type)
 | 
			
		||||
    throw new Error('unknown type - ' + type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function pack (types, values) {
 | 
			
		||||
  if (types.length != values.length) {
 | 
			
		||||
    throw new Error('type/value count mismatch')
 | 
			
		||||
  }
 | 
			
		||||
  var tight = []
 | 
			
		||||
  types.forEach(function (type, index) {
 | 
			
		||||
    tight.push(_pack(type, values[index]))
 | 
			
		||||
  })
 | 
			
		||||
  return convert.hexlify(convert.concat(tight))
 | 
			
		||||
function pack(types, values) {
 | 
			
		||||
    if (types.length != values.length) { throw new Error('type/value count mismatch'); }
 | 
			
		||||
    var tight = [];
 | 
			
		||||
    types.forEach(function(type, index) {
 | 
			
		||||
        tight.push(_pack(type, values[index]));
 | 
			
		||||
    });
 | 
			
		||||
    return convert.hexlify(convert.concat(tight));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function keccak256 (types, values) {
 | 
			
		||||
  return hashKeccak256(pack(types, values))
 | 
			
		||||
function keccak256(types, values) {
 | 
			
		||||
    return hashKeccak256(pack(types, values));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function sha256 (types, values) {
 | 
			
		||||
  return hashSha256(pack(types, values))
 | 
			
		||||
function sha256(types, values) {
 | 
			
		||||
    return hashSha256(pack(types, values));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  pack: pack,
 | 
			
		||||
    pack: pack,
 | 
			
		||||
 | 
			
		||||
  keccak256: keccak256,
 | 
			
		||||
  sha256: sha256
 | 
			
		||||
    keccak256: keccak256,
 | 
			
		||||
    sha256: sha256,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user