import { Objective, ChannelStoredData, DomainBudget, StateVariables } from '@statechannels/wallet-core'; import {filter, map} from 'rxjs/operators'; import {Store} from './store'; import {ChannelStoreEntry} from './channel-store-entry'; export {Store} from './store'; // TODO: Move to somewhere better? export function supportedStateFeed(store: Store, channelId: string) { return store.channelUpdatedFeed(channelId).pipe( filter(e => !!e.supported), map(e => ({state: {...e.channelConstants, ...(e.supported as StateVariables)}})) ); } export enum Errors { duplicateTurnNums = 'multiple states with same turn number', notSorted = 'states not sorted', multipleSignedStates = 'Store signed multiple states for a single turn', staleState = 'Attempting to sign a stale state', channelMissing = 'No channel found with id.', channelFunded = 'Channel already funded.', channelLocked = 'Channel is locked', noBudget = 'No budget exists for domain. ', noAssetBudget = "This domain's budget does contain this asset", channelNotInBudget = "This domain's budget does not reference this channel", noDomainForChannel = 'No domain defined for channel', domainExistsOnChannel = 'Channel already has a domain.', budgetAlreadyExists = 'There already exists a budget for this domain', budgetInsufficient = 'Budget insufficient to reserve funds', amountUnauthorized = 'Amount unauthorized in current budget', cannotFindDestination = 'Cannot find destination for participant', cannotFindPrivateKey = 'Private key missing for your address', notInChannel = 'Attempting to initialize channel as a non-participant', noLedger = 'No ledger exists with peer', amountNotFound = 'Cannot find allocation entry with destination', invalidNonce = 'Invalid nonce', invalidTransition = 'Invalid transition', invalidAppData = 'Invalid app data', emittingDuringTransaction = 'Attempting to emit event during transaction', notMyTurn = "Cannot update channel unless it's your turn" } export interface DBBackend { initialize(cleanSlate: boolean, name: string): Promise; // TODO: Perhaps the backend API should look more like this? // privateKeys(): Promise>; privateKeys(): Promise>; ledgers(): Promise>; nonces(): Promise>; objectives(): Promise; channels(): Promise>; setDestinationAddress(destinationAddress: string): Promise; getDestinationAddress(): Promise; setPrivateKey(key: string, value: string): Promise; getPrivateKey(key: string): Promise; setChannel(key: string, value: ChannelStoredData): Promise; getChannel(key: string): Promise; getBudget(key: string): Promise; setBudget(key: string, budget: DomainBudget): Promise; deleteBudget(key: string): Promise; setLedger(key: string, value: string): Promise; getLedger(key: string): Promise; setNonce(key: string, value: number): Promise; getNonce(key: string): Promise; setObjective(key: number, value: Objective): Promise; getObjective(key: number): Promise; /** * Starts an async database transaction. * * When mode is 'readwrite', acquires a lock on each store listed in stores param. * * dexie backend rejects with 'NotFoundError: TableX not part of transaction', if cb * attempts to use table not listed by stores param. * * Rejects if tx.abort() is called. * * @param mode * @param stores array of ObjectStore names usd in cb * @param cb callback to execute within transaction scope * @returns promise resolving to return value of cb */ transaction( mode: TXMode, stores: S[], cb: (tx: Transaction) => Promise ): Promise; transactionOngoing: boolean; } export type Transaction = { abort(): void; // TODO: We could expose a store function on the transaction and // potentially do away with the individual getters on the backend interface // EG: // store(s: S): ObjectStore; // Or, we could just expose direct properties, like // channels(): Table }; export type TXMode = 'readonly' | 'readwrite'; export const enum ObjectStores { channels = 'channels', objectives = 'objectives', nonces = 'nonces', privateKeys = 'privateKeys', destinationAddress = 'destinationAddress', ledgers = 'ledgers', budgets = 'budgets' } declare global { interface Window { channelProvider: import('@statechannels/iframe-channel-provider').ChannelProviderInterface; ethereum: any; } }