raiden-ts
Version:
Raiden Light Client Typescript/Javascript SDK
138 lines • 4.72 kB
JavaScript
import { getAddress } from '@ethersproject/address';
import { pipe } from 'rxjs';
import { filter, scan, startWith } from 'rxjs/operators';
import { Capabilities, CapsFallback } from '../constants';
import { isActionOf } from '../utils/actions';
import { jsonParse } from '../utils/data';
import { matrixPresence } from './actions';
const userRe = /^@(0x[0-9a-f]{40})[.:]/i;
/**
* Extract the address in a matrix userId and returns it, or undefined it none
*
* @param userId - matrix user identifier
* @returns address contained in userId
*/
export function getAddressFromUserId(userId) {
let address;
try {
const match = userRe.exec(userId);
if (match)
address = getAddress(match[1]);
}
catch (e) { }
return address;
}
/**
* Stringify a caps mapping to a caps url
* E.g.'mxc://raiden.network/cap?k1=true&k2=v2&k2=v3&k4=null&k5=123'
*
* @param caps - Capabilities object/mapping
* @returns stringified version of caps
*/
export function stringifyCaps(caps) {
const url = new URL('mxc://raiden.network/cap');
// URLSearchParams.append can handle all primitives
const appendParam = (key, value) => url.searchParams.append(key, value);
for (const [key, value] of Object.entries(caps)) {
if (Array.isArray(value))
value.forEach(appendParam.bind(null, key));
else
appendParam(key, value);
}
return url.href;
}
/**
* Parse a caps string in the format 'mxc://raiden.network/cap?k1=true&k2=v2&k2=v3&k4=null&k5=123'
* to a { k1: true, k2: ['v2','v3'], k4: null, k5: 123 } object
*
* @param caps - caps string
* @returns Caps mapping object
*/
export function parseCaps(caps) {
if (!caps)
return;
const result = {};
try {
const url = new URL(caps);
url.searchParams.forEach((value, key) => {
let resValue = value;
// interpret *some* types of values
if (/^\d+$/.test(value))
resValue = jsonParse(value);
else {
const lowValue = value.toLowerCase();
if (lowValue === 'none' || lowValue === 'null')
resValue = null;
else if (lowValue === 'false')
resValue = false;
else if (lowValue === 'true')
resValue = true;
}
let val = result[key];
if (val === undefined) {
result[key] = resValue;
}
else {
if (!Array.isArray(val))
result[key] = val = [val];
val.push(resValue);
}
});
return result;
}
catch (err) { }
}
/**
* @param caps - Our or partner caps object (possibly empty/undefined)
* @param cap - Cap to fetch from
* @returns Specified capability, with proper fallback
*/
export function getCap(caps, cap) {
return caps?.[cap] ?? CapsFallback[cap];
}
/**
* Return addresses sorted in lexical order
*
* @param addresses - Addresses to sort
* @returns Addresses sorted in lexical order
*/
export function getSortedAddresses(...addresses) {
return addresses.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
}
/**
* Aggregates seen presence updates by userId
*
* @returns custom operator mapping from stream of RaidenActions to userId-presences dict
*/
export function getPresencesByUserId() {
const emptyDict = {};
return pipe(filter(matrixPresence.success.is), scan((acc, action) => ({ ...acc, [action.payload.userId]: action }), emptyDict), startWith(emptyDict));
}
/**
* Aggregates seen presence updates by online addresses (afawk)
*
* @returns custom operator mapping from stream of RaidenActions to address-presence dict
*/
export function getPresencesByAddress() {
const emptyDict = {};
return pipe(filter(isActionOf([matrixPresence.success, matrixPresence.failure])), scan((acc, action) => {
if (matrixPresence.success.is(action) && action.payload.available) {
acc[action.meta.address] = action;
}
else if (action.meta.address in acc) {
delete acc[action.meta.address];
}
return acc;
}, emptyDict), startWith(emptyDict));
}
/**
* Check if given presence is from an online partner which is another Light Client
* For now, this checks peer is online (known presence) and has Capabilities.DELIVERY set to 0
*
* @param presence - optional presence update
* @returns true if partner is online and is another light-client
*/
export function peerIsOnlineLC(presence) {
return !!presence && !getCap(presence.payload.caps, Capabilities.DELIVERY);
}
//# sourceMappingURL=utils.js.map