Source: wallet/index.js

/**
 * STAYGE wallet module for javascript
 * @module stayge-wallet
*/

'use strict'

const fs = require('fs')
const AdmZip = require('adm-zip');
const IconWallet = require('../icon-js/wallet.js');
const utils = require('../icon-js/utils.js');
const STG = require('./stg.js')
const ACT = require('./act.js')
const Donation = require('./donation.js')
const TodaysIdol = require('./todaysidol.js')
const WOK = require('./wok.js')


 /**
  * Class representing a STAYGE Wallet
  */
class Wallet {

    /**
     * Factory method to create a new wallet with a newly generated private key
     * @return {Wallet}
     */
    static create() {
        return new Wallet(IconWallet.create());
    }


    /**
     * Factory method to create a wallet from the specified private key
     * @param  {String} privateKeyString
     * @return {Wallet}
     */
    static fromPrivateKey(privateKeyString) {
        return new Wallet(IconWallet.fromPrivateKey(privateKeyString));
    }


    /**
     * Factory method to create a wallet from the keystore object
     * @param  {Object|String} keyStoreObj
     * @param  {String} password
     * @return {Wallet}
     */
    static fromKeyStoreObj(keyStoreObj, password) {
        return new Wallet(IconWallet.fromKeyStoreObj(keyStoreObj, password));
    }


    /**
     * Factory method to create a wallet from the keystore file
     * @param  {String} keyStorePath
     * @param  {String} password
     * @return {Wallet}
     */
    static fromKeyStoreFile(keyStorePath, password) {
        const content = fs.readFileSync(keyStorePath);
        const keyStoreObj = JSON.parse(content);
        return new Wallet(IconWallet.fromKeyStoreObj(keyStoreObj, password));
    }

    /**
     * Create a Wallet
     * @param {Object} baseWallet underlying wallet object
     */
    constructor(baseWallet) {
        this._baseWallet = baseWallet;
    }


    /**
     * Return STG score object with the specified score address
     * @param  {String} scoreAddress address of score
     * @return {STG} score object of STG
     */
    stg(scoreAddress) {
        return new STG(this, scoreAddress)
    }


    /**
     * Return ACT score object with the specified score address
     * @param  {String} scoreAddress address of score
     * @return {ACT} score object of ACT
     */
    act(scoreAddress) {
        return new ACT(this, scoreAddress)
    }

    /**
     * Return Donation score object with the specified score address
     * @param  {String} scoreAddress address of score
     * @return {Donation} score object of Donation
     */
    donation(scoreAddress) {
        return new Donation(this, scoreAddress)
    }

    /**
     * Return TodaysIdol score object with the specified score address
     * @param  {String} scoreAddress address of score
     * @return {ACT} score object of TodaysIdol
     */
    todaysidol(scoreAddress) {
        return new TodaysIdol(this, scoreAddress)
    }

    /**
     * Return WOK score object with the specified score address
     * @param  {String} scoreAddress address of score
     * @return {WOK} score object of WOK
     */
    wok(scoreAddress) {
        return new WOK(this, scoreAddress)
    }

    /**
     * Get the private key of the wallet
     * @return {Buffer}
     */
    getPrivateKey() {
        return this._baseWallet.getPrivateKey();
    }


    /**
     * Get the private key string of the wallet
     * @return {String}
     */
    getPrivateKeyString() {
        return this._baseWallet.getPrivateKeyString();
    }


    /**
     * Get a public key of the wallet
     * @return {Buffer}
     */
    getPublicKey() {
        return this._baseWallet.getPublicKey();
    }


    /**
     * Get a public key string of the wallet
     * @return {String}
     */
    getPublicKeyString() {
        return this._baseWallet.getPublicKeyString();
    }

    /**
     * Get the wallet address
     * @return {Buffer}
     */
    getAddress() {
        return this._baseWallet.getAddress();
    }


    /**
     * Get the wallet address string
     * @return {String}
     */
    getAddressString() {
        return this._baseWallet.getAddressString();
    }


    /**
     * Convert a wallet to key store object
     * @param  {String} password password for the wallet
     * @return {Object}
     */
    toKeyStoreObj(password) {
        return this._baseWallet.toKeyStoreObj(password);
    }


    /**
     * set endpoint
     * @param {String} name 'mainnet' | 'testnet'
     */
    setEndPoint(name) {
        return this._baseWallet.setEndPoint(name);
    }


    /**
     * get endpoint
     * @return {String} endpoint information
     */
    getEndPoint() {
        return this._baseWallet.getEndPoint();
    }


    /**
     * Get block information by height
     * @param  {Number|String} height height of block
     * @return {Promise<Object>} block information
     */
    async getBlockByHeight(height) {
        return this._baseWallet.getBlockByHeight(height);
    }


    /**
     * Get block information by hash
     * @param  {String} height hash of block
     * @return {Promise<Object>} block information
     */
    async getBlockByHash(hash) {
        return this._baseWallet.getBlockByHash(hash);
    }


