"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.b64decode = b64decode;
exports.b64encode = b64encode;
exports.evaluatePredicates = exports.credentialSortFn = exports.credDefIdFromRestrictions = exports.createTempConnectionInvitation = exports.createConnectionInvitation = exports.connectFromScanOrDeepLink = exports.connectFromInvitation = void 0;
exports.firstValidCredential = firstValidCredential;
exports.formatIfDate = formatIfDate;
exports.formatTime = formatTime;
exports.generateRandomWalletName = generateRandomWalletName;
exports.getConnectionName = getConnectionName;
exports.getCredentialDefinitionIdForRecord = void 0;
exports.getCredentialEventLabel = getCredentialEventLabel;
exports.getCredentialEventRole = getCredentialEventRole;
exports.getCredentialSchemaIdForRecord = exports.getCredentialInfo = void 0;
exports.getMessageEventRole = getMessageEventRole;
exports.getProofEventLabel = getProofEventLabel;
exports.getProofEventRole = getProofEventRole;
exports.hashToRGBA = exports.hashCode = void 0;
exports.isChildFunction = isChildFunction;
exports.pTypeToText = exports.mergeAttributesAndPredicates = exports.isDataUrl = void 0;
Object.defineProperty(exports, "parsedCredDefName", {
  enumerable: true,
  get: function () {
    return _credDef.parsedCredDefName;
  }
});
Object.defineProperty(exports, "parsedCredDefNameFromCredential", {
  enumerable: true,
  get: function () {
    return _credDef.parsedCredDefNameFromCredential;
  }
});
Object.defineProperty(exports, "parsedSchema", {
  enumerable: true,
  get: function () {
    return _schema.parsedSchema;
  }
});
exports.sortCredentialsForAutoSelect = exports.schemaIdFromRestrictions = exports.retrieveCredentialsForProof = exports.removeExistingInvitationIfRequired = exports.processProofPredicates = exports.processProofAttributes = void 0;
exports.useConnectionImageUrl = useConnectionImageUrl;
exports.useCredentialConnectionLabel = useCredentialConnectionLabel;
var _anoncreds = require("@credo-ts/anoncreds");
var _core = require("@credo-ts/core");
var _BasicMessageRole = require("@credo-ts/core/build/modules/basic-messages/BasicMessageRole");
var _reactHooks = require("@credo-ts/react-hooks");
var _ariesOca = require("@hyperledger/aries-oca");
var _legacy = require("@hyperledger/aries-oca/build/legacy");
var _buffer = require("buffer");
var _moment = _interopRequireDefault(require("moment"));
var _queryString = require("query-string");
var _reactNative = require("react-native");
var _constants = require("../constants");
var _index = require("../localization/index");
var _chat = require("../types/chat");
var _error = require("../types/error");
var _navigators = require("../types/navigators");
var _anonCredsProofRequestMapper = require("./anonCredsProofRequestMapper");
var _credDef = require("./cred-def");
var _parsers = require("./parsers");
var _schema = require("./schema");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
 * Generates a numerical hash based on a given string
 * @see https://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-javascript
 * @param { string } s given string
 * @returns { number } numerical hash value
 */
const hashCode = s => {
  return s.split('').reduce((hash, char) => char.charCodeAt(0) + ((hash << 5) - hash), 0);
};

/**
 * Generates a pseudorandom number between 0 and 1 based on a seed
 * @see https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
 * @see https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript
 * @param { number } seed any number
 * @returns { number } pseudorandom number between 0 and 1
 */
exports.hashCode = hashCode;
const mulberry32 = seed => {
  let t = seed += 0x6d2b79f5;
  t = Math.imul(t ^ t >>> 15, t | 1);
  t ^= t + Math.imul(t ^ t >>> 7, t | 61);
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
};

/**
 * Converts a numerical hash into a hexidecimal color string
 * @see https://helderesteves.com/generating-random-colors-js/#Generating_random_dark_colors
 * @param { number } hash numerical hash value (generated by hashCode function above)
 * @returns { string } hexidecimal string eg. #32d3cc
 */
const hashToRGBA = hash => {
  let color = '#';
  const colorRangeUpperBound = 256;

  // once for r, g, b
  for (let i = 0; i < 3; i++) {
    // append a pseudorandom two-char hexidecimal value from the lower half of the color spectrum (to limit to darker colors)
    color += ('0' + Math.floor(mulberry32(hash + i) * colorRangeUpperBound / 2).toString(16)).slice(-2);
  }
  return color;
};
/**
 *
 * @param time
 * @param params see below
 * shortMonth: whether to use Jun in place of June, Mar in place of March for example (overridden by `format`)
 * format: an optional custom moment format string to create the formatted date from
 * includeHour: whether to add the hour and minute and am/pm. eg 9:32 pm (overridden by `chatFormat` and `trim`)
 * chatFormat: whether to style the date to appear like a chat message timestamp eg. '7 minutes ago' or 'Just now'
 * trim: if true, if it's the same day the date will be trimmed to just the hour, if it's the same year then the year will be trimmed from the date
 * eg. if the current year is 2023, February 12, 2023 will be trimmed to February 12
 * @returns formatted time string
 */
