"use strict";
/**
 * @file Utility
 * @desc These methods are helpers for the Sumer class.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSignature = exports.camelCase = exports.getNetNameWithChainId = exports.getAbi = exports.getUnderlyDecimals = exports.getName = exports.getAddress = exports.request = void 0;
const constants_1 = require("./constants");
const abi_1 = require("./abi");
const ethers_1 = require("ethers");
/* eslint-disable */
let _request;
let http;
let https;
function _nodeJsRequest(options) {
    return new Promise((resolve, reject) => {
        let url = options.url || options.hostname;
        // Use 'https' if the protocol is not specified in 'options.hostname'
        if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) {
            url = 'https://' + url;
        }
        // Choose the right module based on the protocol in 'options.hostname'
        const httpOrHttps = url.indexOf('http://') === 0 ? http : https;
        // Remove the 'http://' so the native node.js module will understand
        options.hostname = url.split('://')[1];
        let body = '';
        const req = httpOrHttps.request(options, (res) => {
            res.on('data', (bodyBuffer) => {
                body += bodyBuffer.toString();
            });
            res.on('end', () => {
                resolve({
                    status: res.statusCode,
                    statusText: res.statusMessage,
                    body,
                });
            });
        });
        req.on('timeout', () => {
            req.abort();
            return reject({
                status: 408,
                statusText: 'Client HTTP request timeout limit reached.',
            });
        });
        req.on('error', (err) => {
            if (req.aborted)
                return;
            if (err !== null && err.toString() === '[object Object]') {
                console.error(JSON.stringify(err));
            }
            else {
                console.error(err);
            }
            return reject();
        });
        if (options.body) {
            req.write(JSON.stringify(options.body));
        }
        req.end();
    });
}
function _webBrowserRequest(options) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        let contentTypeIsSet = false;
        options = options || {};
        const method = options.method || 'GET';
        let url = options.url || options.hostname;
        url += typeof options.path === 'string' ? options.path : '';
        if (typeof url !== 'string') {
            return reject('HTTP Request: Invalid URL.');
        }
        // Use 'https' if the protocol is not specified in 'options.hostname'
        if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) {
            url = 'https://' + url;
        }
        xhr.open(method, url);
        for (const header in options.headers) {
            if ({}.hasOwnProperty.call(options.headers, header)) {
                const lcHeader = header.toLowerCase();
                contentTypeIsSet = lcHeader === 'content-type' ? true : contentTypeIsSet;
                xhr.setRequestHeader(header, options.headers[header]);
            }
        }
        if (!contentTypeIsSet) {
            xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        }
        xhr.onload = function () {
            let body;
            if (xhr.status >= 100 && xhr.status < 400) {
                try {
                    JSON.parse(xhr.response);
                    body = xhr.response;
                }
                catch (e) {
                    body = xhr.statusText;
                }
                return resolve({
                    status: xhr.status,
                    statusText: xhr.statusText,
                    body,
                });
            }
            else {
                return reject({
                    status: xhr.status,
                    statusText: xhr.statusText,
                });
            }
        };
        if (method !== 'GET') {
            xhr.send(JSON.stringify(options.body));
        }
        else {
            xhr.send();
        }
    });
}
try {
    window;
    _request = _webBrowserRequest;
}
catch (e) {
    http = require('http');
    https = require('https');
    _request = _nodeJsRequest;
}
/**
 * A generic HTTP request method that works in Node.js and the Web Browser.
 *
 * @param {object} options HTTP request options. See Node.js http.request
 *     documentation for details.
 *
 * @hidden
 *
 * @returns {Promise<object>} Returns a promise and eventually an HTTP response
 *     (JavaScript object).
 */
function request(options) {
    return _request.apply(null, [options]);
}
exports.request = request;
/* eslint-enable */
/**
 * Gets the contract address of the named contract. This method supports
 *     contracts used by the Sumer Protocol.
 *
 * @param {string} contract The name of the contract.
 * @param {string} [network] Optional name of the Ethereum network. Main net and
 *     all the popular public test nets are supported.
 *
 * @returns {string} Returns the address of the contract.
 *
 * @example
 * ```
 * console.log('cETH Address: ', Sumer.util.getAddress(Sumer.cETH));
 * ```
 */
function getAddress(contract, network = 'mainnet') {
    return (0, constants_1.getAddress)(network, contract);
}
exports.getAddress = getAddress;
function getName(tokenAddr, network = 'mainnet') {
    return (0, constants_1.getName)(network, tokenAddr);
}
exports.getName = getName;
function getUnderlyDecimals(tokenAddr, network = 'mainnet') {
    return (0, constants_1.getDecimalsOfUnderly)(network, tokenAddr);
}
exports.getUnderlyDecimals = getUnderlyDecimals;
/**
 * Gets a contract ABI as a JavaScript array. This method supports
 *     contracts used by the Sumer Protocol.
 *
 * @param {string} contract The name of the contract.
 *
 * @returns {Array} Returns the ABI of the contract as a JavaScript array.
 *
 * @example
 * ```
 * console.log('cETH ABI: ', Sumer.util.getAbi('cEther'));
 * ```
 */
function getAbi(contract) {
    return abi_1.abi[contract];
}
exports.getAbi = getAbi;
/**
 * Gets the name of an Ethereum network based on its chain ID.
 *
 * @param {string} chainId The chain ID of the network.
 *
 * @returns {string} Returns the name of the Ethereum network.
 *
 * @example
 * ```
 * console.log('Ropsten : ', Sumer.util.getNetNameWithChainId(3));
 * ```
 */
function getNetNameWithChainId(chainId) {
    const networks = {
        1: 'mainnet',
        3: 'ropsten',
        4: 'rinkeby',
        5: 'goerli',
        42: 'kovan',
    };
    return networks[chainId];
}
exports.getNetNameWithChainId = getNetNameWithChainId;
function camelCase(name) {
    return name[0].toUpperCase() + name.substring(1);
}
exports.camelCase = camelCase;
const getSignature = async ({ signer, tokenSymbol, chainId, verifyingContract, spender, value }) => {
    const tokenContract = new ethers_1.Contract(verifyingContract, abi_1.abi.ERC20MinterBurnerPauserPermit, signer);
    const account = await signer.getAddress();
    const nonce = await tokenContract.nonces(account);
    let name = 'PermitToken';
    let version = '1.0';
    if (tokenSymbol === 'MTRG') {
        name = 'MeterGov';
        version = 'v1.0';
    }
    console.log(`get signature with name ${name} and version ${version}`);
    const deadline = Math.floor(Date.now() / 1000) + 100;
    let signature = await signer.signTypedData({ name, version, chainId, verifyingContract }, {
        Permit: [
            { name: 'owner', type: 'address' },
            { name: 'spender', type: 'address' },
            { name: 'value', type: 'uint256' },
            { name: 'nonce', type: 'uint256' },
            { name: 'deadline', type: 'uint256' },
        ],
    }, { owner: account, spender: spender, value: value, nonce: nonce, deadline: deadline });
    if (signature.endsWith('00') || signature.endsWith('01')) {
        const { r, s, v } = ethers_1.ethers.Signature.from(signature);
        signature = ethers_1.ethers.Signature.from({ r, s, v }).serialized;
    }
    return { signature, deadline };
};
exports.getSignature = getSignature;
//# sourceMappingURL=util.js.map