Source: common.js

import * as chainQuery   from "#core/blockchain/chainQuery.js";
import * as mnemonic     from "#core/keyManager/mnemonic.js";
import * as derivation   from "#core/keyManager/derivation.js";
import * as microblock   from "#core/blockchain/microblock.js";
import * as flowManager  from "#core/flowManager/flowManager.js";
import * as fileSystem   from "#core/storage/fileSystem.js";
import * as textEncoder  from "#core/util/textEncoder.js";
import * as application  from "#core/object/application.js";
import * as organization from "#core/object/organization.js";
import * as crypto       from "#core/crypto/crypto.js";
import * as util         from "#core/util/util.js";
import * as uint8        from "#core/util/uint8.js";
import * as CST          from "#core/constants/constants.js";

// ============================================================================================================================ //
//  constants                                                                                                                   //
// ============================================================================================================================ //
export const constants = {
  // CST.ID
  OBJ_ACCOUNT     : CST.ID.OBJ_ACCOUNT,
  OBJ_NODE        : CST.ID.OBJ_NODE,
  OBJ_ORGANIZATION: CST.ID.OBJ_ORGANIZATION,
  OBJ_USER        : CST.ID.OBJ_USER,
  OBJ_APPLICATION : CST.ID.OBJ_APPLICATION,
  OBJ_FLOW        : CST.ID.OBJ_FLOW,
  OBJECT_NAME     : CST.ID.OBJECT_NAME,

  // CST.DATA
  SECTION_NAME: CST.DATA.SECTION_NAME,
  FLOW_PUBLIC_DATA: CST.DATA.S_FLOW_PUBLIC_DATA,

  // CST.CONFIG
  TOKEN_NAME        : CST.CONFIG.TOKEN_NAME,
  MASTERBLOCK_PERIOD: CST.CONFIG.MASTERBLOCK_PERIOD,

  // microblock
  MICROBLOCK_SECTION_HEADER_SIZE: microblock.SECTION_HEADER_SIZE,

  // masterblock
  MASTERBLOCK_CONTENT_HEADER_SIZE: 0
};

// ============================================================================================================================ //
//  core methods                                                                                                                //
// ============================================================================================================================ //
export const core = {
  constants: CST,
  storage: {
    fileSystem: fileSystem
  },
  util: {
    helpers    : util,
    textEncoder: textEncoder,
    uint8      : uint8
  },
};

// ============================================================================================================================ //
//  blockchain methods                                                                                                          //
// ============================================================================================================================ //
export const getChainStatus     = userFunction(chainQuery.getStatus);
export const getMasterBlockList = userFunction(chainQuery.getMasterBlockList);
export const getMasterBlock     = userFunction(chainQuery.getMasterBlock);

/**
 * Returns information about the micro-chain specified by the provided id.
 *
 * @param id {Uint8Array} The id of the micro block.
 *
 *
 *
 * @return {Promise<{
 *     status: number,
 *     currentBlock: null,
 *     currentNonce: number,
 *     type: number,
 *     microBlock: {
 *      masterBlock: number,
 *       version: number,
 *       nonce: number,
 *       hash: Uint8Array,
 *       prevHash: Uint8Array,
 *       ts: number,
 *       nSection: number,
 *       sections: {
 *           type: number,
 *           size: number,
 *           data: Uint8Array,
 *       }[],
 *       gas: number,
 *       gasPrice: number,
 *       index: number,
 *       size: number,
 *       type: number,
 *     }[],
 * }>}
 */
export const getMicroChain      = userFunction(chainQuery.getMicroChain);

/**
 *  Returns information on the micro-block associated with the provided hash.
 *
 * @param id {Uint8Array} The id of the micro block.
 *
 * @returns {Promise<{masterBlock: number,
 *       version: number,
 *       nonce: number,
 *       hash: Uint8Array,
 *       prevHash: Uint8Array,
 *       ts: number,
 *       nSection: number,
 *       gas: number,
 *       gasPrice: number,
 *       index: number,
 *       size: number,
 *       type: number
 *       }>}
 */
export const getMicroBlock      = userFunction(chainQuery.getMicroBlock);

/**
 * Returns a promise returning a public data the micro block at position `nonce` in the micro-chain having flowId identifier
 * based in the application and associated with the applicationId.
 *
 * @function loadPublicDataFromMicroBlock
 * @param applicationId The id of the application containing the designated micro-block.
 * @param flowId The id of the flow containing the designated micro-block.
 * @param nonce The position of the designated micro-block (should start at 1).
 *
 * @returns {Promise<{
 *    valid: boolean,
 *    msg: any,
 *    appDef: object
 *    }>}
 */
export const loadPublicDataFromMicroBlock = userFunction(flowManager.loadPublicDataFromMicroBlock)

// ============================================================================================================================ //
//  key management methods                                                                                                      //
// ============================================================================================================================ //
export const getMatchingWords               = userFunction(mnemonic.getMatchingWords);

/**
 * Generates and returns a list of words.
 *
 * @function generateWordList
 * @param {number} nbWords - The number of words to generate.
 * @returns {string[]} A list containing the generated words, with a size of nbWords.
 */
export const generateWordList               = userFunction(mnemonic.generateWordList);

/**
 * Derives and returns a seed from a list of words.
 *
 * @function getSeedFromWordList
 * @param words {string[]} The words from which the seed is derived.
 *
 * @returns {Uint8Array} The seed.
 */
export const getSeedFromWordList            = mnemonic.getSeedFromWordList;