    /**
     * Get a last block information
     * @return {Promise<Object>} block information
     */
    async getLastBlock() {
        return this._baseWallet.getLastBlock();
    }


    /**
     * Get balance of the wallet
     * @return {Promise<String>} balance of the wallet owner
     */
    async getBalance() {
        return this._baseWallet.getBalance();
    }


    /**
     * Get total supply of ICX
     * @return {Promise<String>} total supply of underlying network
     */
    async getTotalSupply() {
        return this._baseWallet.getTotalSupply();
    }


    /**
     * Transfer coins
     * @param {String} to address of recipient
     * @param {Number} value value to transfer
     * @return {Promise<String>} hash of transaction
     */
    async transferCoin(to, value) {
        return this._baseWallet.transferICX(to, value);
    }


    /**
     * Transafer a message
     * @param  {String} to address of recipent
     * @param  {String} msg message to transfer
     * @return {Promise<String>} hash of transaction
     */
    async transferMessage(to, msg) {
        return this._baseWallet.transferMessage(
            to,
            msg.length > 0 ? utils.convertToHex(msg) : msg
        );
    }


    /**
     * Send a transaction for calling a smart contract's method
     * @param  {String} contractAddress
     * @param  {String} contractMethod
     * @param  {Object} methodParams
     * @return {Promise<String>} hash of transacgtion
     */
    async callContractTx(
        contractAddress,
        contractMethod,
        methodParams
    ) {
        return this._baseWallet.callScoreTx(contractAddress, contractMethod, methodParams);
    }


    /**
     * Install a smart contract on the underlying blockchain
     * @param  {String} contractPath
     * @param  {Object} installParams
     * @return {Promise<String>} txHash
     */
    async installContract(contractPath, installParams) {
        const zip = new AdmZip(contractPath);
        const contractContent = '0x' + zip.toBuffer().toString('hex');
        return this._baseWallet.installScore(contractContent, installParams);
    }


    /**
     * Update the smart contract on the underlying blockchain
     * @param  {type} contractAddress
     * @param  {type} contractPath
     * @param  {type} updateParams
     * @return {Promise<String>} txHash
     */
    async updateContract(
        contractAddress,
        contractPath,
        updateParams
    ) {
        const zip = new AdmZip(contractPath);
        const contractContent = '0x' + zip.toBuffer().toString('hex');
        return this._baseWallet.updateScore(contractAddress, contractContent, updateParams);
    }


    /**
     * Call a smart contract's external function for querying
     * @param  {String} to
     * @param  {String} method
     * @param  {Object} params
     * @return {Promise<String>}
     */
    async call(to, method, params) {
        return this._baseWallet.call(to, method, params);
    }

    /**
     * Get the smart contract's external API list
     * @param  {String} address
     * @return {Promise<Object>}
     */
    async getContractApi(address) {
        return this._baseWallet.getScoreApi(address);
    }


    /**
     * Get the transaction result requested by transaction hash
     * @param  {String} txHash
     * @param  {Number} timeout seconds to timeout. if not specified, it will be set to the default value of 0
     * @return {Promise<Object>}
     */
    async getTransactionResult(txHash, timeout=0) {
        const SLEEP_UNIT = 500;
        let loopcnt = 0;
        let i = 0;

        timeout = timeout || 0;
        loopcnt = (timeout === 0) ? 1 : (timeout * 1000 / SLEEP_UNIT);

        for (i = 0; i < loopcnt; i++) {
            try {
                const txResult = await this._baseWallet.getTransactionResult(txHash)
                return txResult;
            } catch (err) {
                //console.log(`getTransactionResult = ${err.message}`);

                if (err.message.indexOf('Pending') !== -1 ||
                    err.message.indexOf('Invalid params txHash') !== -1) {
                    await utils.sleep(500);
                } else {
                    throw err;
                }
            }
        }

        throw new Error(`The transaction of ${txHash} is pending`);
    }

    /**
     * Get the transaction information by txHash
     * @param  {String} txHash
     * @return {Promise<Object>}
     */
    async getTransactionByHash(txHash) {
        return this._baseWallet.getTransactionByHash(txHash);
    }


    /**
     * deposit for fee sharing
     * @param  {String} contractAddress
     * @param  {Number} amt
     * @return {Promise<String>} hash of transaction
     */
    async depositFeeSharing(
        contractAddress,
        amt
    ) {
        return this._baseWallet.depositFeeSharing(contractAddress, amt);
    }


    /**
     * withdraw the deposit for fee sharing
     * @param  {String} contractAddress
     * @param  {Number} amt
     * @return {Promise<String>} hash of transaction
     */
    async withdrawFeeSharing(
        contractAddress,
        depositId
    ) {
        return this._baseWallet.withdrawFeeSharing(contractAddress, depositId);
    }


    /**
     * Returns symbol
     * @return {Promise<String>}
     */
    async getScoreStatus(contractAddress) {
        const status = await this.call(
            'cx0000000000000000000000000000000000000001',
            'getScoreStatus',
            {
                address: contractAddress
            }
        );

        return status;
    }

}


/** @type {Wallet} */
module.exports = Wallet;