raiden-ts
Version:
Raiden Light Client Typescript/Javascript SDK
618 lines (617 loc) • 29 kB
TypeScript
/// <reference types="pouchdb-core" />
/// <reference types="lodash" />
import './polyfills';
import type { Signer } from '@ethersproject/abstract-signer';
import type { BigNumberish } from '@ethersproject/bignumber';
import { BigNumber } from '@ethersproject/bignumber';
import type { Network } from '@ethersproject/networks';
import type { ExternalProvider } from '@ethersproject/providers';
import { JsonRpcProvider } from '@ethersproject/providers';
import logging from 'loglevel';
import type { Observable } from 'rxjs';
import type { RaidenAction, RaidenEvent, raidenSynced } from './actions';
import type { RaidenChannels } from './channels/state';
import type { RaidenConfig } from './config';
import { PartialRaidenConfig } from './config';
import type { Paths, RaidenPFS, SuggestedPartner } from './services/types';
import { InputPaths, PFS } from './services/types';
import type { RaidenState } from './state';
import type { RaidenTransfer } from './transfers/state';
import type { ContractsInfo, OnChange, RaidenEpicDeps } from './types';
import { EventTypes } from './types';
import type { Decodable } from './utils/types';
import { Address, Hash, UInt } from './utils/types';
export declare class Raiden {
private readonly deps;
private readonly epic;
/**
* action$ exposes the internal events pipeline. It's intended for debugging, and its interface
* must not be relied on, as its actions interfaces and structures can change without warning.
*/
readonly action$: Observable<RaidenAction>;
/**
* state$ is exposed only so user can listen to state changes and persist them somewhere else.
* Format/content of the emitted objects are subject to changes and not part of the public API
*/
readonly state$: Observable<RaidenState>;
/**
* channels$ is public interface, exposing a view of the currently known channels
* Its format is expected to be kept backwards-compatible, and may be relied on
*/
readonly channels$: Observable<RaidenChannels>;
/**
* A subset ot RaidenActions exposed as public events.
* The interface of the objects emitted by this Observable are expected not to change internally,
* but more/new events may be added over time.
*/
readonly events$: Observable<RaidenEvent>;
/**
* Observable of completed and pending transfers
* Every time a transfer state is updated, it's emitted here. 'key' property is unique and
* may be used as identifier to know which transfer got updated.
*/
readonly transfers$: Observable<RaidenTransfer>;
/** RaidenConfig object */
config: RaidenConfig;
/** RaidenConfig observable (for reactive use) */
config$: Observable<RaidenConfig>;
/** Observable of latest average (10) block times */
blockTime$: Observable<number>;
/** When started, is set to a promise which resolves when node finishes syncing */
synced: Promise<raidenSynced['payload'] | undefined>;
/**
* Get constant token details from token contract, caches it.
* Rejects only if 'token' contract doesn't define totalSupply and decimals methods.
* name and symbol may be undefined, as they aren't actually part of ERC20 standard, although
* very common and defined on most token contracts.
*
* @param token - address to fetch info from
* @returns token info
*/
getTokenInfo: (token: string) => Promise<{
totalSupply: BigNumber;
decimals: number;
name?: string | undefined;
symbol?: string | undefined;
}>;
private readonly store;
/** Expose ether's Provider.resolveName for ENS support */
readonly resolveName: (name: string) => Promise<Address>;
/** The address of the token that is used to pay the services (SVT/RDN). */
userDepositTokenAddress: () => Promise<Address>;
private epicMiddleware?;
/**
* Constructs a Raiden instance from state machine parameters
*
* It expects ready Redux and Epics params, with some async members already resolved and set in
* place, therefore this constructor is expected to be used only for tests and advancecd usage
* where finer control is needed to tweak how some of these members are initialized;
* Most users should usually prefer the [[create]] async factory, which already takes care of
* these async initialization steps and accepts more common parameters.
*
* @param state - Validated and decoded initial/rehydrated RaidenState
* @param deps - Constructed epics dependencies object, including signer, provider, fetched
* network and contracts information.
* @param epic - State machine root epic
* @param reducer - State machine root reducer
*/
constructor(state: RaidenState, deps: RaidenEpicDeps, epic?: (action$: Observable<RaidenAction>, state$: Observable<RaidenState>, deps: RaidenEpicDeps) => Observable<RaidenAction>, reducer?: (state: RaidenState | undefined, action: RaidenAction) => RaidenState);
/**
* Async helper factory to make a Raiden instance from more common parameters.
*
* An async factory is needed so we can do the needed async requests to construct the required
* parameters ahead of construction time, and avoid partial initialization then
*
* @param this - Raiden class or subclass
* @param connection - A URL or provider to connect to, one of:
* <ul>
* <li>JsonRpcProvider instance,</li>
* <li>a Metamask's web3.currentProvider object or,</li>
* <li>a hostname or remote json-rpc connection string</li>
* </ul>
* @param account - An account to use as main account, one of:
* <ul>
* <li>Signer instance (e.g. Wallet) loaded with account/private key or</li>
* <li>hex-encoded string address of a remote account in provider or</li>
* <li>hex-encoded string local private key or</li>
* <li>number index of a remote account loaded in provider
* (e.g. 0 for Metamask's loaded account)</li>
* </ul>
* @param storage - diverse storage related parameters to load from and save to
* @param storage.state - State uploaded by user; should be decodable by RaidenState;
* it is auto-migrated
* @param storage.adapter - PouchDB adapter; default to 'indexeddb' on browsers and 'leveldb' on
* node. If you provide a custom one, ensure you call PouchDB.plugin on it.
* @param storage.prefix - Database name prefix; use to set a directory to store leveldown db;
* @param contractsOrUDCAddress - Contracts deployment info, or UserDeposit contract address
* @param config - Raiden configuration
* @param subkey - Whether to use a derived subkey or not
* @param subkeyOriginUrl - URL of origin to generate a subkey for (defaults
* to global context)
* @returns Promise to Raiden SDK client instance
*/
static create<R extends typeof Raiden>(this: R, connection: JsonRpcProvider | ExternalProvider | string, account: Signer | string | number, storage?: {
state?: any;
adapter?: any;
prefix?: string;
}, contractsOrUDCAddress?: ContractsInfo | string, config?: Decodable<PartialRaidenConfig>, subkey?: true, subkeyOriginUrl?: string): Promise<InstanceType<R>>;
/**
* Starts redux/observables by subscribing to all epics and emitting initial state and action
*
* No event should be emitted before start is called
*/
start(): Promise<void>;
/**
* Gets the running state of the instance
*
* @returns undefined if not yet started, true if running, false if already stopped
*/
get started(): boolean | undefined;
/**
* Triggers all epics to be unsubscribed
*/
stop(): Promise<void>;
/**
* Instance's Logger, compatible with console's API
*
* @returns Logger object
*/
get log(): logging.Logger;
/**
* Get current RaidenState object. Can be serialized safely with [[encodeRaidenState]]
*
* @returns Current Raiden state
*/
get state(): RaidenState;
/**
* Current provider getter
*
* @returns ether's provider instance
*/
get provider(): JsonRpcProvider;
/**
* Get current account address (subkey's address, if subkey is being used)
*
* @returns Instance address
*/
get address(): Address;
/**
* Get main account address (if subkey is being used, undefined otherwise)
*
* @returns Main account address
*/
get mainAddress(): Address | undefined;
/**
* Get current network from provider
*
* @returns Network object containing blockchain's name & chainId
*/
get network(): Network;
/**
* Returns a promise to current block number, as seen in provider and state
*
* @returns Promise to current block number
*/
getBlockNumber(): Promise<number>;
/**
* Returns the currently used SDK version.
*
* @returns SDK version
*/
static get version(): string;
/**
* Returns the version of the used Smart Contracts.
*
* @returns Smart Contract version
*/
static get contractVersion(): string;
/**
* Returns the Smart Contracts addresses and deployment blocks
*
* @returns Smart Contracts info
*/
get contractsInfo(): ContractsInfo;
/**
* Update Raiden Config with a partial (shallow) object
*
* @param config - Partial object containing keys and values to update in config
*/
updateConfig(config: PartialRaidenConfig): void;
/**
* Dumps database content for backup
*
* @yields Rows of objects
*/
dumpDatabase(): AsyncGenerator<import("./db/types").RaidenDatabaseMeta | import("lodash").Omit<PouchDB.Core.ExistingDocument<PouchDB.Core.AllDocsMeta>, "_rev">, void, undefined>;
/**
* Get ETH balance for given address or self
*
* @param address - Optional target address. If omitted, gets own balance
* @returns BigNumber of ETH balance
*/
getBalance(address?: string): Promise<BigNumber>;
/**
* Get token balance and token decimals for given address or self
*
* @param token - Token address to fetch balance. Must be one of the monitored tokens.
* @param address - Optional target address. If omitted, gets own balance
* @returns BigNumber containing address's token balance
*/
getTokenBalance(token: string, address?: string): Promise<BigNumber>;
/**
* Returns a list of all token addresses registered as token networks in registry
*
* @param rescan - Whether to rescan events from scratch
* @returns Promise to list of token addresses
*/
getTokenList(rescan?: boolean): Promise<Address[]>;
/**
* Scans initially and start monitoring a token for channels with us, returning its Tokennetwork
* address
*
* Throws an exception if token isn't registered in current registry
*
* @param token - token address to monitor, must be registered in current token network registry
* @returns Address of TokenNetwork contract
*/
monitorToken(token: string): Promise<Address>;
/**
* Open a channel on the tokenNetwork for given token address with partner
*
* If token isn't yet monitored, starts monitoring it
*
* @param token - Token address on currently configured token network registry
* @param partner - Partner address
* @param options - (optional) option parameter
* @param options.deposit - Deposit to perform in parallel with channel opening
* @param options.confirmConfirmation - Whether to wait `confirmationBlocks` after last
* transaction confirmation; default=true if confirmationBlocks
* @param onChange - Optional callback for status change notification
* @returns txHash of channelOpen call, iff it succeeded
*/
openChannel(token: string, partner: string, options?: {
deposit?: BigNumberish;
confirmConfirmation?: boolean;
}, onChange?: OnChange<EventTypes, {
txHash: string;
}>): Promise<Hash>;
/**
* Deposit tokens on channel between us and partner on tokenNetwork for token
*
* @param token - Token address on currently configured token network registry
* @param partner - Partner address
* @param amount - Number of tokens to deposit on channel
* @param options - tx options
* @param options.confirmConfirmation - Whether to wait `confirmationBlocks` after last
* transaction confirmation; default=true if config.confirmationBlocks
* @returns txHash of setTotalDeposit call, iff it succeeded
*/
depositChannel(token: string, partner: string, amount: BigNumberish, { confirmConfirmation, }?: {
confirmConfirmation?: boolean;
}): Promise<Hash>;
/**
* Close channel between us and partner on tokenNetwork for token
* This method will fail if called on a channel not in 'opened' or 'closing' state.
* When calling this method on an 'opened' channel, its state becomes 'closing', and from there
* on, no payments can be performed on the channel. If for any reason the closeChannel
* transaction fails, channel's state stays as 'closing', and this method can be called again
* to retry sending 'closeChannel' transaction. After it's successful, channel becomes 'closed',
* and can be settled after 'settleTimeout' seconds (when it then becomes 'settleable').
*
* @param token - Token address on currently configured token network registry
* @param partner - Partner address
* @returns txHash of closeChannel call, iff it succeeded
*/
closeChannel(token: string, partner: string): Promise<Hash>;
/**
* Settle channel between us and partner on tokenNetwork for token
* This method will fail if called on a channel not in 'settleable' or 'settling' state.
* Channel becomes 'settleable' settleTimeout seconds after closed (detected automatically
* while Raiden Light Client is running or later on restart). When calling it, channel state
* becomes 'settling'. If for any reason transaction fails, it'll stay on this state, and this
* method can be called again to re-send a settleChannel transaction.
*
* @param token - Token address on currently configured token network registry
* @param partner - Partner address
* @returns txHash of settleChannel call, iff it succeeded
*/
settleChannel(token: string, partner: string): Promise<Hash>;
/**
* Returns object describing address's users availability on transport
* After calling this method, any further presence update to valid transport peers of this
* address will trigger a corresponding MatrixPresenceUpdateAction on events$
*
* @param address - checksummed address to be monitored
* @returns Promise to object describing availability and last event timestamp
*/
getAvailability(address: string): Promise<{
userId: string;
available: boolean;
ts: number;
}>;
/**
* Get list of past and pending transfers
*
* @param filter - Filter options
* @param filter.pending - true: only pending; false: only completed; undefined: all
* @param filter.token - filter by token address
* @param filter.partner - filter by partner address
* @param filter.end - filter by initiator or target address
* @param options - PouchDB.ChangesOptions object
* @param options.offset - Offset to skip entries
* @param options.limit - Limit number of entries
* @param options.desc - Set to true to get newer transfers first
* @returns promise to array of all transfers
*/
getTransfers(filter?: {
pending?: boolean;
token?: string;
partner?: string;
end?: string;
}, options?: {
offset?: number;
limit?: number;
desc?: boolean;
}): Promise<RaidenTransfer[]>;
/**
* Send a Locked Transfer!
* This will reject if LockedTransfer signature prompt is canceled/signature fails, or be
* resolved to the transfer unique identifier (secrethash) otherwise, and transfer status can be
* queried with this id on this.transfers$ observable, which will just have emitted the 'pending'
* transfer. Any following transfer state change will be notified through this observable.
*
* @param token - Token address on currently configured token network registry
* @param target - Target address
* @param value - Amount to try to transfer
* @param options - Optional parameters for transfer:
* @param options.paymentId - payment identifier, a random one will be generated if missing
* @param options.secret - Secret to register, a random one will be generated if missing
* @param options.secrethash - Must match secret, if both provided, or else, secret must be
* informed to target by other means, and reveal can't be performed
* @param options.paths - Used to specify possible routes & fees instead of querying PFS.
* Should receive a decodable super-set of the public RaidenPaths interface
* @param options.pfs - Use this PFS instead of configured or automatically choosen ones.
* Is ignored if paths were already provided. If neither are set and config.pfs is not
* disabled (null), use it if set or if undefined (auto mode), fetches the best
* PFS from ServiceRegistry and automatically fetch routes from it.
* @param options.lockTimeout - Specify a lock timeout for transfer;
* default is expiryFactor * revealTimeout
* @param options.encryptSecret - Whether to force encrypting the secret or not,
* if target supports it
* @returns A promise to transfer's unique key (id) when it's accepted
*/
transfer(token: string, target: string, value: BigNumberish, options?: {
paymentId?: BigNumberish;
secret?: string;
secrethash?: string;
paths?: Decodable<InputPaths>;
pfs?: RaidenPFS;
lockTimeout?: number;
encryptSecret?: boolean;
}): Promise<string>;
/**
* Waits for the transfer identified by a secrethash to fail or complete
* The returned promise will resolve with the final transfer state, or reject if anything fails
*
* @param transferKey - Transfer identifier as returned by [[transfer]]
* @returns Promise to final RaidenTransfer
*/
waitTransfer(transferKey: string): Promise<RaidenTransfer>;
/**
* Request a path from PFS
*
* If a direct route is possible, it'll be returned. Else if PFS is set up, a request will be
* performed and the cleaned/validated path results will be resolved.
* Else, if no route can be found, promise is rejected with respective error.
*
* @param token - Token address on currently configured token network registry
* @param target - Target address
* @param value - Minimum capacity required on routes
* @param options - Optional parameters
* @param options.pfs - Use this PFS instead of configured or automatically choosen ones
* @returns A promise to returned routes/paths result
*/
findRoutes(token: string, target: string, value: BigNumberish, options?: {
pfs?: RaidenPFS;
}): Promise<Paths>;
/**
* Checks if a direct transfer of token to target could be performed and returns it on a
* single-element array of Paths
*
* @param token - Token address on currently configured token network registry
* @param target - Target address
* @param value - Minimum capacity required on route
* @returns Promise to a [Raiden]Paths array containing the single, direct route, or undefined
*/
directRoute(token: string, target: string, value: BigNumberish): Promise<Paths | undefined>;
/**
* Returns a sorted array of info of available PFS
*
* It uses data polled from ServiceRegistry, which is available only when config.pfs is
* undefined, instead of set or disabled (null), and will reject if not.
* It can reject if the validated list is empty, meaning we can be out-of-sync (we're outdated or
* they are) with PFSs deployment, or no PFS is available on this TokenNetwork/blockchain.
*
* @returns Promise to array of PFS, which is the interface which describes a PFS
*/
findPFS(): Promise<PFS[]>;
/**
* Mints the amount of tokens of the provided token address.
* Throws an error, if
* <ol>
* <li>Executed on main net</li>
* <li>`token` or `options.to` is not a valid address</li>
* <li>Token could not be minted</li>
* </ol>
*
* @param token - Address of the token to be minted
* @param amount - Amount to be minted
* @param options - tx options
* @param options.to - Beneficiary, defaults to mainAddress or address
* @returns transaction
*/
mint(token: string, amount: BigNumberish, { to }?: {
to?: string;
}): Promise<Hash>;
/**
* Registers and creates a new token network for the provided token address.
* Throws an error, if
* <ol>
* <li>Executed on main net</li>
* <li>`token` is not a valid address</li>
* <li>Token is already registered</li>
* <li>Token could not be registered</li>
* </ol>
*
* @param token - Address of the token to be registered
* @param channelParticipantDepositLimit - The deposit limit per channel participant
* @param tokenNetworkDepositLimit - The deposit limit of the whole token network
* @returns Address of new token network
*/
registerToken(token: string, channelParticipantDepositLimit?: BigNumberish, tokenNetworkDepositLimit?: BigNumberish): Promise<Address>;
/**
* Fetches balance of UserDeposit Contract for SDK's account minus cached spent IOUs
*
* @returns Promise to UDC remaining capacity
*/
getUDCCapacity(): Promise<BigNumber>;
/**
* Fetches total_deposit of UserDeposit Contract for SDK's account
*
* The usable part of the deposit should be fetched with [[getUDCCapacity]], but this function
* is useful when trying to deposit based on the absolute value of totalDeposit.
*
* @returns Promise to UDC total deposit
*/
getUDCTotalDeposit(): Promise<BigNumber>;
/**
* Deposits the amount to the UserDeposit contract with the target/signer as a beneficiary.
* The deposited amount can be used as a collateral in order to sign valid IOUs that will
* be accepted by the Services.
*
* Throws an error, in the following cases:
* <ol>
* <li>The amount specified equals to zero</li>
* <li>The target has an insufficient token balance</li>
* <li>The "approve" transaction fails with an error</li>
* <li>The "deposit" transaction fails with an error</li>
* </ol>
*
* @param amount - The amount to deposit on behalf of the target/beneficiary.
* @param onChange - callback providing notifications about state changes
* @returns transaction hash
*/
depositToUDC(amount: BigNumberish, onChange?: OnChange<EventTypes, {
txHash: string;
}>): Promise<Hash>;
/**
* Transfer value ETH on-chain to address.
* If subkey is being used, use main account by default, or subkey account if 'subkey' is true
* Example:
* // transfer 0.1 ETH from main account to subkey account, when subkey is used
* await raiden.transferOnchainBalance(raiden.address, parseEther('0.1'));
* // transfer entire balance from subkey account back to main account
* await raiden.transferOnchainBalance(raiden.mainAddress, undefined, { subkey: true });
*
* @param to - Recipient address
* @param value - Amount of ETH (in Wei) to transfer. Use ethers/utils::parseEther if needed
* Defaults to a very big number, which will cause all entire balance to be transfered
* @param options - tx options
* @param options.subkey - By default, if using subkey, main account is used to send transactions
* Set this to true if one wants to force sending the transaction with the subkey
* @param options.gasPrice - Set to force a specific gasPrice; used to calculate transferable
* amount when transfering entire balance. If left unset, uses average network gasPrice
* @returns transaction hash
*/
transferOnchainBalance(to: string, value?: BigNumberish, { subkey, gasPrice: price }?: {
subkey?: boolean;
gasPrice?: BigNumberish;
}): Promise<Hash>;
/**
* Transfer value tokens on-chain to address.
* If subkey is being used, use main account by default, or subkey account if 'subkey' is true
*
* @param token - Token address
* @param to - Recipient address
* @param value - Amount of tokens (in Wei) to transfer. Use ethers/utils::parseUnits if needed
* Defaults to a very big number, which will cause all entire balance to be transfered
* @param options - tx options
* @param options.subkey - By default, if using subkey, main account is used to send transactions
* Set this to true if one wants to force sending the transaction with the subkey
* @returns transaction hash
*/
transferOnchainTokens(token: string, to: string, value?: BigNumberish, { subkey }?: {
subkey?: boolean;
}): Promise<Hash>;
/**
* Fetches our current UDC withdraw plan
*
* @returns Promise to object containing maximum 'amount' planned for withdraw and
* 'withdrawableAfter' second at which withdraw will become available,
* and 'ready' after it can be withdrawn with [[withdrawFromUDC]];
* resolves to undefined if there's no current plan
*/
getUDCWithdrawPlan(): Promise<{
amount: UInt<32>;
withdrawableAfter: number;
ready: boolean;
} | undefined>;
/**
* Records a UDC withdraw plan for our UDC deposit, capped at whole balance.
*
* @param value - Maximum value which we may try to withdraw.
* @returns Promise to hash of plan transaction, if it succeeds.
*/
planUDCWithdraw(value?: BigNumberish): Promise<Hash>;
/**
* Complete a planned UDC withdraw and get the deposit to account.
*
* Maximum 'value' is the one from current plan, attempting to withdraw a larger value will throw
* an error, but a smaller value is valid. This method may only be called after plan is 'ready'
*
* @param value - Maximum value which we may try to withdraw. An error will be thrown if this
* value is larger than [[getUDCCapacity]]+[[getUDCWithdrawPlan]].amount
* @param options - options object
* @param options.subkey - if true, force withdrawing to subkey instead of the main account as
* beneficiary
* @returns Promise to hash of plan transaction, if it succeeds.
*/
withdrawFromUDC(value?: BigNumberish, options?: {
subkey?: boolean;
}): Promise<Hash>;
/**
* Requests to withdraw from channel
*
* The requested amount defaults to the maximum withdrawable amount, which is exposed in
* [[channels$]] observable as the [[RaidenChannel.ownWithdrawable]] member.
* This involves requesting partner a signature which confirms they agree that we have the right
* for this amount of tokens, then a transaction is sent on-chain to withdraw tokens to the
* effective account.
* If this process fails, the amount remains locked until it can be expired later (defaults to
* config.expiryFactory * config.revealTimeout seconds).
*
* @param token - Token address on currently configured token network registry
* @param partner - Partner address
* @param amount - Amount of tokens (in wei) to withdraw, must be between 1 and ownWithdrawable
* @returns Promise to the hash of the mined withdraw transaction
*/
withdrawChannel(token: string, partner: string, amount?: BigNumberish): Promise<Hash>;
/**
* Fetches an ordered list of suggested partners from provided, configured or first found PFS
*
* @param token - Token address to get partners for
* @param options - Request options
* @param options.pfs - PFS to use, instead of configured or automatic
* @returns Ordered array of suggested partners, with address and scoring values according to PFS
*/
suggestPartners(token: string, options?: {
pfs?: RaidenPFS;
}): Promise<SuggestedPartner[]>;
/**
* Fetches contract's settleTimeout
*
* @returns settleTimeout constant value from contracts
*/
get settleTimeout(): number;
}
export default Raiden;