sendStore.js 2.38 KiB
Newer Older
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
Amaury Martiny's avatar
Amaury Martiny committed
// SPDX-License-Identifier: BSD-3-Clause
import { action, computed, observable } from 'mobx';
Amaury Martiny's avatar
Amaury Martiny committed
import { blockNumber$, post$ } from '@parity/light.js';
Amaury Martiny's avatar
Amaury Martiny committed
import { contractForToken, txForErc20, txForEth } from '../utils/estimateGas';
Amaury Martiny's avatar
Amaury Martiny committed
import Debug from '../utils/debug';
import parityStore from './parityStore';

Amaury Martiny's avatar
Amaury Martiny committed
const debug = Debug('sendStore');
Amaury Martiny's avatar
Amaury Martiny committed

Amaury Martiny's avatar
Amaury Martiny committed
export class SendStore {
Amaury Martiny's avatar
Amaury Martiny committed
  @observable blockNumber; // Current block number, used to calculate tx confirmations.
  tx = {}; // The actual tx we are sending. No need to be observable.
Amaury Martiny's avatar
Amaury Martiny committed
  @observable txStatus; // Status of the tx, see wiki for details.
Amaury Martiny's avatar
Amaury Martiny committed
  acceptRequest = (requestId, password) => {
    // Since we accepted this request, we also start to listen to blockNumber,
    // to calculate the number of confirmations
Amaury Martiny's avatar
Amaury Martiny committed
    this.subscription = blockNumber$().subscribe(this.setBlockNumber);
Amaury Martiny's avatar
Amaury Martiny committed
    return parityStore.api.signer.confirmRequest(requestId, null, password);
Amaury Martiny's avatar
Amaury Martiny committed
  /**
   * Back to defaults.
   */
  clear = () => {
Amaury Martiny's avatar
Amaury Martiny committed
    this.tx = {};
Amaury Martiny's avatar
Amaury Martiny committed
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  };

Amaury Martiny's avatar
Amaury Martiny committed
  /**
   * Get the number of confirmations our transaction has.
   */
  @computed
  get confirmations () {
Amaury Martiny's avatar
Amaury Martiny committed
    if (!this.txStatus || !this.txStatus.confirmed) {
      return -1;
    }
    return this.blockNumber - +this.txStatus.confirmed.blockNumber;
  }

Amaury Martiny's avatar
Amaury Martiny committed
  /**
   * Create a transaction.
   */
Amaury Martiny's avatar
Amaury Martiny committed
  send = (token, password) => {
Amaury Martiny's avatar
Amaury Martiny committed
    const tx =
      token.address === 'ETH' ? txForEth(this.tx) : txForErc20(this.tx, token);
Amaury Martiny's avatar
Amaury Martiny committed
    const send$ =
Amaury Martiny's avatar
Amaury Martiny committed
      token.address === 'ETH'
Amaury Martiny's avatar
Amaury Martiny committed
        ? post$(tx)
        : contractForToken(token.address).transfer$(...tx.args, tx.options);
Amaury Martiny's avatar
Amaury Martiny committed
    debug('Sending tx.', tx);
Amaury Martiny's avatar
Amaury Martiny committed

Amaury Martiny's avatar
Amaury Martiny committed
    return new Promise((resolve, reject) => {
      send$.subscribe(txStatus => {
        // When we arrive to the `requested` stage, we accept the request
        if (txStatus.requested) {
          this.acceptRequest(txStatus.requested, password)
            .then(resolve)
            .catch(reject);
        }
        this.setTxStatus(txStatus);
Amaury Martiny's avatar
Amaury Martiny committed
        debug('Tx status updated.', txStatus);
Amaury Martiny's avatar
Amaury Martiny committed
      });
Amaury Martiny's avatar
Amaury Martiny committed
  @action
  setBlockNumber = blockNumber => {
    this.blockNumber = blockNumber;
Amaury Martiny's avatar
Amaury Martiny committed
  @action
  setTx = tx => {
    this.tx = tx;
Amaury Martiny's avatar
Amaury Martiny committed
  };

  @action
  setTxStatus = txStatus => {
    this.txStatus = txStatus;
  };
}

export default new SendStore();