exports.hashToRGBA = hashToRGBA;
function formatTime(time, params) {
  var _formatString;
  const getMonthKey = 'MMMM';
  const momentTime = (0, _moment.default)(time);
  const monthKey = momentTime.format(getMonthKey);
  const customMonthFormatRe = /M+/;
  const shortMonth = params === null || params === void 0 ? void 0 : params.shortMonth;
  const format = params === null || params === void 0 ? void 0 : params.format;
  const includeHour = params === null || params === void 0 ? void 0 : params.includeHour;
  const chatFormat = params === null || params === void 0 ? void 0 : params.chatFormat;
  const trim = params === null || params === void 0 ? void 0 : params.trim;
  const shortDateFormatMaskLength = 3;
  const millisecondsAgo = (0, _moment.default)().diff(momentTime);
  const lessThanAMinuteAgo = millisecondsAgo / 1000 / 60 < 1;
  const lessThanAnHourAgo = millisecondsAgo / 1000 / 60 / 60 < 1;
  const now = new Date();
  const sameYear = time.getFullYear() === now.getFullYear();
  const sameDay = time.getDate() === now.getDate() && time.getMonth() === now.getMonth() && sameYear;
  const isPortuguese = _index.i18n.resolvedLanguage === 'pt-BR';
  const isNonEnglish = _index.i18n.resolvedLanguage === 'fr' || isPortuguese;
  const hoursFormat = isPortuguese ? 'HH:mm' : 'h:mm a';
  // for the shortened approach eg. in chat bubbles
  if (chatFormat) {
    if (lessThanAMinuteAgo) {
      return _index.i18n.t('Date.JustNow');
    }
    if (lessThanAnHourAgo) {
      const minutesAgo = Math.floor(millisecondsAgo / 1000 / 60);
      return minutesAgo === 1 ? `${_index.i18n.t('Date.MinuteAgo')}` : `${_index.i18n.t('Date.MinutesAgo', {
        count: minutesAgo
      })}`;
    }
    if (sameDay) {
      return momentTime.format(hoursFormat);
    }
  }
  let formatString = _index.i18n.t('Date.ShortFormat');
  let formattedTime = '';
  // if sameDay and abbreviated
  if (sameDay && trim) {
    return momentTime.format(hoursFormat);
  }
  if (format) {
    formatString = format;
    formattedTime = momentTime.format(format);
  } else {
    if (!shortMonth) {
      formatString = _index.i18n.t('Date.LongFormat');
    }

    // if translation fails
    if (formatString === 'Date.ShortFormat' || formatString === 'Date.LongFormat' || formatString === undefined) {
      formatString = 'MMM D';
    }

    // if trim is true, don't include the year for same year times
    formattedTime = trim && sameYear ? momentTime.format(formatString) :
    // if non-english, don't include comma between year and month
    isNonEnglish ? `${momentTime.format(formatString)} ${momentTime.format('YYYY')}` : `${momentTime.format(formatString)}, ${momentTime.format('YYYY')}`;
    if (includeHour) {
      formattedTime = `${formattedTime}, ${momentTime.format(hoursFormat)}`;
    }
  }
  const customMonthFormat = (_formatString = formatString) === null || _formatString === void 0 || (_formatString = _formatString.match(customMonthFormatRe)) === null || _formatString === void 0 ? void 0 : _formatString[0];
  if (customMonthFormat) {
    let monthReplacement = '';
    const monthReplacementKey = momentTime.format(customMonthFormat);
    if (customMonthFormat.length === shortDateFormatMaskLength) {
      // then we know we're dealing with a short date format: 'MMM'
      monthReplacement = _index.i18n.t(`Date.MonthShort.${monthKey}`);
    } else if (customMonthFormat.length > shortDateFormatMaskLength) {
      // then we know we're working with a long date format: 'MMMM'
      monthReplacement = _index.i18n.t(`Date.MonthLong.${monthKey}`);
    }
    // if translation doesn't work
    if (monthReplacement === `Date.MonthLong.${monthKey}` || monthReplacement === `Date.MonthShort.${monthKey}`) {
      monthReplacement = monthReplacementKey;
    }
    if (monthReplacement) {
      formattedTime = formattedTime.replace(monthReplacementKey, monthReplacement);
    }
  }
  return formattedTime;
}

// need to use rolling b64 encode/decode to prevent hermes from 2048 byte truncation
function b64encode(inp) {
  var _inp$match;
  return ((_inp$match = inp.match(/.{1,3}/g)) === null || _inp$match === void 0 ? void 0 : _inp$match.map(chunk => {
    return _buffer.Buffer.from(chunk).toString('base64');
  }).join('')) ?? '';
}
function b64decode(b64) {
  var _b64$match;
  return ((_b64$match = b64.match(/.{1,4}/g)) === null || _b64$match === void 0 ? void 0 : _b64$match.map(chunk => {
    if (chunk.length < 4) {
      chunk += '='.repeat(4 - chunk.length);
    }
    return _buffer.Buffer.from(chunk, 'base64').toString();
  }).join('')) ?? '';
}
function formatIfDate(format, value) {
  const potentialDate = value ? value.toString() : null;
  if (format === 'YYYYMMDD' && potentialDate && potentialDate.length === format.length) {
    const year = potentialDate.substring(0, 4);
    const month = potentialDate.substring(4, 6);
    const day = potentialDate.substring(6, 8);
    // NOTE: JavaScript counts months from 0 to 11: January = 0, December = 11.
    const date = new Date(Number(year), Number(month) - 1, Number(day));
    if (!isNaN(date.getDate())) {
      return formatTime(date, {
        shortMonth: true
      });
    }
  }
  return value;
}
function getConnectionName(connection, alternateContactNames) {
  return (connection === null || connection === void 0 ? void 0 : connection.id) && alternateContactNames[connection === null || connection === void 0 ? void 0 : connection.id] || (connection === null || connection === void 0 ? void 0 : connection.theirLabel) || (connection === null || connection === void 0 ? void 0 : connection.alias) || (connection === null || connection === void 0 ? void 0 : connection.id) || '';
}
function useCredentialConnectionLabel(credential) {
  const connection = (0, _reactHooks.useConnectionById)((credential === null || credential === void 0 ? void 0 : credential.connectionId) ?? '');
  if (!credential) {
    return '';
  }
  if (credential.connectionId) {
    return (connection === null || connection === void 0 ? void 0 : connection.alias) || (connection === null || connection === void 0 ? void 0 : connection.theirLabel) || credential.connectionId;
  }
  return 'Unknown Contact';
}
function useConnectionImageUrl(connectionId) {
  const connection = (0, _reactHooks.useConnectionById)(connectionId);
  if (!connection) {
    return undefined;
  }
  return connection.imageUrl ?? undefined;
}
function firstValidCredential(fields, revoked = true) {
  var _first;
  if (!fields.length) {
    return null;
  }
  let first = null;
  const firstNonRevoked = fields.filter(field => !field.revoked)[0];
  if (firstNonRevoked) {
    first = firstNonRevoked;
  } else if (fields.length && revoked) {
    first = fields[0];
  }
  if (!((_first = first) !== null && _first !== void 0 && _first.credentialInfo)) {
    return null;
  }
  return first;
}

/**
 * A sorting function for the Array `sort()` function
 * @param a First retrieved credential
 * @param b Second retrieved credential
 */
