UNPKG

xud

Version:
161 lines 6.99 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createSimnetChannels = void 0; const http_1 = __importDefault(require("http")); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const command_1 = require("../cli/command"); const xudrpc_pb_1 = require("../proto/xudrpc_pb"); const processResponse = (resolve, reject) => { return (error, response) => { if (error) { reject(error); } else { resolve(response); } }; }; const getBalance = (client, currency) => __awaiter(void 0, void 0, void 0, function* () { const request = new xudrpc_pb_1.GetBalanceRequest(); if (currency) { request.setCurrency(currency.toUpperCase()); } const balances = yield new Promise((resolve, reject) => { client.getBalance(request, processResponse(resolve, reject)); }); return balances; }); const openConnextChannel = (client, currency, amount) => __awaiter(void 0, void 0, void 0, function* () { const request = new xudrpc_pb_1.OpenChannelRequest(); request.setCurrency(currency.toUpperCase()); request.setAmount(amount); const openChannelResponse = yield new Promise((resolve, reject) => { client.openChannel(request, processResponse(resolve, reject)); }); return openChannelResponse; }); const checkBalanceObservable = (client, currency, minimumBalance, getBalance$) => { return getBalance$.pipe(operators_1.mergeMap((balanceResponse) => { const balancesMap = balanceResponse.getBalancesMap(); const currencyBalance = balancesMap.get(currency); const balances = { walletBalance: currencyBalance.getWalletBalance(), channelBalance: currencyBalance.getChannelBalance(), }; if (balances.walletBalance < minimumBalance) { // the balance is under our specified threshold // we'll hit the faucet with our connext address // and then recheck the balance return getConnextAddressObservable(client).pipe(operators_1.mergeMap((connextAddress) => { return rxjs_1.from(faucetRequest(connextAddress)).pipe( // we wait 31 seconds (~2 blocks) before checking the balance again operators_1.delay(31000), operators_1.mergeMap(() => checkBalanceObservable(client, currency, minimumBalance, getBalance$))); })); } else { return rxjs_1.of(balances); } })); }; const getInfo = (client) => __awaiter(void 0, void 0, void 0, function* () { const request = new xudrpc_pb_1.GetInfoRequest(); const info = yield new Promise((resolve, reject) => { client.getInfo(request, processResponse(resolve, reject)); }); return info; }); const getConnextAddressObservable = (client) => { return rxjs_1.from(getInfo(client)).pipe(operators_1.mergeMap((info) => { const connext = info.getConnext(); if (connext && connext.getAddress()) { return rxjs_1.of(connext.getAddress()); } return rxjs_1.throwError('connext address not found'); }), operators_1.catchError((_error, caught) => { return caught.pipe(operators_1.delay(5000)); })); }; const faucetRequest = (connextAddress) => { return new Promise((resolve, reject) => { const options = { method: 'POST', hostname: 'xud1.simnet.exchangeunion.com', port: 9000, path: '/faucet', }; const payload = { address: connextAddress, }; const payloadStr = JSON.stringify(payload); options.headers = { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payloadStr), }; const req = http_1.default.request(options, (res) => { switch (res.statusCode) { case 200: resolve(res); break; default: reject('faucet request failed'); break; } }); req.on('error', reject); if (payloadStr) { req.write(payloadStr); } req.end(); }); }; const createSimnetChannel = ({ client, currency, minChannelAmount, channelAmount, retryInterval, getBalance$, }) => { const balances$ = checkBalanceObservable(client, currency, channelAmount, getBalance$); const simnetChannel$ = balances$.pipe(operators_1.mergeMap((balances) => { if (balances.channelBalance >= minChannelAmount) { // in case we already have enough channelBalance we won't attempt // to open a channel return rxjs_1.empty(); } else { return rxjs_1.from(openConnextChannel(client, currency, channelAmount)).pipe(operators_1.mapTo(currency)); } }), // when error happens operators_1.retryWhen(errors => errors.pipe( // we wait for retryInterval and attempt again operators_1.delay(retryInterval), // for a maximum of 10 times operators_1.take(10), // until we give up completely operators_1.concat(rxjs_1.throwError('unrecoverable error happened - giving up')))), // complete the observable when the flow is successful operators_1.take(1)); return simnetChannel$; }; const createSimnetChannels = (config) => { const client$ = rxjs_1.defer(() => rxjs_1.from(command_1.loadXudClient({}))).pipe(operators_1.share()); return client$.pipe(operators_1.mergeMap((client) => { const getBalance$ = rxjs_1.defer(() => rxjs_1.from(getBalance(client))).pipe(operators_1.share()); return rxjs_1.from( // we map our channels config into observables config.channels.map(channelConfig => createSimnetChannel(Object.assign(Object.assign({}, channelConfig), { client, getBalance$, retryInterval: config.retryInterval })))).pipe( // execute them in order operators_1.concatAll()); })); }; exports.createSimnetChannels = createSimnetChannels; //# sourceMappingURL=simnet-connext-channels.js.map