All files / src instrument.js

54.55% Statements 36/66
66.67% Branches 26/39
53.33% Functions 8/15
54.84% Lines 34/62

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 1609x 9x         14x 14x 14x 14x       6x 4x   2x                                                 5x 5x 5x 5x 5x 5x 5x                       5x                   5x 5x                                   6x   6x 8x 4x   4x   6x               5x             5x 14x     5x 6x     5x 1x     5x                                                           9x            
const INSTR_CONTRACT_NAME = 'instr.ore';
const INSTR_TABLE_NAME = 'tokens';
 
/* Private */
// NOTE: if the endTime is 0, the instrument is valid forever
function isActive(instrument) {
  const startTime = instrument.start_time;
  const endTime = instrument.end_time;
  const currentTime = Math.floor(Date.now() / 1000);
  return (currentTime > startTime && (currentTime < endTime || endTime === 0));
}
 
function hasCategory(instrument, category) {
  if (instrument.instrument.instrument_class === category) {
    return true;
  }
  return false;
}
 
function sortByMintedAt(instruments) {
  // sorts the instruments by minted_at property
  // minted_at represents the time when the instrument is either minted or updated
  instruments.sort((a, b) => a.instrument.minted_at - b.instrument.minted_at);
  return instruments;
}
 
function sortByCheapestRight(instruments, rightName) {
  // sorts the instruments by the price for the right
  instruments.sort((a, b) => {
    const rightA = this.getRight(a, rightName);
    const rightB = this.getRight(b, rightName);
    return rightA.price_in_cpu - rightB.price_in_cpu;
  });
  return instruments;
}
 
async function getInstruments(params) {
  // Returns instruments indexed by owner/instrumentTemplate/instrumentClass
  // Returns all instruments by default
  let keyType;
  let index;
  let results = [];
  const lowerBound = 0;
  const upperBound = -1;
  const limit = -1;
  Eif (params.key_name === 'owner') {
    keyType = 'i64';
    index = 2;
  } else if (params.key_name === 'instrument_template') {
    keyType = 'i64';
    index = 3;
  } else if (params.key_name === 'instrument_class') {
    keyType = 'i64';
    index = 4;
  } else {
    // index by instrument_id
    keyType = 'i64';
    index = 1;
  }
  const parameters = {
    ...params,
    json: true,
    lower_bound: params.lower_bound || lowerBound,
    upper_bound: params.upper_bound || upperBound,
    scope: params.scope || params.code,
    limit: params.limit || limit,
    key_type: keyType || 'i64',
    index_position: index || 1
  };
  results = await this.eos.rpc.get_table_rows(parameters);
  return results.rows;
}
 
/* Public */
async function getAllInstruments() {
  // Returns all the instruments
  const instruments = await getInstruments.bind(this)({
    code: 'instr.ore',
    table: 'tokens'
  });
  return instruments;
}
 
function getRight(instrument, rightName) {
  const {
    instrument: {
      rights
    } = {}
  } = instrument;
 
  const right = rights.find((rightObject) => {
    if (rightObject.right_name === rightName) {
      return rightObject;
    }
    return undefined;
  });
  return right;
}
 
async function findInstruments(oreAccountName, activeOnly = true, category = undefined, rightName = undefined) {
  // Where args is search criteria could include (category, rights_name)
  // It gets all the instruments owned by a user using secondary index on the owner key
  // Note: this requires an index on the rights collection (to filter right names)
 
  let instruments = await getInstruments.bind(this)({
    code: 'instr.ore',
    table: 'tokens',
    lower_bound: oreAccountName,
    key_name: 'owner'
  });
 
  if (activeOnly) {
    instruments = instruments.filter(element => isActive(element));
  }
 
  if (category) {
    instruments = instruments.filter(element => hasCategory(element, category));
  }
 
  if (rightName) {
    instruments = await this.getInstrumentsByRight.bind(this)(instruments, rightName);
  }
 
  return instruments;
}
 
function sortInstruments(instruments, rightName, sortOrder = 'cheapestThenMostRecent') {
  // sorts the instruments depending on the search criteria :
  // cheapestThenMostRecent - returns the cheapest instrument for the right and if there are more than one with the same price, then returns the latest created/updated instrument
  // mostRecent - returns the latest instrument created/updated for the right
  let sortedInstruments;
  let cheapestInstrument;
  let cheapestPrice;
  let cheapestInstruments;
 
  switch (sortOrder) {
    case 'cheapestThenMostRecent':
      sortedInstruments = sortByCheapestRight.bind(this)(instruments, rightName);
      cheapestInstrument = sortedInstruments[0];
      cheapestPrice = this.getRight(cheapestInstrument, rightName).price_in_cpu;
      cheapestInstruments = sortedInstruments.filter(instrument => this.getRight(instrument, rightName).price_in_cpu === cheapestPrice);
 
      sortedInstruments = sortByMintedAt(cheapestInstruments);
      break;
    case 'mostRecent':
      sortedInstruments = sortByMintedAt(instruments);
      break;
    default:
      break;
  }
  return sortedInstruments[sortedInstruments.length - 1];
}
 
module.exports = {
  getRight,
  getAllInstruments,
  findInstruments,
  sortInstruments
};