UNPKG

raiden-ts

Version:

Raiden Light Client Typescript/Javascript SDK

92 lines 3.78 kB
import { defer, merge, of } from 'rxjs'; import { filter, ignoreElements, take } from 'rxjs/operators'; import { messageSend } from '../../messages/actions'; import { isResponseOf } from '../../utils/actions'; import { completeWith, repeatUntil } from '../../utils/rx'; import { Direction } from '../state'; /** * Exponential back-off infinite generator * * @param start - First yielded value * @param max - Ceiling of values, won't increase above this number * @param multiplier - Multiply yielded value by this factor on each iteration * @yields Numbers representing delays in exponential backoff strategy of growth */ export function* exponentialBackoff(start = 1e3, max = 60e3, multiplier = 1.4) { let delay = start; while (true) { yield delay; delay = Math.min(max, Math.ceil(delay * multiplier)); } } /** * Dispatches an actions and waits until a condition is satisfied. * * @param action$ - Observable of actions that will be monitored * @param request - The request/action that will be dispatched * @param predicate - The condition that will that was to be satisfied for the observable to * complete * @returns Observable of the request type. */ export function dispatchAndWait$(action$, request, predicate) { return merge( // wait until respective success/failure action is seen before completing action$.pipe(filter(predicate), take(1), // don't output success/failure action, just wait for first match to complete ignoreElements()), // output once of(request)); } /** * Retry sending a message until some condition is met * * @param send - messageSend.request to be sent * @param action$ - RaidenActions observable * @param notifier - Stops retrying when this notifier emits * @param delayMs - Delay between retries, or Iterator yielding delays * @returns Observable which retry messageSend.request until notifier emits */ export function retrySendUntil$(send, action$, notifier, delayMs = 30e3) { let first = true; return defer(() => { if (first) { first = false; } else if (send.payload.userId) { // from 1st retry on, pop payload.userId, to force re-fetch presence/metadata const { userId: _, ...payload } = send.payload; send = { ...send, payload }; } return dispatchAndWait$(action$, send, isResponseOf(messageSend, send.meta)); }).pipe(repeatUntil(notifier, delayMs), completeWith(action$)); } /** * Creates a type-guard function which verifies 'msg' is of given type between withdraw messages * and that total_withdraw and expiration matches given 'data'. * May be used to find matching messages in [[ChannelEnd]]'s 'pendingWithdraws' array * * @param type - Literal type tag to filter * @param data - Optional data to match, either in 'meta' or another 'message' format * @returns Typeguard function to check for matching withdraw protocol messages */ export function matchWithdraw(type, data) { return (msg) => msg.type === type && (!data || (msg.expiration.eq(data.expiration) && msg.total_withdraw.eq('totalWithdraw' in data ? data.totalWithdraw : data.total_withdraw))); } /** * @param req - WithdrawRequest message * @param channel - Channel in which it was received * @returns withdraw async action meta for respective request */ export function withdrawMetaFromRequest(req, channel) { return { tokenNetwork: channel.tokenNetwork, partner: channel.partner.address, direction: req.participant === channel.partner.address ? Direction.RECEIVED : Direction.SENT, expiration: req.expiration.toNumber(), totalWithdraw: req.total_withdraw, }; } //# sourceMappingURL=utils.js.map