const credentialSortFn = (a, b) => {
  if (a.revoked && !b.revoked) {
    return 1;
  } else if (!a.revoked && b.revoked) {
    return -1;
  } else {
    return b.timestamp - a.timestamp;
  }
};
exports.credentialSortFn = credentialSortFn;
const credNameFromRestriction = queries => {
  let schema_name = '';
  let cred_def_id = '';
  let schema_id = '';
  queries === null || queries === void 0 || queries.forEach(query => {
    schema_name = (query === null || query === void 0 ? void 0 : query.schema_name) ?? schema_name;
    cred_def_id = (query === null || query === void 0 ? void 0 : query.cred_def_id) ?? cred_def_id;
    schema_id = (query === null || query === void 0 ? void 0 : query.schema_id) ?? schema_id;
  });
  if (schema_name && (schema_name.toLowerCase() !== 'default' || schema_name.toLowerCase() !== 'credential')) {
    return schema_name;
  } else {
    return (0, _credDef.parseCredDefFromId)(cred_def_id, schema_id);
  }
};
const credDefIdFromRestrictions = queries => {
  var _queries$filter$;
  return (queries === null || queries === void 0 || (_queries$filter$ = queries.filter(rstr => rstr.cred_def_id)[0]) === null || _queries$filter$ === void 0 ? void 0 : _queries$filter$.cred_def_id) ?? '';
};
exports.credDefIdFromRestrictions = credDefIdFromRestrictions;
const schemaIdFromRestrictions = queries => {
  const rstrWithSchemaId = queries === null || queries === void 0 ? void 0 : queries.filter(rstr => rstr.schema_id || rstr.issuer_did && rstr.schema_name && rstr.schema_version)[0];

  // the '2' here is the enum of the transaction type which, for schemas, is always 2
  const schemaId = rstrWithSchemaId ? rstrWithSchemaId.schema_id || `${rstrWithSchemaId.issuer_did}:2:${rstrWithSchemaId.schema_name}:${rstrWithSchemaId.schema_version}` : '';
  return schemaId;
};
exports.schemaIdFromRestrictions = schemaIdFromRestrictions;
const isDataUrl = value => {
  return typeof value === 'string' && value.startsWith('data:image/');
};
exports.isDataUrl = isDataUrl;
/**
 * Retrieve current credentials info filtered by `credentialDefinitionId` if given.
 * @param credDefId Credential Definition Id
 * @returns Array of `AnonCredsCredentialInfo`
 */
const getCredentialInfo = (credId, fields) => {
  const credentialInfo = [];
  Object.keys(fields).forEach(proofKey => {
    credentialInfo.push(...fields[proofKey].map(attr => attr.credentialInfo));
  });
  return !credId ? credentialInfo : credentialInfo.filter(cred => cred.credentialId === credId);
};

/**
 * Evaluate if given attribute value satisfies the predicate.
 * @param attribute Credential attribute value
 * @param pValue Predicate value
 * @param pType Predicate type ({@link AnonCredsPredicateType})
 * @returns `true`if predicate is satisfied, otherwise `false`
 */
exports.getCredentialInfo = getCredentialInfo;
const evaluateOperation = (attribute, pValue, pType) => {
  if (pType === '>=') {
    return attribute >= pValue;
  }
  if (pType === '>') {
    return attribute > pValue;
  }
  if (pType === '<=') {
    return attribute <= pValue;
  }
  if (pType === '<') {
    return attribute < pValue;
  }
  return false;
};

/**
 * Given proof credential items, evaluate and return its predicates, setting `satisfied` property.
 * @param proofCredentialsItems
 * @returns Array of evaluated predicates
 */
const evaluatePredicates = (fields, credId) => proofCredentialItems => {
  const predicates = proofCredentialItems.predicates;
  if (!predicates || predicates.length == 0) {
    return [];
  }
  if (credId && credId != proofCredentialItems.credId || !proofCredentialItems.credId) {
    return [];
  }
  const credentialAttributes = getCredentialInfo(proofCredentialItems.credId, fields).map(ci => ci.attributes);
  return predicates.map(predicate => {
    const {
      pType: pType,
      pValue: pValue,
      name: field
    } = predicate;
    let satisfied = false;
    if (field) {
      const attribute = (credentialAttributes.find(attr => attr[field] != undefined) ?? {})[field];
      if (attribute && pValue) {
        satisfied = evaluateOperation(Number(attribute), Number(pValue), pType);
      }
    }
    return {
      ...predicate,
      satisfied
    };
  });
};