/**
 * Retrieves and returns a world list from a seed.
 *
 * @param seed {Uint8Array} The seed from which the list of words is derived.
 *
 * @returns The word list.
 */
export const getWordListFromSeed            = userFunction(mnemonic.getWordListFromSeed);

/**
 * Derives and returns a pepper from a seed and a nonce.
 *
 * @param seed {Uint8Array} The seed used to derive the pepper.
 * @param nonce {number} The nonce to derive a different pepper from the same seed.
 *
 * @returns {Promise<Uint8Array>} The pepper.
 */
export const derivePepperFromSeed  = userFunction(derivation.derivePepperFromSeed);

/**
 * Derives and returns a 256-bits AES key from the provided password.
 *
 * @function deriveAesKeyFromPassword
 * @param password {string} The password from which the password is derived.
 *
 * @returns {Promise<Uint8Array>} The AES key.
 *
 * @example
 * const password = "myPassword";
 * const key = await deriveAesKeyFromPassword( password );
 */
export const deriveAesKeyFromPassword       = userFunction(derivation.deriveAesKeyFromPassword);
export const deriveAesKeyFromBits           = userFunction(derivation.deriveAesKeyFromBits);
export const deriveAccountPrivateKey        = userFunction(derivation.deriveAccountPrivateKey);
export const deriveNodePrivateKey           = userFunction(derivation.deriveNodePrivateKey);
export const deriveOrganizationPrivateKey   = userFunction(derivation.deriveOrganizationPrivateKey);

/**
 * Derives and returns the private key from a pepper and a nonce.
 *
 * ```js
 * const pepper = derivePepperFromSeed( seed, nonce );
 * const privateKey = deriveUserPrivateKey( pepper, applicationId );
 * ```
 *
 * @param pepper {Uint8Array} The pepper used to derive the private key.
 * @param applicationId {string} The id of the application to derive a different private key for each application.
 *
 * @returns {Promise<Uint8Array>} The derived private key.
 */
export const deriveUserPrivateKey           = userFunction(derivation.deriveUserPrivateKey);
export const deriveActorPrivateKey          = userFunction(derivation.deriveActorPrivateKey);

/**
 * Derives and returns the private key from a pepper and a nonce.
 *
 * The generated private key is used to authenticate in applications.
 *
 * ```js
 * const pepper = derivePepperFromSeed( seed, nonce );
 * const privateKey = deriveAuthenticationPrivateKey( pepper, applicationId );
 * ```
 *
 * @param pepper {Uint8Array} The pepper used to derive the private key.
 * @param applicationId {string} The id of the application to derive a different private key for each application.
 *
 * @returns {Promise<Uint8Array>} The derived private key.
 */
export const deriveAuthenticationPrivateKey = userFunction(derivation.deriveAuthenticationPrivateKey);

/**
 * Derives and returns the public key from the public key.
 *
 * @param privateKey {Uint8Array} The private key from which the public key is derived.
 *
 * @returns {Promise<Uint8Array>} The public key.
 */
export const getPublicKey = userFunction(derivation.getPublicKey);

/**
 * Returns the signature of the data, signed by the provided private signature key.
 *
 * @param privateKey {Uint8Array} The private key used to sign the data.
 * @param data {any} The data to be signed.
 *
 * @returns {Promise<Uint8Array>} The signature.
 */
export const sign  = userFunction(crypto.secp256k1.sign);

// ============================================================================================================================ //
//  flow methods                                                                                                                //
// ============================================================================================================================ //
export const loadFromMicroblock = userFunction(flowManager.loadFromMicroblock);
export const loadFromMicrochain = userFunction(flowManager.loadFromMicrochain);
export const prepareApproval    = userFunction(flowManager.prepareApproval);

/**
 * Processes a provided flow to extract a record.
 *
 * @param obj {{applicationId: string;
 *     appDescription: {
 *         name: string,
 *         rootDomain: string,
 *         homepageUrl: string,
 *         logoUrl: string,
 *     },
 *     "flowObject": {
 *         "chain": {
 *             currentNonce: number,
 *             hash: Uint8Array,
 *             "microBlock":
 *                 {
 *                     "version": number,
 *                     "nonce": number,
 *                     "ts": number,
 *                     "gas": number,
 *                     "gasPrice": number,
 *                 }[]
 *         }
 *     }}} The flow.
 *  @param nonce {number} The nonce of the flow.
 *
 *  @returns {Promise<object>}
 */
export const processRecord      = userFunction(flowManager.processRecord);
export const getFlatRecord      = userFunction(flowManager.getFlatRecord);

/**
 * Returns a section from a block.
 *
 * @param block {{
 *    sections: {
 *      type: number,
 *    }
 *  }}
 *  @param id {number}
 *  @param key {Uint8Array|undefined}
 *
 *  @returns {Promise<object>}
 */
export const getSection         = userFunction(microblock.getSection)

// ============================================================================================================================ //
//  application methods                                                                                                         //
// ============================================================================================================================ //
export const applicationChanged = userFunction(application.isChanged);
export const publishApplication = userFunction(application.publish);

// ============================================================================================================================ //
//  organization methods                                                                                                        //
// ============================================================================================================================ //
export const organizationChanged = userFunction(organization.isChanged);
export const publishOrganization = userFunction(organization.publish);

// ============================================================================================================================ //
//  userFunction()                                                                                                              //
// ============================================================================================================================ //
function userFunction(func) {
  return function(...arg) {
    try {
      return func(...arg);
    }
    catch(e) {
      console.error(e);
      return null;
    }
  }
}