# All files / src bridgeState.js

100% Statements 46/46
100% Branches 2/2
100% Functions 9/9
100% Lines 44/44

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114

    1x
    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x

    1x

    3x
    3x
    3x

    3x

    3x

    3x

    3x

    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x
    3x

    3x
    3x
    3x

    3x

    3x

    3x
    3x
    3x

    3x

    1x

    1x
    1x

    3x

    3x

    3x

    3x

    6x
    6x

     /**
     * Copyright (c) 2018-present, Leap DAO (leapdao.org)
     *
     * This source code is licensed under the Mozilla Public License Version 2.0
     * found in the LICENSE file in the root directory of this source tree.
     */

    const Web3 = require('web3');
    const { Period, Block, Outpoint } = require('leap-core');
    const ContractsEventsSubscription = require('./utils/ContractsEventsSubscription');
    const { handleEvents } = require('./utils');
    const { GENESIS } = require('./utils/constants');
    const { logNode } = require('./utils/debug');

    const bridgeABI = require('./abis/bridgeAbi');
    const exitABI = require('./abis/exitHandler');
    const operatorABI = require('./abis/operator');

    module.exports = class BridgeState {
      constructor(db, privKey, config) {
        this.config = config;
        this.web3 = new Web3();
        this.web3.setProvider(
          new this.web3.providers.HttpProvider(config.rootNetwork)
        );

        this.exitHandlerContract = new this.web3.eth.Contract(
          exitABI,
          config.exitHandlerAddr
        );
        this.bridgeContract = new this.web3.eth.Contract(
          bridgeABI,
          config.bridgeAddr
        );
        this.operatorContract = new this.web3.eth.Contract(
          operatorABI,
          config.operatorAddr
        );

        this.account = privKey
          ? this.web3.eth.accounts.privateKeyToAccount(privKey)
          : this.web3.eth.accounts.create();

        this.db = db;
        this.blockHeight = 0;
        this.currentState = null;
        this.networkId = config.networkId;
        this.currentPeriod = new Period(GENESIS);
        this.previousPeriod = null;
        this.deposits = {};
        this.exits = {};
        this.epochLengths = [];
      }

      async init() {
        logNode('Syncing events...');
        this.lastBlockSynced = await this.db.getLastBlockSynced();
        const genesisBlock = await this.bridgeContract.methods
          .genesisBlockNumber()
          .call();
        const contracts = [
          this.operatorContract,
          this.bridgeContract,
          this.exitHandlerContract,
        ];
        this.eventsSubscription = new ContractsEventsSubscription(
          this.web3,
          contracts,
          genesisBlock
        );
        await this.watchContractEvents();
        await this.initBlocks();
        logNode('Synced');
      }

      async watchContractEvents() {
        this.eventsSubscription.subscribe(
          handleEvents({
            NewDeposit: ({ returnValues: event }) => {
              this.deposits[event.depositId] = {
                depositor: event.depositor,
                color: event.color,
                amount: event.amount,
              };
            },
            ExitStarted: ({ returnValues: event }) => {
              const outpoint = new Outpoint(event.txHash, Number(event.outIndex));
              this.exits[outpoint.getUtxoId()] = {
                txHash: event.txHash,
                outIndex: Number(event.outIndex),
                exitor: event.exitor,
                color: event.color,
                amount: event.amount,
              };
            },
            EpochLength: ({ returnValues: event }) => {
              this.epochLengths.push(Number(event.epochLength));
            },
          })
        );
        await this.eventsSubscription.init();
      }

      async initBlocks() {
        const blockOptions = {
          timestamp: Math.round(Date.now() / 1000),
        };
        const blocks = [new Block(0, blockOptions), new Block(1, blockOptions)];

        blocks.forEach(b => this.currentPeriod.addBlock(b));
        await Promise.all(blocks.map(b => this.db.storeBlock(b)));
      }
    };