// scans through requested attributes and records
// Builds and returns label: value attributes
// Flagging any attribute not found in wallet credentials
exports.evaluatePredicates = evaluatePredicates;
const addMissingDisplayAttributes = (attrReq, records) => {
  const {
    name,
    names,
    restrictions
  } = attrReq;
  const credName = credNameFromRestriction(restrictions);
  const credDefId = credDefIdFromRestrictions(restrictions);
  const schemaId = schemaIdFromRestrictions(restrictions);

  //there is no credId in this context so use credName as a placeholder
  const processedAttributes = {
    credExchangeRecord: undefined,
    altCredentials: [credName],
    credId: credName,
    schemaId,
    credDefId,
    credName: credName,
    attributes: []
  };

  // Filter records for requested schema id of credential definition id
  const filteredCredentialRecords = records.filter(record => getCredentialSchemaIdForRecord(record) === schemaId || getCredentialDefinitionIdForRecord(record) === credDefId);

  // for reach requested attribute
  // scan through filtered credential attributes
  // display any that are found
  // flag any not found attributes with an error
  for (const attributeName of [...(names ?? (name && [name]) ?? [])]) {
    // filter through credential record attributes for a given name
    const [attribute] = filteredCredentialRecords.map(item => {
      var _item$credentialAttri;
      return (_item$credentialAttri = item.credentialAttributes) === null || _item$credentialAttri === void 0 ? void 0 : _item$credentialAttri.filter(attribute => attribute.name === attributeName);
    });
    if (attribute && attribute.length > 0) {
      var _processedAttributes$;
      // attribute found, display as expected
      (_processedAttributes$ = processedAttributes.attributes) === null || _processedAttributes$ === void 0 || _processedAttributes$.push(new _legacy.Attribute({
        revoked: false,
        credentialId: credName,
        name: attributeName,
        value: attribute[0].value,
        hasError: false
      }));
    } else {
      var _processedAttributes$2;
      // no attribute found, flag this with an error
      (_processedAttributes$2 = processedAttributes.attributes) === null || _processedAttributes$2 === void 0 || _processedAttributes$2.push(new _legacy.Attribute({
        revoked: false,
        credentialId: credName,
        name: attributeName,
        value: '',
        hasError: true
      }));
    }
  }
  return processedAttributes;
};
const processProofAttributes = (t, request, credentials, credentialRecords, groupByReferent) => {
  const processedAttributes = {};
  const requestedProofAttributes = request === null || request === void 0 ? void 0 : request.requested_attributes;
  const retrievedCredentialAttributes = credentials === null || credentials === void 0 ? void 0 : credentials.attributes;
  const requestNonRevoked = request === null || request === void 0 ? void 0 : request.non_revoked; // non_revoked interval can sometimes be top level

  // no proof or credential attributes, nothing to process, leave early
  if (!requestedProofAttributes || !retrievedCredentialAttributes) {
    return {};
  }
  for (const key of Object.keys(retrievedCredentialAttributes)) {
    const altCredentials = [...(retrievedCredentialAttributes[key] ?? [])].sort(credentialSortFn).map(cred => cred.credentialId);
    const credentialList = [...(retrievedCredentialAttributes[key] ?? [])].sort(credentialSortFn);
    const {
      name,
      names,
      non_revoked,
      restrictions
    } = requestedProofAttributes[key];

    // system assumes one of these values is present in a proof request
    const proofCredDefId = credDefIdFromRestrictions(restrictions);
    const proofSchemaId = schemaIdFromRestrictions(restrictions);

    // No credentials satisfy proof request, process attribute errors
    if (credentialList.length <= 0) {
      const missingAttributes = addMissingDisplayAttributes(requestedProofAttributes[key], credentialRecords ?? []);
      const missingCredGroupKey = groupByReferent ? key : missingAttributes.credName;
      if (!processedAttributes[missingCredGroupKey]) {
        processedAttributes[missingCredGroupKey] = missingAttributes;
      } else {
        var _processedAttributes$3;
        (_processedAttributes$3 = processedAttributes[missingCredGroupKey].attributes) === null || _processedAttributes$3 === void 0 || _processedAttributes$3.push(...(missingAttributes.attributes ?? []));
      }
    }
    //iterate over all credentials that satisfy the proof
    for (const credential of credentialList) {
      var _credential$credentia, _credential$credentia2;
      let credName = key;
      if (credential !== null && credential !== void 0 && (_credential$credentia = credential.credentialInfo) !== null && _credential$credentia !== void 0 && _credential$credentia.credentialDefinitionId || credential !== null && credential !== void 0 && (_credential$credentia2 = credential.credentialInfo) !== null && _credential$credentia2 !== void 0 && _credential$credentia2.schemaId) {
        var _credential$credentia3, _credential$credentia4;
        credName = (0, _credDef.parseCredDefFromId)(credential === null || credential === void 0 || (_credential$credentia3 = credential.credentialInfo) === null || _credential$credentia3 === void 0 ? void 0 : _credential$credentia3.credentialDefinitionId, credential === null || credential === void 0 || (_credential$credentia4 = credential.credentialInfo) === null || _credential$credentia4 === void 0 ? void 0 : _credential$credentia4.schemaId);
      }
      let revoked = false;
      let credExchangeRecord = undefined;
      if (credential) {
        var _credExchangeRecord;
        credExchangeRecord = credentialRecords === null || credentialRecords === void 0 ? void 0 : credentialRecords.find(record => record.credentials.map(cred => cred.credentialRecordId).includes(credential.credentialId) || record.id === credential.credentialId);
        revoked = ((_credExchangeRecord = credExchangeRecord) === null || _credExchangeRecord === void 0 ? void 0 : _credExchangeRecord.revocationNotification) !== undefined;
      } else {
        continue;
      }
      for (const attributeName of [...(names ?? (name && [name]) ?? [])]) {
        var _processedAttributes$4;
        if (!processedAttributes[credential.credentialId]) {
          var _credential$credentia5, _credential$credentia6;
          // init processedAttributes object
          processedAttributes[credential.credentialId] = {
            credExchangeRecord,
            altCredentials,
            credId: credential === null || credential === void 0 ? void 0 : credential.credentialId,
            schemaId: (credential === null || credential === void 0 || (_credential$credentia5 = credential.credentialInfo) === null || _credential$credentia5 === void 0 ? void 0 : _credential$credentia5.schemaId) ?? proofSchemaId,
            credDefId: (credential === null || credential === void 0 || (_credential$credentia6 = credential.credentialInfo) === null || _credential$credentia6 === void 0 ? void 0 : _credential$credentia6.credentialDefinitionId) ?? proofCredDefId,
            credName,
            attributes: []
          };
        }
        const attributeValue = credential ? credential.credentialInfo.attributes[attributeName] : null;
        (_processedAttributes$4 = processedAttributes[credential.credentialId].attributes) === null || _processedAttributes$4 === void 0 || _processedAttributes$4.push(new _legacy.Attribute({
          ...requestedProofAttributes[key],
          revoked,
          credentialId: credential.credentialId,
          name: attributeName,
          value: attributeValue,
          nonRevoked: requestNonRevoked ?? non_revoked
        }));
      }
    }
  }
  return processedAttributes;
};
exports.processProofAttributes = processProofAttributes;
const mergeAttributesAndPredicates = (attributes, predicates) => {
  const merged = {
    ...attributes
  };
  for (const [key, predicate] of Object.entries(predicates)) {
    const existingEntry = merged[key];
    if (existingEntry) {
      var _existingEntry$altCre;
      const mergedAltCreds = (_existingEntry$altCre = existingEntry.altCredentials) === null || _existingEntry$altCre === void 0 ? void 0 : _existingEntry$altCre.filter(credId => {
        var _predicate$altCredent;
        return (_predicate$altCredent = predicate.altCredentials) === null || _predicate$altCredent === void 0 ? void 0 : _predicate$altCredent.includes(credId);
      });
      merged[key] = {
        ...existingEntry,
        ...predicate
      };
      merged[key].altCredentials = mergedAltCreds;
    } else {
      merged[key] = predicate;
    }
  }
  return merged;
};
exports.mergeAttributesAndPredicates = mergeAttributesAndPredicates;
const addMissingDisplayPredicates = predReq => {
  var _processedPredicates$;
  const {
    name,
    p_type: pType,
    p_value: pValue,
    restrictions
  } = predReq;
  const credName = credNameFromRestriction(restrictions);
  const credDefId = credDefIdFromRestrictions(restrictions);
  const schemaId = schemaIdFromRestrictions(restrictions);

  //there is no credId in this context so use credName as a placeholder
  const processedPredicates = {
    credExchangeRecord: undefined,
    altCredentials: [credName],
    credId: credName,
    schemaId,
    credDefId,
    credName: credName,
    predicates: []
  };
  (_processedPredicates$ = processedPredicates.predicates) === null || _processedPredicates$ === void 0 || _processedPredicates$.push(new _legacy.Predicate({
    revoked: false,
    credentialId: credName,
    name: name,
    pValue,
    pType
  }));
  return processedPredicates;
};
const processProofPredicates = (request, credentials, credentialRecords, groupByReferent) => {
  const processedPredicates = {};
  const requestedProofPredicates = request === null || request === void 0 ? void 0 : request.requested_predicates;
  const retrievedCredentialPredicates = credentials === null || credentials === void 0 ? void 0 : credentials.predicates;
  const requestNonRevoked = request === null || request === void 0 ? void 0 : request.non_revoked; // // non_revoked interval can sometimes be top level

  if (!requestedProofPredicates || !retrievedCredentialPredicates) {
    return {};
  }
  for (const key of Object.keys(retrievedCredentialPredicates)) {
    const altCredentials = [...(retrievedCredentialPredicates[key] ?? [])].sort(credentialSortFn).map(cred => cred.credentialId);
    const credentialList = [...(retrievedCredentialPredicates[key] ?? [])].sort(credentialSortFn);
    const {
      name,
      p_type: pType,
      p_value: pValue,
      non_revoked,
      restrictions
    } = requestedProofPredicates[key];
    const proofCredDefId = credDefIdFromRestrictions(restrictions);
    const proofSchemaId = schemaIdFromRestrictions(restrictions);
    if (credentialList.length <= 0) {
      const missingPredicates = addMissingDisplayPredicates(requestedProofPredicates[key]);
      const missingCredGroupKey = groupByReferent ? key : missingPredicates.credName;
      if (!processedPredicates[missingCredGroupKey]) {
        processedPredicates[missingCredGroupKey] = missingPredicates;
      } else {
        var _processedPredicates$2;
        (_processedPredicates$2 = processedPredicates[missingCredGroupKey].predicates) === null || _processedPredicates$2 === void 0 || _processedPredicates$2.push(...(missingPredicates.predicates ?? []));
      }
    }
    for (const credential of credentialList) {
      var _requestedProofPredic, _credential$credentia7, _credential$credentia8, _processedPredicates$3;
      let revoked = false;
      let credExchangeRecord = undefined;
      if (credential) {
        var _credExchangeRecord2;
        credExchangeRecord = credentialRecords === null || credentialRecords === void 0 ? void 0 : credentialRecords.find(record => record.credentials.map(cred => cred.credentialRecordId).includes(credential.credentialId) || record.id === credential.credentialId);
        revoked = ((_credExchangeRecord2 = credExchangeRecord) === null || _credExchangeRecord2 === void 0 ? void 0 : _credExchangeRecord2.revocationNotification) !== undefined;
      } else {
        continue;
      }
      const {
        credentialDefinitionId,
        schemaId
      } = {
        ...credential,
        ...(credential === null || credential === void 0 ? void 0 : credential.credentialInfo)
      };
      const credNameRestriction = credNameFromRestriction((_requestedProofPredic = requestedProofPredicates[key]) === null || _requestedProofPredic === void 0 ? void 0 : _requestedProofPredic.restrictions);
      let credName = credNameRestriction ?? key;
      if (credential !== null && credential !== void 0 && (_credential$credentia7 = credential.credentialInfo) !== null && _credential$credentia7 !== void 0 && _credential$credentia7.credentialDefinitionId || credential !== null && credential !== void 0 && (_credential$credentia8 = credential.credentialInfo) !== null && _credential$credentia8 !== void 0 && _credential$credentia8.schemaId) {
        var _credential$credentia9, _credential$credentia10;
        credName = (0, _credDef.parseCredDefFromId)(credential === null || credential === void 0 || (_credential$credentia9 = credential.credentialInfo) === null || _credential$credentia9 === void 0 ? void 0 : _credential$credentia9.credentialDefinitionId, credential === null || credential === void 0 || (_credential$credentia10 = credential.credentialInfo) === null || _credential$credentia10 === void 0 ? void 0 : _credential$credentia10.schemaId);
      }
      if (!processedPredicates[credential.credentialId]) {
        processedPredicates[credential.credentialId] = {
          altCredentials,
          credExchangeRecord,
          credId: credential.credentialId,
          schemaId: schemaId ?? proofSchemaId,
          credDefId: credentialDefinitionId ?? proofCredDefId,
          credName: credName,
          predicates: []
        };
      }
      (_processedPredicates$3 = processedPredicates[credential.credentialId].predicates) === null || _processedPredicates$3 === void 0 || _processedPredicates$3.push(new _legacy.Predicate({
        ...requestedProofPredicates[key],
        credentialId: credential === null || credential === void 0 ? void 0 : credential.credentialId,
        name,
        revoked,
        pValue,
        pType,
        nonRevoked: requestNonRevoked ?? non_revoked
      }));
    }
  }
  return processedPredicates;
};
exports.processProofPredicates = processProofPredicates;
const retrieveCredentialsForProof = async (agent, proof, fullCredentials, t, groupByReferent) => {
  // This is the only valid state to retrieve credentials for a proof
  // `getCredentialsForRequest` will fail otherwise.
  if (proof.state !== _core.ProofState.RequestReceived) {
    return;
  }
  try {
    var _format$request, _format$request2, _format$request3, _format$request5, _format$request6;
    const format = await agent.proofs.getFormatData(proof.id);
    const hasPresentationExchange = ((_format$request = format.request) === null || _format$request === void 0 ? void 0 : _format$request.presentationExchange) !== undefined;
    const hasAnonCreds = ((_format$request2 = format.request) === null || _format$request2 === void 0 ? void 0 : _format$request2.anoncreds) !== undefined;
    const hasIndy = ((_format$request3 = format.request) === null || _format$request3 === void 0 ? void 0 : _format$request3.indy) !== undefined;

    // Will fail if credential not in state 'request-received'
    const credentialsAsPromise = agent.proofs.getCredentialsForRequest({
      proofRecordId: proof.id,
      proofFormats: {
        // FIXME: Credo will try to use the format, even if the value is undefined (but the key is present)
        // We should ignore the key, if the value is undefined. For now this is a workaround.
        ...(hasIndy ? {
          indy: {
            // Setting `filterByNonRevocationRequirements` to `false` returns all
            // credentials even if they are revokable (and revoked). We need this to
            // be able to show why a proof cannot be satisfied. Otherwise we can only
            // show failure.
            filterByNonRevocationRequirements: true
          }
        } : {}),
        ...(hasAnonCreds ? {
          anoncreds: {
            // Setting `filterByNonRevocationRequirements` to `false` returns all
            // credentials even if they are revokable (and revoked). We need this to
            // be able to show why a proof cannot be satisfied. Otherwise we can only
            // show failure.
            filterByNonRevocationRequirements: true
          }
        } : {}),
        ...(hasPresentationExchange ? {
          presentationExchange: {}
        } : {})
      }
    });

    // Will fail if credential not in state 'request-received'
    const credentialsWithRevokedAsPromise = agent.proofs.getCredentialsForRequest({
      proofRecordId: proof.id,
      proofFormats: {
        // FIXME: Credo will try to use the format, even if the value is undefined (but the key is present)
        // We should ignore the key, if the value is undefined. For now this is a workaround.
        ...(hasIndy ? {
          indy: {
            // Setting `filterByNonRevocationRequirements` to `false` returns all
            // credentials even if they are revokable (and revoked). We need this to
            // be able to show why a proof cannot be satisfied. Otherwise we can only
            // show failure.
            filterByNonRevocationRequirements: false
          }
        } : {}),
        ...(hasAnonCreds ? {
          anoncreds: {
            // Setting `filterByNonRevocationRequirements` to `false` returns all
            // credentials even if they are revokable (and revoked). We need this to
            // be able to show why a proof cannot be satisfied. Otherwise we can only
            // show failure.
            filterByNonRevocationRequirements: false
          }
        } : {}),
        ...(hasPresentationExchange ? {
          presentationExchange: {}
        } : {})
      }
    });
    const [credentials, credentialsWithRevoked] = await Promise.all([credentialsAsPromise, credentialsWithRevokedAsPromise]);

    // In the case where there are only revoked credentials to satisfy a proof,
    // include them for errors on the proof screen, otherwise leave them out
    const addRevokedCredsIfNeeded = (proofFormat, proofItem) => {
      if (credentials.proofFormats[proofFormat] && credentialsWithRevoked.proofFormats[proofFormat]) {
        var _credentials$proofFor;
        Object.keys(((_credentials$proofFor = credentials.proofFormats[proofFormat]) === null || _credentials$proofFor === void 0 ? void 0 : _credentials$proofFor[proofItem]) ?? {}).forEach(key => {
          var _credentials$proofFor2;
          if (credentials.proofFormats[proofFormat] && !((_credentials$proofFor2 = credentials.proofFormats[proofFormat]) !== null && _credentials$proofFor2 !== void 0 && (_credentials$proofFor2 = _credentials$proofFor2[proofItem][key]) !== null && _credentials$proofFor2 !== void 0 && _credentials$proofFor2.length)) {
            var _credentials$proofFor3, _credentialsWithRevok;
            (_credentials$proofFor3 = credentials.proofFormats[proofFormat]) === null || _credentials$proofFor3 === void 0 || _credentials$proofFor3[proofItem][key].push(...(((_credentialsWithRevok = credentialsWithRevoked.proofFormats[proofFormat]) === null || _credentialsWithRevok === void 0 ? void 0 : _credentialsWithRevok[proofItem][key]) ?? []));
          }
        });
      }
    };
    for (const proofFormat of ['indy', 'anoncreds']) {
      for (const proofItem of ['attributes', 'predicates']) {
        addRevokedCredsIfNeeded(proofFormat, proofItem);
      }
    }
    if (!credentials) {
      throw new Error(t('ProofRequest.RequestedCredentialsCouldNotBeFound'));
    }
    if (!format) {
      throw new Error(t('ProofRequest.RequestedCredentialsCouldNotBeFound'));
    }
    if (!(format && credentials && fullCredentials)) {
      return;
    }
    if (hasPresentationExchange) {
      var _format$request4;
      // FIXME: non revocation requirements
      const presentationExchange = (_format$request4 = format.request) === null || _format$request4 === void 0 ? void 0 : _format$request4.presentationExchange;
      const difPexCredentialsForRequest = credentials.proofFormats.presentationExchange;
      if (!difPexCredentialsForRequest || !presentationExchange) throw new Error('Invalid presentation request');
      const presentationDefinition = presentationExchange.presentation_definition;
      const descriptorMetadata = (0, _anonCredsProofRequestMapper.getDescriptorMetadata)(difPexCredentialsForRequest);
      const anonCredsProofRequest = (0, _anonCredsProofRequestMapper.createAnonCredsProofRequest)(presentationDefinition, descriptorMetadata);
      const anonCredsCredentialsForRequest = await (0, _anoncreds.getCredentialsForAnonCredsProofRequest)(agent.context, anonCredsProofRequest, {
        filterByNonRevocationRequirements: false
      });
      const filtered = (0, _anonCredsProofRequestMapper.filterInvalidProofRequestMatches)(anonCredsCredentialsForRequest, descriptorMetadata);
      const processedAttributes = processProofAttributes(t, anonCredsProofRequest, filtered, fullCredentials, groupByReferent);
      const processedPredicates = processProofPredicates(anonCredsProofRequest, filtered, fullCredentials, groupByReferent);
      const groupedProof = Object.values(mergeAttributesAndPredicates(processedAttributes, processedPredicates));
      return {
        groupedProof,
        retrievedCredentials: filtered,
        fullCredentials,
        descriptorMetadata
      };
    }
    const proofRequest = ((_format$request5 = format.request) === null || _format$request5 === void 0 ? void 0 : _format$request5.anoncreds) ?? ((_format$request6 = format.request) === null || _format$request6 === void 0 ? void 0 : _format$request6.indy);
    const proofFormat = credentials.proofFormats.anoncreds ?? credentials.proofFormats.indy;
    const attributes = processProofAttributes(t, proofRequest, proofFormat, fullCredentials, groupByReferent);
    const predicates = processProofPredicates(proofRequest, proofFormat, fullCredentials, groupByReferent);
    const groupedProof = Object.values(mergeAttributesAndPredicates(attributes, predicates));
    return {
      groupedProof,
      retrievedCredentials: proofFormat,
      fullCredentials
    };
  } catch (err) {
    const error = new _error.BifoldError(t('Error.Title1043'), t('Error.Message1043'), (err === null || err === void 0 ? void 0 : err.message) ?? err, 1043);
    _reactNative.DeviceEventEmitter.emit(_constants.EventTypes.ERROR_ADDED, error);
  }
};
exports.retrieveCredentialsForProof = retrieveCredentialsForProof;
const pTypeToText = (item, t, attributeTypes) => {
  const itemCopy = {
    ...item
  };
  const pTypeMap = {
    '>=': t('ProofRequest.PredicateGe'),
    '>': t('ProofRequest.PredicateGr'),
    '<=': t('ProofRequest.PredicateLe'),
    '<': t('ProofRequest.PredicateLs')
  };
  const pTypeDateMap = {
    '>=': t('ProofRequest.PredicateGeDate'),
    '>': t('ProofRequest.PredicateGeDate'),
    '<=': t('ProofRequest.PredicateLeDate'),
    '<': t('ProofRequest.PredicateLeDate')
  };
  const pTypeDateOffset = {
    '>=': -1,
    '<=': 1
  };
  if (attributeTypes && attributeTypes[item.name ?? ''] == _ariesOca.CaptureBaseAttributeType.DateTime) {
    itemCopy.pType = pTypeDateMap[item.pType] ?? item.pType;
    itemCopy.pValue = parseInt(`${itemCopy.pValue}`) + (pTypeDateOffset[item.pType] ?? 0);
  } else {
    itemCopy.pType = pTypeMap[item.pType] ?? item.pType;
  }
  return itemCopy;
};

