You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

116 lines
5.5 KiB

// @flow
import type { Observable } from 'rxjs'
import type { BigNumber } from 'bignumber.js'
import type { Account, Operation, Currency } from '@ledgerhq/live-common/lib/types'
// a WalletBridge is implemented on renderer side.
// this is an abstraction on top of libcore / ethereumjs / ripple js / ...
// that would directly be called from UI needs.
export type DeviceId = string // for now it's just usb path
export type Observer<T> = {
next: T => void,
complete: () => void,
error: (?Error) => void,
}
export type Subscription = {
+unsubscribe: () => void,
}
export type EditProps<Transaction> = {
account: Account,
value: Transaction,
onChange: Transaction => void,
}
export interface WalletBridge<Transaction> {
// in "import"/"recover" step, we need a way to scan all accounts from the device
// for a given currency.
// deviceId currently is the device path.
// observer is an Observer of Account object. Account are expected to be `archived` by default because we want to import all and opt-in on what account to use.
// the scan can stop once all accounts are discovered.
// the function returns a Subscription and you MUST stop everything if it is unsubscribed.
// TODO return Observable
scanAccountsOnDevice(currency: Currency, deviceId: DeviceId): Observable<Account>;
// synchronize an account. meaning updating the account object with latest state.
// function receives the initialAccount object so you can actually know what the user side currently have
// then you must emit one or more updater functions to inform data changes.
// an update function is just a Account => Account that perform the changes (to avoid race condition issues)
// this can emit new version of the account. typically these field can change over time:
// operations if there are new ones (prepended), balance, blockHeight, ...
// the synchronize can stop once everything is up to date. it is the user side responsability to start it again.
// we should be able to interrupt the Subscription but we'll leave this usecase for later. if you don't support interruption, please `console.warn`
synchronize(initialAccount: Account): Observable<(Account) => Account>;
// for a given account, UI wants to load more operations in the account.operations
// if you can't do it or there is no more things to load, just return account,
// otherwise return (asynchronously) an account updater that add operations in account.operations
// count is user's desired number of ops to pull (but implementation can decide to ignore it or not)
pullMoreOperations(initialAccount: Account, count: number): Promise<(Account) => Account>;
isRecipientValid(currency: Currency, recipient: string): Promise<boolean>;
getRecipientWarning(currency: Currency, recipient: string): Promise<?Error>;
// Related to send funds:
// a Transaction object is a black box that can be improved by the following methods & components...
// IMPORTANT: this is only a temporary object on UI side! not on libcore side
// underlying implementation can have the same concept too, the point is we need sync api for the UI
// if you have async api under the hood, you will have to cache things and return tmp values..
createTransaction(account: Account): Transaction;
editTransactionAmount(account: Account, transaction: Transaction, amount: BigNumber): Transaction;
getTransactionAmount(account: Account, transaction: Transaction): BigNumber;
editTransactionRecipient(
account: Account,
transaction: Transaction,
recipient: string,
): Transaction;
getTransactionRecipient(account: Account, transaction: Transaction): string;
// render the whole Fees section of the form
EditFees?: *; // React$ComponentType<EditProps<Transaction>>;
// render the whole advanced part of the form
EditAdvancedOptions?: *; // React$ComponentType<EditProps<Transaction>>;
// validate the transaction and all currency specific validations here, we can return false
// to disable the button without throwing an error if we are handling the error on a different
// input or throw an error that will highlight the issue on the amount field
checkValidTransaction(account: Account, transaction: Transaction): Promise<boolean>;
getTotalSpent(account: Account, transaction: Transaction): Promise<BigNumber>;
// NB this is not used yet but we'll use it when we have MAX
getMaxAmount(account: Account, transaction: Transaction): Promise<BigNumber>;
/**
* finalize the transaction by
* - signing it with the ledger device
* - broadcasting it to network
* - retrieve and return the optimistic Operation that this transaction is likely to create in the future
*
* NOTE: in future, when transaction balance is close to account.balance, we could wipe it all at this level...
* to implement that, we might want to have special logic `account.balance-transaction.amount < dust` but not sure where this should leave (i would say on UI side because we need to inform user visually).
*/
signAndBroadcast(
account: Account,
transaction: Transaction,
deviceId: DeviceId,
): Observable<{ type: 'signed' } | { type: 'broadcasted', operation: Operation }>;
// Implement an optimistic response for signAndBroadcast.
// you likely should add the operation in account.pendingOperations but maybe you want to clean it (because maybe some are replaced / cancelled by this one?)
addPendingOperation?: (account: Account, optimisticOperation: Operation) => Account;
getDefaultEndpointConfig?: () => string;
validateEndpointConfig?: (endpointConfig: string) => Promise<void>;
}