@raiden_network/raiden-cli
Version:
Raiden Light Client standalone app with a REST API via HTTP
303 lines (302 loc) • 11.5 kB
JavaScript
;
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;