/**
 * @deprecated The function should not be used
 */
exports.pTypeToText = pTypeToText;
const sortCredentialsForAutoSelect = credentials => {
  const requestedAttributes = Object.values(credentials === null || credentials === void 0 ? void 0 : credentials.attributes).pop();
  const requestedPredicates = Object.values(credentials === null || credentials === void 0 ? void 0 : credentials.predicates).pop();
  const sortFn = (a, b) => {
    if (a.revoked && !b.revoked) {
      return 1;
    } else if (!a.revoked && b.revoked) {
      return -1;
    } else {
      return b.timestamp - a.timestamp;
    }
  };
  requestedAttributes && requestedAttributes.sort(sortFn);
  requestedPredicates && requestedPredicates.sort(sortFn);
  return credentials;
};

/**
 * Useful for multi use invitations
 * @param agent an Agent instance
 * @param invitationId id of invitation
 */
exports.sortCredentialsForAutoSelect = sortCredentialsForAutoSelect;
const removeExistingInvitationIfRequired = async (agent, invitationId) => {
  try {
    const oobRecord = await (agent === null || agent === void 0 ? void 0 : agent.oob.findByReceivedInvitationId(invitationId));
    if (oobRecord) {
      await (agent === null || agent === void 0 ? void 0 : agent.oob.deleteById(oobRecord.id));
    }
  } catch (error) {
    // findByReceivedInvitationId will throw if unsuccessful but that's not a problem
    // it just means there is nothing to delete
  }
};

