LedgerHQ/ledger-live-common

[spec] Rework of Bridge Interface (prepareTransaction, getTransactionStatus)

Closed this issue · 0 comments

gre commented

We introduce two new methods in AccountBridge: prepareTransaction and getTransactionStatus, more generic functions to covers some existing methods and even more.

NEW: AccountBridge#prepareTransaction

  prepareTransaction(
    account: Account,
    transaction: Transaction
  ): Promise<Transaction>;

It is a new hook that eventually should be called initially and after each change of Transaction.
It basically fill up/update information in the Transaction object: gas limit, fees,...

The goal is that this becomes a unified hook and more standard lifecycle. It should be idempotent, resilient and support concurrency.

to be covered by prepareTransaction

  • fetchTransactionNetworkInfo / applyTransactionNetworkInfo / other kind of fetching fees (currently mostly done outside of the bridge)

NEW: AccountBridge#getTransactionStatus

  getTransactionStatus(
    account: Account,
    transaction: Transaction
  ): Promise<TransactionStatus>;

This method returns complementary general information out of a Transaction that can be displayed to the user or used as validation status (error, warnings, to display...). We will also return estimatedFees that is not available today, typically for ERC20.

It is the unified and central point to every derived state that is not directly in Transaction.

It should be efficient and not contain intensive work like prepareTransaction can potentially have (network calls).

Here is current TransactionStatus. More might be added in future.

// TransactionStatus is a view of Transaction with general info to be used on the UI and status info.
type TransactionStatus = {
  // summarize if the transaction is good to go or have validation error
  transactionError: ?Error,
  // null if recipient is valid, otherwise it will be an error, likely InvalidAddress error
  recipientError: ?Error,
  // null if recipient have no warning. recipient can be valid but have warning to display (e.g. ETH EIP55)
  recipientWarning: ?Error,
  // ? should UI show a warning about fees being high (currently have been hardcoded to be if fee>10% of amount)
  showFeeWarning: boolean,
  // estimated total fees the tx is going to cost. (in the mainAccount currency)
  estimatedFees: BigNumber,
  // actual amount that the recipient will receive (in account currency)
  amount: BigNumber,
  // total amount that the sender will spend (in account currency)
  totalSpent: BigNumber,
  // ? will it wipe all possible amount of the account
  useAllAmount: boolean
};

What is plan to get deprecated by getTransactionStatus

  • checkValidRecipient
  • checkValidTransaction
  • getTotalSpent
  • getMaxAmount

Deprecation plan:

  • first we introduce the 2 methods. We migrate all over the place to get rid of deprecated method usages.
  • then a future major version of live-common will clean up the bridge.

Summary of what will be the essential methods of the 2 bridges

interface CurrencyBridge {
  // discover all accounts available on a Ledger device
  scanAccountsOnDevice(
    currency: CryptoCurrency,
    deviceId: DeviceId
  ): Observable<Account>;
}

interface AccountBridge<T: Transaction> {
  // synchronize an account
  startSync(
    initialAccount: Account,
    observation: boolean
  ): Observable<(Account) => Account>;

  // start a new transaction
  createTransaction(account: Account): T;

  // at any time we get a Transaction, this will fulfill some information in it
  prepareTransaction(
    account: Account,
    transaction: T
  ): Promise<T>;

  // calculate / get derived state of the Transaction, useful to display summary / errors / warnings. tell if the transaction is ready.
  getTransactionStatus(
    account: Account,
    transaction: T
  ): Promise<TransactionStatus>;

  // sign with a Ledger device and broadcast the transaction to the blockchain
  signAndBroadcast(
    account: Account,
    transaction: T,
    deviceId: DeviceId
  ): Observable<SignAndBroadcastEvent>;
}

And that's essentially all we need.

some other methods remain but are getting deprecated.