UNPKG

@raiden_network/raiden-cli

Version:

Raiden Light Client standalone app with a REST API via HTTP

303 lines (302 loc) 11.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRaidenConfig = exports.parseArguments = void 0; const ethers_1 = require("ethers"); const fs_1 = require("fs"); const inquirer_1 = __importDefault(require("inquirer")); const yargs_1 = __importDefault(require("yargs/yargs")); const raiden_ts_1 = require("raiden-ts"); const config_json_1 = __importDefault(require("./config.json")); const disclaimer_json_1 = __importDefault(require("./disclaimer.json")); async function checkDisclaimer(accepted) { console.info(disclaimer_json_1.default); if (accepted === undefined) { ({ accepted } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'accepted', message: 'I have read, understood and hereby agree to the above Terms of Use, Privacy Policy including the Disclaimer and Privacy Warning', default: false, }, ])); } else if (accepted) { console.info('Disclaimer accepted by command line parameter.'); } (0, raiden_ts_1.assert)(accepted, 'Disclaimer not accepted!'); } function parseFeeOption(args) { const parsedOption = {}; if (!args?.length) return parsedOption; (0, raiden_ts_1.assert)(args.length % 2 === 0, 'fees must have the format [address, number]'); for (let i = 0; i < args.length; i += 2) { (0, raiden_ts_1.assert)(raiden_ts_1.Address.is(args[i]), `Invalid address: ${i} = ${args[i]}`); (0, raiden_ts_1.assert)(args[i + 1].match(/^\d+$/), 'Invalid numeric value'); parsedOption[args[i]] = args[i + 1]; } return parsedOption; } function constructMediationFeeConfiguration(mediationFeeConfiguration = {}, { capMediationFees, flatFee = {}, proportionalFee = {}, proportionalImbalanceFee = {}, }) { for (const [address, value] of Object.entries(flatFee)) { mediationFeeConfiguration = { ...mediationFeeConfiguration, [address]: { ...mediationFeeConfiguration[address], flat: value }, }; } for (const [address, value] of Object.entries(proportionalFee)) { mediationFeeConfiguration = { ...mediationFeeConfiguration, [address]: { ...mediationFeeConfiguration[address], proportional: value }, }; } for (const [address, value] of Object.entries(proportionalImbalanceFee)) { mediationFeeConfiguration = { ...mediationFeeConfiguration, [address]: { ...mediationFeeConfiguration[address], imbalance: value }, }; } for (const [address, configurationOfToken] of Object.entries(mediationFeeConfiguration)) { mediationFeeConfiguration[address] = { ...mediationFeeConfiguration[ethers_1.ethers.constants.AddressZero], ...configurationOfToken, cap: capMediationFees, }; } return mediationFeeConfiguration; } function parseEndpoint(url) { const match = url.match(/^(?:\w+:\/\/)?([^\/]*):(\d+)$/); (0, raiden_ts_1.assert)(match, 'Invalid endpoint'); const [, host, port] = match; return [host || '127.0.0.1', +port]; } const yargsOptions = { datadir: { type: 'string', default: './storage', desc: 'Dir path where to store state', }, loadState: { type: 'string', desc: 'Path to JSON file to upload/rehydrate state from', normalize: true, }, configFile: { type: 'string', desc: 'JSON file path containing config object', normalize: true, }, keystorePath: { type: 'string', default: './', desc: 'Path for ethereum keystore directory', normalize: true, }, address: { type: 'string', desc: 'Address of private key to use', check: raiden_ts_1.Address.is, }, passwordFile: { type: 'string', desc: 'Path for text file containing password for keystore file', normalize: true, }, userDepositContractAddress: { type: 'string', desc: "Address of UserDeposit contract to use as contract's entrypoint; optionally, append ':<block>' to start scanning since this block", }, acceptDisclaimer: { type: 'boolean', desc: 'By setting this parameter you confirm that you have read, understood and accepted the disclaimer, privacy warning and terms of use.', }, blockchainQueryInterval: { type: 'number', default: raiden_ts_1.DEFAULT_POLLING_INTERVAL, desc: 'Time interval after which to check for new blocks (in seconds)', }, defaultRevealTimeout: { type: 'number', default: raiden_ts_1.DEFAULT_REVEAL_TIMEOUT, desc: 'Default transfer reveal timeout, in seconds', }, ethRpcEndpoint: { type: 'string', default: 'http://127.0.0.1:8545', desc: 'Ethereum JSON RPC node endpoint to use for blockchain interaction', }, logFile: { type: 'string', desc: 'Output all logs to this file instead of stdout/stderr', normalize: true, }, matrixServer: { type: 'string', default: 'auto', desc: 'URL of Matrix Transport server', }, rpc: { type: 'boolean', default: true, desc: 'Start with or without the RPC server', }, rpccorsdomain: { type: 'string', default: 'http://localhost:*/*', desc: 'Comma separated list of domains to accept cross origin requests.', }, apiAddress: { type: 'string', default: '127.0.0.1:5001', desc: 'host:port to bind to and listen for API requests', coerce: parseEndpoint, }, routingMode: { choices: ['pfs', 'local', 'private'], default: 'pfs', desc: 'Anything else than "pfs" disables mediated transfers', }, pathfindingServiceAddress: { type: 'array', desc: 'Force given PFS URL list to be used, automatically chosing the first responding provider for transfers, instead of auto-selecting valid from "ServiceRegistry" contract', }, pathfindingMaxPaths: { type: 'number', default: raiden_ts_1.DEFAULT_PFS_MAX_PATHS, desc: 'Set maximum number of paths to be requested from the path finding service.', }, pathfindingMaxFee: { type: 'string', default: '50000000000000000', desc: 'Set max fee per request paid to the path finding service.', coerce: (value) => (0, raiden_ts_1.decode)((0, raiden_ts_1.UInt)(32), value), }, pathfindingIouTimeout: { type: 'number', default: raiden_ts_1.DEFAULT_PFS_IOU_TIMEOUT, desc: 'Number of seconds before a new IOU to the PFS expires.', }, enableMonitoring: { type: 'boolean', default: false, desc: "Enables monitoring if there's a UDC deposit", }, flatFee: { // this ensures addresses are not converted to numbers while preserving parseFeeOption return type string: true, nargs: 2, desc: 'Sets the flat fee required for every mediation in wei of the mediated token for a certain token address: [address value] pair', coerce: parseFeeOption, }, proportionalFee: { string: true, nargs: 2, desc: 'Sets the proportional fee required for every mediation, in micros (parts per million, 1% = 10000) of the mediated token for a certain token address: [address value] pair', coerce: parseFeeOption, }, proportionalImbalanceFee: { string: true, nargs: 2, desc: 'Sets the proportional imbalance fee penalty required for every mediation, in micros (parts per million, 1% = 10000) of the mediated token for a certain token address: [address value] pair', coerce: parseFeeOption, }, capMediationFees: { type: 'boolean', default: true, desc: 'Enables capping mediation fees to not allow them to be negative (output transfers amount always less than or equal input transfers)', }, gasPrice: { string: true, desc: "Set gasPrice factor for transactions's priority fees, as a multiplier of default `maxPriorityFeePerGas` (2.5 Gwei) or RPC gasPrice; some aliases: normal|rpc=1.0, medium=1.05, fast=1.2, faster|rapid=1.5", coerce(val) { if (!val) return; if (Array.isArray(val)) val = val[val.length - 1]; let value; switch (val) { case 'normal': case 'rpc': return 1.0; case 'medium': return 1.05; case 'fast': return 1.2; case 'faster': case 'rapid': return 1.5; default: value = +val; (0, raiden_ts_1.assert)(value && value > 0, `invalid gasPrice: ${val}`); return value; } }, }, webUi: { type: 'boolean', default: false, desc: 'Serves Raiden webUI in /ui path', }, }; /** * Parse Raiden CLI parameters * * @returns Parsed options */ async function parseArguments() { const argv = (0, yargs_1.default)(process.argv.slice(2)); const result = await argv .env('RAIDEN') .usage('Usage: $0 [options]') .options(yargsOptions) .help() .alias('h', 'help') .version() .alias('V', 'version').argv; await checkDisclaimer(result.acceptDisclaimer); return result; } exports.parseArguments = parseArguments; /** * Create a (partial) Raiden config object from parsed CLI arguments * * @param argv - Parsed arguments * @returns Partial Raiden config */ async function createRaidenConfig(argv) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let config = config_json_1.default; if (argv.configFile) config = { ...config, ...JSON.parse(await fs_1.promises.readFile(argv.configFile, 'utf-8')) }; config = { ...config, pollingInterval: Math.floor(argv.blockchainQueryInterval * 1000), revealTimeout: argv.defaultRevealTimeout, pfsMaxPaths: argv.pathfindingMaxPaths, pfsMaxFee: argv.pathfindingMaxFee, pfsIouTimeout: argv.pathfindingIouTimeout, ...(argv.gasPrice ? { gasPriceFactor: argv.gasPrice } : undefined), }; if (argv.matrixServer !== 'auto') config = { ...config, matrixServer: argv.matrixServer }; if (argv.routingMode !== 'pfs') config = { ...config, pfsMode: raiden_ts_1.PfsMode.disabled }; else if (!argv.pathfindingServiceAddress) config = { ...config, pfsMode: raiden_ts_1.PfsMode.auto }; else config = { ...config, pfsMode: raiden_ts_1.PfsMode.onlyAdditional, additionalServices: argv.pathfindingServiceAddress, }; if (!argv.enableMonitoring) config = { ...config, monitoringReward: null }; const mediationFees = constructMediationFeeConfiguration(config.mediationFees, argv); config = { ...config, mediationFees }; return config; } exports.createRaidenConfig = createRaidenConfig;