/**
 * Get a oob record and connection record from a URI using built-in Credo methods
 * @param uri a URI that is either a redirect URL or contains a base64 encoded connection invite in query params
 * @param agent an Agent instance
 * @param implicitInvitations a boolean to determine if implicit invitation behavior should be used
 * @param reuseConnection a boolean to determine if connection reuse should be allowed
 * @returns an object containing an OOB record and, if not connectionless, a connection record
 */
exports.removeExistingInvitationIfRequired = removeExistingInvitationIfRequired;
const connectFromInvitation = async (uri, agent, implicitInvitations = false, reuseConnection = false) => {
  const invitation = await (agent === null || agent === void 0 ? void 0 : agent.oob.parseInvitation(uri));
  if (!invitation) {
    throw new Error('Could not parse invitation from URL');
  }
  if (implicitInvitations) {
    try {
      if (invitation.getDidServices().length > 0) {
        const did = (0, _core.parseDid)(invitation.getDidServices()[0]);
        const record = await (agent === null || agent === void 0 ? void 0 : agent.oob.receiveImplicitInvitation({
          did: did.did,
          label: invitation.label,
          handshakeProtocols: invitation.handshakeProtocols
        }));
        return record === null || record === void 0 ? void 0 : record.outOfBandRecord;
      }
    } catch (e) {
      // don't throw an error, will try to connect again below
    }
  }
  const record = await (agent === null || agent === void 0 ? void 0 : agent.oob.receiveInvitation(invitation, {
    reuseConnection
  }));
  return record === null || record === void 0 ? void 0 : record.outOfBandRecord;
};
exports.connectFromInvitation = connectFromInvitation;
const processBetaUrlIfRequired = uri => {
  let aUrl = uri;

  // _oob is a beta query param, not supported by Credo.
  aUrl = uri.replace('_oob', 'oob');

  // _url is a beta query param, not supported by Credo.
  if (uri.includes('_url')) {
    var _parseUrl;
    const queryParams = (_parseUrl = (0, _queryString.parseUrl)(uri)) === null || _parseUrl === void 0 ? void 0 : _parseUrl.query;
    const b64UrlRedirect = queryParams['_url'];
    aUrl = b64decode(b64UrlRedirect);
  }
  return aUrl;
};

/**
 * Receive a message from a scan or deeplink and navigate accordingly
 * @param uri a URI either containing a base64 encoded connection invite in the query parameters or a redirect URL itself
 * @param agent an Agent instance
 * @param logger injected logger from DI container
 * @param navigation a navigation object from either the Scan screen, Home screen, or PasteUrl screen
 * @param isDeepLink a boolean to communicate where the uri is coming from
 * @param implicitInvitations a boolean to determine if implicit invitation behavior should be used
 * @param reuseConnection a boolean to determine if connection reuse should be allowed
 * @throws Error with message containing the primary and beta error messages if both fail
 */
const connectFromScanOrDeepLink = async (uri, agent, logger, navigation, isDeepLink, implicitInvitations = false, reuseConnection = false) => {
  if (!agent) {
    return;
  }

  // TODO:(jl) Do we care if the connection is a deep link?
  logger.info(`Attempting to connect from ${isDeepLink ? 'deeplink' : 'qr scan'}`);
  try {
    if ((0, _parsers.isOpenIdCredentialOffer)(uri)) {
      navigation.navigate(_navigators.Stacks.ConnectionStack, {
        screen: _navigators.Screens.Connection,
        params: {
          oobRecordId: '',
          openIDUri: uri
        }
      });
      return;
    }
    if ((0, _parsers.isOpenIdPresentationRequest)(uri)) {
      navigation.navigate(_navigators.Stacks.ConnectionStack, {
        screen: _navigators.Screens.Connection,
        params: {
          oobRecordId: '',
          openIDPresentationUri: uri
        }
      });
      return;
    }
    const aUrl = processBetaUrlIfRequired(uri);
    const receivedInvitation = await connectFromInvitation(aUrl, agent, implicitInvitations, reuseConnection);
    if (receivedInvitation !== null && receivedInvitation !== void 0 && receivedInvitation.id) {
      navigation.navigate(_navigators.Stacks.ConnectionStack, {
        screen: _navigators.Screens.Connection,
        params: {
          oobRecordId: receivedInvitation.id
        }
      });
    }
  } catch (error) {
    logger.error('Problem during connect strategy, error:', error);
    throw error;
  }
};

/**
 * Create a new connection invitation
 *
 * @param agent an Agent instance
 * @param goalCode add goalCode to connection invitation
 * @returns a connection record
 */
exports.connectFromScanOrDeepLink = connectFromScanOrDeepLink;
const createConnectionInvitation = async (agent, goalCode) => {
  const record = await (agent === null || agent === void 0 ? void 0 : agent.oob.createInvitation({
    goalCode
  }));
  if (!record) {
    throw new Error('Could not create new invitation');
  }
  const invitationUrl = record.outOfBandInvitation.toUrl({
    domain: _constants.domain
  });
  return {
    record,
    invitation: record.outOfBandInvitation,
    invitationUrl
  };
};

/**
 * Create a new connection invitation with a goal code specifying that it will be deleted after issuing or verifying once depending on type
 *
 * @param agent an Agent instance
 * @param type add goalCode to connection invitation
 * @returns a connection record
 */
exports.createConnectionInvitation = createConnectionInvitation;
const createTempConnectionInvitation = async (agent, type) => {
  return createConnectionInvitation(agent, `aries.vc.${type}.once`);
};

/**
 * Typeguard to check if any React children is represented as a function
 * instead of a Node. I,e., when it's a {@link ChildFn}.
 *
 * @param children any React children
 * @returns true if the children is a function, false otherwise
 */
exports.createTempConnectionInvitation = createTempConnectionInvitation;
function isChildFunction(children) {
  return typeof children === 'function';
}

// Fetches the credential definition id for a given credential exchange record, returns null if ID is not found
const getCredentialDefinitionIdForRecord = record => {
  var _record$metadata$get;
  // assumes record is anonCred
  return ((_record$metadata$get = record.metadata.get('_anoncreds/credential')) === null || _record$metadata$get === void 0 ? void 0 : _record$metadata$get.credentialDefinitionId) ?? null;
};

// Fetches the schema id for a given credential exchange record, returns null if ID is not found
exports.getCredentialDefinitionIdForRecord = getCredentialDefinitionIdForRecord;
const getCredentialSchemaIdForRecord = record => {
  var _record$metadata$get2;
  // assumes record is anonCred
  return ((_record$metadata$get2 = record.metadata.get('_anoncreds/credential')) === null || _record$metadata$get2 === void 0 ? void 0 : _record$metadata$get2.schemaId) ?? null;
};
exports.getCredentialSchemaIdForRecord = getCredentialSchemaIdForRecord;
function getCredentialEventRole(record) {
  switch (record.state) {
    // assuming only Holder states are supported here
    case _core.CredentialState.ProposalSent:
      return _chat.Role.me;
    case _core.CredentialState.OfferReceived:
      return _chat.Role.them;
    case _core.CredentialState.RequestSent:
      return _chat.Role.me;
    case _core.CredentialState.Declined:
      return _chat.Role.me;
    case _core.CredentialState.CredentialReceived:
      return _chat.Role.me;
    case _core.CredentialState.Done:
      return _chat.Role.me;
    default:
      return _chat.Role.me;
  }
}
function getCredentialEventLabel(record) {
  switch (record.state) {
    // assuming only Holder states are supported here
    case _core.CredentialState.ProposalSent:
      return 'Chat.CredentialProposalSent';
    case _core.CredentialState.OfferReceived:
      return 'Chat.CredentialOfferReceived';
    case _core.CredentialState.RequestSent:
      return 'Chat.CredentialRequestSent';
    case _core.CredentialState.Declined:
      return 'Chat.CredentialDeclined';
    case _core.CredentialState.CredentialReceived:
    case _core.CredentialState.Done:
      return 'Chat.CredentialReceived';
    default:
      return '';
  }
}
function getProofEventRole(record) {
  switch (record.state) {
    case _core.ProofState.RequestSent:
      return _chat.Role.me;
    case _core.ProofState.ProposalReceived:
      return _chat.Role.me;
    case _core.ProofState.PresentationReceived:
      return _chat.Role.them;
    case _core.ProofState.RequestReceived:
      return _chat.Role.them;
    case _core.ProofState.ProposalSent:
    case _core.ProofState.PresentationSent:
      return _chat.Role.me;
    case _core.ProofState.Declined:
      return _chat.Role.me;
    case _core.ProofState.Abandoned:
      return _chat.Role.them;
    case _core.ProofState.Done:
      return record.isVerified !== undefined ? _chat.Role.them : _chat.Role.me;
    default:
      return _chat.Role.me;
  }
}
function getProofEventLabel(record) {
  switch (record.state) {
    case _core.ProofState.RequestSent:
    case _core.ProofState.ProposalReceived:
      return 'Chat.ProofRequestSent';
    case _core.ProofState.PresentationReceived:
      return 'Chat.ProofPresentationReceived';
    case _core.ProofState.RequestReceived:
      return 'Chat.ProofRequestReceived';
    case _core.ProofState.ProposalSent:
    case _core.ProofState.PresentationSent:
      return 'Chat.ProofRequestSatisfied';
    case _core.ProofState.Declined:
      return 'Chat.ProofRequestRejected';
    case _core.ProofState.Abandoned:
      return 'Chat.ProofRequestRejectReceived';
    case _core.ProofState.Done:
      return record.isVerified !== undefined ? 'Chat.ProofPresentationReceived' : 'Chat.ProofRequestSatisfied';
    default:
      return '';
  }
}
function getMessageEventRole(record) {
  return record.role === _BasicMessageRole.BasicMessageRole.Sender ? _chat.Role.me : _chat.Role.them;
}
function generateRandomWalletName() {
  let name = 'My Wallet - ';
  for (let i = 0; i < 4; i++) {
    name = name.concat(Math.floor(Math.random() * 10).toString());
  }
  return name;
}
//# sourceMappingURL=helpers.js.map